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 ValkyriesVision v0.7.1
ValkyriesVision.dll
Decompiled 10 hours agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("ValkyriesVision")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+2bbf86e877e27e1209e821faad47f1a13a786407")] [assembly: AssemblyProduct("ValkyriesVision")] [assembly: AssemblyTitle("ValkyriesVision")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 ValkyriesVision { public enum RevealMode { Biome, Rings } public enum RingScaling { EqualRadius, EqualArea } public enum OceanOption { Never, Eikthyr, Elder, Bonemass, Moder, Yagluth, Queen, Fader, Kall } public enum RevealStyle { Translucent, Clear } public enum ProgressionSource { Player, World } [BepInPlugin("com.drakexi.valkyriesvision", "Valkyrie's Vision", "0.7.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "com.drakexi.valkyriesvision"; public const string PluginName = "Valkyrie's Vision"; public const string PluginVersion = "0.7.1"; private const float WorldRadius = 10000f; private const float StartupDelay = 10f; private const float CheckInterval = 5f; private const int PixelsPerFrame = 50000; private const int BiomePixelsPerFrame = 20000; private static readonly string[] BossNames = new string[8] { "Eikthyr", "Elder", "Bonemass", "Moder", "Yagluth", "Queen", "Fader", "Kall" }; private static readonly string[] DefaultKeys = new string[8] { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader", "defeated_frozenking_p3" }; private static readonly Biome[] BossBiomes; private ConfigEntry<RevealMode> _mode; private ConfigEntry<RingScaling> _scaling; private ConfigEntry<OceanOption> _ocean; private ConfigEntry<string> _oceanEarlyKeys; private ConfigEntry<bool> _showMessages; private ConfigEntry<bool> _debugLogging; private ConfigEntry<float> _messageSeconds; private ConfigEntry<bool> _playStinger; private static FieldInfo _centerTextField; private static FieldInfo _stingerField; private readonly ConfigEntry<string>[] _bossKeys = new ConfigEntry<string>[8]; private static FieldInfo _fogField; private static Func<Minimap, int, int, bool> _explore; private static Func<Minimap, int, int, bool> _exploreOthers; private static FieldInfo _exploredField; private static FieldInfo _exploredOthersField; private static bool _useDirectMarking; private string _failedSignature; private ConfigEntry<RevealStyle> _style; private ConfigEntry<ProgressionSource> _source; private bool _inWorld; private bool _busy; private float _worldReadyTime; private float _nextCheck; private string _appliedSignature; private Biome[] _biomeCache; private Biome _appliedMask; private static readonly Biome[] MessageOrder; private void Awake() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Expected O, but got Unknown _mode = ((BaseUnityPlugin)this).Config.Bind<RevealMode>("General", "RevealMode", RevealMode.Biome, Desc("Biome: each boss reveals its own biome everywhere. Rings: each boss reveals a larger circle from the world center.")); _scaling = ((BaseUnityPlugin)this).Config.Bind<RingScaling>("General", "RingScaling", RingScaling.EqualArea, Desc("Rings mode only. EqualRadius: each boss adds 1/8 of the radius. EqualArea: each boss adds 1/8 of the map area.")); _ocean = ((BaseUnityPlugin)this).Config.Bind<OceanOption>("General", "OceanReveal", OceanOption.Queen, Desc("Biome mode only. Which boss kill reveals the ocean. Never = only the early keys below can reveal it.")); _style = ((BaseUnityPlugin)this).Config.Bind<RevealStyle>("General", "RevealStyle", RevealStyle.Translucent, Desc("Translucent: revealed areas look like map data shared by other players (a light haze). Clear: fully revealed, like your own exploration.")); _source = ((BaseUnityPlugin)this).Config.Bind<ProgressionSource>("General", "ProgressionSource", ProgressionSource.Player, Desc("Player: each player only gets reveals for bosses they were present for (like the player-based raids world modifier). World: reveals for every boss anyone on the world has defeated.")); _oceanEarlyKeys = ((BaseUnityPlugin)this).Config.Bind<string>("General", "OceanRevealEarlyKeys", "BossHildir1,BossHildir2,BossHildir3", Desc("Biome mode only. Comma-separated world keys that reveal the ocean early once ALL are set (default: Hildir's three mini-bosses). Blank = no early reveal.")); _showMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("Personal", "ShowMessages", true, new ConfigDescription("Show an on-screen message when new areas are revealed. Personal setting, not controlled by the server.", (AcceptableValueBase)null, Array.Empty<object>())); _messageSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Personal", "MessageSeconds", 5f, new ConfigDescription("How many seconds the reveal message stays fully visible before fading.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>())); _playStinger = ((BaseUnityPlugin)this).Config.Bind<bool>("Personal", "PlayStinger", true, new ConfigDescription("Play the game's 'new biome discovered' sound with the reveal message.", (AcceptableValueBase)null, Array.Empty<object>())); _debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Personal", "DebugLogging", false, new ConfigDescription("Write the list of bosses and keyed creatures to the BepInEx log on world load.", (AcceptableValueBase)null, Array.Empty<object>())); for (int i = 0; i < 8; i++) { _bossKeys[i] = ((BaseUnityPlugin)this).Config.Bind<string>("BossKeys", BossNames[i], DefaultKeys[i], Desc("World key set when " + BossNames[i] + " is defeated. Blank = ignored.")); } _fogField = typeof(Minimap).GetField("m_fogTexture", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method = typeof(Minimap).GetMethod("Explore", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(int), typeof(int) }, null); MethodInfo method2 = typeof(Minimap).GetMethod("ExploreOthers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(int), typeof(int) }, null); _exploredField = typeof(Minimap).GetField("m_explored", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _exploredOthersField = typeof(Minimap).GetField("m_exploredOthers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (_fogField == null || method == null || method2 == null || _exploredField == null || _exploredOthersField == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Minimap internals (m_fogTexture / m_explored / Explore / ExploreOthers). Mod disabled."); ((Behaviour)this).enabled = false; return; } _centerTextField = typeof(MessageHud).GetField("m_messageCenterText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _stingerField = typeof(MessageHud).GetField("m_biomeFoundStinger", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _explore = (Func<Minimap, int, int, bool>)Delegate.CreateDelegate(typeof(Func<Minimap, int, int, bool>), method); _exploreOthers = (Func<Minimap, int, int, bool>)Delegate.CreateDelegate(typeof(Func<Minimap, int, int, bool>), method2); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valkyrie's Vision 0.7.1 loaded."); } private static ConfigDescription Desc(string text) { //IL_000a: 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_0017: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new ConfigDescription(text, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } }); } private void Update() { if (!((Object)(object)Player.m_localPlayer != (Object)null) || !((Object)(object)Minimap.instance != (Object)null) || WorldGenerator.instance == null || !((Object)(object)ZoneSystem.instance != (Object)null)) { if (_inWorld) { ResetSession(); } return; } if (!_inWorld) { _inWorld = true; _worldReadyTime = Time.time; if (_debugLogging.Value) { DumpBosses(); } } if (!_busy && !(Time.time - _worldReadyTime < 10f) && !(Time.time < _nextCheck)) { _nextCheck = Time.time + 5f; bool[] array = new bool[8]; for (int i = 0; i < 8; i++) { string value = _bossKeys[i].Value; array[i] = !string.IsNullOrEmpty(value) && KeySet(value); } int num = (int)(_ocean.Value - 1); bool flag = (num >= 0 && array[num]) || AllKeysSet(_oceanEarlyKeys.Value); string text = string.Format("{0}|{1}|{2}|{3}|{4}|{5}", _mode.Value, _scaling.Value, _style.Value, _source.Value, flag, string.Join(",", Array.ConvertAll(array, (bool d) => (!d) ? "0" : "1"))); if (!(text == _appliedSignature) && !(text == _failedSignature)) { ((MonoBehaviour)this).StartCoroutine(RevealRoutine(text, array, flag)); } } } private static string BiomeLine(Biome biome) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0005: 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: Expected I4, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if ((int)biome <= 16) { switch (biome - 1) { default: if ((int)biome != 8) { if ((int)biome != 16) { break; } return "The Valkyrie's vision stretches across the Plains."; } return "The Valkyrie's vision pierces the canopy of the Black Forest."; case 0: return "The Valkyrie's vision sweeps across the Meadows."; case 1: return "The Valkyrie's vision cuts through the gloom of the Swamp."; case 3: return "The Valkyrie's vision soars over the peaks of the Mountains."; case 2: break; } } else if ((int)biome <= 64) { if ((int)biome == 32) { return "The Valkyrie's vision burns through the smoke of the Ashlands."; } if ((int)biome == 64) { return "The Valkyrie's vision falls upon the frozen Deep North."; } } else { if ((int)biome == 256) { return "The Valkyrie's vision glides across the open seas."; } if ((int)biome == 512) { return "The Valkyrie's vision parts the fog of the Mistlands."; } } return null; } private static string BiomeMessage(Biome newBiomes) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0011: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_002d: 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) if ((int)newBiomes == 768) { return "The Valkyrie's vision parts the fog of the Mistlands and glides across the open seas."; } int num = 0; Biome biome = (Biome)0; Biome[] messageOrder = MessageOrder; foreach (Biome val in messageOrder) { if ((newBiomes & val) != 0) { num++; biome = val; } } if (num != 1) { return "The Valkyrie's vision reveals the lands of your fallen foes."; } return BiomeLine(biome); } private void ShowCenterMessage(string text) { MessageHud instance = MessageHud.instance; if (string.IsNullOrEmpty(text) || (Object)(object)instance == (Object)null) { return; } if (_playStinger.Value && _stingerField != null) { object? value = _stingerField.GetValue(instance); Object val = (Object)((value is Object) ? value : null); if (val != (Object)null) { Object.Instantiate(val); } } if (!Hud.IsUserHidden()) { Graphic val2 = (Graphic)((_centerTextField != null) ? /*isinst with value type is only supported in some contexts*/: null); PropertyInfo propertyInfo = (((Object)(object)val2 != (Object)null) ? ((object)val2).GetType().GetProperty("text") : null); if ((Object)(object)val2 == (Object)null || propertyInfo == null) { instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true); } else { ((MonoBehaviour)this).StartCoroutine(HoldCenterText(val2, propertyInfo, text)); } } } private IEnumerator HoldCenterText(Graphic centerText, PropertyInfo textProp, string text) { textProp.SetValue(centerText, text, null); centerText.CrossFadeAlpha(1f, 0f, true); float end = Time.unscaledTime + _messageSeconds.Value; while (Time.unscaledTime < end) { yield return null; if ((Object)(object)centerText == (Object)null || (string)textProp.GetValue(centerText, null) != text) { yield break; } } centerText.CrossFadeAlpha(0f, 1.5f, true); } private bool KeySet(string key) { if (_source.Value != ProgressionSource.Player) { return ZoneSystem.instance.GetGlobalKey(key); } if ((Object)(object)Player.m_localPlayer != (Object)null) { return ((Humanoid)Player.m_localPlayer).HaveUniqueKey(key); } return false; } private bool AllKeysSet(string list) { if (string.IsNullOrWhiteSpace(list)) { return false; } bool result = false; string[] array = list.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length != 0) { result = true; if (!KeySet(text)) { return false; } } } return result; } private void ResetSession() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)this).StopAllCoroutines(); _inWorld = false; _busy = false; _appliedSignature = null; _failedSignature = null; _biomeCache = null; _appliedMask = (Biome)0; } private void DumpBosses() { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if ((Object)(object)prefab == (Object)null) { continue; } Character component = prefab.GetComponent<Character>(); if (!((Object)(object)component == (Object)null)) { if (component.m_boss) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Boss prefab: " + ((Object)prefab).name + " | defeat key: '" + component.m_defeatSetGlobalKey + "'")); } else if (!string.IsNullOrEmpty(component.m_defeatSetGlobalKey)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Keyed creature: " + ((Object)prefab).name + " | defeat key: '" + component.m_defeatSetGlobalKey + "'")); } } } } private IEnumerator BuildBiomeCache(Minimap map, int size, float pixel) { Biome[] cache = (Biome[])(object)new Biome[size * size]; int half = size / 2; float halfPixel = pixel / 2f; int work = 0; for (int y = 0; y < size; y++) { float wy = (float)(y - half) * pixel + halfPixel; for (int x = 0; x < size; x++) { float num = (float)(x - half) * pixel + halfPixel; cache[y * size + x] = (Biome)(int)WorldGenerator.instance.GetBiome(num, wy, 0.02f, false); int num2 = work + 1; work = num2; if (num2 >= 20000) { work = 0; yield return null; if ((Object)(object)Minimap.instance != (Object)(object)map) { yield break; } } } } _biomeCache = cache; } private IEnumerator RevealRoutine(string signature, bool[] defeated, bool ocean) { _busy = true; IEnumerator inner = RevealRoutineInner(signature, defeated, ocean); while (true) { object current; try { if (!inner.MoveNext()) { break; } current = inner.Current; goto IL_0095; } catch (Exception ex) { _failedSignature = signature; ((BaseUnityPlugin)this).Logger.LogError((object)("Reveal failed. This is usually a conflict with another mod that changes the map (map reveal or exploration mods). It will be retried when your progress or settings change. Details: " + ex)); } break; IL_0095: yield return current; } _busy = false; } private IEnumerator RevealRoutineInner(string signature, bool[] defeated, bool ocean) { Minimap map = Minimap.instance; bool translucent = _style.Value == RevealStyle.Translucent; Func<Minimap, int, int, bool> mark = (translucent ? _exploreOthers : _explore); BitArray exploredOthers = (BitArray)_exploredOthersField.GetValue(map); Texture2D fog = (Texture2D)_fogField.GetValue(map); BitArray explored = (BitArray)_exploredField.GetValue(map); int size = map.m_textureSize; float pixel = map.m_pixelSize; int half = size / 2; float halfPixel = pixel / 2f; int count = 0; for (int i = 0; i < defeated.Length; i++) { if (defeated[i]) { count++; } } RevealMode mode = _mode.Value; Biome mask = (Biome)0; float radiusSq = 0f; bool revealAll = count >= 8; if (mode == RevealMode.Biome) { for (int j = 0; j < 8; j++) { if (defeated[j]) { mask |= BossBiomes[j]; } } if (ocean) { mask = (Biome)(mask | 0x100); } if ((int)mask != 0 && _biomeCache == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Building biome map..."); IEnumerator build = BuildBiomeCache(map, size, pixel); while (build.MoveNext()) { yield return build.Current; } if (_biomeCache == null) { _busy = false; yield break; } } } else { float num = (float)count / 8f; float num2 = ((_scaling.Value == RingScaling.EqualRadius) ? (10000f * num) : (10000f * Mathf.Sqrt(num))); radiusSq = num2 * num2; } int revealed = 0; int work = 0; if ((mode == RevealMode.Biome) ? ((int)mask > 0) : (count > 0)) { for (int y = 0; y < size; y++) { float wy = (float)(y - half) * pixel + halfPixel; for (int x = 0; x < size; x++) { bool flag; if (mode == RevealMode.Biome) { flag = (_biomeCache[y * size + x] & mask) > 0; } else { float num3 = (float)(x - half) * pixel + halfPixel; flag = revealAll || num3 * num3 + wy * wy <= radiusSq; } if (flag && (!translucent || !explored[y * size + x]) && Mark(mark, map, x, y, translucent, explored, exploredOthers, fog, size)) { revealed++; } int i = work + 1; work = i; if (i >= 50000) { work = 0; yield return null; if ((Object)(object)Minimap.instance != (Object)(object)map) { _busy = false; yield break; } } } } } if (revealed > 0) { fog.Apply(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Reveal pass done: mode={mode}, bosses={count}, ocean={ocean}, newly revealed pixels={revealed}"); if (revealed > 0 && _showMessages.Value) { string text = ((mode == RevealMode.Biome) ? BiomeMessage((Biome)(mask & ~_appliedMask)) : (revealAll ? "The Valkyrie's vision now spans the entire world." : "The Valkyrie's vision reaches farther across the world.")); ShowCenterMessage(text); } if (mode == RevealMode.Biome) { _appliedMask = mask; } _appliedSignature = signature; } private bool Mark(Func<Minimap, int, int, bool> gameMark, Minimap map, int x, int y, bool translucent, BitArray explored, BitArray exploredOthers, Texture2D fog, int size) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (!_useDirectMarking) { try { return gameMark(map, x, y); } catch (Exception ex) { _useDirectMarking = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("The game's map-reveal function threw an error, most likely because another map mod hooks it. Switching to direct map marking so reveals still work. Details: " + ex)); } } BitArray bitArray = (translucent ? exploredOthers : explored); int index = y * size + x; if (bitArray[index]) { return false; } Color pixel = fog.GetPixel(x, y); if (translucent) { pixel.g = 0f; } else { pixel.r = 0f; } fog.SetPixel(x, y, pixel); bitArray[index] = true; return true; } static Plugin() { Biome[] array = new Biome[8]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); BossBiomes = (Biome[])(object)array; Biome[] array2 = new Biome[9]; RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); MessageOrder = (Biome[])(object)array2; } } }