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 LocationIntro v1.1.1
VKTR_LocationIntro.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Splatform; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace VKTR.LocationIntro; [BepInPlugin("vktr.locationintro", "VKTR_LocationIntro", "1.1.1")] public class Plugin : BaseUnityPlugin { public const string GUID = "vktr.locationintro"; internal static ConfigEntry<float> Scale; internal static ConfigEntry<float> OffsetX; internal static ConfigEntry<float> OffsetY; internal static ConfigEntry<int> HistorySize; internal static ConfigEntry<bool> HomeEnabled; internal static ConfigEntry<float> HomeRadius; internal static ConfigEntry<PinType> HomePinType; internal static ConfigEntry<float> ExtenderRadius; internal static ConfigEntry<float> SettlementRadius; internal static ConfigEntry<float> SquareRadius; internal static ConfigEntry<float> CurlyRadius; internal static ConfigEntry<bool> AltarEnabled; internal static ConfigEntry<bool> TraderEnabled; internal static ConfigEntry<float> PoiMargin; internal const float PoiFallbackRadius = 20f; internal const float TraderRadius = 20f; internal static Plugin Instance; internal static ManualLogSource Log; internal const float ArrivalDelay = 0.5f; internal static readonly TimedList Biomes = new TimedList(() => HistorySize.Value); private void Awake() { //IL_0238: Unknown result type (might be due to invalid IL or missing references) Scale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Scale", 0.75f, "Size of the intro compared to the vanilla biome intro."); OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "HorizontalOffset", 25.3f, "Horizontal offset of the intro center from the screen center, in % of screen width (positive = right)."); OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "VerticalOffset", 27.8f, "Vertical offset of the intro center from the screen center, in % of screen height (positive = up)."); HistorySize = ((BaseUnityPlugin)this).Config.Bind<int>("Biomes", "HistorySize", 2, "How many recently visited biomes are remembered. A remembered biome does not show its intro again."); HomeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Homes", "Enabled", true, "Show the pin name when you enter the area of a home pin."); HomeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Homes", "Radius", 30f, "Radius in meters of the area around a home pin."); HomePinType = ((BaseUnityPlugin)this).Config.Bind<PinType>("Homes", "PinType", (PinType)1, "Map pin icon treated as a home (Icon1 = house)."); SettlementRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Homes", "SettlementRadius", 15f, "Radius in meters of a settlement: a campfire pin named (Settlement name). Works like a home."); ExtenderRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Homes", "ExtenderRadius", 8f, "Radius in meters of a home extender: a dot pin named (Home name) that adds area to the home with that name."); SquareRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Pins", "SquareBracketRadius", 15f, "Radius in meters for pins named [Like This], any icon."); CurlyRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Pins", "CurlyBracketRadius", 30f, "Radius in meters for pins named {Like This}, any icon."); AltarEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Points of interest", "BossAltars", true, "Show the boss name when you reach a boss altar."); TraderEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Points of interest", "Traders", true, "Show the trader name when you reach a trader."); PoiMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Points of interest", "Margin", 5f, "Meters added to the size of the location (boss altars, Forge of Potential)."); if (Traverse.Create((object)((BaseUnityPlugin)this).Config).Property("OrphanedEntries", (object[])null).GetValue() is IDictionary { Count: >0 } dictionary) { dictionary.Clear(); ((BaseUnityPlugin)this).Config.Save(); } Instance = this; Log = ((BaseUnityPlugin)this).Logger; new Harmony("vktr.locationintro").PatchAll(); } } internal class TimedList { internal struct Entry { public string Name; public double Time; public int Day; public float Hour; } internal const float ExpireHours = 5f; private readonly List<Entry> m_entries = new List<Entry>(); private readonly Func<int> m_max; private static double HourSeconds => (double)(((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.m_dayLengthSec : 1800) / 24.0; internal TimedList(Func<int> max) { m_max = max; } internal void Clear() { m_entries.Clear(); } internal bool Mark(string name) { double now = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : ((double)Time.time)); double expire = 5.0 * HourSeconds; m_entries.RemoveAll((Entry e) => now - e.Time > expire); int num = m_entries.FindIndex((Entry e) => e.Name == name); bool flag = num >= 0; if (flag) { m_entries.RemoveAt(num); } double num2 = HourSeconds * 24.0; m_entries.Insert(0, new Entry { Name = name, Time = now, Day = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetDay(now) : 0), Hour = (float)(now % num2 / num2 * 24.0) }); int num3 = Mathf.Max(1, m_max()); while (m_entries.Count > num3) { m_entries.RemoveAt(m_entries.Count - 1); } return flag; } } internal static class State { internal static string CurrentBiome; internal static string PortalBiome; internal static string LastHome; internal static string LastPlace; internal static readonly TimedList Pois = new TimedList(() => 3); internal static bool PortalPending; internal static string PendingDeparture; internal static string PendingBiome; internal static bool Settling; internal static bool OnShip; internal static bool OceanSeen; internal static bool InOcean; internal static bool InHome => (Object)(object)InsideHome() != (Object)null; internal static bool Sailing { get { Player localPlayer = Player.m_localPlayer; if (OnShip && (Object)(object)localPlayer != (Object)null) { return !((Character)localPlayer).IsSwimming(); } return false; } } internal static bool PushPoi(string name) { return Pois.Mark(name); } internal static ZoneTrigger InsideHome() { ZoneTrigger zoneTrigger = ZoneTrigger.Inside(ZoneKind.Home); ZoneTrigger zoneTrigger2 = ZoneTrigger.Inside(ZoneKind.HomeExt); if ((Object)(object)zoneTrigger == (Object)null) { return zoneTrigger2; } if ((Object)(object)zoneTrigger2 == (Object)null) { return zoneTrigger; } if (!(zoneTrigger.EnteredAt >= zoneTrigger2.EnteredAt)) { return zoneTrigger2; } return zoneTrigger; } internal static void UpdateShip() { Player localPlayer = Player.m_localPlayer; bool flag = (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InNumShipVolumes > 0 && (Object)(object)Ship.GetLocalShip() != (Object)null; if (flag == OnShip) { return; } OnShip = flag; if (!flag) { OceanSeen = false; if (!PortalPending && !Settling) { EvaluateHere(ShipLandingBiome(localPlayer)); } } } private static string ShipLandingBiome(Player p) { if ((Object)(object)p == (Object)null || CurrentBiome == null || InOcean) { return null; } bool flag = Plugin.Biomes.Mark(CurrentBiome); if (!IsKnown(p, CurrentBiome) || flag) { return null; } return CurrentBiome; } internal static void EvaluateHere(string biome) { ZoneTrigger zoneTrigger = InsideHome(); ZoneTrigger zoneTrigger2 = zoneTrigger ?? ZoneTrigger.Inside(ZoneKind.Place) ?? ZoneTrigger.Inside(ZoneKind.Altar) ?? ZoneTrigger.Inside(ZoneKind.Poi) ?? ZoneTrigger.Inside(ZoneKind.Trader); if ((Object)(object)zoneTrigger2 != (Object)null) { ZoneTrigger.OnEnter(zoneTrigger2); } if (biome != null && (Object)(object)zoneTrigger == (Object)null) { IntroMessage.Show(biome); } } internal static void Reset() { Plugin.Biomes.Clear(); Pois.Clear(); CurrentBiome = (PortalBiome = (LastHome = (LastPlace = null))); PendingDeparture = (PendingBiome = null); PortalPending = (Settling = (OnShip = (OceanSeen = false))); } internal static bool IsKnown(Player p, string name) { if (Traverse.Create((object)p).Field("m_knownBiome").GetValue() is ICollection<string> collection) { return collection.Contains(name); } return false; } } [HarmonyPatch(typeof(Player), "AddKnownBiome")] internal static class AddKnownBiomePatch { private static void Prefix(Player __instance, BiomeSector __0, out bool __state) { __state = (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __0 != null && State.IsKnown(__instance, __0.GetName(false)); } private static void Postfix(Player __instance, BiomeSector __0, bool __state) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || __0 == null || State.PortalPending) { return; } string text = (State.CurrentBiome = __0.GetName(false)); State.InOcean = (int)__0.Biome == 256; bool flag = __state; if ((int)__0.Biome == 256) { Plugin.Biomes.Clear(); bool num = flag && !State.OceanSeen && !State.InHome; State.OceanSeen = true; if (num) { IntroMessage.Show(text, exclusive: false, ocean: true); } } else if (!State.Sailing) { bool flag2 = Plugin.Biomes.Mark(text); if (flag && !flag2 && !State.InHome) { IntroMessage.Show(text); } } } } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] internal static class PortalPatch { private static void Postfix(Player __0) { if (!((Object)(object)__0 == (Object)null) && !((Object)(object)__0 != (Object)(object)Player.m_localPlayer) && ((Character)__0).IsTeleporting()) { Plugin.Biomes.Clear(); State.LastHome = null; State.LastPlace = null; State.Pois.Clear(); State.PendingBiome = null; State.OceanSeen = false; State.PendingDeparture = State.CurrentBiome; State.PortalPending = true; } } } [HarmonyPatch(typeof(Player), "UpdateTeleport")] internal static class ArrivalPatch { private static void Prefix(Player __instance, out bool __state) { __state = ((Character)__instance).IsTeleporting(); } private static void Postfix(Player __instance, bool __state) { //IL_0038: 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_0079: Invalid comparison between Unknown and I4 if (__state && !((Character)__instance).IsTeleporting() && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && State.PortalPending) { State.PortalPending = false; WorldGenerator instance = WorldGenerator.instance; BiomeSector val = ((instance != null) ? instance.GetBiomeSector(((Component)__instance).transform.position, false) : null); string text = ((val != null) ? val.GetName(false) : null); string pendingDeparture = State.PendingDeparture; State.PendingDeparture = null; if (text == null) { State.PortalBiome = pendingDeparture; return; } State.CurrentBiome = text; State.InOcean = (int)val.Biome == 256; bool num = State.IsKnown(__instance, text) && text != State.PortalBiome; Plugin.Biomes.Mark(text); State.PortalBiome = pendingDeparture; State.PendingBiome = (num ? text : null); State.Settling = true; ((MonoBehaviour)Plugin.Instance).StartCoroutine(Settle()); } } private static IEnumerator Settle() { yield return (object)new WaitForSeconds(0.5f); State.Settling = false; string pendingBiome = State.PendingBiome; State.PendingBiome = null; State.EvaluateHere(pendingBiome); } } [HarmonyPatch(typeof(Player), "SetSleeping")] internal static class SleepPatch { private static void Prefix(Player __instance, out bool __state) { __state = __instance.IsSleeping(); } private static void Postfix(Player __instance, bool __state) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer || __state) && __instance.IsSleeping()) { Plugin.Biomes.Clear(); State.PortalBiome = null; State.LastPlace = null; State.OceanSeen = false; State.Pois.Clear(); } } } internal enum ZoneKind { Home, Altar, Place, Trader, Poi, HomeExt } internal class ZoneTrigger : MonoBehaviour { private static readonly List<ZoneTrigger> s_all = new List<ZoneTrigger>(); private static int s_layer = -1; internal ZoneKind Kind; internal float Radius; internal PinData Pin; internal OfferingBowl Bowl; internal Trader TraderRef; internal string PoiName; private readonly HashSet<Collider> m_inside = new HashSet<Collider>(); private float m_enteredAt; private static readonly Dictionary<string, string> BossPinNames = new Dictionary<string, string> { { "Eikthyrnir", "$enemy_eikthyr" }, { "GDKing", "$enemy_gdking" }, { "Bonemass", "$enemy_bonemass" }, { "Dragonqueen", "$enemy_dragon" }, { "GoblinKing", "$enemy_goblinking" }, { "Mistlands_DvergrBossEntrance1", "$enemy_seekerqueen" }, { "FaderLocation", "$enemy_fader_codename" }, { "DN_Bossroom", "$hud_pin_dnboss" } }; internal const string NamelessTrader = "vktr:nameless_trader"; internal float EnteredAt => m_enteredAt; internal string Label { get { //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (Kind == ZoneKind.Home) { return PinZones.HomeName(Pin); } float radius; if (Kind == ZoneKind.Place) { return PinZones.Parse(Pin?.m_name, out radius); } if (Kind == ZoneKind.HomeExt) { return PinZones.ExtenderLabel(Pin); } if (Kind == ZoneKind.Trader) { return TraderName(TraderRef); } if (Kind == ZoneKind.Poi) { return PoiName; } if ((Object)(object)Bowl == (Object)null) { return null; } Location location = Location.GetLocation(((Component)Bowl).transform.position, false); if ((Object)(object)location != (Object)null && BossPinNames.TryGetValue(Utils.GetPrefabName(((Component)location).gameObject), out var value)) { return value; } Character val = (((Object)(object)Bowl.m_bossPrefab != (Object)null) ? Bowl.m_bossPrefab.GetComponent<Character>() : null); if (!((Object)(object)val != (Object)null)) { return Bowl.m_name; } return val.m_name; } } internal bool IsInside => m_inside.Count > 0; private static string TraderName(Trader t) { if ((Object)(object)t == (Object)null) { return null; } if (!string.IsNullOrEmpty(t.m_name)) { return t.m_name; } return "vktr:nameless_trader"; } internal static ZoneTrigger Create(ZoneKind kind, Vector3 pos, float radius) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0060: 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_008e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LocationIntro_" + kind); val.layer = TriggerLayer(); CapsuleCollider val2 = val.AddComponent<CapsuleCollider>(); val2.direction = 1; val2.radius = radius; ((Collider)val2).isTrigger = true; if (kind == ZoneKind.Home || kind == ZoneKind.Place || kind == ZoneKind.HomeExt) { val2.height = 4000f; val.transform.position = new Vector3(pos.x, 0f, pos.z); } else { val2.height = 400f; val.transform.position = pos; } ZoneTrigger zoneTrigger = val.AddComponent<ZoneTrigger>(); zoneTrigger.Kind = kind; zoneTrigger.Radius = radius; return zoneTrigger; } private static int TriggerLayer() { if (s_layer >= 0) { return s_layer; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance != (Object)null) { foreach (GameObject prefab in instance.m_prefabs) { EffectArea val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponentInChildren<EffectArea>(true) : null); if ((Object)(object)val != (Object)null) { s_layer = ((Component)val).gameObject.layer; break; } } } if (s_layer >= 0) { return s_layer; } int num = LayerMask.NameToLayer("character_trigger"); if (num < 0) { return 0; } return num; } internal static ZoneTrigger Inside(ZoneKind kind) { ZoneTrigger zoneTrigger = null; foreach (ZoneTrigger item in s_all) { if (item.Kind == kind && item.IsInside && ((Object)(object)zoneTrigger == (Object)null || item.m_enteredAt > zoneTrigger.m_enteredAt)) { zoneTrigger = item; } } return zoneTrigger; } internal static void ResetAll() { foreach (ZoneTrigger item in s_all) { item.m_inside.Clear(); } } private static bool IsLocal(Collider c) { if ((Object)(object)c != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { return (Object)(object)((Component)c).GetComponentInParent<Player>() == (Object)(object)Player.m_localPlayer; } return false; } private void OnEnable() { s_all.Add(this); } private void OnDisable() { s_all.Remove(this); m_inside.Clear(); } private void OnTriggerEnter(Collider other) { if (IsLocal(other)) { bool num = m_inside.Count == 0; m_inside.Add(other); if (num) { m_enteredAt = Time.time; OnEnter(this); } } } private void OnTriggerExit(Collider other) { if (IsLocal(other)) { m_inside.Remove(other); } } internal static void OnEnter(ZoneTrigger z) { if (State.PortalPending || State.Settling || State.Sailing) { return; } string label = z.Label; if (string.IsNullOrEmpty(label)) { return; } bool inHome = State.InHome; switch (z.Kind) { case ZoneKind.Home: case ZoneKind.HomeExt: if (Plugin.HomeEnabled.Value && !(label == State.LastHome)) { State.LastHome = label; IntroMessage.Show(label, exclusive: true); } return; case ZoneKind.Place: if (label == State.LastPlace) { return; } State.LastPlace = label; break; case ZoneKind.Trader: if (!Plugin.TraderEnabled.Value || State.PushPoi(label)) { return; } break; case ZoneKind.Altar: if (!Plugin.AltarEnabled.Value || State.PushPoi(label)) { return; } break; default: if (State.PushPoi(label)) { return; } break; } if (!inHome) { IntroMessage.Show(label); } } } internal static class PinZones { private class Candidate { public PinData Pin; public ZoneKind Kind; public float Radius; public int Serial; public int Rank; } internal static readonly Dictionary<PinData, ZoneTrigger> Zones = new Dictionary<PinData, ZoneTrigger>(); internal static readonly HashSet<PinData> ActiveExtenders = new HashSet<PinData>(); private static readonly Dictionary<string, string> s_homeDisplay = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<PinData, Candidate> s_candidates = new Dictionary<PinData, Candidate>(); private static int s_serial; internal static int Bulk; private static long s_hostPlayerId; internal static string Parse(string raw, out float radius) { radius = 0f; if (string.IsNullOrEmpty(raw)) { return raw; } string text = raw.Trim(); if (text.Length >= 2) { if (text[0] == '[' && text[text.Length - 1] == ']') { radius = Plugin.SquareRadius.Value; return text.Substring(1, text.Length - 2).Trim(); } if (text[0] == '{' && text[text.Length - 1] == '}') { radius = Plugin.CurlyRadius.Value; return text.Substring(1, text.Length - 2).Trim(); } } return text; } private static string RoundName(PinData pin, PinType type) { //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) if (pin == null || pin.m_type != type || string.IsNullOrEmpty(pin.m_name)) { return null; } string text = pin.m_name.Trim(); if (text.Length < 3 || text[0] != '(' || text[text.Length - 1] != ')') { return null; } string text2 = text.Substring(1, text.Length - 2).Trim(); if (text2.Length <= 0) { return null; } return text2; } internal static string ExtenderParent(PinData pin) { return RoundName(pin, (PinType)3); } internal static string SettlementName(PinData pin) { return RoundName(pin, (PinType)0); } internal static string HomeName(PinData pin) { float radius; return SettlementName(pin) ?? Parse(pin?.m_name, out radius); } internal static string ExtenderLabel(PinData pin) { string text = ExtenderParent(pin); if (text == null || !s_homeDisplay.TryGetValue(text, out var value)) { return text; } return value; } private static bool Desired(PinData pin, out ZoneKind kind, out float radius) { //IL_0050: 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) if (ExtenderParent(pin) != null) { kind = ZoneKind.HomeExt; radius = Plugin.ExtenderRadius.Value; return radius > 0f; } if (SettlementName(pin) != null) { kind = ZoneKind.Home; radius = Plugin.SettlementRadius.Value; return radius > 0f; } Parse(pin.m_name, out radius); bool flag = pin.m_type == Plugin.HomePinType.Value; kind = ((!flag) ? ZoneKind.Place : ZoneKind.Home); if (flag && radius <= 0f) { radius = Plugin.HomeRadius.Value; } return radius > 0f; } internal static void Ensure(PinData pin) { if (pin == null) { return; } if (!Desired(pin, out var kind, out var radius)) { s_candidates.Remove(pin); return; } if (!s_candidates.TryGetValue(pin, out var value)) { Dictionary<PinData, Candidate> dictionary = s_candidates; Candidate obj = new Candidate { Pin = pin, Serial = ++s_serial }; value = obj; dictionary[pin] = obj; } value.Kind = kind; value.Radius = radius; } internal static void Remove(PinData pin) { if (pin != null) { s_candidates.Remove(pin); DestroyZone(pin); } } internal static void Clear() { ActiveExtenders.Clear(); foreach (ZoneTrigger value in Zones.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } Zones.Clear(); s_candidates.Clear(); } private static void DestroyZone(PinData pin) { if (Zones.TryGetValue(pin, out var value)) { Zones.Remove(pin); if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } } internal static void Resolve() { //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) if (Bulk > 0 || (Object)(object)Minimap.instance == (Object)null) { return; } HashSet<PinData> hashSet = ((Traverse.Create((object)Minimap.instance).Field("m_pins").GetValue() is IEnumerable<PinData> collection) ? new HashSet<PinData>(collection) : new HashSet<PinData>()); List<PinData> list = new List<PinData>(); foreach (PinData key in s_candidates.Keys) { if (!hashSet.Contains(key)) { list.Add(key); } } foreach (PinData key2 in Zones.Keys) { if (!s_candidates.ContainsKey(key2)) { list.Add(key2); } } foreach (PinData item in list) { Remove(item); } HashSet<string> hashSet2 = new HashSet<string>(StringComparer.OrdinalIgnoreCase); s_homeDisplay.Clear(); foreach (Candidate value2 in s_candidates.Values) { if (value2.Kind != ZoneKind.Home) { continue; } string text = HomeName(value2.Pin); if (!string.IsNullOrEmpty(text)) { hashSet2.Add(text); if (!s_homeDisplay.ContainsKey(text)) { s_homeDisplay[text] = text; } } } bool flag = false; HashSet<PinData> hashSet3 = new HashSet<PinData>(); foreach (Candidate value3 in s_candidates.Values) { if (value3.Kind == ZoneKind.HomeExt && hashSet2.Contains(ExtenderParent(value3.Pin))) { hashSet3.Add(value3.Pin); } } if (!hashSet3.SetEquals(ActiveExtenders)) { ActiveExtenders.Clear(); ActiveExtenders.UnionWith(hashSet3); flag = true; } PlatformUserID author; long hostId = HostIdentity(out author); List<Candidate> list2 = new List<Candidate>(s_candidates.Values); foreach (Candidate item2 in list2) { item2.Rank = Rank(item2.Pin, hostId, author); } list2.Sort((Candidate a, Candidate b) => (a.Rank == b.Rank) ? a.Serial.CompareTo(b.Serial) : b.Rank.CompareTo(a.Rank)); List<Candidate> list3 = new List<Candidate>(); foreach (Candidate item3 in list2) { if (item3.Kind == ZoneKind.HomeExt && !ActiveExtenders.Contains(item3.Pin)) { DestroyZone(item3.Pin); continue; } bool flag2 = false; foreach (Candidate item4 in list3) { if (item4.Kind == item3.Kind) { float num = item4.Pin.m_pos.x - item3.Pin.m_pos.x; float num2 = item4.Pin.m_pos.z - item3.Pin.m_pos.z; float num3 = Mathf.Max(item4.Radius, item3.Radius); if (num * num + num2 * num2 < num3 * num3) { flag2 = true; break; } } } Zones.TryGetValue(item3.Pin, out var value); if (flag2) { if ((Object)(object)value != (Object)null || Zones.ContainsKey(item3.Pin)) { DestroyZone(item3.Pin); } continue; } list3.Add(item3); if (!((Object)(object)value != (Object)null) || value.Kind != item3.Kind || !Mathf.Approximately(value.Radius, item3.Radius)) { DestroyZone(item3.Pin); value = ZoneTrigger.Create(item3.Kind, item3.Pin.m_pos, item3.Radius); value.Pin = item3.Pin; Zones[item3.Pin] = value; } } if (flag) { Traverse.Create((object)Minimap.instance).Field("m_pinUpdateRequired").SetValue((object)true); } } private static int Rank(PinData pin, long hostId, PlatformUserID hostAuthor) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //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) bool flag = pin.m_ownerID == 0; ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || !((!instance.IsServer()) ? (!flag && ((hostId != 0L && pin.m_ownerID == hostId) || (hostAuthor != PlatformUserID.None && pin.m_author == hostAuthor))) : (flag && !instance.IsDedicated()))) { return flag ? 1 : 0; } return 2; } private static long HostIdentity(out PlatformUserID author) { //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_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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) author = PlatformUserID.None; ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null || instance.IsServer()) { return 0L; } ZNetPeer serverPeer = instance.GetServerPeer(); if (serverPeer == null) { return s_hostPlayerId; } foreach (PlayerInfo player in instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (((ZDOID)(ref characterID)).UserID != serverPeer.m_uid) { continue; } author = player.m_userInfo.m_id; ZDOMan instance2 = ZDOMan.instance; ZDO val = ((instance2 != null) ? instance2.GetZDO(player.m_characterID) : null); if (val != null) { long num = val.GetLong(ZDOVars.s_playerID, 0L); if (num != 0L) { s_hostPlayerId = num; } } break; } return s_hostPlayerId; } internal static void EnsureAll() { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || !(Traverse.Create((object)instance).Field("m_pins").GetValue() is IEnumerable<PinData> enumerable)) { return; } foreach (PinData item in enumerable) { Ensure(item); } } } [HarmonyPatch(typeof(Minimap), "UpdatePins")] public static class PinVisibilityPatch { private static readonly FieldRef<Minimap, bool[]> s_visible = AccessTools.FieldRefAccess<Minimap, bool[]>("m_visibleIconTypes"); public static bool IsVisible(Minimap map, PinData pin) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) bool flag = s_visible.Invoke(map)[pin.m_type]; if (!PinZones.ActiveExtenders.Contains(pin)) { return flag; } return !flag; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { FieldInfo fieldInfo = AccessTools.Field(typeof(Minimap), "m_visibleIconTypes"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(PinData), "m_type"); MethodInfo operand = AccessTools.Method(typeof(PinVisibilityPatch), "IsVisible", (Type[])null, (Type[])null); List<CodeInstruction> list = new List<CodeInstruction>(instructions); bool flag = false; for (int i = 0; i + 3 < list.Count; i++) { if (flag) { break; } if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && CodeInstructionExtensions.LoadsField(list[i + 2], fieldInfo2, false) && list[i + 3].opcode == OpCodes.Ldelem_U1) { list[i].opcode = OpCodes.Nop; list[i].operand = null; list[i + 2].opcode = OpCodes.Nop; list[i + 2].operand = null; list[i + 3].opcode = OpCodes.Call; list[i + 3].operand = operand; flag = true; } } if (!flag) { Plugin.Log.LogWarning((object)"UpdatePins changed: home extenders stay visible as normal dots."); } return list; } } [HarmonyPatch(typeof(Minimap), "SetMapData")] internal static class SetMapDataPatch { private static void Prefix() { PinZones.Bulk++; } private static void Finalizer() { PinZones.Bulk--; PinZones.Resolve(); } } [HarmonyPatch(typeof(Minimap), "AddSharedMapData")] internal static class SharedMapDataPatch { private static void Prefix() { PinZones.Bulk++; } private static void Finalizer() { PinZones.Bulk--; PinZones.Resolve(); } } [HarmonyPatch(typeof(Minimap), "AddPin")] internal static class AddPinPatch { private static void Postfix(PinData __result) { PinZones.Ensure(__result); PinZones.Resolve(); } } [HarmonyPatch(typeof(Minimap), "OnPinTextEntered")] internal static class RenamePinPatch { private static void Postfix() { PinZones.EnsureAll(); PinZones.Resolve(); } } [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })] internal static class RemovePinPatch { private static void Prefix(PinData __0) { PinZones.Remove(__0); } private static void Postfix() { PinZones.Resolve(); } } [HarmonyPatch(typeof(Minimap), "ClearPins")] internal static class ClearPinsPatch { private static void Prefix() { PinZones.Clear(); } } internal static class PoiZones { private class Entry { public GameObject Owner; public ZoneTrigger Zone; public float Override; public Action<ZoneTrigger> Setup; public ZoneKind Kind; } private static readonly List<Entry> s_pending = new List<Entry>(); internal static void Register(GameObject owner, ZoneKind kind, float overrideRadius, Action<ZoneTrigger> setup) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) Entry entry = new Entry { Owner = owner, Kind = kind, Override = overrideRadius, Setup = setup }; if (kind == ZoneKind.Trader) { Build(entry, null); return; } Location location = Location.GetLocation(owner.transform.position, false); Build(entry, location); if ((Object)(object)location == (Object)null) { s_pending.Add(entry); } } internal static void OnLocation(Location loc) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) for (int num = s_pending.Count - 1; num >= 0; num--) { Entry entry = s_pending[num]; if ((Object)(object)entry.Owner == (Object)null) { s_pending.RemoveAt(num); } else if (loc.IsInside(entry.Owner.transform.position, 0f, false)) { s_pending.RemoveAt(num); Build(entry, loc); } } } private static void Build(Entry e, Location loc) { //IL_003f: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)e.Zone != (Object)null) { Object.Destroy((Object)(object)((Component)e.Zone).gameObject); } Vector3 pos = (((Object)(object)loc != (Object)null) ? ((Component)loc).transform.position : e.Owner.transform.position); float radius = ((e.Override > 0f) ? e.Override : (((Object)(object)loc != (Object)null) ? (loc.m_exteriorRadius + Plugin.PoiMargin.Value) : 20f)); e.Zone = ZoneTrigger.Create(e.Kind, pos, radius); e.Setup(e.Zone); ZoneLink zoneLink = e.Owner.GetComponent<ZoneLink>(); if ((Object)(object)zoneLink == (Object)null) { zoneLink = e.Owner.AddComponent<ZoneLink>(); } zoneLink.Zone = e.Zone; } } internal class ZoneLink : MonoBehaviour { internal ZoneTrigger Zone; private void OnDestroy() { if ((Object)(object)Zone != (Object)null) { Object.Destroy((Object)(object)((Component)Zone).gameObject); } } } [HarmonyPatch(typeof(Location), "Awake")] internal static class LocationPatch { private static void Postfix(Location __instance) { PoiZones.OnLocation(__instance); if (Utils.GetPrefabName(((Component)__instance).gameObject) == "StartTemple") { PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Poi, 12f, delegate(ZoneTrigger z) { z.PoiName = "vktr:sacrificial_stones"; }); } } } [HarmonyPatch(typeof(OfferingBowl), "Start")] internal static class AltarPatch { private static float OverrideFor(string boss) { if (!(boss == "Fader")) { if (boss == "SeekerQueen") { return -1f; } return 0f; } return 30f; } private static void Postfix(OfferingBowl __instance) { if ((Object)(object)__instance.m_bossPrefab == (Object)null) { return; } float num = OverrideFor(((Object)__instance.m_bossPrefab).name); if (!(num < 0f)) { OfferingBowl bowl = __instance; PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Altar, num, delegate(ZoneTrigger z) { z.Bowl = bowl; }); } } } [HarmonyPatch(typeof(Ship), "OnTriggerEnter")] internal static class ShipEnterPatch { private static void Postfix() { State.UpdateShip(); } } [HarmonyPatch(typeof(Ship), "OnTriggerExit")] internal static class ShipExitPatch { private static void Postfix() { State.UpdateShip(); } } [HarmonyPatch(typeof(Ship), "OnDestroyed")] internal static class ShipDestroyedPatch { private static void Postfix() { State.UpdateShip(); } } [HarmonyPatch(typeof(Game), "Start")] internal static class GameStartPatch { private static void Postfix() { State.Reset(); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class SpawnPatch { private static void Postfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { ZoneTrigger.ResetAll(); State.OnShip = false; PinZones.Resolve(); } } } [HarmonyPatch(typeof(Piece), "Awake")] internal static class PoiPatch { private static readonly HashSet<string> Names = new HashSet<string> { "$piece_upgradestation" }; private static void Postfix(Piece __instance) { if (!ZNetView.m_forceDisableInit && __instance.m_name != null && Names.Contains(__instance.m_name) && !((Object)(object)((Component)__instance).GetComponent<ZoneLink>() != (Object)null)) { string name = __instance.m_name; PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Poi, 0f, delegate(ZoneTrigger z) { z.PoiName = name; }); } } } [HarmonyPatch(typeof(Trader), "Start")] internal static class TraderPatch { private static void Postfix(Trader __instance) { Trader t = __instance; PoiZones.Register(((Component)__instance).gameObject, ZoneKind.Trader, 20f, delegate(ZoneTrigger z) { z.TraderRef = t; }); } } internal static class CustomText { internal const string SacrificialStones = "vktr:sacrificial_stones"; private static readonly Dictionary<string, string> s_sacrificialStones = new Dictionary<string, string> { { "English", "Sacrificial Stones" }, { "Swedish", "Offerstoderna" }, { "French", "Pierres sacrificielles" }, { "Italian", "Pietre Sacrificali" }, { "German", "Opfersteine" }, { "Spanish", "Piedras de Sacrificio" }, { "Russian", "Жертвенные камни" }, { "Romanian", "Pietrele de Sacrificiu" }, { "Bulgarian", "Жертвените Камъни" }, { "Finnish", "Uhrikivet" }, { "Danish", "Offerstenene" }, { "Norwegian", "Offersteinene" }, { "Icelandic", "Fórnarsteinarnir" }, { "Turkish", "Kurban Taşları" }, { "Lithuanian", "Aukojimo akmenys" }, { "Czech", "Obětní kameny" }, { "Hungarian", "Áldozati kövek" }, { "Slovak", "Obetné kamene" }, { "Polish", "Kamienie Ofiarne" }, { "Dutch", "Offerstenen" }, { "Portuguese_European", "Pedras de Sacrifício" }, { "Portuguese_Brazilian", "Pedras de Sacrifício" }, { "Chinese", "献祭石" }, { "Chinese_Trad", "獻祭石碑" }, { "Japanese", "犠牲の石" }, { "Korean", "희생의 돌" }, { "Thai", "แท\u0e48นบ\u0e39ชา" }, { "Georgian", "მსხვერპლშეწირვის ქვები" }, { "Ukrainian", "Священні камені" }, { "Latvian", "Upurakmeņi" } }; internal static string Get(string key) { if (key != "vktr:sacrificial_stones") { return null; } string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"); if (text == null || !s_sacrificialStones.TryGetValue(text, out var value)) { return s_sacrificialStones["English"]; } return value; } } internal class IntroMessage : MonoBehaviour { private const float FadeTime = 0.25f; private static IntroMessage s_current; private static readonly Queue<string> s_queue = new Queue<string>(); private Animator m_animator; private CanvasGroup m_group; private string m_text; private bool m_fading; internal static void Show(string text, bool exclusive = false, bool ocean = false) { if (!string.IsNullOrEmpty(text) && (!State.Sailing || ocean)) { if (exclusive) { s_queue.Clear(); } else if (State.InHome || s_queue.Contains(text)) { return; } if ((Object)(object)s_current == (Object)null) { Spawn(text); } else if (s_current.m_fading || !(s_current.m_text == text)) { s_queue.Enqueue(text); s_current.m_fading = true; } } } private static void Next() { while (s_queue.Count > 0 && !Spawn(s_queue.Dequeue())) { } } private static bool Spawn(string text) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0063: 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_0079: 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) MessageHud instance = MessageHud.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_biomeFoundPrefab == (Object)null) { return false; } Transform transform = ((Component)instance).transform; RectTransform hudRect = (RectTransform)(object)((transform is RectTransform) ? transform : null); GameObject val = new GameObject("LocationIntro", new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(((Component)instance).transform, false); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; ((Transform)val2).SetAsLastSibling(); GameObject val3 = Object.Instantiate<GameObject>(instance.m_biomeFoundPrefab, (Transform)(object)val2); Transform val4 = Utils.FindChild(val3.transform, "Title", (IterativeSearchType)0); TMP_Text val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<TMP_Text>() : null); if ((Object)(object)val5 != (Object)null) { val5.text = ((text == "vktr:nameless_trader") ? "" : (CustomText.Get(text) ?? Localization.instance.Localize(text))); } AudioSource[] componentsInChildren = val3.GetComponentsInChildren<AudioSource>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } IntroMessage introMessage = val.AddComponent<IntroMessage>(); introMessage.m_text = text; introMessage.m_group = val.AddComponent<CanvasGroup>(); introMessage.m_group.interactable = false; introMessage.m_group.blocksRaycasts = false; introMessage.m_animator = val3.GetComponentInChildren<Animator>(); if ((Object)(object)introMessage.m_animator != (Object)null) { introMessage.m_animator.Update(0f); } s_current = introMessage; Place(val2, hudRect, val3); return true; } private static void Place(RectTransform rt, RectTransform hudRect, GameObject inst) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0162: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019b: 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_01a2: Unknown result type (might be due to invalid IL or missing references) Canvas componentInParent = ((Component)hudRect).GetComponentInParent<Canvas>(); Camera val = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(float.MaxValue, float.MaxValue); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(float.MinValue, float.MinValue); Vector3[] array = (Vector3[])(object)new Vector3[4]; bool flag = false; Graphic[] componentsInChildren = inst.GetComponentsInChildren<Graphic>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].rectTransform.GetWorldCorners(array); Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val, array[0]); Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val, array[2]); if (!(Mathf.Abs(val5.x - val4.x) > (float)Screen.width * 0.95f)) { val2 = Vector2.Min(val2, Vector2.Min(val4, val5)); val3 = Vector2.Max(val3, Vector2.Max(val4, val5)); flag = true; } } if (flag) { float value = Plugin.Scale.Value; Vector2 val6 = (val2 + val3) * 0.5f; Vector2 val7 = default(Vector2); ((Vector2)(ref val7))..ctor((float)Screen.width * (0.5f + Plugin.OffsetX.Value / 100f), (float)Screen.height * (0.5f + Plugin.OffsetY.Value / 100f)); Vector3 val8 = default(Vector3); RectTransformUtility.ScreenPointToWorldPointInRectangle(hudRect, val6, val, ref val8); Vector3 val9 = default(Vector3); RectTransformUtility.ScreenPointToWorldPointInRectangle(hudRect, val7, val, ref val9); Vector3 position = ((Transform)rt).position; ((Transform)rt).localScale = new Vector3(value, value, 1f); Vector3 val10 = position + value * (val8 - position); ((Transform)rt).position = position + (val9 - val10); } } private void Update() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) int num; if (!((Object)(object)m_animator == (Object)null)) { AnimatorStateInfo currentAnimatorStateInfo = m_animator.GetCurrentAnimatorStateInfo(0); num = (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("done") ? 1 : 0); } else { num = 1; } bool flag = (byte)num != 0; if (m_fading) { CanvasGroup obj = m_group; obj.alpha -= Time.unscaledDeltaTime / 0.25f; flag |= m_group.alpha <= 0f; } if (flag) { Finish(); } } private void Finish() { if (!((Object)(object)s_current != (Object)(object)this)) { s_current = null; Object.Destroy((Object)(object)((Component)this).gameObject); Next(); } } private void OnDestroy() { if ((Object)(object)s_current == (Object)(object)this) { s_current = null; s_queue.Clear(); } } }