using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CustomEnemyLocation")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.5.0")] [assembly: AssemblyInformationalVersion("1.0.5")] [assembly: AssemblyProduct("CustomEnemyLocation")] [assembly: AssemblyTitle("CustomEnemyLocation")] [assembly: AssemblyVersion("1.0.5.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace com.ugleh.repo { [BepInPlugin("com.ugleh.repo.customenemylocation", "Custom Enemy Location", "1.0.5")] public sealed class CustomEnemyLocationPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__20 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CustomEnemyLocationPlugin <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int num = <>1__state; CustomEnemyLocationPlugin customEnemyLocationPlugin = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; } else { <>1__state = -1; } if (customEnemyLocationPlugin._enableEnemyIcons.Value) { customEnemyLocationPlugin.TryTrackEnemies(); } else { ClearAllMarkers(); } <>2__current = (object)new WaitForSeconds(Mathf.Clamp(customEnemyLocationPlugin._scanIntervalSeconds.Value, 0.1f, 10f)); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "com.ugleh.repo.customenemylocation"; public const string PluginName = "Custom Enemy Location"; public const string PluginVersion = "1.0.5"; private static readonly FieldInfo? EnemyDeadField = typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? EnemyParentSpawnedField = typeof(EnemyParent).GetField("Spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? PlayerDeathHeadField = typeof(PlayerAvatar).GetField("playerDeathHead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private ConfigEntry _enableEnemyIcons; private ConfigEntry _enemyIconColorHex; private ConfigEntry _scanIntervalSeconds; private ConfigEntry _hideDeadEnemies; private ConfigEntry _onlyTrackSpawnedEnemies; private Sprite? _markerSprite; private Sprite? _fallbackSprite; private bool _loggedMissingSprite; private bool _loggedReady; internal static ManualLogSource Log { get; private set; } = null; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _enableEnemyIcons = ((BaseUnityPlugin)this).Config.Bind("General", "Enable Enemy Icons", true, "Toggle visibility of enemies on the minimap"); _enemyIconColorHex = ((BaseUnityPlugin)this).Config.Bind("General", "Enemy Icon Color (Hex)", "#8000FF", "Hex color code for enemy icons (e.g. #FF0000 for red)"); _scanIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("General", "Scan Interval Seconds", 0.75f, "How often to look for new enemy instances."); _hideDeadEnemies = ((BaseUnityPlugin)this).Config.Bind("General", "Hide Dead Enemies", true, "Hide dots for enemies whose EnemyHealth.dead flag is set."); _onlyTrackSpawnedEnemies = ((BaseUnityPlugin)this).Config.Bind("General", "Only Track Spawned Enemies", true, "Only show dots for enemies whose EnemyParent.Spawned flag is set."); ((MonoBehaviour)this).StartCoroutine(ScanLoop()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom Enemy Location 1.0.5 loaded."); } [IteratorStateMachine(typeof(d__20))] private IEnumerator ScanLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__20(0) { <>4__this = this }; } private void TryTrackEnemies() { //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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (!MapIsReady()) { return; } Sprite val = ResolveMarkerSprite(); if ((Object)(object)val == (Object)null) { if (!_loggedMissingSprite) { _loggedMissingSprite = true; Log.LogWarning((object)"Could not resolve a map marker sprite yet; enemy dots will appear once the map/player marker is available."); } return; } _loggedMissingSprite = false; Color color = ParseColor(_enemyIconColorHex.Value, new Color(0.5f, 0f, 1f, 1f)); Enemy[] array = Object.FindObjectsOfType(); foreach (Enemy val2 in array) { if (!ShouldTrack(val2)) { HideMarker(val2); continue; } EnemyMapMarker enemyMapMarker = ((Component)val2).GetComponent(); if ((Object)(object)enemyMapMarker == (Object)null) { enemyMapMarker = ((Component)val2).gameObject.AddComponent(); } enemyMapMarker.Configure(val, color, GetIconScaleByEnemyType(val2.Type)); enemyMapMarker.TryAddToMap(); } } private bool MapIsReady() { try { if (!SemiFunc.RunIsLevel() || SemiFunc.RunIsShop() || SemiFunc.RunIsArena() || SemiFunc.RunIsLobby()) { return false; } } catch (Exception) { return false; } if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated) { return false; } if ((Object)(object)Map.Instance == (Object)null || (Object)(object)Map.Instance.CustomObject == (Object)null || (Object)(object)Map.Instance.OverLayerParent == (Object)null) { return false; } if (!_loggedReady) { _loggedReady = true; Log.LogInfo((object)"Map is ready; enemy tracker is attaching markers."); } return true; } private bool ShouldTrack(Enemy enemy) { if ((Object)(object)enemy == (Object)null || !((Behaviour)enemy).isActiveAndEnabled || !((Component)enemy).gameObject.activeInHierarchy) { return false; } if (_onlyTrackSpawnedEnemies.Value && !IsSpawned(enemy)) { return false; } if (_hideDeadEnemies.Value) { return !IsDead(enemy); } return true; } private static bool IsSpawned(Enemy enemy) { if (EnemyParentSpawnedField == null) { return true; } EnemyParent componentInParent = ((Component)enemy).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return true; } object value = EnemyParentSpawnedField.GetValue(componentInParent); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool IsDead(Enemy enemy) { if (EnemyDeadField == null) { return false; } EnemyHealth component = ((Component)enemy).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } object value = EnemyDeadField.GetValue(component); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private Sprite? ResolveMarkerSprite() { if ((Object)(object)_markerSprite != (Object)null) { return _markerSprite; } _markerSprite = FindPlayerDeathHeadSprite(); if ((Object)(object)_markerSprite != (Object)null) { return _markerSprite; } if (_fallbackSprite == null) { _fallbackSprite = CreateCircleSprite(); } return _fallbackSprite; } private static Sprite? FindPlayerDeathHeadSprite() { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null || GameDirector.instance.PlayerList.Count == 0) { return null; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if (!((Object)(object)player == (Object)null)) { object? obj = PlayerDeathHeadField?.GetValue(player); PlayerDeathHead val = (PlayerDeathHead)((obj is PlayerDeathHead) ? obj : null); if (val != null && (Object)(object)val.mapCustom != (Object)null && (Object)(object)val.mapCustom.sprite != (Object)null) { return val.mapCustom.sprite; } } } return null; } private static Sprite CreateCircleSprite() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); Color32[] array = (Color32[])(object)new Color32[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = (float)j - 15.5f; float num2 = (float)i - 15.5f; byte b = (byte)Mathf.RoundToInt(Mathf.Clamp01(13.94f - Mathf.Sqrt(num * num + num2 * num2)) * 255f); array[i * 32 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b); } } val.SetPixels32(array); val.Apply(false, true); ((Object)val).name = "CustomEnemyLocationFallbackCircle"; Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 32f); ((Object)obj).name = "CustomEnemyLocationFallbackCircle"; return obj; } private static Color ParseColor(string value, Color fallback) { //IL_002d: 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) string text = value.Trim(); if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } Color result = default(Color); if (!ColorUtility.TryParseHtmlString(text, ref result)) { return fallback; } return result; } private static float GetIconScaleByEnemyType(EnemyType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown return (int)type switch { 0 => 0.65f, 1 => 0.85f, 2 => 1f, 3 => 1.25f, 4 => 1.5f, _ => 1f, }; } private static void HideMarker(Enemy enemy) { if (!((Object)(object)enemy == (Object)null)) { EnemyMapMarker component = ((Component)enemy).GetComponent(); if ((Object)(object)component != (Object)null) { component.ResetMarker(); } } } private static void ClearAllMarkers() { EnemyMapMarker[] array = Object.FindObjectsOfType(); foreach (EnemyMapMarker obj in array) { obj.ResetMarker(); Object.Destroy((Object)(object)obj); } } } internal sealed class EnemyMapMarker : MonoBehaviour { private static readonly FieldInfo? MapCustomEntityField = typeof(MapCustom).GetField("mapCustomEntity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private MapCustom? _mapCustom; private Sprite? _sprite; private Color _color; private float _scale = 1f; private bool _added; private bool _loggedAddFailure; public void Configure(Sprite sprite, Color color, float scale) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_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) _sprite = sprite; _color = color; _scale = scale; EnsureMapCustom(); if (!((Object)(object)_mapCustom == (Object)null)) { _mapCustom.autoAdd = false; _mapCustom.sprite = sprite; _mapCustom.color = color; ApplyScale(_mapCustom, _scale); } } public void TryAddToMap() { //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) if (_added || (Object)(object)_sprite == (Object)null || !((Behaviour)this).isActiveAndEnabled || !((Component)this).gameObject.activeInHierarchy) { return; } EnsureMapCustom(); if ((Object)(object)_mapCustom == (Object)null) { return; } try { _mapCustom.sprite = _sprite; _mapCustom.color = _color; _mapCustom.Add(); _added = HasMapEntity(_mapCustom); ApplyScale(_mapCustom, _scale); _loggedAddFailure = false; } catch (Exception ex) { if (!_loggedAddFailure) { _loggedAddFailure = true; CustomEnemyLocationPlugin.Log.LogWarning((object)("Failed to add enemy marker for " + ((Object)((Component)this).gameObject).name + ": " + ex.Message)); } } } public void ResetMarker() { if ((Object)(object)_mapCustom != (Object)null) { _mapCustom.Hide(); DestroyMapEntity(_mapCustom); } _added = false; } private void OnDisable() { ResetMarker(); } private void OnDestroy() { ResetMarker(); } private void EnsureMapCustom() { if (!((Object)(object)_mapCustom != (Object)null)) { _mapCustom = ((Component)this).GetComponent(); if ((Object)(object)_mapCustom == (Object)null) { _mapCustom = ((Component)this).gameObject.AddComponent(); } } } private static bool HasMapEntity(MapCustom mapCustom) { if (MapCustomEntityField == null) { return true; } object? value = MapCustomEntityField.GetValue(mapCustom); MapCustomEntity val = (MapCustomEntity)((value is MapCustomEntity) ? value : null); if (val != null) { return (Object)(object)val != (Object)null; } return false; } private static void ApplyScale(MapCustom mapCustom, float scale) { //IL_0031: 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) if (!(MapCustomEntityField == null)) { object? value = MapCustomEntityField.GetValue(mapCustom); MapCustomEntity val = (MapCustomEntity)((value is MapCustomEntity) ? value : null); if (val != null && (Object)(object)val != (Object)null) { ((Component)val).transform.localScale = Vector3.one * scale; } } } private static void DestroyMapEntity(MapCustom mapCustom) { if (!(MapCustomEntityField == null)) { object? value = MapCustomEntityField.GetValue(mapCustom); MapCustomEntity val = (MapCustomEntity)((value is MapCustomEntity) ? value : null); if (val != null && (Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } MapCustomEntityField.SetValue(mapCustom, null); } } } }