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 OdinsBeacon v0.1.0
OdinsBeacon.dll
Decompiled 19 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OdinsBeacon")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ce1fe04c1e0d3a2923c660dc5676ceccf87de5a5")] [assembly: AssemblyProduct("OdinsBeacon")] [assembly: AssemblyTitle("OdinsBeacon")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace OdinsMissingPatch { [BepInPlugin("rauschekuh.odinsbeacon", "Odin's Beacon", "0.1.0")] public class OdinsBeaconPlugin : BaseUnityPlugin { public const string GUID = "rauschekuh.odinsbeacon"; public const string NAME = "Odin's Beacon"; public const string VERSION = "0.1.0"; private static readonly Tweak[] Tweaks = new Tweak[1] { PlayerMarks.Instance }; private void Awake() { TweakHost.Start((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, "rauschekuh.odinsbeacon", Tweaks); } } internal sealed class PlayerMarks : Tweak { private sealed class Mark { internal Image Fill; internal Image Far; internal Image Rings; internal readonly List<Image> Sparks = new List<Image>(); } [HarmonyPatch(typeof(EnemyHud), "LateUpdate")] private static class DrawMarks { private static void Postfix(EnemyHud __instance) { Instance.Draw(__instance); } } internal static readonly PlayerMarks Instance = new PlayerMarks(); private ConfigEntry<float> hideWithin; private ConfigEntry<float> showFrom; private ConfigEntry<float> farFrom; private ConfigEntry<float> hideBeyond; private ConfigEntry<float> size; private ConfigEntry<Color> centreColor; private ConfigEntry<Color> edgeColor; private ConfigEntry<Color> farEdgeColor; private ConfigEntry<bool> offScreen; private ConfigEntry<bool> sparks; private static int blockMask; private const float SelfHit = 0.75f; private readonly List<Vector3> targets = new List<Vector3>(); private readonly List<PlayerInfo> publicPlayers = new List<PlayerInfo>(); private readonly HashSet<ZDOID> loaded = new HashSet<ZDOID>(); private readonly List<Mark> dots = new List<Mark>(); private Sprite ringSprite; private Sprite nearSprite; private Sprite farSprite; private Sprite sparkSprite; private Color[] spriteColors; private static int sparkCount = 5; private static float sparkRate = 0.7f; private static float sparkTravel = 0.9f; private static float sparkSize = 0.22f; private const float OuterRadius = 0.97f; private const float DiscOverlap = 0.04f; private static float outlineWidth = 0.21f; private static float ringWidth = 0.07f; private static float gradientCurve = 1f; private static float farScale = 0.75f; private static Color ringColor = new Color(0.882f, 0.655f, 0.4f, 1f); private static Color outlineColor = new Color(0.19f, 0.13f, 0.08f, 1f); private static bool shapeChanged; private static float ruggedness = 0.2f; private static int bumps = 5; internal override string Section => "Player Marks"; protected override string Summary => "A small round mark shows where every other player is, once they are out of sight or far enough away."; private PlayerMarks() { } protected override void Bind(ConfigFile config) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00df: 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) //IL_0149: Unknown result type (might be due to invalid IL or missing references) hideWithin = config.Bind<float>(Section, "HideWithin", 10f, "Metres within which a player never gets a mark, seen or not."); showFrom = config.Bind<float>(Section, "ShowFrom", 50f, "Metres from which a player always gets a mark. Between HideWithin and this, only a player hidden behind terrain or a building gets one."); farFrom = config.Bind<float>(Section, "FarFrom", 400f, "Metres at which the mark has turned FarEdgeColor and shrunk to its smallest size."); hideBeyond = config.Bind<float>(Section, "HideBeyond", 0f, "Metres beyond which a player gets no mark at all. 0 shows every player, however far."); size = config.Bind<float>(Section, "MarkSize", 16f, new ConfigDescription("Diameter of the whole mark, rings included, in HUD units (about pixels at 1080p). Everything in it scales together.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 64f), Array.Empty<object>())); centreColor = config.Bind<Color>(Section, "CentreColor", new Color(0.667f, 0.502f, 0.318f, 1f), "Colour at the centre of the mark, fading out to EdgeColor."); edgeColor = config.Bind<Color>(Section, "EdgeColor", new Color(1f, 0.557f, 0f, 1f), "Colour at the edge of the mark, inside the rings. For a far player it moves to the centre."); farEdgeColor = config.Bind<Color>(Section, "FarEdgeColor", new Color(0.553f, 0.776f, 0.894f, 1f), "Colour at the edge of the mark for a player at FarFrom and beyond."); offScreen = config.Bind<bool>(Section, "ShowOffScreen", true, "Keep the mark of a player off screen or behind you on the screen's edge, in their direction."); sparks = config.Bind<bool>(Section, "Sparks", true, "Little sparks drift outward from every mark, in its edge colour."); } private void CollectTargets(Player local) { //IL_0044: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) targets.Clear(); loaded.Clear(); foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && !((Object)(object)allPlayer == (Object)(object)local)) { loaded.Add(((Character)allPlayer).GetZDOID()); if (!((Character)allPlayer).IsDead()) { targets.Add(((Character)allPlayer).GetHeadPoint() + Vector3.up * 0.6f); } } } if (!((Object)(object)ZNet.instance != (Object)null)) { return; } publicPlayers.Clear(); ZNet.instance.GetOtherPublicPlayers(publicPlayers); foreach (PlayerInfo publicPlayer in publicPlayers) { if (!loaded.Contains(publicPlayer.m_characterID)) { targets.Add(publicPlayer.m_position + Vector3.up * 2.4f); } } } private void Draw(EnemyHud hud) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) int num = 0; UpdateSprites(); Player localPlayer = Player.m_localPlayer; Camera mainCamera = Utils.GetMainCamera(); if (base.On && !((Object)(object)localPlayer == (Object)null) && !((Object)(object)mainCamera == (Object)null) && !((Object)(object)hud.m_hudRoot == (Object)null) && !Minimap.IsOpen() && !InventoryGui.IsVisible()) { CollectTargets(localPlayer); Vector3 position = ((Component)localPlayer).transform.position; foreach (Vector3 target in targets) { if (Place(hud, mainCamera, position, target, num)) { num++; } } } for (int i = num; i < dots.Count; i++) { if (dots[i] != null && (Object)(object)dots[i].Fill != (Object)null) { ((Component)dots[i].Fill).gameObject.SetActive(false); } } } private bool Place(EnemyHud hud, Camera camera, Vector3 from, Vector3 target, int index) { //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_005e: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_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_00de: 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_004d: 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_0100: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0220: 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_0224: 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_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0262: 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_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) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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) float num = Vector3.Distance(from, target); if (num < hideWithin.Value || (hideBeyond.Value > 0f && num > hideBeyond.Value)) { return false; } if (num < showFrom.Value && !Blocked(((Component)camera).transform.position, target)) { return false; } Vector3 val = Utils.WorldToScreenPointScaled(camera, target); float num2 = Mathf.InverseLerp(Mathf.Max(showFrom.Value, hideWithin.Value), farFrom.Value, num); float num3 = size.Value * Mathf.Lerp(1f, farScale, num2); Vector2 val2 = new Vector2((float)Screen.width, (float)Screen.height) * 0.5f; Vector2 val3 = new Vector2(val.x, val.y) - val2; bool num4 = val.z < 0f; if (num4) { val3 = -val3; } Vector2 val4 = val2 - Vector2.one * num3; if (num4 || Mathf.Abs(val3.x) > val4.x || Mathf.Abs(val3.y) > val4.y) { if (!offScreen.Value) { return false; } if (((Vector2)(ref val3)).sqrMagnitude < 1f) { val3 = Vector2.down; } float num5 = Mathf.Min((val3.x != 0f) ? (val4.x / Mathf.Abs(val3.x)) : float.MaxValue, (val3.y != 0f) ? (val4.y / Mathf.Abs(val3.y)) : float.MaxValue); val3 *= num5; } Mark mark = Dot(hud, index); ((Graphic)mark.Far).color = new Color(1f, 1f, 1f, num2); ((Graphic)mark.Fill).rectTransform.sizeDelta = new Vector2(num3, num3); ((Component)mark.Fill).transform.position = Vector2.op_Implicit(val2 + val3); ((Component)mark.Fill).gameObject.SetActive(true); Spark(mark, index, num3, Color.Lerp(edgeColor.Value, farEdgeColor.Value, num2)); return true; } private void Spark(Mark mark, int index, float diameter, Color color) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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) int num = (sparks.Value ? sparkCount : 0); while (mark.Sparks.Count < num) { Image val = NewImage("Spark", ((Component)mark.Fill).transform, sparkSprite); ((Component)val).transform.SetAsFirstSibling(); mark.Sparks.Add(val); } for (int i = 0; i < mark.Sparks.Count; i++) { Image val2 = mark.Sparks[i]; ((Component)val2).gameObject.SetActive(i < num); if (i < num) { float num2 = Time.time * sparkRate + Hash(index * 31 + i); float num3 = Mathf.Floor(num2); float num4 = num2 - num3; float num5 = Hash((float)(index * 7919 + i * 131) + num3) * (float)Math.PI * 2f; float num6 = diameter * (0.485f + sparkTravel * num4); ((Graphic)val2).rectTransform.anchoredPosition = new Vector2(Mathf.Cos(num5), Mathf.Sin(num5)) * num6; ((Graphic)val2).rectTransform.sizeDelta = Vector2.one * diameter * sparkSize * (1f - 0.5f * num4); val2.sprite = sparkSprite; color.a = Step01(num4 * 6f) * (1f - num4); ((Graphic)val2).color = color; } } } private static float Hash(float n) { float num = Mathf.Sin(n * 12.9898f) * 43758.547f; return num - Mathf.Floor(num); } private static bool Blocked(Vector3 eye, Vector3 target) { //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_0049: 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_005f: 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_0062: Unknown result type (might be due to invalid IL or missing references) if (blockMask == 0) { blockMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }); } Vector3 val = target - eye; float magnitude = ((Vector3)(ref val)).magnitude; RaycastHit val2 = default(RaycastHit); if (magnitude > 0.75f && Physics.Raycast(eye, val / magnitude, ref val2, magnitude, blockMask)) { return ((RaycastHit)(ref val2)).distance < magnitude - 0.75f; } return false; } private Mark Dot(EnemyHud hud, int index) { while (dots.Count <= index) { dots.Add(null); } if (dots[index] == null || (Object)(object)dots[index].Fill == (Object)null) { Image val = NewImage("OdinsMissingPatch_PlayerMark", hud.m_hudRoot.transform, nearSprite); ((Component)val).transform.SetAsFirstSibling(); dots[index] = new Mark { Fill = val, Far = Stretched(NewImage("Far", ((Component)val).transform, farSprite)), Rings = Stretched(NewImage("Rings", ((Component)val).transform, ringSprite)) }; } Mark mark = dots[index]; mark.Fill.sprite = nearSprite; mark.Far.sprite = farSprite; mark.Rings.sprite = ringSprite; return mark; } private static Image Stretched(Image image) { //IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references) ((Graphic)image).rectTransform.anchorMin = Vector2.zero; ((Graphic)image).rectTransform.anchorMax = Vector2.one; ((Graphic)image).rectTransform.sizeDelta = Vector2.zero; return image; } private static Image NewImage(string name, Transform parent, Sprite sprite) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(parent, false); Image component = val.GetComponent<Image>(); component.sprite = sprite; ((Graphic)component).raycastTarget = false; return component; } private void UpdateSprites() { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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_00c6: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[3] { centreColor.Value, edgeColor.Value, farEdgeColor.Value }; if ((Object)(object)sparkSprite == (Object)null) { sparkSprite = Draw((float r, float edge) => new Color(1f, 1f, 1f, 1f - Step01(r)), rugged: false); } if (shapeChanged || !((Object)(object)nearSprite != (Object)null) || !((Object)(object)farSprite != (Object)null) || !((Object)(object)ringSprite != (Object)null) || spriteColors == null || !(array[0] == spriteColors[0]) || !(array[1] == spriteColors[1]) || !(array[2] == spriteColors[2])) { shapeChanged = false; float ringRadius = 0.97f - outlineWidth; float hole = ringRadius - ringWidth; float radius = hole + 0.04f; Destroy(nearSprite); Destroy(farSprite); Destroy(ringSprite); nearSprite = Disc(array[0], array[1], radius); farSprite = Disc(array[1], array[2], radius); ringSprite = Draw(delegate(float r, float edge) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001c: 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) Color result = Color.Lerp(outlineColor, ringColor, Inside(r, ringRadius, edge)); result.a = Inside(r, 0.97f, edge) - Inside(r, hole, edge); return result; }, rugged: true); spriteColors = array; } } private static Sprite Disc(Color centre, Color edge, float radius) { //IL_0006: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) return Draw(delegate(float r, float width) { //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_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_003d: Unknown result type (might be due to invalid IL or missing references) Color result = Color.Lerp(centre, edge, Step01(Mathf.Pow(r / radius, gradientCurve))); result.a = Inside(r, radius, width); return result; }, rugged: true); } private static void Destroy(Sprite sprite) { if ((Object)(object)sprite != (Object)null) { Object.Destroy((Object)(object)sprite.texture); Object.Destroy((Object)(object)sprite); } } private static float Inside(float r, float radius, float edge) { return 1f - Step01((r - radius + edge) / (2f * edge)); } private static float Step01(float t) { t = Mathf.Clamp01(t); return t * t * (3f - 2f * t); } private static float Outline(float angle) { float num = 0.5f * Mathf.Sin((float)bumps * angle + 1.3f) + 0.3f * Mathf.Sin((float)(2 * bumps + 1) * angle + 0.4f) + 0.2f * Mathf.Sin((float)(3 * bumps + 2) * angle + 2.1f); return (1f + ruggedness * num) / (1f + ruggedness); } private static Sprite Draw(Func<float, float, Color> pixel, bool rugged = false) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00b5: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, true); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)2; Vector2 val2 = default(Vector2); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { ((Vector2)(ref val2))..ctor((float)j + 0.5f - 32f, (float)i + 0.5f - 32f); float num = ((Vector2)(ref val2)).magnitude / 32f; if (rugged) { num /= Outline(Mathf.Atan2(val2.y, val2.x)); } val.SetPixel(j, i, pixel(num, 1f / 32f)); } } val.Apply(true); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); } } internal static class Danger { [HarmonyPatch(typeof(Player), "RPC_OnTargeted")] [Serves(new Type[] { typeof(Danger) })] private static class NoticeEnragedEnemy { private static void Postfix(Player __instance, bool alerted) { if (alerted && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { lastEnraged = Time.time; } } } private const float CheckInterval = 0.25f; private const float EnragedMemory = 1.5f; internal const string Section = "General"; internal static ConfigEntry<float> ThreatRadius; internal static ConfigEntry<bool> EnragedEnemies; internal static ConfigEntry<bool> BossFights; private static float lastCheck = float.NegativeInfinity; private static bool inDanger; private static float lastEnraged = float.NegativeInfinity; internal static void Bind(ConfigFile config, string effect) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown ThreatRadius = config.Bind<float>("General", "ThreatRadius", 25f, new ConfigDescription("Metres. A hostile creature closer than this puts you in combat, whether it has noticed you or not: " + effect, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>())); EnragedEnemies = config.Bind<bool>("General", "EnragedEnemies", true, "An enemy that has noticed you and is coming for you puts you in combat at any distance, not only inside ThreatRadius. Off means only the radius counts."); BossFights = config.Bind<bool>("General", "BossFights", true, "A boss health bar on screen puts you in combat, whoever the boss is after and however far away it is."); } internal static bool Near(Player player) { if (Time.time - lastCheck < 0.25f) { return inDanger; } lastCheck = Time.time; inDanger = Enraged() || BossBarShowing() || HostileWithin(player, ThreatRadius.Value); return inDanger; } private static bool Enraged() { if (EnragedEnemies.Value) { return Time.time - lastEnraged < 1.5f; } return false; } private static bool BossBarShowing() { if (BossFights.Value && (Object)(object)EnemyHud.instance != (Object)null) { return EnemyHud.instance.ShowingBossHud(); } return false; } private static bool HostileWithin(Player player, float radius) { //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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; float num = radius * radius; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)player, allCharacter)) { Vector3 val = ((Component)allCharacter).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= num) { return true; } } } return false; } } internal static class FavoriteMark { internal const string Key = "OMP_Favorite"; internal static bool IsSet(ItemData item) { if (item != null && item.m_customData != null && item.m_customData.TryGetValue("OMP_Favorite", out var value)) { return value == "1"; } return false; } } internal static class Hotkeys { internal static bool Pressed(KeyboardShortcut shortcut) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return false; } return ModifiersHeld(shortcut); } internal static bool Held(KeyboardShortcut shortcut) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return false; } return ModifiersHeld(shortcut); } internal static string Describe(params KeyboardShortcut[] chord) { //IL_000e: 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_0016: 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_0037: 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) List<string> list = new List<string>(); for (int i = 0; i < chord.Length; i++) { KeyboardShortcut val = chord[i]; if ((int)((KeyboardShortcut)(ref val)).MainKey == 0) { continue; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref val)).Modifiers) { list.Add(KeyName(modifier)); } list.Add(KeyName(((KeyboardShortcut)(ref val)).MainKey)); } return string.Join(" + ", list.ToArray()); } private unsafe static string KeyName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) string text = ZInput.KeyCodeToDisplayName(key); if (!string.IsNullOrEmpty(text) && !text.StartsWith("$")) { return text; } return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } private static bool ModifiersHeld(KeyboardShortcut shortcut) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } } internal static class LegacyConfig { private const string OldFile = "rauschekuh.odinsmissingpatch.cfg"; internal static HashSet<string> Sections(string path) { HashSet<string> hashSet = new HashSet<string>(); try { if (File.Exists(path)) { foreach (ConfigDefinition key in Read(path).Keys) { hashSet.Add(key.Section); } } } catch (Exception ex) { TweakHost.Log.LogWarning((object)("could not read " + path + ": " + ex.Message)); } return hashSet; } internal static void Import(ConfigFile config, HashSet<string> known) { try { string path = Path.Combine(Paths.ConfigPath, "rauschekuh.odinsmissingpatch.cfg"); if (!File.Exists(path)) { return; } Dictionary<ConfigDefinition, string> dictionary = Read(path); int num = 0; foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config) { if (!known.Contains(item.Key.Section) && dictionary.TryGetValue(item.Key, out var value)) { item.Value.SetSerializedValue(value); num++; } } if (num > 0) { config.Save(); TweakHost.Log.LogInfo((object)("took " + num + " setting(s) over from rauschekuh.odinsmissingpatch.cfg")); } } catch (Exception ex) { TweakHost.Log.LogWarning((object)("could not read the settings of rauschekuh.odinsmissingpatch.cfg: " + ex.Message)); } } private static Dictionary<ConfigDefinition, string> Read(string path) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown Dictionary<ConfigDefinition, string> dictionary = new Dictionary<ConfigDefinition, string>(); string text = ""; string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2.StartsWith("#")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2); continue; } int num = text2.IndexOf('='); if (num > 0 && text.Length > 0) { dictionary[new ConfigDefinition(text, text2.Substring(0, num).Trim())] = text2.Substring(num + 1).Trim(); } } return dictionary; } } internal static class Palette { internal static readonly Color Gold = new Color(1f, 0.8f, 0.3f, 1f); internal static readonly Color ChestYellow = new Color(1f, 0.84f, 0.3f, 1f); internal const string ChestYellowTag = "<color=#ffd64d>"; } [AttributeUsage(AttributeTargets.Class)] internal sealed class ServesAttribute : Attribute { internal readonly Type[] Tweaks; public bool Optional { get; set; } public ServesAttribute(params Type[] tweaks) { Tweaks = tweaks; } } [AttributeUsage(AttributeTargets.Class)] internal sealed class AlwaysAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class)] internal sealed class LoadHookAttribute : Attribute { } internal static class Patcher { private sealed class PatchClass { internal Type Type; internal Tweak[] Serves; internal bool Optional; internal bool LoadHook; internal bool Applied; internal bool Failed; } private static readonly List<PatchClass> classes = new List<PatchClass>(); private static Harmony harmony; private static ManualLogSource log; internal static void Map(IList<Tweak> tweaks, ManualLogSource logSource) { log = logSource; Dictionary<Type, Tweak> byType = tweaks.ToDictionary((Tweak t) => t.GetType()); Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { if (!type.IsDefined(typeof(HarmonyPatch), inherit: false)) { continue; } Tweak[] array = Owners(type, byType); if (array != null) { classes.Add(new PatchClass { Type = type, Serves = array, Optional = type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).Cast<ServesAttribute>().Any((ServesAttribute s) => s.Optional), LoadHook = type.IsDefined(typeof(LoadHookAttribute), inherit: false) }); } } } private static Tweak[] Owners(Type type, Dictionary<Type, Tweak> byType) { if (type.IsDefined(typeof(AlwaysAttribute), inherit: false)) { return new Tweak[0]; } ServesAttribute servesAttribute = (ServesAttribute)type.GetCustomAttributes(typeof(ServesAttribute), inherit: false).FirstOrDefault(); if (servesAttribute != null) { List<Tweak> list = new List<Tweak>(); Type[] tweaks = servesAttribute.Tweaks; foreach (Type tweak in tweaks) { if (byType.TryGetValue(tweak, out var value)) { list.Add(value); continue; } if (typeof(Tweak).IsAssignableFrom(tweak)) { log.LogWarning((object)(type.FullName + " serves " + tweak.Name + ", which is not in the Tweaks list")); continue; } list.AddRange(byType.Values.Where((Tweak t) => t.Uses.Contains(tweak))); } if (list.Count <= 0) { return null; } return list.Distinct().ToArray(); } Type declaringType = type.DeclaringType; while (declaringType != null) { if (byType.TryGetValue(declaringType, out var value2)) { return new Tweak[1] { value2 }; } declaringType = declaringType.DeclaringType; } log.LogWarning((object)(type.FullName + " belongs to no tweak and names none, so it is always applied")); return new Tweak[0]; } internal static bool AnyServedOn(Type patchClass) { foreach (PatchClass @class in classes) { if (@class.Type != patchClass) { continue; } Tweak[] serves = @class.Serves; for (int i = 0; i < serves.Length; i++) { if (serves[i].On) { return true; } } return false; } return false; } internal static bool MayNeedRestart(Tweak tweak) { return classes.Any((PatchClass c) => c.LoadHook && c.Serves.Contains(tweak)); } internal static void Apply(Harmony instance, IList<Tweak> tweaks) { harmony = instance; foreach (PatchClass @class in classes) { if (@class.Serves.Length == 0 || @class.Serves.Any((Tweak t) => t.Wanted && !t.Broken)) { TryApply(@class); } } foreach (Tweak tweak in tweaks) { if (tweak.Wanted && !tweak.Broken) { GoLive(tweak); } tweak.Enabled.SettingChanged += delegate { SwitchedOn(tweak); }; } } private static void SwitchedOn(Tweak tweak) { if (!tweak.Wanted || tweak.Patched || tweak.Broken) { return; } List<PatchClass> list = classes.Where((PatchClass c) => c.Serves.Contains(tweak) && !c.Applied && !c.Failed).ToList(); if (list.Any((PatchClass c) => c.LoadHook)) { log.LogInfo((object)(tweak.Section + " was off at launch and takes effect at the next start of the game")); return; } foreach (PatchClass item in list) { TryApply(item); } if (!tweak.Broken) { GoLive(tweak); log.LogInfo((object)(tweak.Section + " switched on")); } } private static void GoLive(Tweak tweak) { tweak.Patched = true; tweak.Refresh(); } private static void TryApply(PatchClass patch) { try { harmony.CreateClassProcessor(patch.Type).Patch(); patch.Applied = true; } catch (Exception ex) { patch.Failed = true; Unpatch(patch); string message = (ex.InnerException ?? ex).Message; if (patch.Serves.Length == 0 || patch.Optional) { log.LogError((object)(patch.Type.FullName + " could not be patched, carrying on without it: " + message)); return; } Tweak[] serves = patch.Serves; for (int i = 0; i < serves.Length; i++) { Break(serves[i], patch.Type, message); } } } private static void Break(Tweak tweak, Type failed, string cause) { if (tweak.Broken) { return; } tweak.Broken = true; tweak.Patched = false; log.LogError((object)(tweak.Section + " is switched off: " + failed.FullName + " could not be patched, most likely because a game update changed it. " + cause)); foreach (PatchClass @class in classes) { if (@class.Applied && @class.Serves.Contains(tweak) && !@class.Serves.Any((Tweak t) => !t.Broken && (t.Patched || t.Wanted))) { Unpatch(@class); @class.Applied = false; } } tweak.Refresh(); } private static void Unpatch(PatchClass patch) { try { foreach (MethodBase item in harmony.GetPatchedMethods().ToList()) { Patches patchInfo = Harmony.GetPatchInfo(item); if (patchInfo == null) { continue; } foreach (Patch item2 in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers) .Concat(patchInfo.ILManipulators) .ToList()) { if (item2.owner == harmony.Id && item2.PatchMethod.DeclaringType == patch.Type) { harmony.Unpatch(item, item2.PatchMethod); } } } } catch (Exception ex) { log.LogError((object)("could not take out " + patch.Type.FullName + ": " + ex.Message)); } } } internal static class Translations { [HarmonyPatch(typeof(Localization), "SetupLanguage")] [Always] private static class Load { private static void Postfix(Localization __instance, string language) { if (__instance == null || !Read() || !Reader()) { return; } object obj = null; try { obj = textAsset.Invoke(new object[1] { csv }); loadCsv.Invoke(__instance, new object[2] { obj, Has(language) ? language : "English" }); Revision++; } catch (Exception ex) { TweakHost.Log.LogWarning((object)("could not load translations.csv: " + ex.Message)); } finally { Object val = (Object)((obj is Object) ? obj : null); if (val != (Object)null) { Object.Destroy(val); } } } } private const string FileName = "translations.csv"; private const string Fallback = "English"; private static string csv; private static string[] languages; private static ConstructorInfo textAsset; private static MethodInfo loadCsv; private static bool looked; internal static int Revision { get; private set; } private static bool Read() { if (languages != null) { return csv != null; } languages = new string[0]; try { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "translations.csv"); if (!File.Exists(text)) { TweakHost.Log.LogDebug((object)("no translations.csv beside the DLL: " + text)); return false; } csv = File.ReadAllText(text); using (StringReader stringReader = new StringReader(csv)) { string text2 = stringReader.ReadLine(); languages = ((text2 != null) ? text2.Split(new char[1] { ',' }) : new string[0]); } for (int i = 0; i < languages.Length; i++) { languages[i] = languages[i].Trim().Trim(new char[1] { '"' }); } } catch (Exception ex) { csv = null; TweakHost.Log.LogWarning((object)("could not read translations.csv: " + ex.Message)); } return csv != null; } private static bool Has(string language) { string[] array = languages; for (int i = 0; i < array.Length; i++) { if (array[i] == language) { return true; } } return false; } private static bool Reader() { if (looked) { if (loadCsv != null) { return textAsset != null; } return false; } looked = true; Type type = Type.GetType("UnityEngine.TextAsset, UnityEngine.CoreModule"); if (type != null) { textAsset = type.GetConstructor(new Type[1] { typeof(string) }); loadCsv = typeof(Localization).GetMethod("LoadCSV", new Type[2] { type, typeof(string) }); } if (loadCsv == null || textAsset == null) { TweakHost.Log.LogWarning((object)"Localization.LoadCSV not found; the mod's words stay untranslated"); return false; } return true; } } internal abstract class Tweak { private const float MinMultiplier = 0.1f; private const float MaxMultiplier = 20f; private const string RestartNote = " If it was off when the game started, switching it on may only take effect after a restart."; private ConfigEntry<bool> enabled; private readonly List<Action> settingHandlers = new List<Action>(); internal abstract string Section { get; } protected abstract string Summary { get; } internal virtual Type[] Uses => Type.EmptyTypes; internal bool On { get { if (Patched) { return Wanted; } return false; } } internal bool Wanted { get { if (enabled != null) { return enabled.Value; } return false; } } internal ConfigEntry<bool> Enabled => enabled; internal bool Patched { get; set; } internal bool Broken { get; set; } protected virtual void Bind(ConfigFile config) { } internal void Setup(ConfigFile config, bool mayNeedRestart) { enabled = config.Bind<bool>(Section, "Enabled", true, Summary + (mayNeedRestart ? " If it was off when the game started, switching it on may only take effect after a restart." : "")); Bind(config); } internal void Refresh() { foreach (Action settingHandler in settingHandlers) { settingHandler(); } } protected ConfigEntry<float> BindMultiplier(ConfigFile config, string key, float value, string description) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown return config.Bind<float>(Section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>())); } protected ConfigEntry<string> BindList(ConfigFile config, string key, string value, string description, Action<List<string>> apply) { ConfigEntry<string> entry = config.Bind<string>(Section, key, value, description); entry.SettingChanged += delegate { apply(Items(entry.Value)); }; apply(Items(entry.Value)); return entry; } internal static List<string> Items(string list) { List<string> list2 = new List<string>(); string[] array = (list ?? "").Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { list2.Add(text); } } return list2; } protected void OnSettingChanged(ConfigFile config, Action handler) { settingHandlers.Add(handler); config.SettingChanged += delegate(object sender, SettingChangedEventArgs args) { if (args.ChangedSetting.Definition.Section == Section) { handler(); } }; } } internal static class TweakHost { internal static ManualLogSource Log; internal static BaseUnityPlugin Plugin; internal static void Start(BaseUnityPlugin plugin, ManualLogSource logger, ConfigFile config, string guid, Tweak[] tweaks, Action<ConfigFile> bindShared = null) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown Plugin = plugin; Log = logger; HashSet<string> known = LegacyConfig.Sections(config.ConfigFilePath); bindShared?.Invoke(config); Patcher.Map(tweaks, logger); foreach (Tweak tweak in tweaks) { tweak.Setup(config, Patcher.MayNeedRestart(tweak)); } LegacyConfig.Import(config, known); Patcher.Apply(new Harmony(guid), tweaks); string text = string.Join(", ", (from t in tweaks where t.On select t.Section).ToArray()); logger.LogInfo((object)((text.Length > 0) ? ("tweaks on: " + text) : "every tweak is switched off")); } } internal static class UiAssets { private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>(); private static MethodInfo loadImage; internal static Sprite Icon(string name) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0069: 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) if (icons.TryGetValue(name, out var value)) { return value; } value = null; try { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = IconPath(directoryName, name); if (text != null) { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (LoadPng(val, File.ReadAllBytes(text))) { ((Texture)val).filterMode = (FilterMode)1; value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } else { TweakHost.Log.LogWarning((object)("icon missing: " + name + ".png, looked in " + Path.Combine(directoryName, "icons") + " and " + directoryName)); } } catch (Exception ex) { TweakHost.Log.LogWarning((object)("could not load icon " + name + ": " + ex.Message)); } icons[name] = value; return value; } private static string IconPath(string dir, string name) { string path = name + ".png"; string[] array = new string[2] { Path.Combine(Path.Combine(dir, "icons"), path), Path.Combine(dir, path) }; foreach (string text in array) { if (File.Exists(text)) { return text; } } return null; } private static bool LoadPng(Texture2D texture, byte[] png) { if (loadImage == null) { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); loadImage = ((type != null) ? type.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }) : null); if (loadImage == null) { TweakHost.Log.LogWarning((object)"ImageConversion.LoadImage not found; icons stay blank"); return false; } } return (bool)loadImage.Invoke(null, new object[2] { texture, png }); } internal static GameObject TooltipPrefab(InventoryGui gui) { InventoryGrid playerGrid = gui.m_playerGrid; GameObject val = (((Object)(object)playerGrid != (Object)null) ? playerGrid.m_elementPrefab : null); InventoryElement val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<InventoryElement>() : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_tooltip != (Object)null && (Object)(object)val2.m_tooltip.m_tooltipPrefab != (Object)null) { return val2.m_tooltip.m_tooltipPrefab; } UITooltip[] componentsInChildren = ((Component)gui).GetComponentsInChildren<UITooltip>(true); foreach (UITooltip val3 in componentsInChildren) { if ((Object)(object)val3.m_tooltipPrefab != (Object)null) { return val3.m_tooltipPrefab; } } return null; } } }