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 SnakeTography v1.8.82
SnakeSquadCartographySnapshot.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SnakeSquadCartographySnapshot")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+be87a06804e2bdea813de87a1bd3e0099fa35086")] [assembly: AssemblyProduct("SnakeSquadCartographySnapshot")] [assembly: AssemblyTitle("SnakeSquadCartographySnapshot")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SnakeSquadCartographySnapshot { [BepInPlugin("com.snakesquad.cartographysnapshot", "SnakeSquad Cartography Snapshot", "1.17.1")] public class CartographySnapshotPlugin : BaseUnityPlugin { private class ConfigurationManagerAttributes { public Action<ConfigEntryBase>? CustomDrawer; } [HarmonyPatch(typeof(MapTable), "OnWrite")] private static class MapTable_OnWrite_TrackWriteInProgress { internal static bool isWriteInProgress; private const float ForcedCheckDebounceSeconds = 5f; private static float lastForcedCheckTime = float.NegativeInfinity; private static void Prefix() { isWriteInProgress = true; } private static void Postfix() { isWriteInProgress = false; if (!string.IsNullOrEmpty(snapshotUrl.Value) && (!onlyInNoMapMode.Value || Game.m_noMap) && !(Time.realtimeSinceStartup - lastForcedCheckTime < 5f)) { lastForcedCheckTime = Time.realtimeSinceStartup; ((MonoBehaviour)instance).StartCoroutine(SnapshotViewer.RefreshInBackground(snapshotUrl.Value, snapshotKey.Value, requestTimeoutSeconds.Value, forceTileCheck: true)); } } } [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData), typeof(bool) })] private static class MapTable_OnRead_ShowSnapshot { private static void Postfix(MapTable __instance, ItemData item) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (item == null && !MapTable_OnWrite_TrackWriteInProgress.isWriteInProgress && !string.IsNullOrEmpty(snapshotUrl.Value) && (!onlyInNoMapMode.Value || Game.m_noMap) && PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false)) { ((MonoBehaviour)instance).StartCoroutine(SnapshotViewer.ShowSnapshot(snapshotUrl.Value, snapshotKey.Value, requestTimeoutSeconds.Value, showPlayerMarker.Value, ((Component)__instance).transform.position, autoCloseDistance.Value)); } } } private const string PluginGUID = "com.snakesquad.cartographysnapshot"; private const string PluginName = "SnakeSquad Cartography Snapshot"; private const string PluginVersion = "1.17.1"; internal static ConfigEntry<string> snapshotUrl; internal static ConfigEntry<string> snapshotKey; internal static ConfigEntry<string> accessClientId; internal static ConfigEntry<string> accessClientSecret; internal static ConfigEntry<bool> onlyInNoMapMode; internal static ConfigEntry<int> requestTimeoutSeconds; internal static ConfigEntry<bool> showPlayerMarker; internal static ConfigEntry<bool> verboseTileLogging; internal static ConfigEntry<float> autoCloseDistance; internal static ConfigEntry<bool> downloadOnStartup; private static CartographySnapshotPlugin instance; internal static MonoBehaviour CoroutineHost => (MonoBehaviour)(object)instance; private void Awake() { //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown instance = this; snapshotUrl = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Snapshot URL", "https://draw.snakesquad.net/valheim-snapshot.png", "URL to fetch a PNG from when a Cartography Table is read. Leave empty to disable this plugin's behavior entirely."); snapshotKey = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Snapshot Key", "", "Shared secret sent as the X-Snapshot-Key request header. Get this from whoever runs the snapshot service. If left empty, it's filled in on the next launch from the snapshot-credentials.txt installed alongside the mod (the SnakeTography package includes one)."); accessClientId = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Access Client Id", "", "Cloudflare Access service-token id, sent as the CF-Access-Client-Id header - the snapshot service sits behind Cloudflare Access, which turns away requests without it. Filled in from snapshot-credentials.txt like the Snapshot Key."); accessClientSecret = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Access Client Secret", "", "Cloudflare Access service-token secret, sent as the CF-Access-Client-Secret header. Filled in from snapshot-credentials.txt like the Snapshot Key."); onlyInNoMapMode = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Only In No Map Mode", true, "If on, the snapshot only replaces the Cartography Table's (otherwise do-nothing) behavior when the server's 'No Map' setting is active. If off, it always shows the snapshot."); requestTimeoutSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "Request Timeout Seconds", 15, "How long to wait for the snapshot image to download before giving up."); showPlayerMarker = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Show Player Marker", true, "If on, draws a dot on the snapshot at your current position, using the geometry headers the snapshot service returns. If those headers are missing from a response, no marker is drawn regardless of this setting."); verboseTileLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Debugging", "Verbose Tile Logging", false, "If on, logs detailed info about each map tile download to LogOutput.log (status, timing, size, error text) - useful for diagnosing tile-loading issues. Off by default to avoid log spam during normal play."); autoCloseDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "Auto-Close Distance", 10f, "If you walk more than this many meters from the Cartography Table while the snapshot is open, it closes automatically - typical crafting-station behavior."); downloadOnStartup = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Download Map Detail On Startup", true, "If on, checks the map and starts downloading any missing or outdated sharp-zoom tiles as soon as the game launches, in the background, so they're ready before you reach a Cartography Table. If off, that only starts when a table is used."); ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Reload Config From Disk", false, new ConfigDescription("Click to reload this plugin's settings from the .cfg file on disk immediately, without restarting Valheim - for after hand-editing Snapshot Key/URL.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = DrawReloadConfigButton } })); ApplyBundledCredentials(); Harmony val = new Harmony("com.snakesquad.cartographysnapshot"); Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { try { val.CreateClassProcessor(type).Patch(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Couldn't apply patch " + type.Name + " (a game update may have changed what it hooks) - that part of the plugin is disabled: " + ex.Message)); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Patched: " + string.Join(", ", from m in val.GetPatchedMethods() select m.DeclaringType?.Name + "." + m.Name))); if (downloadOnStartup.Value && !string.IsNullOrEmpty(snapshotUrl.Value)) { ((MonoBehaviour)this).StartCoroutine(SnapshotViewer.RefreshInBackground(snapshotUrl.Value, snapshotKey.Value, requestTimeoutSeconds.Value)); } } private void ApplyBundledCredentials() { string path = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? ""; try { string path2 = Path.Combine(path, "snapshot-credentials.txt"); if (File.Exists(path2)) { string[] array = File.ReadAllLines(path2); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0 && !text.TrimStart(Array.Empty<char>()).StartsWith("#")) { string text2 = text.Substring(0, num).Trim(); string value = text.Substring(num + 1).Trim(); FillIfEmpty((ConfigEntry<string>?)(text2 switch { "Snapshot Key" => snapshotKey, "Access Client Id" => accessClientId, "Access Client Secret" => accessClientSecret, _ => null, }), value, "snapshot-credentials.txt"); } } } string path3 = Path.Combine(path, "snapshot-key.txt"); if (File.Exists(path3)) { FillIfEmpty(snapshotKey, File.ReadAllText(path3).Trim(), "snapshot-key.txt"); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Couldn't read the bundled credentials file: " + ex.Message)); } } private void FillIfEmpty(ConfigEntry<string>? entry, string value, string source) { if (entry != null && value.Length != 0 && string.IsNullOrEmpty(entry.Value)) { entry.Value = value; ((BaseUnityPlugin)this).Logger.LogInfo((object)(((ConfigEntryBase)entry).Definition.Key + " was empty - filled it in from the " + source + " installed with the mod.")); } } internal static void PrepareSnapshotRequest(UnityWebRequest request, string key) { request.redirectLimit = 0; SetHeaderIfPresent(request, "X-Snapshot-Key", key); SetHeaderIfPresent(request, "CF-Access-Client-Id", accessClientId.Value); SetHeaderIfPresent(request, "CF-Access-Client-Secret", accessClientSecret.Value); } private static void SetHeaderIfPresent(UnityWebRequest request, string name, string? value) { if (!string.IsNullOrEmpty(value)) { request.SetRequestHeader(name, value.Trim()); } } internal static bool IsAccessDenied(UnityWebRequest request) { switch (request.responseCode) { default: return (request.error?.IndexOf("redirect", StringComparison.OrdinalIgnoreCase) ?? (-1)) >= 0; case 300L: case 301L: case 302L: case 303L: case 305L: case 306L: case 307L: case 308L: case 309L: case 310L: case 311L: case 312L: case 313L: case 314L: case 315L: case 316L: case 317L: case 318L: case 319L: case 320L: case 321L: case 322L: case 323L: case 324L: case 325L: case 326L: case 327L: case 328L: case 329L: case 330L: case 331L: case 332L: case 333L: case 334L: case 335L: case 336L: case 337L: case 338L: case 339L: case 340L: case 341L: case 342L: case 343L: case 344L: case 345L: case 346L: case 347L: case 348L: case 349L: case 350L: case 351L: case 352L: case 353L: case 354L: case 355L: case 356L: case 357L: case 358L: case 359L: case 360L: case 361L: case 362L: case 363L: case 364L: case 365L: case 366L: case 367L: case 368L: case 369L: case 370L: case 371L: case 372L: case 373L: case 374L: case 375L: case 376L: case 377L: case 378L: case 379L: case 380L: case 381L: case 382L: case 383L: case 384L: case 385L: case 386L: case 387L: case 388L: case 389L: case 390L: case 391L: case 392L: case 393L: case 394L: case 395L: case 396L: case 397L: case 398L: case 399L: case 403L: return true; } } internal static string AccessDeniedMessage(UnityWebRequest request) { return $"Cloudflare Access turned the request away (HTTP {request.responseCode}) - access token missing or wrong: check Access Client Id and Access Client Secret."; } private static void DrawReloadConfigButton(ConfigEntryBase _) { if (GUILayout.Button("Reload now", Array.Empty<GUILayoutOption>())) { ((BaseUnityPlugin)instance).Config.Reload(); ((BaseUnityPlugin)instance).Logger.LogInfo((object)"Config reloaded from disk."); } } } internal static class SnapshotViewer { private readonly struct SnapshotContext { public readonly string Url; public readonly string Key; public readonly int TimeoutSeconds; public readonly bool HasGeometry; public readonly float PixelsPerUnit; public readonly float LeftX; public readonly float TopZ; public readonly Vector3 TablePosition; public readonly float AutoCloseDistance; public SnapshotContext(string url, string key, int timeoutSeconds, bool hasGeometry, float pixelsPerUnit, float leftX, float topZ, Vector3 tablePosition, float autoCloseDistance) { //IL_0036: 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) Url = url; Key = key; TimeoutSeconds = timeoutSeconds; HasGeometry = hasGeometry; PixelsPerUnit = pixelsPerUnit; LeftX = leftX; TopZ = topZ; TablePosition = tablePosition; AutoCloseDistance = autoCloseDistance; } } private class CloseOnInput : MonoBehaviour { private void Update() { if (Input.GetKeyDown((KeyCode)27)) { escapeCloseFrame = Time.frameCount; Close(); } else if (Input.GetKeyDown((KeyCode)101)) { Close(); } } } private class PanZoom : MonoBehaviour { private const float MinZoom = 1f; private const float MaxZoom = 8f; private const float ZoomPerScrollNotch = 0.5f; private const float ClickMovementThreshold = 6f; private const float MagnificationBeforeNextLevel = 1.15f; private const float VisibleMarginFraction = 0.1f; private const float StatusRefreshSeconds = 0.5f; private RectTransform mapRect; private RectTransform viewportRect; private Vector2 fitSize; private float zoom = 1f; private bool dragging; private Vector3 lastMousePosition; private Vector3 mouseDownPosition; private Canvas canvas; private Texture2D overviewTexture; private bool hasGeometry; private float pixelsPerUnit; private float leftX; private float topZ; private Vector3 tablePosition; private float autoCloseDistance; private readonly RectTransform?[] layers = (RectTransform?[])(object)new RectTransform[TileCache.Levels.Length]; private readonly Dictionary<string, RawImage> tileImages = new Dictionary<string, RawImage>(); private readonly HashSet<string> visibleKeys = new HashSet<string>(); private readonly List<TileCache.Cell> cellsBuffer = new List<TileCache.Cell>(); private readonly List<TileCache.Cell> wantedCells = new List<TileCache.Cell>(); private bool tilesDirty = true; private float nextStatusRefresh; private TextMeshProUGUI? loadingText; private bool refreshingTiles; public void Initialize(RectTransform map, RectTransform viewport, Vector2 baseFitSize) { //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) mapRect = map; viewportRect = viewport; fitSize = baseFitSize; } public void InitializeTiles(Texture2D texture, SnapshotContext context) { //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) overviewTexture = texture; hasGeometry = context.HasGeometry; pixelsPerUnit = context.PixelsPerUnit; leftX = context.LeftX; topZ = context.TopZ; tablePosition = context.TablePosition; autoCloseDistance = context.AutoCloseDistance; } private void Awake() { canvas = ((Component)this).GetComponent<Canvas>(); } private void Start() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_004f: 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_0065: 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) for (int i = 0; i < layers.Length; i++) { RectTransform val = (RectTransform)new GameObject($"TileLayer{i}", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent((Transform)(object)mapRect, false); ((Transform)val).SetSiblingIndex(i); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = Vector2.zero; val.offsetMax = Vector2.zero; layers[i] = val; } TileCache.TexturesChanged += OnTexturesChanged; ((MonoBehaviour)this).StartCoroutine(KeepCursorFree()); } private IEnumerator KeepCursorFree() { WaitForEndOfFrame waitForEndOfFrame = new WaitForEndOfFrame(); while (true) { yield return waitForEndOfFrame; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void OnDestroy() { TileCache.TexturesChanged -= OnTexturesChanged; TileCache.SetWanted(new List<TileCache.Cell>()); } private void OnTexturesChanged() { if ((Object)(object)layers[0] != (Object)null) { RefreshTiles(); } } private void Update() { //IL_0033: 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_001b: 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_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_007b: 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_00d3: 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_0100: 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_0110: 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_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_011d: 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_01c6: 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_0198: 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_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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && Vector3.Distance(((Component)localPlayer).transform.position, tablePosition) > autoCloseDistance) { Close(); return; } float y = Input.mouseScrollDelta.y; if (y != 0f) { float num = Mathf.Clamp(zoom + y * 0.5f, 1f, 8f); if (num != zoom) { zoom = num; mapRect.sizeDelta = fitSize * zoom; ClampPosition(); tilesDirty = true; } } if (Input.GetMouseButtonDown(0)) { dragging = true; lastMousePosition = Input.mousePosition; mouseDownPosition = Input.mousePosition; } else if (Input.GetMouseButtonUp(0)) { dragging = false; if (Vector3.Distance(Input.mousePosition, mouseDownPosition) < 6f) { Close(); return; } } if (dragging && Input.GetMouseButton(0)) { Vector3 val = Input.mousePosition - lastMousePosition; lastMousePosition = Input.mousePosition; if (val != Vector3.zero) { Vector2 anchoredPosition = mapRect.anchoredPosition; RectTransform obj = mapRect; obj.anchoredPosition += Vector2.op_Implicit(val); ClampPosition(); tilesDirty |= mapRect.anchoredPosition != anchoredPosition; } } if (Input.GetKeyDown((KeyCode)114) && (zoom != 1f || mapRect.anchoredPosition != Vector2.zero)) { zoom = 1f; mapRect.sizeDelta = fitSize; mapRect.anchoredPosition = Vector2.zero; tilesDirty = true; } if (tilesDirty || Time.unscaledTime >= nextStatusRefresh) { RefreshTiles(); } } private void ClampPosition() { //IL_0006: 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_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_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_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_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_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_0065: 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_0072: 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) Vector2 sizeDelta = mapRect.sizeDelta; Rect rect = viewportRect.rect; Vector2 val = Vector2.Max((sizeDelta - ((Rect)(ref rect)).size) * 0.5f, Vector2.zero); Vector2 anchoredPosition = mapRect.anchoredPosition; anchoredPosition.x = Mathf.Clamp(anchoredPosition.x, 0f - val.x, val.x); anchoredPosition.y = Mathf.Clamp(anchoredPosition.y, 0f - val.y, val.y); mapRect.anchoredPosition = anchoredPosition; } private void RefreshTiles() { if (refreshingTiles) { tilesDirty = true; return; } refreshingTiles = true; try { RefreshTilesCore(); } finally { refreshingTiles = false; } } private void RefreshTilesCore() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) tilesDirty = false; nextStatusRefresh = Time.unscaledTime + 0.5f; if (!hasGeometry || (Object)(object)layers[0] == (Object)null) { return; } float num = ((Texture)overviewTexture).width; _ = ((Texture)overviewTexture).height; float num2 = num / pixelsPerUnit; float num3 = mapRect.sizeDelta.x * canvas.scaleFactor / num2; int num4 = -1; float num5 = pixelsPerUnit; TileCache.Level[] levels = TileCache.Levels; foreach (TileCache.Level level in levels) { if (num3 <= num5 * 1.15f) { break; } num4 = level.Index; num5 = level.PixelsPerUnit; } visibleKeys.Clear(); wantedCells.Clear(); bool flag = false; if (num4 >= 0 && TryGetVisibleWorldRect(out var x, out var x2, out var z, out var z2)) { float num6 = (x2 - x) * 0.1f; float num7 = (z2 - z) * 0.1f; for (int j = 0; j <= num4; j++) { TileCache.CellsIntersecting(TileCache.Levels[j], x - num6, x2 + num6, z - num7, z2 + num7, cellsBuffer); foreach (TileCache.Cell item in cellsBuffer) { wantedCells.Add(item); Texture2D texture = TileCache.GetTexture(item); if ((Object)(object)texture == (Object)null) { flag |= j == num4 && !TileCache.IsKnownEmpty(item); continue; } visibleKeys.Add(item.Key); ShowTile(item, texture, layers[j]); } } } foreach (KeyValuePair<string, RawImage> tileImage in tileImages) { if (!visibleKeys.Contains(tileImage.Key) && ((Component)tileImage.Value).gameObject.activeSelf) { ((Component)tileImage.Value).gameObject.SetActive(false); } } TileCache.SetWanted(wantedCells); UpdateStatus(flag && (TileCache.IsSyncing || TileCache.IsLoadingFromDisk)); } private void ShowTile(TileCache.Cell cell, Texture2D texture, RectTransform layer) { //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_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_0099: 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_00e3: 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) if (!tileImages.TryGetValue(cell.Key, out RawImage value)) { GameObject val = new GameObject(cell.Key); val.transform.SetParent((Transform)(object)layer, false); value = val.AddComponent<RawImage>(); ((Graphic)value).raycastTarget = false; float num = ((Texture)overviewTexture).width; float num2 = ((Texture)overviewTexture).height; Rect worldRect = cell.WorldRect; RectTransform rectTransform = ((Graphic)value).rectTransform; rectTransform.anchorMin = new Vector2((((Rect)(ref worldRect)).xMin - leftX) * pixelsPerUnit / num, 1f - (topZ - ((Rect)(ref worldRect)).yMin) * pixelsPerUnit / num2); rectTransform.anchorMax = new Vector2((((Rect)(ref worldRect)).xMax - leftX) * pixelsPerUnit / num, 1f - (topZ - ((Rect)(ref worldRect)).yMax) * pixelsPerUnit / num2); rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; tileImages[cell.Key] = value; } if ((Object)(object)value.texture != (Object)(object)texture) { value.texture = (Texture)(object)texture; } if (!((Component)value).gameObject.activeSelf) { ((Component)value).gameObject.SetActive(true); } } private bool TryGetVisibleWorldRect(out float x0, out float x1, out float z0, out float z1) { //IL_0006: 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_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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) Vector2 val = mapRect.sizeDelta * 0.5f; Rect rect = viewportRect.rect; Vector2 val2 = ((Rect)(ref rect)).size * 0.5f; Vector2 anchoredPosition = mapRect.anchoredPosition; float num = anchoredPosition.x - val.x; float num2 = anchoredPosition.y + val.y; float num3 = val.x * 2f; float num4 = val.y * 2f; float num5 = Mathf.Max(num, 0f - val2.x); float num6 = Mathf.Min(anchoredPosition.x + val.x, val2.x); float num7 = Mathf.Min(num2, val2.y); float num8 = Mathf.Max(anchoredPosition.y - val.y, 0f - val2.y); float num9 = (float)((Texture)overviewTexture).width / pixelsPerUnit; float num10 = (float)((Texture)overviewTexture).height / pixelsPerUnit; x0 = leftX + (num5 - num) / num3 * num9; x1 = leftX + (num6 - num) / num3 * num9; z1 = topZ - (num2 - num7) / num4 * num10; z0 = topZ - (num2 - num8) / num4 * num10; if (x1 > x0) { return z1 > z0; } return false; } private void UpdateStatus(bool waitingForTilesInView) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0116: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) string text = ""; if (waitingForTilesInView) { text = "Loading sharper view..."; } if (TileCache.IsSyncing && TileCache.SyncTotal > 0) { text = text + ((text.Length > 0) ? " " : "") + $"Downloading map detail: {TileCache.SyncDone}/{TileCache.SyncTotal}"; } if (text.Length == 0) { if ((Object)(object)loadingText != (Object)null) { ((Component)loadingText).gameObject.SetActive(false); } return; } if ((Object)(object)loadingText == (Object)null) { GameObject val = new GameObject("TileLoading"); val.transform.SetParent(((Component)this).transform, false); val.SetActive(false); loadingText = val.AddComponent<TextMeshProUGUI>(); TMP_FontAsset val2 = FindGameFontAsset(); if ((Object)(object)val2 != (Object)null) { ((TMP_Text)loadingText).font = val2; } ((TMP_Text)loadingText).alignment = (TextAlignmentOptions)514; ((TMP_Text)loadingText).fontSize = 18f; ((Graphic)loadingText).color = new Color(1f, 1f, 1f, 0.85f); RectTransform rectTransform = ((TMP_Text)loadingText).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0.95f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; } ((TMP_Text)loadingText).text = text; ((Component)loadingText).gameObject.SetActive(true); } } private static readonly ManualLogSource logger = Logger.CreateLogSource("SnakeSquadCartographySnapshot"); private static GameObject? overlay; private static bool isFetching; private static CursorLockMode previousCursorLockState; private static bool previousCursorVisible; private static string? displayedUrl; private static bool displayedShowPlayerMarker; private static Vector3 displayedTablePosition; private static float displayedAutoCloseDistance; private static string? cachedUrl; private static string? cachedETag; private static Texture2D? cachedTexture; private static bool cachedHasGeometry; private static float cachedPixelsPerUnit; private static float cachedLeftX; private static float cachedTopZ; private static TMP_FontAsset? cachedFontAsset; private static bool blockUntilMouseReleased; private static int escapeCloseFrame = -1; public static bool IsOpen => (Object)(object)overlay != (Object)null; public static bool ShouldBlockPlayerActions { get { if ((Object)(object)overlay != (Object)null) { return true; } if (blockUntilMouseReleased && !Input.GetMouseButton(0) && !Input.GetMouseButton(1)) { blockUntilMouseReleased = false; } return blockUntilMouseReleased; } } public static bool ShouldSuppressGameMenu { get { if (!((Object)(object)overlay != (Object)null)) { return Time.frameCount == escapeCloseFrame; } return true; } } public static IEnumerator ShowSnapshot(string url, string key, int timeoutSeconds, bool showPlayerMarker, Vector3 tablePosition, float autoCloseDistance) { //IL_0023: 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)overlay != (Object)null)) { if ((Object)(object)cachedTexture == (Object)null || cachedUrl != url) { yield return FetchAndCache(url, key, timeoutSeconds, silent: false); } if ((Object)(object)overlay == (Object)null && (Object)(object)cachedTexture != (Object)null && cachedUrl == url) { Display(cachedTexture, showPlayerMarker ? TryGetCachedPlayerMarkerFraction(cachedTexture) : ((Vector2?)null), new SnapshotContext(url, key, timeoutSeconds, cachedHasGeometry, cachedPixelsPerUnit, cachedLeftX, cachedTopZ, tablePosition, autoCloseDistance), showPlayerMarker); } if (cachedUrl == url) { SyncTiles(key, timeoutSeconds); } } } private static void SyncTiles(string key, int timeoutSeconds, bool force = false) { if ((Object)(object)cachedTexture != (Object)null && cachedHasGeometry && cachedUrl != null) { TileCache.EnsureSynced(cachedUrl, key, timeoutSeconds, cachedETag, cachedLeftX, cachedTopZ, cachedPixelsPerUnit, ((Texture)cachedTexture).width, ((Texture)cachedTexture).height, force); } else if (force) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Couldn't check the map right now.", 0, (Sprite)null, false); } } } public static IEnumerator RefreshInBackground(string url, string key, int timeoutSeconds, bool forceTileCheck = false) { yield return FetchAndCache(url, key, timeoutSeconds, silent: true); if (!forceTileCheck) { yield break; } if (cachedUrl == url) { SyncTiles(key, timeoutSeconds, force: true); yield break; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, "Couldn't check the map right now.", 0, (Sprite)null, false); } } private static IEnumerator FetchAndCache(string url, string key, int timeoutSeconds, bool silent) { if (isFetching) { yield break; } isFetching = true; UnityWebRequest request = UnityWebRequestTexture.GetTexture(url); try { request.timeout = timeoutSeconds; CartographySnapshotPlugin.PrepareSnapshotRequest(request, key); if (url == cachedUrl && !string.IsNullOrEmpty(cachedETag)) { request.SetRequestHeader("If-None-Match", cachedETag); } yield return request.SendWebRequest(); isFetching = false; if (CartographySnapshotPlugin.IsAccessDenied(request)) { ReportFetchProblem(silent, CartographySnapshotPlugin.AccessDeniedMessage(request), "Map access token is missing or wrong (check the mod's config)."); yield break; } if (request.responseCode == 0L) { ReportFetchProblem(silent, "Failed to reach " + url + ": " + request.error, "Could not reach the map server."); yield break; } switch (request.responseCode) { case 200L: { if ((int)request.result != 1) { ReportFetchProblem(silent, $"Snapshot request to {url} returned 200 but the response body wasn't a usable image ({request.result}).", "Could not load the map."); break; } Texture2D content = DownloadHandlerTexture.GetContent(request); float value = 0f; float value2 = 0f; float value3 = 0f; bool num = TryGetFloatHeader(request, "X-Snapshot-Pixels-Per-Unit", out value) && TryGetFloatHeader(request, "X-Snapshot-Left-X", out value2) && TryGetFloatHeader(request, "X-Snapshot-Top-Z", out value3) && value > 0f; if ((Object)(object)cachedTexture != (Object)null && (Object)(object)cachedTexture != (Object)(object)content) { Object.Destroy((Object)(object)cachedTexture); } cachedUrl = url; cachedETag = request.GetResponseHeader("ETag"); cachedTexture = content; cachedHasGeometry = num; cachedPixelsPerUnit = value; cachedLeftX = value2; cachedTopZ = value3; RefreshDisplayedOverlayIfShowing(url, key, timeoutSeconds); SyncTiles(key, timeoutSeconds); break; } case 304L: if ((Object)(object)cachedTexture == (Object)null || url != cachedUrl) { ReportFetchProblem(silent, "Snapshot server returned 304 but we have no cached image for this URL.", "Could not load the map."); break; } logger.LogInfo((object)"Snapshot unchanged since last check (304)."); SyncTiles(key, timeoutSeconds); break; case 401L: ReportFetchProblem(silent, "Snapshot request returned 401 - Snapshot Key is missing or wrong.", "Map snapshot key is missing or wrong (check the mod's config)."); break; case 503L: { string responseHeader = request.GetResponseHeader("Retry-After"); logger.LogInfo((object)("Snapshot not ready yet (503), Retry-After: " + (responseHeader ?? "none") + ".")); if (!silent) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "The map hasn't finished rendering yet - try again shortly.", 0, (Sprite)null, false); } } break; } default: ReportFetchProblem(silent, $"Snapshot request to {url} returned HTTP {request.responseCode}.", "Could not load the map."); break; } } finally { ((IDisposable)request)?.Dispose(); } } private static void ReportFetchProblem(bool silent, string logMessage, string playerMessage) { if (silent) { logger.LogInfo((object)("Background refresh: " + logMessage)); return; } logger.LogWarning((object)logMessage); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, playerMessage, 0, (Sprite)null, false); } } private static void RefreshDisplayedOverlayIfShowing(string url, string key, int timeoutSeconds) { //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_0073: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)overlay == (Object)null) && !(displayedUrl != url) && !((Object)(object)cachedTexture == (Object)null)) { bool flag = displayedShowPlayerMarker; Vector3 tablePosition = displayedTablePosition; float autoCloseDistance = displayedAutoCloseDistance; Close(); Display(cachedTexture, flag ? TryGetCachedPlayerMarkerFraction(cachedTexture) : ((Vector2?)null), new SnapshotContext(url, key, timeoutSeconds, cachedHasGeometry, cachedPixelsPerUnit, cachedLeftX, cachedTopZ, tablePosition, autoCloseDistance), flag); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Map updated.", 0, (Sprite)null, false); } } } private static Vector2? ComputeMarkerFraction(float pixelsPerUnit, float leftX, float topZ, Texture2D texture) { //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_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_0055: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } Vector3 position = ((Component)localPlayer).transform.position; float num = (position.x - leftX) * pixelsPerUnit; float num2 = (topZ - position.z) * pixelsPerUnit; return new Vector2(Mathf.Clamp01(num / (float)((Texture)texture).width), Mathf.Clamp01(num2 / (float)((Texture)texture).height)); } private static Vector2? TryGetCachedPlayerMarkerFraction(Texture2D texture) { if (!cachedHasGeometry) { return null; } return ComputeMarkerFraction(cachedPixelsPerUnit, cachedLeftX, cachedTopZ, texture); } private static bool TryGetFloatHeader(UnityWebRequest request, string headerName, out float value) { return float.TryParse(request.GetResponseHeader(headerName), NumberStyles.Float, CultureInfo.InvariantCulture, out value); } private static void Display(Texture2D texture, Vector2? playerMarkerFraction, SnapshotContext context, bool showPlayerMarker) { //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_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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //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_00b4: 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_00cf: 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_00e4: 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_00f9: Expected O, but got Unknown //IL_0124: 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_0144: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: 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_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_027e: 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_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) displayedUrl = context.Url; displayedShowPlayerMarker = showPlayerMarker; displayedTablePosition = context.TablePosition; displayedAutoCloseDistance = context.AutoCloseDistance; previousCursorLockState = Cursor.lockState; previousCursorVisible = Cursor.visible; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; GameObject val = new GameObject("SnakeSquadCartographySnapshotCanvas"); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 32767; val.AddComponent<CanvasScaler>(); val.AddComponent<GraphicRaycaster>(); val.AddComponent<CloseOnInput>(); GameObject val2 = new GameObject("Background"); val2.transform.SetParent(val.transform, false); Image obj2 = val2.AddComponent<Image>(); ((Graphic)obj2).color = new Color(0f, 0f, 0f, 0.85f); RectTransform rectTransform = ((Graphic)obj2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; GameObject val3 = new GameObject("Viewport"); val3.transform.SetParent(val.transform, false); val3.AddComponent<RectMask2D>(); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.05f, 0.08f); component.anchorMax = new Vector2(0.95f, 0.95f); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; GameObject val4 = new GameObject("Map"); val4.transform.SetParent(val3.transform, false); RawImage obj3 = val4.AddComponent<RawImage>(); obj3.texture = (Texture)(object)texture; RectTransform rectTransform2 = ((Graphic)obj3).rectTransform; rectTransform2.anchorMin = new Vector2(0.5f, 0.5f); rectTransform2.anchorMax = new Vector2(0.5f, 0.5f); rectTransform2.pivot = new Vector2(0.5f, 0.5f); rectTransform2.anchoredPosition = Vector2.zero; Rect rect = component.rect; Vector2 size = ((Rect)(ref rect)).size; float num = (float)((Texture)texture).width / (float)((Texture)texture).height; float num2 = size.x / size.y; Vector2 baseFitSize = (rectTransform2.sizeDelta = ((num > num2) ? new Vector2(size.x, size.x / num) : new Vector2(size.y * num, size.y))); AddFrame(val4.transform); if (playerMarkerFraction.HasValue) { Vector2 valueOrDefault = playerMarkerFraction.GetValueOrDefault(); AddPlayerMarker(val4.transform, valueOrDefault); } PanZoom panZoom = val.AddComponent<PanZoom>(); panZoom.Initialize(rectTransform2, component, baseFitSize); panZoom.InitializeTiles(texture, context); AddHintText(val.transform); overlay = val; } private static void AddFrame(Transform imageTransform) { //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_0046: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00c2: 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_00d6: 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_0100: 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_0114: Unknown result type (might be due to invalid IL or missing references) Color frameColor = new Color(0.9f, 0.85f, 0.65f, 0.95f); AddStrip("FrameTop", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -5f), Vector2.zero); AddStrip("FrameBottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 5f)); AddStrip("FrameLeft", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(5f, 0f)); AddStrip("FrameRight", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-5f, 0f), Vector2.zero); void AddStrip(string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax) { //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_0021: 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_0046: 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) GameObject val = new GameObject(name); val.transform.SetParent(imageTransform, false); Image obj = val.AddComponent<Image>(); ((Graphic)obj).color = frameColor; ((Graphic)obj).raycastTarget = false; RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = anchorMin; rectTransform.anchorMax = anchorMax; rectTransform.offsetMin = offsetMin; rectTransform.offsetMax = offsetMax; } } private static void AddPlayerMarker(Transform parent, Vector2 fraction) { //IL_0002: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //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) //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) //IL_008e: 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_00ba: 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_00d5: 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_00fe: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(fraction.x, 1f - fraction.y); GameObject val2 = new GameObject("PlayerMarkerBacking"); val2.transform.SetParent(parent, false); Image obj = val2.AddComponent<Image>(); ((Graphic)obj).color = Color.white; RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = val; rectTransform.anchorMax = val; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.sizeDelta = new Vector2(16f, 16f); rectTransform.anchoredPosition = Vector2.zero; GameObject val3 = new GameObject("PlayerMarkerDot"); val3.transform.SetParent(val2.transform, false); Image obj2 = val3.AddComponent<Image>(); ((Graphic)obj2).color = new Color(0.95f, 0.2f, 0.15f); RectTransform rectTransform2 = ((Graphic)obj2).rectTransform; rectTransform2.anchorMin = Vector2.zero; rectTransform2.anchorMax = Vector2.one; rectTransform2.offsetMin = new Vector2(3f, 3f); rectTransform2.offsetMax = new Vector2(-3f, -3f); } private static void AddHintText(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0047: 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_008d: 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_00a2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Hint"); val.transform.SetParent(parent, false); val.SetActive(false); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).text = "Scroll: zoom • Left-drag: pan • R: reset view • E / Esc / click: close"; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).fontSize = 20f; ((Graphic)val2).color = Color.white; TMP_FontAsset val3 = FindGameFontAsset(); if ((Object)(object)val3 != (Object)null) { ((TMP_Text)val2).font = val3; } RectTransform rectTransform = ((TMP_Text)val2).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 0.06f); rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; val.SetActive(true); } private static TMP_FontAsset? FindGameFontAsset() { if ((Object)(object)cachedFontAsset != (Object)null) { return cachedFontAsset; } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); cachedFontAsset = ((array.Length != 0) ? array[0] : null); return cachedFontAsset; } public static void Close() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)overlay != (Object)null) { Object.Destroy((Object)(object)overlay); overlay = null; blockUntilMouseReleased = true; displayedUrl = null; Cursor.lockState = previousCursorLockState; Cursor.visible = previousCursorVisible; } } internal static void LogDebug(string message) { if (CartographySnapshotPlugin.verboseTileLogging.Value) { logger.LogInfo((object)message); } } } internal static class InputBlocker { [HarmonyPatch(typeof(Player), "SetControls")] private static class Player_SetControls_BlockActions { private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold, ref bool crouch, ref bool dodge) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && SnapshotViewer.ShouldBlockPlayerActions) { attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (block = (blockHold = (crouch = (dodge = false))))))); } } } [HarmonyPatch] private static class Player_SetMouseLook_Freeze { private static bool Prepare() { return FindMethod(typeof(Player), "SetMouseLook", (MethodInfo _) => true) != null; } private static MethodBase TargetMethod() { return FindMethod(typeof(Player), "SetMouseLook", (MethodInfo _) => true); } private static bool Prefix(object __instance) { if (SnapshotViewer.IsOpen) { return __instance != Player.m_localPlayer; } return true; } } [HarmonyPatch] private static class ZInput_GetMouseDelta_Zero { private static bool Prepare() { return FindMethod(typeof(ZInput), "GetMouseDelta", (MethodInfo m) => m.ReturnType == typeof(Vector2)) != null; } private static MethodBase TargetMethod() { return FindMethod(typeof(ZInput), "GetMouseDelta", (MethodInfo m) => m.ReturnType == typeof(Vector2)); } private static void Postfix(ref Vector2 __result) { //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) if (SnapshotViewer.IsOpen) { __result = Vector2.zero; } } } [HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")] private static class ZInput_GetMouseScrollWheel_Zero { private static void Postfix(ref float __result) { if (SnapshotViewer.IsOpen) { __result = 0f; } } } [HarmonyPatch] private static class Menu_Update_SuppressWhileMapOpen { private static bool Prepare() { return FindMethod(typeof(Menu), "Update", (MethodInfo m) => m.GetParameters().Length == 0) != null; } private static MethodBase TargetMethod() { return FindMethod(typeof(Menu), "Update", (MethodInfo m) => m.GetParameters().Length == 0); } private static bool Prefix() { return !SnapshotViewer.ShouldSuppressGameMenu; } } [HarmonyPatch] private static class Menu_Show_SuppressWhileMapOpen { private static bool Prepare() { return FindMethod(typeof(Menu), "Show", (MethodInfo m) => m.GetParameters().Length == 0) != null; } private static MethodBase TargetMethod() { return FindMethod(typeof(Menu), "Show", (MethodInfo m) => m.GetParameters().Length == 0); } private static bool Prefix() { return !SnapshotViewer.ShouldSuppressGameMenu; } } private static MethodInfo? FindMethod(Type type, string name, Func<MethodInfo, bool> predicate) { return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == name && !m.IsAbstract && predicate(m)); } } internal static class TileCache { internal sealed class Level { public readonly int Index; public readonly float CellWorldSize; public readonly int CellPixels; public float PixelsPerUnit => (float)CellPixels / CellWorldSize; public Level(int index, float cellWorldSize, int cellPixels) { Index = index; CellWorldSize = cellWorldSize; CellPixels = cellPixels; } } internal sealed class Cell { public readonly string Key; public readonly Level Level; public readonly Rect WorldRect; public readonly string Url; public Cell(string key, Level level, Rect worldRect, string url) { //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) Key = key; Level = level; WorldRect = worldRect; Url = url; } } private sealed class Meta { public string Url = ""; public string TileETag = ""; public string OverviewETag = ""; public string ContentHash = ""; public bool IsEmpty => ContentHash == "-"; } private enum FetchOutcome { Updated, Unchanged, Rejected, AccessDenied, Failed } internal static readonly Level[] Levels = new Level[2] { new Level(0, 2048f, 512), new Level(1, 1024f, 512) }; private const string EmptyHash = "-"; private static Dictionary<string, string>? manifest; private const float MinCellWorldSide = 10f; private const int MinTimeoutSeconds = 30; private const int MaxAttempts = 4; private const float DefaultRetryDelaySeconds = 2f; private const int MaxConsecutiveFailures = 8; private const int MinTilePixelWidth = 64; private const int DiskLoadsPerFrame = 2; private const int MaxLoadedTextures = 240; private static readonly ManualLogSource logger = Logger.CreateLogSource("SnakeSquadCartographySnapshot"); private static string snapshotUrl = ""; private static string snapshotKey = ""; private static int timeoutSeconds; private static string overviewETag = ""; private static float minX; private static float maxX; private static float minZ; private static float maxZ; private static int configVersion; private static readonly List<Cell> cells = new List<Cell>(); private static readonly Dictionary<string, Cell> cellsByKey = new Dictionary<string, Cell>(); private static string? cacheDirectory; private static readonly Dictionary<string, Meta> metas = new Dictionary<string, Meta>(); private static readonly HashSet<string> refreshedThisSession = new HashSet<string>(); private static readonly HashSet<string> rejectedThisSession = new HashSet<string>(); private static readonly Dictionary<string, Texture2D> loaded = new Dictionary<string, Texture2D>(); private static readonly Dictionary<string, int> lastUsedFrame = new Dictionary<string, int>(); private static readonly Queue<string> diskLoadQueue = new Queue<string>(); private static readonly HashSet<string> diskLoadPending = new HashSet<string>(); private static bool diskLoaderRunning; private static bool workerRunning; private static readonly HashSet<string> failedThisPass = new HashSet<string>(); private static readonly List<Cell> wanted = new List<Cell>(); private static bool forceQueued; private static int updatedFine; private static int updatedCoarse; private const int MaxConcurrentFetches = 2; private static readonly HashSet<string> inFlight = new HashSet<string>(); private static int consecutiveFailures; private static bool pauseSync; private static bool accessDenied; private static readonly Func<Texture2D, byte[], bool>? loadImage = BindLoadImage(); public static bool IsSyncing => workerRunning; public static bool IsLoadingFromDisk => diskLoaderRunning; public static int SyncTotal { get; private set; } public static int SyncDone { get; private set; } public static event Action? TexturesChanged; public static void EnsureSynced(string url, string key, int timeout, string? etag, float leftX, float topZ, float pixelsPerUnit, int width, int height, bool force = false) { if (!(pixelsPerUnit <= 0f) && width > 0 && height > 0) { Configure(url, key, timeout, etag ?? "", leftX, leftX + (float)width / pixelsPerUnit, topZ - (float)height / pixelsPerUnit, topZ); if (workerRunning) { forceQueued |= force; } else if (force || cells.Any(NeedsFetch)) { CartographySnapshotPlugin.CoroutineHost.StartCoroutine(Worker(force)); } } } private static void Configure(string url, string key, int timeout, string etag, float newMinX, float newMaxX, float newMinZ, float newMaxZ) { snapshotKey = key; timeoutSeconds = timeout; overviewETag = etag; if (!(url == snapshotUrl) || newMinX != minX || newMaxX != maxX || newMinZ != minZ || newMaxZ != maxZ) { if (url != snapshotUrl) { SetCacheDirectory(url); } snapshotUrl = url; minX = newMinX; maxX = newMaxX; minZ = newMinZ; maxZ = newMaxZ; configVersion++; BuildCells(); } } private static void BuildCells() { //IL_01bf: Unknown result type (might be due to invalid IL or missing references) cells.Clear(); cellsByKey.Clear(); string text = (snapshotUrl.Contains("?") ? "&" : "?"); Level[] levels = Levels; foreach (Level level in levels) { float cellWorldSize = level.CellWorldSize; int num = Mathf.FloorToInt(minX / cellWorldSize); int num2 = Mathf.CeilToInt(maxX / cellWorldSize) - 1; int num3 = Mathf.FloorToInt(minZ / cellWorldSize); int num4 = Mathf.CeilToInt(maxZ / cellWorldSize) - 1; for (int j = num; j <= num2; j++) { for (int k = num3; k <= num4; k++) { float num5 = Mathf.Max((float)j * cellWorldSize, minX); float num6 = Mathf.Min((float)(j + 1) * cellWorldSize, maxX); float num7 = Mathf.Max((float)k * cellWorldSize, minZ); float num8 = Mathf.Min((float)(k + 1) * cellWorldSize, maxZ); if (!(num6 - num5 < 10f) && !(num8 - num7 < 10f)) { int num9 = Mathf.Max(64, Mathf.RoundToInt((float)level.CellPixels * (num6 - num5) / cellWorldSize)); string url = snapshotUrl + text + "x0=" + F(num5) + "&z0=" + F(num8) + "&x1=" + F(num6) + "&z1=" + F(num7) + "&w=" + num9.ToString(CultureInfo.InvariantCulture); string key = CellKey(level.Index, j, k); Cell cell = new Cell(key, level, new Rect(num5, num7, num6 - num5, num8 - num7), url); cells.Add(cell); cellsByKey[key] = cell; } } } } SnapshotViewer.LogDebug($"[MapTile] grid: {cells.Count} tiles over x {F(minX)}..{F(maxX)}, z {F(minZ)}..{F(maxZ)}."); } private static string CellKey(int level, int ix, int iz) { return $"L{level}_{ix}_{iz}"; } public static void CellsIntersecting(Level level, float x0, float x1, float z0, float z1, List<Cell> output) { output.Clear(); float cellWorldSize = level.CellWorldSize; int num = Mathf.FloorToInt(x0 / cellWorldSize); int num2 = Mathf.FloorToInt(x1 / cellWorldSize); int num3 = Mathf.FloorToInt(z0 / cellWorldSize); int num4 = Mathf.FloorToInt(z1 / cellWorldSize); for (int i = num; i <= num2; i++) { for (int j = num3; j <= num4; j++) { if (cellsByKey.TryGetValue(CellKey(level.Index, i, j), out Cell value)) { output.Add(value); } } } } public static void SetWanted(List<Cell> cellsInView) { wanted.Clear(); wanted.AddRange(cellsInView); } public static Texture2D? GetTexture(Cell cell) { lastUsedFrame[cell.Key] = Time.frameCount; if (loaded.TryGetValue(cell.Key, out Texture2D value)) { return value; } if (metas.TryGetValue(cell.Key, out Meta value2) && !value2.IsEmpty && diskLoadPending.Add(cell.Key)) { diskLoadQueue.Enqueue(cell.Key); if (!diskLoaderRunning) { CartographySnapshotPlugin.CoroutineHost.StartCoroutine(DiskLoader()); } } return null; } public static bool IsKnownEmpty(Cell cell) { if (metas.TryGetValue(cell.Key, out Meta value) && value.IsEmpty) { return value.Url == cell.Url; } return false; } private static bool NeedsFetch(Cell cell) { if (failedThisPass.Contains(cell.Key) || rejectedThisSession.Contains(cell.Url)) { return false; } if (!metas.TryGetValue(cell.Key, out Meta value) || value.Url != cell.Url) { return true; } if (manifest != null) { return value.ContentHash != ManifestHash(cell); } if (overviewETag.Length <= 0) { return !refreshedThisSession.Contains(cell.Key); } return value.OverviewETag != overviewETag; } private static IEnumerator Worker(bool fresh) { workerRunning = true; updatedFine = 0; updatedCoarse = 0; failedThisPass.Clear(); inFlight.Clear(); consecutiveFailures = 0; pauseSync = false; accessDenied = false; int seenConfigVersion = -1; List<Cell> ordered = new List<Cell>(); int orderedIndex = 0; SyncDone = 0; yield return LoadManifest(fresh); pauseSync |= accessDenied; while (true) { if (seenConfigVersion != configVersion) { ApplyManifest(); seenConfigVersion = configVersion; Vector3 origin = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero); ordered = (from c in cells.Where(NeedsFetch) orderby c.Level.Index select c).ThenBy(delegate(Cell c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_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) Rect worldRect = c.WorldRect; Vector2 val = ((Rect)(ref worldRect)).center - new Vector2(origin.x, origin.z); return ((Vector2)(ref val)).sqrMagnitude; }).ToList(); orderedIndex = 0; SyncTotal = SyncDone + inFlight.Count + ordered.Count; logger.LogInfo((object)$"Map tiles: {ordered.Count} of {cells.Count} need downloading."); } Cell cell = null; if (!pauseSync && inFlight.Count < 2) { cell = wanted.FirstOrDefault((Cell c) => cellsByKey.TryGetValue(c.Key, out Cell value) && value == c && !inFlight.Contains(c.Key) && NeedsFetch(c)); if (cell == null) { for (; orderedIndex < ordered.Count && (inFlight.Contains(ordered[orderedIndex].Key) || !NeedsFetch(ordered[orderedIndex])); orderedIndex++) { } cell = ((orderedIndex < ordered.Count) ? ordered[orderedIndex] : null); } } if (cell != null) { inFlight.Add(cell.Key); CartographySnapshotPlugin.CoroutineHost.StartCoroutine(Lane(cell)); } else if (inFlight.Count == 0 && (pauseSync || orderedIndex >= ordered.Count)) { if (pauseSync || !wanted.Any((Cell c) => cellsByKey.TryGetValue(c.Key, out Cell value) && value == c && NeedsFetch(c))) { break; } } else { yield return null; } } if (accessDenied) { logger.LogWarning((object)"Map tiles: Cloudflare Access turned the requests away - access token missing or wrong: check Access Client Id and Access Client Secret. Stopping until the next time a Cartography Table is used."); } else if (pauseSync) { logger.LogWarning((object)$"Map tiles: {8} downloads failed in a row - pausing until the next time a Cartography Table is used."); } int num = cells.Count((Cell c) => rejectedThisSession.Contains(c.Url)); if (!accessDenied) { logger.LogInfo((object)(((failedThisPass.Count == 0) ? "Map tiles: all up to date." : $"Map tiles: done, but {failedThisPass.Count} couldn't be downloaded - they'll be retried the next time a Cartography Table is used.") + ((num > 0) ? $" {num} were refused by the server (see the [MapTile] lines with Verbose Tile Logging on)." : ""))); } if (fresh) { int num2 = ((updatedFine > 0) ? updatedFine : updatedCoarse); string text = (accessDenied ? "Map access token is missing or wrong (check the mod's config)." : ((failedThisPass.Count > 0) ? $"Map update incomplete: {failedThisPass.Count} areas couldn't be downloaded." : ((num2 > 0) ? string.Format("Map updated: {0} {1}.", num2, (num2 == 1) ? "area" : "areas") : "Map up to date."))); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } manifest = null; workerRunning = false; TileCache.TexturesChanged?.Invoke(); if (forceQueued) { forceQueued = false; CartographySnapshotPlugin.CoroutineHost.StartCoroutine(Worker(fresh: true)); } } private static void CountUpdated(Cell cell) { if (cell.Level.Index == Levels.Length - 1) { updatedFine++; } else { updatedCoarse++; } } private static IEnumerator Lane(Cell cell) { FetchOutcome outcome = FetchOutcome.Failed; yield return FetchCell(cell, delegate(FetchOutcome result) { outcome = result; }); inFlight.Remove(cell.Key); SyncDone++; switch (outcome) { case FetchOutcome.Updated: consecutiveFailures = 0; CountUpdated(cell); yield break; case FetchOutcome.Unchanged: consecutiveFailures = 0; yield break; case FetchOutcome.Rejected: rejectedThisSession.Add(cell.Url); yield break; case FetchOutcome.AccessDenied: accessDenied = true; pauseSync = true; yield break; } failedThisPass.Add(cell.Key); if (++consecutiveFailures >= 8) { pauseSync = true; } } private static IEnumerator FetchCell(Cell cell, Action<FetchOutcome> done) { for (int attempt = 1; attempt <= 4; attempt++) { UnityWebRequest request = UnityWebRequest.Get(cell.Url); Meta oldMeta; try { request.timeout = Mathf.Max(timeoutSeconds, 30); CartographySnapshotPlugin.PrepareSnapshotRequest(request, snapshotKey); if (metas.TryGetValue(cell.Key, out oldMeta) && oldMeta.Url == cell.Url && oldMeta.TileETag.Length > 0) { request.SetRequestHeader("If-None-Match", oldMeta.TileETag); } float startTime = Time.realtimeSinceStartup; yield return request.SendWebRequest(); float num = Time.realtimeSinceStartup - startTime; long responseCode = request.responseCode; object[] obj = new object[7] { cell.Key, attempt, responseCode, request.result, num, null, null }; DownloadHandler downloadHandler = request.downloadHandler; obj[5] = ((downloadHandler == null) ? ((int?)null) : downloadHandler.data?.Length).GetValueOrDefault(); obj[6] = cell.Url; SnapshotViewer.LogDebug(string.Format("[MapTile] {0} attempt {1}: {2} {3} in {4:F1}s ({5} bytes) {6}", obj) + (string.IsNullOrEmpty(request.error) ? "" : (" error=\"" + request.error + "\"")) + ((responseCode >= 400) ? (" body=\"" + ShortBody(request) + "\"") : "")); if (CartographySnapshotPlugin.IsAccessDenied(request)) { done(FetchOutcome.AccessDenied); yield break; } if (responseCode == 304 && oldMeta != null) { oldMeta.OverviewETag = overviewETag; oldMeta.ContentHash = ManifestHash(cell) ?? oldMeta.ContentHash; SaveMeta(cell.Key, oldMeta); refreshedThisSession.Add(cell.Key); done(FetchOutcome.Unchanged); yield break; } if (responseCode == 200 && (int)request.result == 1) { byte[] bytes = request.downloadHandler.data ?? Array.Empty<byte>(); if (!Store(cell, bytes, request.GetResponseHeader("ETag") ?? "")) { done(FetchOutcome.Failed); yield break; } refreshedThisSession.Add(cell.Key); done(FetchOutcome.Updated); yield break; } if (responseCode >= 400 && responseCode < 500 && responseCode != 401 && responseCode != 408 && responseCode != 429) { done(FetchOutcome.Rejected); yield break; } if (attempt != 4) { if ((responseCode == 429 || responseCode == 503) ? true : false) { float num2 = ParseRetryAfterSeconds(request.GetResponseHeader("Retry-After")); SnapshotViewer.LogDebug($"[MapTile] {cell.Key}: HTTP {responseCode}, waiting {num2:F1}s."); yield return (object)new WaitForSecondsRealtime(num2); continue; } if (responseCode == 0L && attempt < 2) { goto IL_044d; } } } finally { ((IDisposable)request)?.Dispose(); } break; IL_044d: oldMeta = null; } done(FetchOutcome.Failed); } private static bool Store(Cell cell, byte[] bytes, string tileETag) { if (!IsPng(bytes)) { SnapshotViewer.LogDebug("[MapTile] " + cell.Key + ": response wasn't a PNG."); return false; } Meta meta = new Meta { Url = cell.Url, TileETag = tileETag, OverviewETag = overviewETag, ContentHash = (ManifestHash(cell) ?? "") }; try { if (cacheDirectory != null) { File.WriteAllBytes(Path.Combine(cacheDirectory, cell.Key + ".png"), bytes); SaveMeta(cell.Key, meta); } } catch (Exception ex) { logger.LogWarning((object)("Couldn't save map tile " + cell.Key + " to disk (it'll still be shown this session): " + ex.Message)); } metas[cell.Key] = meta; bool flag = wanted.Any((Cell c) => c.Key == cell.Key); if (loaded.TryGetValue(cell.Key, out Texture2D value) || flag) { Texture2D val = Decode(bytes); if ((Object)(object)val == (Object)null) { SnapshotViewer.LogDebug("[MapTile] " + cell.Key + ": PNG couldn't be decoded."); return true; } loaded[cell.Key] = val; TileCache.TexturesChanged?.Invoke(); if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } EvictIfNeeded(); } return true; } private static bool IsPng(byte[] bytes) { if (bytes.Length > 8 && bytes[0] == 137 && bytes[1] == 80 && bytes[2] == 78) { return bytes[3] == 71; } return false; } private static IEnumerator DiskLoader() { diskLoaderRunning = true; yield return null; while (diskLoadQueue.Count > 0) { for (int i = 0; i < 2; i++) { if (diskLoadQueue.Count <= 0) { break; } string text = diskLoadQueue.Dequeue(); diskLoadPending.Remove(text); if (!loaded.ContainsKey(text) && cacheDirectory != null) { string path = Path.Combine(cacheDirectory, text + ".png"); Texture2D val = null; try { val = (File.Exists(path) ? Decode(File.ReadAllBytes(path)) : null); } catch (Exception ex) { logger.LogWarning((object)("Couldn't read saved map tile " + text + ": " + ex.Message)); } if ((Object)(object)val == (Object)null) { metas.Remove(text); continue; } loaded[text] = val; TileCache.TexturesChanged?.Invoke(); EvictIfNeeded(); } } yield return null; } diskLoaderRunning = false; TileCache.TexturesChanged?.Invoke(); } private static Func<Texture2D, byte[], bool>? BindLoadImage() { MethodInfo methodInfo = (Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? (from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetType("UnityEngine.ImageConversion")).FirstOrDefault((Type t) => t != null))?.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (methodInfo == null) { logger.LogWarning((object)"UnityEngine.ImageConversion.LoadImage not found - saved map tiles can't be shown."); return null; } return (Func<Texture2D, byte[], bool>)Delegate.CreateDelegate(typeof(Func<Texture2D, byte[], bool>), methodInfo); } private static Texture2D? Decode(byte[] bytes) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown if (loadImage == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true); if (!loadImage(val, bytes)) { Object.Destroy((Object)(object)val); return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)2; val.Apply(true, false); if (((Texture)val).width % 4 == 0 && ((Texture)val).height % 4 == 0) { val.Compress(false); } val.Apply(false, true); return val; } private static void EvictIfNeeded() { if (loaded.Count <= 240) { return; } int recentFrame = Time.frameCount - 2; int value; foreach (string item in (from k in loaded.Keys where !lastUsedFrame.TryGetValue(k, out value) || value < recentFrame orderby lastUsedFrame.TryGetValue(k, out value) ? value : 0 select k).Take(loaded.Count - 240).ToList()) { Object.Destroy((Object)(object)loaded[item]); loaded.Remove(item); } } private static void SetCacheDirectory(string url) { foreach (Texture2D value in loaded.Values) { Object.Destroy((Object)(object)value); } loaded.Clear(); metas.Clear(); refreshedThisSession.Clear(); diskLoadQueue.Clear(); diskLoadPending.Clear(); using MD5 mD = MD5.Create(); string path = string.Concat(from b in mD.ComputeHash(Encoding.UTF8.GetBytes(url)).Take(6) select b.ToString("x2")); cacheDirectory = Path.Combine(Path.Combine(Paths.CachePath, "SnakeSquadCartographySnapshot"), path); try { Directory.CreateDirectory(cacheDirectory); string[] files = Directory.GetFiles(cacheDirectory, "*.meta"); foreach (string path2 in files) { string[] array = File.ReadAllLines(path2); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path2); Meta meta = new Meta { Url = ((array.Length != 0) ? array[0] : ""), TileETag = ((array.Length > 1) ? array[1] : ""), OverviewETag = ((array.Length > 2) ? array[2] : ""), ContentHash = ((array.Length > 3) ? array[3] : "") }; if (array.Length >= 3 && (meta.IsEmpty || File.Exists(Path.Combine(cacheDirectory, fileNameWithoutExtension + ".png")))) { metas[fileNameWithoutExtension] = meta; } } logger.LogInfo((object)$"Map tile cache: {metas.Count} tiles saved in {cacheDirectory}."); } catch (Exception ex) { logger.LogWarning((object)("Couldn't use the map tile cache folder " + cacheDirectory + " - tiles won't be saved between sessions: " + ex.Message)); cacheDirectory = null; } } private static void SaveMeta(string key, Meta meta) { if (cacheDirectory != null) { File.WriteAllLines(Path.Combine(cacheDirectory, key + ".meta"), new string[4] { meta.Url, meta.TileETag, meta.OverviewETag, meta.ContentHash }); } } private static IEnumerator LoadManifest(bool fresh) { manifest = null; string text = (snapshotUrl.Contains("?") ? "&" : "?"); string text2 = string.Join(",", Levels.Select((Level l) => F(l.CellWorldSize))); string text3 = snapshotUrl + text + "manifest=1&cells=" + text2 + (fresh ? "&fresh=1" : ""); UnityWebRequest request = UnityWebRequest.Get(text3); try { request.timeout = Mathf.Max(timeoutSeconds, 30); CartographySnapshotPlugin.PrepareSnapshotRequest(request, snapshotKey); yield return request.SendWebRequest(); if (CartographySnapshotPlugin.IsAccessDenied(request)) { accessDenied = true; yield break; } DownloadHandler downloadHandler = request.downloadHandler; byte[] bytes = ((downloadHandler != null) ? downloadHandler.data : null) ?? Array.Empty<byte>(); if (request.responseCode != 200 || (int)request.result != 1 || IsPng(bytes)) { logger.LogInfo((object)$"Map tiles: no tile manifest from the server (HTTP {request.responseCode}) - re-checking every tile whose map version is out of date."); yield break; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); string[] array = request.downloadHandler.text.Split(new char[1] { '\n' }); foreach (string obj in array) { string text4 = obj.Trim(); if (text4.Length != 0 && !text4.StartsWith("#")) { string[] array2 = text4.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); float size; Level level = ((array2.Length == 4 && float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out size)) ? Levels.FirstOrDefault((Level l) => Mathf.Approximately(l.CellWorldSize, size)) : null); if (level == null || !int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !int.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { logger.LogWarning((object)("Map tiles: couldn't read tile manifest line \"" + text4 + "\" - ignoring the manifest.")); yield break; } dictionary[CellKey(level.Index, result, result2)] = array2[3]; } } manifest = dictionary; logger.LogInfo((object)$"Map tiles: tile manifest lists {dictionary.Count} non-empty tiles."); } finally { ((IDisposable)request)?.Dispose(); } } private static string? ManifestHash(Cell cell) { if (manifest == null) { return null; } if (!manifest.TryGetValue(cell.Key, out string value)) { return "-"; } return value; } private static void ApplyManifest() { if (manifest == null) { return; } bool flag = false; foreach (Cell cell in cells) { string text = ManifestHash(cell); metas.TryGetValue(cell.Key, out Meta value); if (text == "-") { if (value != null && value.IsEmpty && value.Url == cell.Url && value.OverviewETag == overviewETag) { continue; } Meta meta = new Meta { Url = cell.Url, OverviewETag = overviewETag, ContentHash = "-" }; metas[cell.Key] = meta; try { SaveMeta(cell.Key, meta); if (cacheDirectory != null) { File.Delete(Path.Combine(cacheDirectory, cell.Key + ".png")); } } catch (Exception ex) { logger.LogWarning((object)("Couldn't update saved map tile " + cell.Key + ": " + ex.Message)); } if (value != null && !value.IsEmpty) { CountUpdated(cell); } if (loaded.TryGetValue(cell.Key, out Texture2D value2)) { loaded.Remove(cell.Key); Object.Destroy((Object)(object)value2); flag = true; } } else if (value != null && !value.IsEmpty && value.Url == cell.Url && value.ContentHash == text && value.OverviewETag != overviewETag) { value.OverviewETag = overviewETag; SaveMeta(cell.Key, value); } } if (flag) { TileCache.TexturesChanged?.Invoke(); } } private static string ShortBody(UnityWebRequest request) { DownloadHandler downloadHandler = request.downloadHandler; string text = ((downloadHandler != null) ? downloadHandler.text : null) ?? ""; text = text.Replace('\n', ' ').Replace('\r', ' '); if (text.Length <= 200) { return text; } return text.Substring(0, 200) + "..."; } private static float ParseRetryAfterSeconds(string? header) { if (string.IsNullOrEmpty(header) || !float.TryParse(header, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !(result > 0f)) { return 2f; } return result; } private static string F(float value) { return value.ToString(CultureInfo.InvariantCulture); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }
SnakeSquadCoordMarker.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SnakeSquadCoordMarker")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+be87a06804e2bdea813de87a1bd3e0099fa35086")] [assembly: AssemblyProduct("SnakeSquadCoordMarker")] [assembly: AssemblyTitle("SnakeSquadCoordMarker")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SnakeSquadCoordMarker { internal static class ClipboardHelper { private const uint CF_UNICODETEXT = 13u; [DllImport("user32.dll")] private static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll")] private static extern bool CloseClipboard(); [DllImport("user32.dll")] private static extern bool EmptyClipboard(); [DllImport("user32.dll")] private static extern IntPtr SetClipboardData(uint uFormat, IntPtr data); public static void SetText(string text) { if (!OpenClipboard(IntPtr.Zero)) { return; } try { EmptyClipboard(); IntPtr intPtr = Marshal.StringToHGlobalUni(text); if (SetClipboardData(13u, intPtr) == IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } finally { CloseClipboard(); } } } [BepInPlugin("com.snakesquad.coordmarker", "SnakeSquad Coordinate Marker", "1.10.2")] public class CoordMarkerPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class InitTerminalPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleEvent <>9__0_1; public static ConsoleEvent <>9__0_2; public static ConsoleEvent <>9__0_3; internal void <Postfix>b__0_0(ConsoleEventArgs args) { //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_005f: 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_008c: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("No player found."); return; } int num = args.FullLine.IndexOf(' '); string text = ((num >= 0) ? args.FullLine.Substring(num + 1).Trim() : ""); Vector3 position = ((Component)localPlayer).transform.position; markers.Add((text, position.x, position.z)); args.Context.AddString($"Marked '{text}' at ({position.x:F0}, {position.z:F0}) — {markers.Count} marker(s) pending export."); } internal void <Postfix>b__0_1(ConsoleEventArgs args) { if (markers.Count == 0) { args.Context.AddString("No markers to export. Use 'mark <note>' first."); return; } bool flag = false; string[] array = args.FullLine.Split(new char[1] { ' ' }); for (int i = 0; i < array.Length; i++) { if (array[i] == "-d") { flag = true; break; } } StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < markers.Count; j++) { (string note, float x, float z) tuple = markers[j]; string item = tuple.note; float item2 = tuple.x; float item3 = tuple.z; string value = item.Replace("|", "-").Replace(";", ","); stringBuilder.Append(value).Append('|').Append(item2.ToString("F0")) .Append(',') .Append(item3.ToString("F0")); if (j < markers.Count - 1) { stringBuilder.Append("; "); } } ClipboardHelper.SetText(stringBuilder.ToString()); if (flag) { int count = markers.Count; markers.Clear(); args.Context.AddString($"Copied {count} marker(s) to clipboard and cleared them."); } else { args.Context.AddString($"Copied {markers.Count} marker(s) to clipboard. Still pending - run 'markexport -d' or 'markclear' once you've confirmed the paste worked."); } } internal void <Postfix>b__0_2(ConsoleEventArgs args) { int count = markers.Count; markers.Clear(); args.Context.AddString($"Cleared {count} pending marker(s)."); } internal void <Postfix>b__0_3(ConsoleEventArgs args) { if (markers.Count == 0) { args.Context.AddString("No pending markers."); return; } foreach (var (arg, num, num2) in markers) { args.Context.AddString($" {arg}: ({num:F0}, {num2:F0})"); } } } private static void Postfix() { //IL_0033: 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_0029: Expected O, but got Unknown //IL_006c: 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_0062: Expected O, but got Unknown //IL_00a5: 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_009b: Expected O, but got Unknown //IL_00de: 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_00d4: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { //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_005f: 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_008c: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { args.Context.AddString("No player found."); } else { int num = args.FullLine.IndexOf(' '); string text = ((num >= 0) ? args.FullLine.Substring(num + 1).Trim() : ""); Vector3 position = ((Component)localPlayer).transform.position; markers.Add((text, position.x, position.z)); args.Context.AddString($"Marked '{text}' at ({position.x:F0}, {position.z:F0}) — {markers.Count} marker(s) pending export."); } }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("mark", "mark <note> - captures your current position with a note for later export", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { if (markers.Count == 0) { args.Context.AddString("No markers to export. Use 'mark <note>' first."); } else { bool flag = false; string[] array = args.FullLine.Split(new char[1] { ' ' }); for (int i = 0; i < array.Length; i++) { if (array[i] == "-d") { flag = true; break; } } StringBuilder stringBuilder = new StringBuilder(); for (int j = 0; j < markers.Count; j++) { (string note, float x, float z) tuple = markers[j]; string item = tuple.note; float item2 = tuple.x; float item3 = tuple.z; string value = item.Replace("|", "-").Replace(";", ","); stringBuilder.Append(value).Append('|').Append(item2.ToString("F0")) .Append(',') .Append(item3.ToString("F0")); if (j < markers.Count - 1) { stringBuilder.Append("; "); } } ClipboardHelper.SetText(stringBuilder.ToString()); if (flag) { int count = markers.Count; markers.Clear(); args.Context.AddString($"Copied {count} marker(s) to clipboard and cleared them."); } else { args.Context.AddString($"Copied {markers.Count} marker(s) to clipboard. Still pending - run 'markexport -d' or 'markclear' once you've confirmed the paste worked."); } } }; <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("markexport", "markexport [-d] - copies all pending markers to the clipboard. They stay pending unless you pass -d, so a failed/missed paste doesn't lose them - run 'markexport -d' or 'markclear' once you've confirmed the paste worked", (ConsoleEvent)obj2, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>c.<>9__0_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { int count = markers.Count; markers.Clear(); args.Context.AddString($"Cleared {count} pending marker(s)."); }; <>c.<>9__0_2 = val3; obj3 = (object)val3; } new ConsoleCommand("markclear", "markclear - discards all pending markers without exporting", (ConsoleEvent)obj3, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__0_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { if (markers.Count == 0) { args.Context.AddString("No pending markers."); return; } foreach (var (arg, num, num2) in markers) { args.Context.AddString($" {arg}: ({num:F0}, {num2:F0})"); } }; <>c.<>9__0_3 = val4; obj4 = (object)val4; } new ConsoleCommand("marklist", "marklist - shows all pending markers", (ConsoleEvent)obj4, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } private const string PluginGUID = "com.snakesquad.coordmarker"; private const string PluginName = "SnakeSquad Coordinate Marker"; private const string PluginVersion = "1.10.2"; internal static readonly List<(string note, float x, float z)> markers = new List<(string, float, float)>(); private ConfigEntry<KeyboardShortcut> biomeMarkHotkey; private ConfigEntry<bool> markWhereLooking; private ConfigEntry<float> lookMaxDistance; private static int aimLayerMask; private void Awake() { //IL_0011: 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: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) biomeMarkHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Biome Mark Hotkey", "Hotkey", KeyboardShortcut.Empty, "Press to add a mark named after the biome (e.g. 'Black Forest'), same as typing 'mark Black Forest' in the console. Unbound by default - set a key here to use it."); markWhereLooking = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Biome Mark Hotkey", "Mark At Crosshair", true, "If on, the hotkey marks the spot under your crosshair (and names it after that spot's biome) instead of where you're standing. If nothing is under the crosshair within Max Look Distance, it marks where you're standing."); lookMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Biome Mark Hotkey", "Max Look Distance", 100f, new ConfigDescription("How far away, in meters, the crosshair can mark a spot when Mark At Crosshair is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 500f), Array.Empty<object>())); NorthWisp.Bind(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); NorthWispItem.logger = ((BaseUnityPlugin)this).Logger; NetworkObjectGuard.logger = ((BaseUnityPlugin)this).Logger; new Harmony("com.snakesquad.coordmarker").PatchAll(Assembly.GetExecutingAssembly()); } private void Update() { //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_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_009e: 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_00b1: 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_00e2: 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) //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) NorthWispCharged.UpdateCharge(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } KeyboardShortcut value = biomeMarkHotkey.Value; if (!((KeyboardShortcut)(ref value)).IsDown() || !((Character)localPlayer).TakeInput()) { return; } Vector3 val = ((Component)localPlayer).transform.position; string text = "where you're standing"; if (markWhereLooking.Value) { if (TryGetLookPoint(out var point)) { val = point; text = $"{Vector3.Distance(((Component)localPlayer).transform.position, point):F0}m away"; } else { text = $"where you're standing - nothing under the crosshair within {lookMaxDistance.Value:F0}m"; } } string text2 = BiomeName(val); markers.Add((text2, val.x, val.z)); ((Character)localPlayer).Message((MessageType)1, $"Marked {text2} at ({val.x:F0}, {val.z:F0}), {text}. {markers.Count} pending.", 0, (Sprite)null, false); } private bool TryGetLookPoint(out Vector3 point) { //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_006b: 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_0094: 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) point = Vector3.zero; GameCamera instance = GameCamera.instance; if ((Object)(object)instance == (Object)null) { return false; } if (aimLayerMask == 0) { aimLayerMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }); } Transform transform = ((Component)instance).transform; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(transform.position, transform.forward, ref val, lookMaxDistance.Value, aimLayerMask)) { return false; } point = ((RaycastHit)(ref val)).point; return true; } private unsafe static string BiomeName(Vector3 position) { //IL_0012: 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_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) if (WorldGenerator.instance == null) { return "Unknown"; } Biome biome = WorldGenerator.instance.GetBiome(position.x, position.z, 0.02f, false); string text = "$biome_" + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString().ToLowerInvariant(); string text2 = ((Localization.instance != null) ? Localization.instance.Localize(text) : ""); if (string.IsNullOrEmpty(text2) || text2.StartsWith("[") || text2 == text) { text2 = Regex.Replace(((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString(), "(?<=[a-z])(?=[A-Z])", " "); } return text2; } } internal static class NetworkObjectGuard { [HarmonyPatch(typeof(ZNetScene), "RemoveObjects")] private static class RemoveObjectsPatch { private static void Prefix(ZNetScene __instance) { broken.Clear(); foreach (KeyValuePair<ZDO, ZNetView> instance in __instance.m_instances) { if ((Object)(object)instance.Value == (Object)null || instance.Value.GetZDO() == null) { broken.Add(instance.Key); } } foreach (ZDO item in broken) { __instance.m_instances.Remove(item); if (item != null && !item.Persistent && item.IsOwner()) { ZDOMan.instance.DestroyZDO(item); } int num = ((item != null) ? item.GetPrefab() : 0); if (reported.Add(num)) { GameObject prefab = __instance.GetPrefab(num); logger.LogWarning((object)("Cleaned up a broken network object ('" + (((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : num.ToString()) + "') that would otherwise flood the log with errors. Please report this.")); } } } } internal static ManualLogSource logger = null; private static readonly List<ZDO> broken = new List<ZDO>(); private static readonly HashSet<int> reported = new HashSet<int>(); } internal static class NorthWisp { private const string WispPrefabName = "demister_ball"; private const int MaxWisps = 3; private static readonly HashSet<string> visualComponents = new HashSet<string> { "Transform", "MeshFilter", "MeshRenderer", "SkinnedMeshRenderer", "ParticleSystem", "ParticleSystemRenderer", "Light", "LODGroup", "TrailRenderer", "LineRenderer" }; private static readonly List<ThrownWisp> active = new List<ThrownWisp>(); private static ManualLogSource logger = null; internal static ConfigEntry<float> throwDistance = null; internal static ConfigEntry<float> lifetime = null; internal static ConfigEntry<float> hoverHeight = null; internal static ConfigEntry<bool> visibleToOthers = null; internal static ConfigEntry<float> throwStamina = null; public static void Bind(ConfigFile config, ManualLogSource log) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown logger = log; throwDistance = config.Bind<float>("2 - North Wisp", "Throw Distance", 15f, new ConfigDescription("How far north of you a thrown North Wisp flies before it settles, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 50f), Array.Empty<object>())); lifetime = config.Bind<float>("2 - North Wisp", "Lifetime", 12f, new ConfigDescription("Seconds from throwing a North Wisp until it has faded away, flight included.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 120f), Array.Empty<object>())); hoverHeight = config.Bind<float>("2 - North Wisp", "Hover Height", 2f, new ConfigDescription("How high above where you threw it the wisp settles, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); visibleToOthers = config.Bind<bool>("2 - North Wisp", "Visible To Others", true, "Throw a real wisp that every player sees, with or without this mod. Like a Wisplight's wisp, it clears Mistlands mist around itself. Off: only you see it, and it doesn't clear mist."); throwStamina = config.Bind<float>("2 - North Wisp", "Throw Stamina", 5f, new ConfigDescription("Stamina a normal (north) throw costs. 0 makes it free.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>())); NorthWispCharged.Bind(config, log); } public static void Throw(Player player, GameObject visual) { //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_0066: 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_0081: 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_0090: 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_009f: 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) active.RemoveAll((ThrownWisp w) => (Object)(object)w == (Object)null); while (active.Count >= 3) { active[0].Despawn(); active.RemoveAt(0); } Vector3 position = visual.transform.position; Vector3 forward = ((Character)player).GetLookDir(); forward.y = 0f; forward = ((((Vector3)(ref forward)).sqrMagnitude > 0.01f) ? ((Vector3)(ref forward)).normalized : Vector3.forward); NorthWispFx.Throw(position); ThrownWisp thrownWisp = visual.AddComponent<ThrownWisp>(); thrownWisp.LaunchNorth(position, forward, ((Component)player).transform.position.y + hoverHeight.Value, throwDistance.Value, lifetime.Value); active.Add(thrownWisp); } internal static GameObject CreateVisual(Vector3 position) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0058: 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) GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("demister_ball") : null); if ((Object)(object)val == (Object)null) { logger.LogWarning((object)"North wisp: the game's 'demister_ball' prefab wasn't found - using a plain glowing orb instead."); return CreateFallbackOrb(); } if (visibleToOthers.Value && (Object)(object)ZNet.instance != (Object)null) { return Object.Instantiate<GameObject>(val, position, Quaternion.identity); } GameObject val2 = new GameObject("SnakeSquadNorthWispHolder"); val2.SetActive(false); ZNetView.m_forceDisableInit = true; GameObject val3; try { val3 = Object.Instantiate<GameObject>(val, val2.transform); } finally { ZNetView.m_forceDisableInit = false; } StripToVisuals(val3); if (!StrippedCleanly(val3)) { Object.Destroy((Object)(object)val2); return CreateFallbackOrb(); } ((Object)val3).name = "SnakeSquadNorthWisp"; val3.transform.SetParent((Transform)null, false); Object.Destroy((Object)(object)val2); ActivateUnregistered(val3); return val3; } internal static bool StrippedCleanly(GameObject copy) { if ((Object)(object)copy.GetComponentInChildren<ZNetView>(true) == (Object)null) { return true; } logger.LogWarning((object)"North Wisp: couldn't strip a copy of the wisp, so it was dropped."); return false; } internal static void ActivateUnregistered(GameObject copy) { ZNetView.m_forceDisableInit = true; try { copy.SetActive(true); } finally { ZNetView.m_forceDisableInit = false; } } private static void StripToVisuals(GameObject root) { StripExcept(root, visualComponents); } internal static void StripExcept(GameObject root, HashSet<string> keep) { for (int i = 0; i < 2; i++) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !keep.Contains(((object)val).GetType().Name) && (i != 0 || val is MonoBehaviour)) { Object.DestroyImmediate((Object)(object)val); } } } } private static GameObject CreateFallbackOrb() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_002f: 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_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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown Color color = default(Color); ((Color)(ref color))..ctor(0.6f, 0.85f, 1f); GameObject val = new GameObject("SnakeSquadNorthWisp"); Light obj = val.AddComponent<Light>(); obj.type = (LightType)2; obj.color = color; obj.range = 6f; obj.intensity = 2f; Shader val2 = Shader.Find("Sprites/Default"); if ((Object)(object)val2 != (Object)null) { GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)0); Object.Destroy((Object)(object)obj2.GetComponent<Collider>()); obj2.transform.SetParent(val.transform, false); obj2.transform.localScale = Vector3.one * 0.25f; obj2.GetComponent<Renderer>().material = new Material(val2) { color = color }; } return val; } } internal sealed class ThrownWisp : MonoBehaviour { private const float FlightSeconds = 1.6f; private const float ForwardSeconds = 0.6f; private const float ForwardDistance = 4f; private const float ForwardArc = 0.6f; private const float LostSeconds = 1.8f; private const float LostRadius = 0.9f; private const float LostSpin = 5f; private const float NorthSeconds = 2.2f; private const float ArcHeight = 1.5f; private const float FadeSeconds = 3f; private const float WobbleAmount = 0.35f; private const float WobbleSpeed = 0.6f; private const float BobAmount = 0.15f; private const float BobSpeed = 2f; private Vector3 start; private Vector3 settle; private bool north; private Vector3 lostPoint; private float lifetime; private float age; private float seed; private Vector3 baseScale; private Light[] lights; private float[] baseIntensities; private ZNetView? nview; private bool despawned; public void LaunchNorth(Vector3 from, Vector3 forward, float settleHeight, float distance, float totalSeconds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_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_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_0053: 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) north = true; lostPoint = from + forward * 4f + Vector3.up * 0.3f; Vector3 to = lostPoint + Vector3.forward * distance; to.y = settleHeight; Launch(from, to, Mathf.Max(totalSeconds, 6.1000004f)); } public void Launch(Vector3 from, Vector3 to, float totalSeconds) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_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) start = from; settle = to; lifetime = Mathf.Max(totalSeconds, 2.1f); seed = Random.value * 100f; baseScale = ((Component)this).transform.localScale; nview = ((Component)this).GetComponent<ZNetView>(); lights = ((Component)this).GetComponentsInChildren<Light>(true); baseIntensities = new float[lights.Length]; for (int i = 0; i < lights.Length; i++) { baseIntensities[i] = lights[i].intensity; } } private void Update() { //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_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) age += Time.deltaTime; if (age >= lifetime) { Despawn(); return; } Vector3 val; float wobbleWeight; if (north) { val = NorthPath(out wobbleWeight); } else { if (age < 1.6f) { float num = age / 1.6f; float num2 = 1f - (1f - num) * (1f - num) * (1f - num); val = Vector3.Lerp(start, settle, num2) + Vector3.up * (Mathf.Sin(num2 * (float)Math.PI) * 1.5f); } else { val = settle; } wobbleWeight = Mathf.Clamp01((age - 0.8f) / 1.6f); } float num3 = Time.time * 0.6f + seed; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor((Mathf.PerlinNoise(num3, seed) - 0.5f) * 2f, (Mathf.PerlinNoise(seed, num3) - 0.5f) * 2f + Mathf.Sin(Time.time * 2f + seed) * 0.42857146f, (Mathf.PerlinNoise(num3 + 37f, seed + 11f) - 0.5f) * 2f); ((Component)this).transform.position = val + val2 * (0.35f * wobbleWeight); float num4 = Mathf.Clamp01((lifetime - age) / 3f); ((Component)this).transform.localScale = baseScale * num4; for (int i = 0; i < lights.Length; i++) { if ((Object)(object)lights[i] != (Object)null) { lights[i].intensity = baseIntensities[i] * num4; } } } private Vector3 NorthPath(out float wobbleWeight) { //IL_0038: 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_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_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_00b2: 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_00e5: 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_0130: 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_0110: 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 (age < 0.6f) { float num = age / 0.6f; float num2 = 1f - (1f - num) * (1f - num); wobbleWeight = 0f; return Vector3.Lerp(start, lostPoint, num2) + Vector3.up * (Mathf.Sin(num2 * (float)Math.PI) * 0.6f); } wobbleWeight = 1f; float num3 = age - 0.6f; if (num3 < 1.8f) { float num4 = Mathf.Sin(num3 / 1.8f * (float)Math.PI) * 0.9f; float num5 = num3 * 5f + seed; return lostPoint + new Vector3(Mathf.Cos(num5), 0.45f * Mathf.Sin(num5 * 1.7f), Mathf.Sin(num5 * 1.3f)) * num4; } float num6 = num3 - 1.8f; if (num6 < 2.2f) { float num7 = num6 / 2.2f; return Vector3.Lerp(lostPoint, settle, num7 * num7 * (3f - 2f * num7)); } return settle; } public void Despawn() { if (!despawned) { despawned = true; Remove(((Component)this).gameObject, nview); } } internal static void Remove(GameObject wisp, ZNetView? nview) { if ((Object)(object)nview != (Object)null && nview.IsValid()) { nview.ClaimOwnership(); nview.Destroy(); } else { Object.Destroy((Object)(object)wisp); } } } internal static class NorthWispCharged { private enum State { Idle, Charging, Ready, Throwing } [HarmonyPatch(typeof(Humanoid), "StartAttack")] private static class StartAttackPatch { private static bool Prefix(Humanoid __instance, bool secondaryAttack, ref bool __result) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData currentWeapon = __instance.GetCurrentWeapon(); if (!NorthWispItem.IsNorthWisp(currentWeapon)) { return true; } UpdateAttackCosts(currentWeapon); if (startingChargedThrow) { return true; } __result = false; if (state != State.Idle) { return false; } if (!secondaryAttack) { return true; } Player val = (Player)__instance; if (enabled.Value && val.m_queuedSecondAttackTimer > 0f && !((Character)val).InAttack() && !((Character)val).InDodge() && !((Character)val).IsStaggering() && !((Character)val).InMinorAction()) { StartCharge(val); } return false; } } [HarmonyPatch(typeof(Player), "SetControls")] private static class SetControlsPatch { private static void Prefix(Player __instance, ref Vector3 movedir, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge) { //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) if (LocksPlayer && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { movedir = Vector3.zero; jump = false; crouch = false; run = false; autoRun = false; dodge = false; } } } [HarmonyPatch(typeof(Attack), "ProjectileAttackTriggered")] private static class ProjectileAttackTriggeredPatch { private static bool Prefix(Attack __instance) { if (!NorthWispItem.IsNorthWisp(__instance.m_weapon)) { return true; } Humanoid character = __instance.m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { pendingRelease = (val, ((Humanoid)val).m_currentAttack == __instance && ((Humanoid)val).m_currentAttackIsSecondary); } return false; } } private static ManualLogSource logger; internal static ConfigEntry<bool> enabled; internal static ConfigEntry<float> chargeTime; internal static ConfigEntry<float> stamina; internal static ConfigEntry<float> eitr; internal static ConfigEntry<SkillType> skill; internal static ConfigEntry<float> range; internal static ConfigEntry<float> speed; internal static ConfigEntry<float> gravity; internal static ConfigEntry<float> proximityFuse; internal static ConfigEntry<int> bounces; internal static ConfigEntry<float> burstRadius; internal static ConfigEntry<float> spiritDamage; internal static ConfigEntry<float> glowSeconds; internal static ConfigEntry<float> stunSeconds; internal static ConfigEntry<bool> stunBosses; internal static ConfigEntry<float> flashBrightness; internal static ConfigEntry<float> cameraShake; internal static ConfigEntry<float> mistTrailSeconds; internal static ConfigEntry<float> burstMistRadius; private static float? sweepStamina; private static bool warnedNoField; private const float ReadyHoldSeconds = 0.35f; private const float ThrowTimeoutSeconds = 2.5f; private static State state; private static float stateStart; private static float chargeStart; private static GameObject? heldWisp; private static (Player player, bool secondary)? pendingRelease; private static bool startingChargedThrow; private static GameObject? mistClearerRoot; internal static bool LocksPlayer => state != State.Idle; public static void Bind(ConfigFile config, ManualLogSource log) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Expected O, but got Unknown //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Expected O, but got Unknown //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Expected O, but got Unknown //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Expected O, but got Unknown //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Expected O, but got Unknown //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Expected O, but got Unknown //IL_0457: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Expected O, but got Unknown logger = log; enabled = config.Bind<bool>("3 - North Wisp Charged Cast", "Enabled", true, "With the North Wisp in hand, press the secondary attack (middle mouse) to stand still and charge, then shoot a wisp far toward your crosshair. Off: the secondary attack does nothing."); chargeTime = config.Bind<float>("3 - North Wisp Charged Cast", "Charge Time", 0.8f, new ConfigDescription("Seconds you stand charging, after pressing the secondary attack, before the wisp is thrown.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>())); stamina = config.Bind<float>("3 - North Wisp Charged Cast", "Stamina", -1f, new ConfigDescription("Stamina a charged cast costs, before the skill discount (up to a third off at skill 100). -1 (the default) is twice whatever the Bronze Atgeir's sweep (secondary attack) costs in your game. 0 makes it free.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 150f), Array.Empty<object>())); eitr = config.Bind<float>("3 - North Wisp Charged Cast", "Eitr", 0f, new ConfigDescription("Eitr a charged cast costs, before the skill discount. 0 (the default): none, so no eitr food is needed. Above 0 you need eitr from food to cast it at all.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); ConfigEntry<int> val = config.Bind<int>("9 - Internal", "Costs Version", 0, "Don't change: lets the mod update its cost defaults once in old configs."); if (val.Value < 1) { stamina.Value = (float)((ConfigEntryBase)stamina).DefaultValue; eitr.Value = (float)((ConfigEntryBase)eitr).DefaultValue; val.Value = 1; } skill = config.Bind<SkillType>("3 - North Wisp Charged Cast", "Magic Skill", (SkillType)9, "The skill a charged cast trains (when its burst hits an enemy, like a staff's projectile) and that lowers its cost."); range = config.Bind<float>("3 - North Wisp Charged Cast", "Range", 150f, new ConfigDescription("With Gravity at 0 only: how far the charged wisp flies in a straight line, in meters, before it drops, bounces and bursts. Past about 150 m the world around it may not be loaded, so it can vanish without bursting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 250f), Array.Empty<object>())); speed = config.Bind<float>("3 - North Wisp Charged Cast", "Speed", 20f, new ConfigDescription("How fast the charged wisp leaves your hand, in meters per second. With gravity this sets how far you can throw it: 20 reaches about 40 m on flat ground, like a real grenade.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 100f), Array.Empty<object>())); gravity = config.Bind<float>("3 - North Wisp Charged Cast", "Gravity", 1f, new ConfigDescription("How strongly the charged wisp falls (1 = normal gravity). It's thrown in an arc to land where you aim, as far as Speed allows. 0: it flies straight for Range, like before.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); proximityFuse = config.Bind<float>("3 - North Wisp Charged Cast", "Proximity Fuse", 4f, new ConfigDescription("The charged wisp bursts as soon as it passes within this many meters of a hostile creature (once it's a few meters from you). 0: only when it touches one.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>())); ConfigEntry<int> val2 = config.Bind<int>("9 - Internal", "Flight Version", 0, "Don't change: lets the mod update its flight defaults once in old configs."); if (val2.Value < 1) { speed.Value = (float)((ConfigEntryBase)speed).DefaultValue; val2.Value = 1; } bounces = config.Bind<int>("3 - North Wisp Charged Cast", "Bounces", 3, new ConfigDescription("How many times it bounces off the ground, walls or water before it bursts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>())); burstRadius = config.Bind<float>("3 - North Wisp Charged Cast", "Burst Radius", 9f, new ConfigDescription("Enemies within this many meters of the burst take its damage and light up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 25f), Array.Empty<object>())); spiritDamage = config.Bind<float>("3 - North Wisp Charged Cast", "Spirit Damage", 6f, new ConfigDescription("Spirit damage the burst deals to each enemy in range. Like any spirit damage it mostly hurts the undead; most other creatures shrug it off but still light up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); glowSeconds = config.Bind<float>("3 - North Wisp Charged Cast", "Glow Seconds", 5f, new ConfigDescription("How long enemies caught in the burst glow (only players with this mod see the glow).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); stunSeconds = config.Bind<float>("3 - North Wisp Charged Cast", "Stun Seconds", 4f, new ConfigDescription("The burst is a flashbang: hostile creatures in Burst Radius are staggered, and staggered again as it wears off, for this long. Everyone sees it (it's the game's own stagger). 0: no stun.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>())); stunBosses = config.Bind<bool>("3 - North Wisp Charged Cast", "Stun Bosses", false, "Whether the flashbang also staggers bosses."); flashBrightness = config.Bind<float>("3 - North Wisp Charged Cast", "Flash Brightness", 1f, new ConfigDescription("How bright the burst's flash is (1 = a blinding flash about 35 m across that fades in under a second, then a glow). Only players with this mod see the flash itself. 0: just the glow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); cameraShake = config.Bind<float>("3 - North Wisp Charged Cast", "Camera Shake", 1f, new ConfigDescription("How hard the burst shakes your camera when you're within 25 m of it. 0: no shake.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); mistTrailSeconds = config.Bind<float>("3 - North Wisp Charged Cast", "Mist Trail Seconds", 10f, new ConfigDescription("How long the path the charged wisp flew, and the patch around its burst, stay clear of Mistlands mist. Only clears it for you; the wisp itself clears mist for everyone as it passes if Visible To Others is on. 0: no trail.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); burstMistRadius = config.Bind<float>("3 - North Wisp Charged Cast", "Burst Mist Radius", 20f, new ConfigDescription("How wide a patch of mist the burst clears, in meters (radius). A Wisplight clears much less.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); NorthWispFx.logger = log; NorthWispFx.Bind(config); } public static void UpdateCharge() { BurstBroadcast.Register(); if (pendingRelease.HasValue) { (Player player, bool secondary) value = pendingRelease.Value; Player item = value.player; bool item2 = value.secondary; pendingRelease = null; if ((Object)(object)item != (Object)null && (Object)(object)item == (Object)(object)Player.m_localPlayer) { OnThrowReleased(item, item2); } } if (state == State.Idle) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !NorthWispItem.IsNorthWisp(((Humanoid)localPlayer).RightItem) || ((Character)localPlayer).IsStaggering()) { CancelCharge(); return; } switch (state) { case State.Charging: { float num = Mathf.Clamp01((Time.time - chargeStart) / chargeTime.Value); NorthWispFx.UpdateCharge(localPlayer, num, ready: false); if (num >= 1f) { SetState(State.Ready); NorthWispFx.Ready(localPlayer); } break; } case State.Ready: NorthWispFx.UpdateCharge(localPlayer, 1f, ready: true); if (Time.time - stateStart >= 0.35f) { StartChargedThrow(localPlayer); } break; case State.Throwing: NorthWispFx.UpdateCharge(localPlayer, 1f, ready: true); if (Time.time - stateStart >= 2.5f || (!((Character)localPlayer).InAttack() && Time.time - stateStart > 0.3f)) { CancelCharge(); } break; } } private static void SetState(State next) { state = next; stateStart = Time.time; } private static void UpdateAttackCosts(ItemData weapon) { //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) SharedData shared = weapon.m_shared; shared.m_skillType = skill.Value; if (shared.m_attack != null) { shared.m_attack.m_attackStamina = NorthWisp.throwStamina.Value; shared.m_attack.m_attackEitr = 0f; } if (shared.m_secondaryAttack != null) { shared.m_secondaryAttack.m_attackStamina = ((stamina.Value >= 0f) ? stamina.Value : (2f * SweepStamina())); shared.m_secondaryAttack.m_attackEitr = eitr.Value; } } private static void StartCharge(Player player) { //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_0035: Unknown result type (might be due to invalid IL or missing references) if (CanAfford(player)) { SetState(State.Charging); chargeStart = Time.time; Vector3 position = NorthWispFx.HandPoint(player); heldWisp = NorthWisp.CreateVisual(position); heldWisp.transform.position = position; heldWisp.AddComponent<HeldWisp>().Follow(player); NorthWispFx.StartCharge(player); } } private static void CancelCharge() { state = State.Idle; NorthWispFx.StopCharge(); if ((Object)(object)heldWisp != (Object)null) { ThrownWisp.Remove(heldWisp, heldWisp.GetComponent<ZNetView>()); } heldWisp = null; } private static void StartChargedThrow(Player player) { startingChargedThrow = true; bool flag; try { flag = ((Character)player).StartAttack((Character)null, true); } finally { startingChargedThrow = false; } if (flag) { SetState(State.Throwing); } else { CancelCharge(); } } private static void OnThrowReleased(Player player, bool secondary) { //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_000a: 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) if (!secondary) { Vector3 position = NorthWispFx.HandPoint(player); GameObject val = NorthWisp.CreateVisual(position); val.transform.position = position; NorthWisp.Throw(player, val); } else if (state == State.Throwing && !((Object)(object)heldWisp == (Object)null)) { GameObject val2 = heldWisp; heldWisp = null; state = State.Idle; NorthWispFx.StopCharge(); HeldWisp component = val2.GetComponent<HeldWisp>(); if ((Object)(object)component != (Object)null) { component.Release(); } Cast(player, val2); } } private static float SweepStamina() { if (!sweepStamina.HasValue && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("AtgeirBronze"); SharedData val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared); if (val == null) { val = (from i in ObjectDB.instance.m_items select (!((Object)(object)i != (Object)null)) ? null : i.GetComponent<ItemDrop>() into d where (Object)(object)d != (Object)null && (int)d.m_itemData.m_shared.m_skillType == 4 && d.m_itemData.m_shared.m_secondaryAttack != null select d.m_itemData.m_shared).FirstOrDefault(); } if (val?.m_secondaryAttack != null && val.m_secondaryAttack.m_attackStamina > 0f) { sweepStamina = val.m_secondaryAttack.m_attackStamina; logger.LogInfo((object)$"North Wisp: a charged cast costs {2f * sweepStamina:F0} stamina before the skill discount, twice {val.m_name}'s sweep."); } else { sweepStamina = 40f; logger.LogWarning((object)"North Wisp: couldn't find a polearm's sweep cost, so a charged cast costs 80 stamina."); } } return sweepStamina ?? 40f; } private static bool CanAfford(Player player) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) float num = 1f - 0.33f * ((Character)player).GetSkillFactor(skill.Value); float num2 = ((stamina.Value >= 0f) ? stamina.Value : (2f * SweepStamina())) * num; float num3 = eitr.Value * num; if (num3 > 0f) { if (((Character)player).GetMaxEitr() <= 0f) { ((Character)player).Message((MessageType)2, "$hud_eitrrequired", 0, (Sprite)null, false); return false; } if (!((Character)player).HaveEitr(num3)) { if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.EitrBarEmptyFlash(); } return false; } } if (num2 > 0f && !((Character)player).HaveStamina(num2 + 0.1f)) { if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.StaminaBarEmptyFlash(); } return false; } return true; } private static void Cast(Player player, GameObject wisp) { //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_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_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_0092: 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_002c: 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_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_006f: 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_0052: 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_00b3: 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_0074: 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_00e9: 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_00f7: 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_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) //IL_00e2: 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) Vector3 position = wisp.transform.position; GameCamera instance = GameCamera.instance; Vector3 val; if ((Object)(object)instance != (Object)null) { Transform transform = ((Component)instance).transform; RaycastHit val2 = default(RaycastHit); val = (Physics.Raycast(transform.position, transform.forward, ref val2, range.Value, ChargedWisp.SolidMask) ? ((RaycastHit)(ref val2)).point : (transform.position + transform.forward * range.Value)); } else { val = position + ((Character)player).GetLookDir() * range.Value; } Vector3 val3 = val - position; val3 = ((((Vector3)(ref val3)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val3)).normalized : ((Character)player).GetLookDir()); float num = 9.81f * gravity.Value; if (num > 0f) { val3 = ThrowDirection(position, val, speed.Value, num, val3); } NorthWispFx.Cast(position); wisp.AddComponent<ChargedWisp>().Launch(player, position, val3 * speed.Value, num); } private static Vector3 ThrowDirection(Vector3 from, Vector3 target, float v, float g, Vector3 fallback) { //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_0008: 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_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_002b: 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_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_008e: 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_009c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - from; float y = val.y; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.5f) { return fallback; } val /= magnitude; float num = v * v; float num2 = num * num - g * (g * magnitude * magnitude + 2f * y * num); float num3 = ((num2 >= 0f) ? Mathf.Atan((num - Mathf.Sqrt(num2)) / (g * magnitude)) : ((float)Math.PI / 4f)); Vector3 val2 = val * Mathf.Cos(num3) + Vector3.up * Mathf.Sin(num3); return ((Vector3)(ref val2)).normalized; } internal static void DropMistClearer(Vector3 position, float radius = 0f, float seconds = 0f) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (seconds <= 0f) { seconds = mistTrailSeconds.Value; } if (seconds <= 0f || (Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab("demister_ball"); Demister val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<Demister>(true) : null); ParticleSystemForceField val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ParticleSystemForceField>() : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { if (!warnedNoField) { warnedNoField = true; logger.LogWarning((object)"North Wisp: the wisp's mist-clearing field wasn't where expected, so the charged cast leaves no mist trail."); } return; } GameObject val3 = new GameObject("SnakeSquadMistClearer"); val3.SetActive(false); val3.transform.SetParent(MistClearerRoot(), false); val3.transform.position = position; ParticleSystemForceField val4 = val3.AddComponent<ParticleSystemForceField>(); CopyField(val2, val4); Demister val5 = val3.AddComponent<Demister>(); FieldInfo[] fields = typeof(Demister).GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(val5, fieldInfo.GetValue(val)); } val5.m_forceField = val4; if (radius > 0f) { val4.endRange = radius; } val3.SetActive(true); val3.AddComponent<MistClearer>().Init(val4, seconds); } private static Transform MistClearerRoot() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)mistClearerRoot == (Object)null) { mistClearerRoot = new GameObject("SnakeSquadMistClearers"); } return mistClearerRoot.transform; } private static void CopyField(ParticleSystemForceField from, ParticleSystemForceField to) { //IL_0002: 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_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_006e: 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_009e: 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_00c2: 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) to.shape = from.shape; to.startRange = from.startRange; to.endRange = from.endRange; to.length = from.length; to.gravity = from.gravity; to.gravityFocus = from.gravityFocus; to.rotationSpeed = from.rotationSpeed; to.rotationAttraction = from.rotationAttraction; to.rotationRandomness = from.rotationRandomness; to.drag = from.drag; to.multiplyDragByParticleSize = from.multiplyDragByParticleSize; to.multiplyDragByParticleVelocity = from.multiplyDragByParticleVelocity; to.directionX = from.directionX; to.directionY = from.directionY; to.directionZ = from.directionZ; to.vectorField = from.vectorField; to.vectorFieldSpeed = from.vectorFieldSpeed; to.vectorFieldAttraction = from.vectorFieldAttraction; } } internal sealed class ChargedWisp : MonoBehaviour { internal const float Gravity = 9.81f; private const float BounceKeep = 0.55f; private const float Radius = 0.25f; private const float EnemyHitDistance = 1.2f; private const float MaxFallSeconds = 5f; private const float MinBounceSpeed = 3f; private const float TrailSpacing = 8f; private const float LingerSeconds = 4f; private static int solidMask; private Player owner; private ZNetView? nview; private Vector3 position; private Vector3 velocity; private float travelled; private float fallTime; private bool falling; private float gravityNow = 9.81f; private int bounced; private bool done; private Vector3 lastTrailPoint; private const float FuseArmDistance = 3f; internal static int SolidMask { get { if (solidMask == 0) { return solidMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }); } return solidMask; } } private float FuseDistance { get { if (!(travelled >= 3f)) { return 1.2f; } return Mathf.Max(1.2f, NorthWispCharged.proximityFuse.Value); } } public void Launch(Player player, Vector3 from, Vector3 startVelocity, float gravity) { //IL_003b: 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_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_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_004f: Unknown result type (might be due to invalid IL or missing references) owner = player; gravityNow = ((gravity > 0f) ? gravity : 9.81f); falling = gravity > 0f; nview = ((Component)this).GetComponent<ZNetView>(); position = from; velocity = startVelocity; lastTrailPoint = from; NorthWispCharged.DropMistClearer(from); } private void Update() { //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_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_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_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_004a: 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_008c: 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_0094: 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_00dc: 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_00ac: 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_00bd: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: 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_019d: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: 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_01dc: Unknown result type (might be due to invalid IL or missing references) if (done) { return; } if ((Object)(object)owner == (Object)null) { Finish(); return; } float deltaTime = Time.deltaTime; if (falling) { velocity += Vector3.down * (gravityNow * deltaTime); fallTime += deltaTime; } Vector3 val = position; Vector3 val2 = velocity * deltaTime; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 0.0001f) { return; } bool flag = false; Vector3 val3 = Vector3.up; RaycastHit val4 = default(RaycastHit); if (Physics.SphereCast(val, 0.25f, val2 / magnitude, ref val4, magnitude, SolidMask, (QueryTriggerInteraction)1)) { position = ((RaycastHit)(ref val4)).point + ((RaycastHit)(ref val4)).normal * 0.3f; val3 = ((RaycastHit)(ref val4)).normal; flag = true; } else { position = val + val2; float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : float.MinValue); if (position.y < num && velocity.y < 0f) { position.y = num + 0.05f; flag = true; } } travelled += Vector3.Distance(val, position); ((Component)this).transform.position = position; Transform transform = ((Component)this).transform; transform.rotation *= Quaternion.Euler(720f * deltaTime, 0f, 360f * deltaTime); DropTrail(); if (HitsEnemy(val, position)) { Burst(); return; } if (flag) { bounced++; velocity = Vector3.Reflect(velocity, val3) * 0.55f; falling = true; if (bounced > NorthWispCharged.bounces.Value || ((Vector3)(ref velocity)).magnitude < 3f) { Burst(); return; } } if (!falling && travelled >= NorthWispCharged.range.Value) { falling = true; } if (falling && fallTime >= 5f) { Burst(); } } private void DropTrail() { //IL_0001: 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_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_0025: Unknown result type (might be due to invalid IL or missing references) if (Vector3.Distance(lastTrailPoint, position) >= 8f) { lastTrailPoint = position; NorthWispCharged.DropMistClearer(position); } } private bool HitsEnemy(Vector3 from, Vector3 to) { //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_0064: Unknown result type (might be due to invalid IL or missing references) foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)owner) && !((Object)(object)allCharacter.m_nview == (Object)null) && allCharacter.m_nview.IsValid() && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)owner, allCharacter) && DistanceToSegment(allCharacter.GetCenterPoint(), from, to) < FuseDistance) { return true; } } return false; } private static float DistanceToSegment(Vector3 point, 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) //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) Vector3 val = b - a; float num = ((((Vector3)(ref val)).sqrMagnitude > 0f) ? Mathf.Clamp01(Vector3.Dot(point - a, val) / ((Vector3)(ref val)).sqrMagnitude) : 0f); return Vector3.Distance(point, a + val * num); } private void Burst() { //IL_000a: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e7: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_011b: 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_0132: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) if (done) { return; } ShowBurst(position, remote: false); BurstBroadcast.Send(position); List<Character> list = new List<Character>(); NorthWispCharged.DropMistClearer(position, NorthWispCharged.burstMistRadius.Value, NorthWispCharged.mistTrailSeconds.Value * 1.5f); bool flag = false; float value = NorthWispCharged.burstRadius.Value; float value2 = NorthWispCharged.spiritDamage.Value; Character[] array = Character.GetAllCharacters().ToArray(); foreach (Character val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)owner || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid() || val.IsDead() || !BaseAI.IsEnemy((Character)(object)owner, val)) { continue; } Vector3 centerPoint = val.GetCenterPoint(); if (Vector3.Distance(centerPoint, position) > value) { continue; } if (value2 > 0f) { HitData val2 = new HitData(); val2.m_damage.m_spirit = value2; val2.m_point = centerPoint; val2.m_hitCollider = (Collider)(object)val.m_collider; Vector3 val3 = centerPoint - position; Vector3 dir; if (!(((Vector3)(ref val3)).sqrMagnitude > 0.01f)) { dir = Vector3.up; } else { val3 = centerPoint - position; dir = ((Vector3)(ref val3)).normalized; } val2.m_dir = dir; val2.m_ranged = true; val2.SetAttacker((Character)(object)owner); val.Damage(val2); flag = true; } if (NorthWispCharged.glowSeconds.Value > 0f) { SpiritGlow.Create(((Component)val).transform, centerPoint, NorthWispCharged.glowSeconds.Value, 6f, 4f); } if (NorthWispCharged.stunSeconds.Value > 0f && (NorthWispCharged.stunBosses.Value || !val.IsBoss())) { list.Add(val); } } if (list.Count > 0) { FlashStun.Create(position, list, NorthWispCharged.stunSeconds.Value); } if (flag) { ((Character)owner).RaiseSkill(NorthWispCharged.skill.Value, 1f); } done = true; ((Component)this).gameObject.AddComponent<ThrownWisp>().Launch(position, position, 4f); Object.Destroy((Object)(object)this); } internal static void ShowBurst(Vector3 position, bool remote) { //IL_0000: 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_002e: 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) NorthWispFx.Burst(position, remote); SpiritGlow.Create(null, position, 3f, 14f, 4f); if (NorthWispCharged.flashBrightness.Value > 0f) { Flash.Create(position, NorthWispCharged.flashBrightness.Value); } if (NorthWispCharged.cameraShake.Value > 0f && (Object)(object)GameCamera.instance != (Object)null) { GameCamera.instance.AddShake(position, 25f, 2f * NorthWispCharged.cameraShake.Value, false); } } private void Finish() { done = true; ThrownWisp.Remove(((Component)this).gameObject, nview); } } internal static class BurstBroadcast { private const string RpcName = "SnakeSquad_NorthWispBurst"; private static ZRoutedRpc? registeredOn; public static void Register() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && instance != registeredOn) { instance.Register<Vector3>("SnakeSquad_NorthWispBurst", (Action<long, Vector3>)OnBurst); registeredOn = instance; } } public static void Send(Vector3 position) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(0L, "SnakeSquad_NorthWispBurst", new object[1] { position }); } } private static void OnBurst(long sender, Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null && sender != ZRoutedRpc.instance.m_id) { ChargedWisp.ShowBurst(position, remote: true); } } } internal sealed class SpiritGlow : MonoBehaviour { private static readonly Color glowColor = new Color(0.55f, 0.85f, 1f); private Light glowLight; private float seconds; private float age; private float intensity; public static void Create(Transform? parent, Vector3 position, float seconds, float range, float intensity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0011: 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) GameObject val = new GameObject("SnakeSquadSpiritGlow"); val.transform.position = position; if ((Object)(object)parent != (Object)null) { val.transform.SetParent(parent, true); } SpiritGlow spiritGlow = val.AddComponent<SpiritGlow>(); spiritGlow.glowLight = val.AddComponent<Light>(); spiritGlow.glowLight.type = (LightType)2; spiritGlow.glowLight.color = glowColor; spiritGlow.glowLight.range = range; spiritGlow.glowLight.intensity = intensity; spiritGlow.seconds = seconds; spiritGlow.intensity = intensity; } private void Update() { age += Time.deltaTime; if (age >= seconds) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } float num = Mathf.Clamp01((seconds - age) / (seconds / 3f)); glowLight.intensity = intensity * num * (0.8f + 0.2f * Mathf.Sin(age * 6f)); } } internal sealed class MistClearer : MonoBehaviour { private const float FadeSeconds = 2f; private ParticleSystemForceField field; private float baseRange; private float seconds; private float age; public void Init(ParticleSystemForceField forceField, float lifetime) { field = forceField; baseRange = forceField.endRange; seconds = lifetime; } private void Update() { age += Time.deltaTime; if (age >= seconds) { Object.Destroy((Object)(object)((Component)this).gameObject); } else if ((Object)(object)field != (Object)null) { field.endRange = baseRange * Mathf.Clamp01((seconds - age) / 2f); } } } internal sealed class Flash : MonoBehaviour { private const float Seconds = 0.7f; private const float Range = 35f; private const float Intensity = 12f; private Light flashLight; private float strength; private float age; public static void Create(Vector3 position, float strength) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //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_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_0065: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("SnakeSquadWispFlash"); val.transform.position = position + Vector3.up * 0.5f; Flash flash = val.AddComponent<Flash>(); flash.strength = strength; flash.flashLight = val.AddComponent<Light>(); flash.flashLight.type = (LightType)2; flash.flashLight.color = new Color(0.92f, 0.96f, 1f); flash.flashLight.range = 35f; flash.flashLight.intensity = 12f * strength; flash.flashLight.shadows = (LightShadows)0; } private void Update() { age += Time.deltaTime; if (age >= 0.7f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } float num = age / 0.7f; flashLight.intensity = 12f * strength * ((num < 0.15f) ? 1f : Mathf.Pow(1f - (num - 0.15f) / 0.85f, 2f)); } } internal sealed class FlashStun : MonoBehaviour { private const float Interval = 1.2f; private readonly List<Character> targets = new List<Character>(); private Vector3 origin; private float seconds; private float age; private float nextStagger; public static void Create(Vector3 origin, List<Character> characters, float seconds) { //IL_0005: 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_0011: Unknown result type (might be due to invalid IL or missing references) FlashStun flashStun = new GameObject("SnakeSquadWispStun").AddComponent<FlashStun>(); flashStun.origin = origin; flashStun.seconds = seconds; flashStun.targets.AddRange(characters); flashStun.StaggerAll(); } private void Update() { age += Time.deltaTime; if (age >= seconds) { Object.Destroy((Object)(object)((Component)this).gameObject); } else if (age >= nextStagger) { StaggerAll(); } } private void StaggerAll() { //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) //IL_0069: 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_008b: Unknown result type (might be due to invalid IL or missing references) nextStagger = age + 1.2f; targets.RemoveAll((Character c) => (Object)(object)c == (Object)null || (Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid() || c.IsDead()); foreach (Character target in targets) { Vector3 val = ((Component)target).transform.position - origin; val.y = 0f; target.Stagger((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : ((Component)target).transform.forward); } } } internal static class NorthWispFx { private const string Section = "4 - North Wisp Effects"; private const float OneShotSeconds = 6f; private static readonly Color glowColor = new Color(0.55f, 0.85f, 1f); internal static ManualLogSource logger = null; internal static ConfigEntry<string> chargeSound = null; internal static ConfigEntry<string> chargeEffect = null; internal static ConfigEntry<string> warpEffect = null; internal static ConfigEntry<float> warpScale = null; internal static ConfigEntry<string> readySound = null; internal static ConfigEntry<string> readyEffect = null; internal static ConfigEntry<string> humSound = null; internal static ConfigEntry<string> throwSound = null; internal static ConfigEntry<string> castSound = null; internal static ConfigEntry<string> burstEffect = null; internal static ConfigEntry<string> burstSound = null; internal static ConfigEntry<float> soundVolume = null; internal static ConfigEntry<float> soundRange = null; private static ConfigEntry<int> effectsVersion = null; private const int CurrentEffectsVersion = 3; private static readonly Dictionary<string, GameObject?> prefabCache = new Dictionary<string, GameObject>(); private static Dictionary<string, GameObject>? loadedPrefabs; private static Light? handLight; private static GameObject? chargeFx; private static GameObject? warpFx; private static GameObject? readyFx; private static GameObject? humFx; private static readonly HashSet<string> visualScripts = new HashSet<string> { "ZNetView", "ZSyncTransform", "ZSFX", "TimedDestruction", "LightFlicker", "LightLod", "CamShaker", "EffectFade", "Billboard", "LineConnect", "RandomAnimation" }; private static readonly Dictionary<GameObject, bool> visualCache = new Dictionary<GameObject, bool>(); private static readonly HashSet<string> reportedNetworked = new HashSet<string>(); public static void Bind(ConfigFile config) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown chargeSound = config.Bind<string>("4 - North Wisp Effects", "Charge Sound", "", "Played once when you start charging the North Wisp. Empty by default."); chargeEffect = config.Bind<string>("4 - North Wisp Effects", "Charge Effect", "fx_JotunWitch_MagicBlast_Charge,fx_lightningstaff_charge", "Shown at your hand while charging."); warpEffect = config.Bind<string>("4 - North Wisp Effects", "Warp Effect", "vfx_Ashlands_HeatDistortion", "A heat-shimmer warp around your hand while charging. Clear this if it looks wrong."); warpScale = config.Bind<float>("4 - North Wisp Effects", "Warp Scale", 0.15f, new ConfigDescription("Size of the warp effect, relative to the prefab's own size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>())); readySound = config.Bind<string>("4 - North Wisp Effects", "Ready Sound", "sfx_demister_start", "Played once when the charge is full. Avoid potion sounds: players listen for those to know a potion worked."); readyEffect = config.Bind<string>("4 - North Wisp Effects", "Ready Effect", "", "Shown at your hand when the charge is full, until you let go. Empty by default (the hand glow brightens instead)."); humSound = config.Bind<string>("4 - North Wisp Effects", "Hum Sound", "sfx_glowworm_idle_loop", "The hum while a full charge is held."); throwSound = config.Bind<string>("4 - North Wisp Effects", "Throw Sound", "", "Played when you throw a wisp north (a tap). Empty by default."); castSound = config.Bind<string>("4 - North Wisp Effects", "Cast Sound", "", "Played when the charged wisp flies off. Empty by default."); burstEffect = config.Bind<string>("4 - North Wisp Effects", "Burst Effect", "fx_Lightning,vfx_lightningstaff_fire,vfx_HitSparks", "Shown where the charged wisp bursts, on top of its own flash. Only purely visual effects are used: one that carries game logic (damage, summons, chain lightning...) is skipped, and the log says why."); burstSound = config.Bind<string>("4 - North Wisp Effects", "Burst Sound", "sfx_staff_grenade_impact_small", "Played where the charged wisp bursts."); soundVolume = config.Bind<float>("4 - North Wisp Effects", "Sound Volume", 0.5f, new ConfigDescription("Volume of all the North Wisp's sounds, relative to the game's own volume for them.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); soundRange = config.Bind<float>("4 - North Wisp Effects", "Sound Range", 40f, new ConfigDescription("Its sounds fade out with distance and are silent past this many meters. Some vanilla sounds are made to play at full volume wherever they come from; this makes them all fade.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 150f), Array.Empty<object>())); effectsVersion = config.Bind<int>("9 - Internal", "Effects Version", 0, "Don't change: lets the mod update its effect defaults once in old configs."); if (effectsVersion.Value < 3) { ConfigEntry<string>[] array = new ConfigEntry<string>[7] { chargeSound, readySound, readyEffect, humSound, castSound, burstEffect, burstSound }; foreach (ConfigEntry<string> obj in array) { obj.Value = (string)((ConfigEntryBase)obj).DefaultValue; } effectsVersion.Value = 3; } } internal static Transform? Hand(Player player) { if (!((Object)(object)((Humanoid)player).m_visEquipment != (Object)null)) { return null; } return ((Humanoid)player).m_visEquipment.m_rightHand; } internal static Vector3 HandPoint(Player player) { //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_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_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_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_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) Transform val = Hand(player); Vector3 forward = ((Component)player).transform.forward; if (!((Object)(object)val != (Object)null)) { return ((Character)player).GetCenterPoint() + forward * 0.5f; } return val.position + forward * 0.25f; } public static void StartCharge(Player player) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0061: 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_00b1: Unknown result type (might be due to invalid IL or missing references) StopCharge(); Transform val = Hand(player); Vector3 val2 = HandPoint(player); GameObject val3 = new GameObject("SnakeSquadWispHandGlow"); val3.transform.position = val2; val3.transform.SetParent(((Object)(object)val != (Object)null) ? val : ((Component)player).transform, true); handLight = val3.AddComponent<Light>(); handLight.type = (LightType)2; handLight.color = glowColor; handLight.intensity = 0f; handLight.range = 1f; SpawnOneShot(chargeSound, val2); chargeFx = Spawn(chargeEffect, val2, val); warpFx = Spawn(warpEffect, val2, val, warpScale.Value); } public static void UpdateCharge(Player player, float progress, bool ready) { if (!((Object)(object)handLight == (Object)null)) { if (ready) { handLight.range = 4.5f; handLight.intensity = 3f + 0.8f * Mathf.Sin(Time.time * 7f); } else { handLight.range = 1f + 2f * progress; handLight.intensity = 0.3f + 1.5f * progress; } } } public static void Ready(Player player) { //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_0013: 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_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 at = HandPoint(player); Transform parent = Hand(player); SpawnOneShot(readySound, at); readyFx = Spawn(readyEffect, at, parent); humFx = Spawn(humSound, at, parent); } public static void StopCharge() { if ((Object)(object)handLight != (Object)null) { Object.Destroy((Object)(object)((Component)handLight).gameObject); } handLight = null; Remove(ref chargeFx); Remove(ref warpFx); Remove(ref readyFx); Remove(ref humFx); } public static void Throw(Vector3 at) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) SpawnOneShot(throwSound, at); } public static void Cast(Vector3 at) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) SpawnOneShot(castSound, at); } public static void Burst(Vector3 at, bool skipNetworked = false) { //IL_0005: 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) SpawnOneShot(burstEffect, at, skipNetworked); SpawnOneShot(burstSound, at, skipNetworked); } private static void SpawnOneShot(ConfigEntry<string> names, Vector3 at, bool skipNetworked = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GameObject val = Spawn(names, at, null, 1f, skipNetworked); if ((Object)(object)val != (Object)null) { val.AddComponent<RemoveAfter>().seconds = 6f; } } private static GameObject? Spawn(ConfigEntry<string> names, Vector3 at, Transform? parent, float scale = 1f, bool skipNetworked = false) { //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_00d9: 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_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) string[] array = names.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); GameObject val = ((text.Length > 0) ? FindPrefab(text) : null); if ((Object)(object)val == (Object)null || !IsPurelyVisual(val)) { continue; } bool num = (Object)(object)val.GetComponent<ZNetView>() != (Object)null; if (num && reportedNetworked.Add(((Object)val).name)) { logger.LogInfo((object)("North Wisp: effect '" + ((Object)val).name + "' is a network object, so players without the mod see it too.")); } if (num && skipNetworked) { return null; } GameObject val2 = Object.Instantiate<GameObject>(val, at, Quaternion.identity); if ((Object)(object)parent != (Object)null) { val2.transform.SetParent(parent, true); } MakeSoundsLocal(val2); if (!Mathf.Approximately(scale, 1f)) { Transform transform = val2.transform; transf