using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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 Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("REPO_ShowEnemyHealth")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3+1b27dec367654b521dc41d1a2bb4fbcca648c4e7")]
[assembly: AssemblyProduct("ShowEnemyHealth")]
[assembly: AssemblyTitle("REPO_ShowEnemyHealth")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 ShowEnemyHealth
{
internal static class ConfigManager
{
public static ConfigFile ConfigFile { get; private set; }
public static ConfigEntry<bool> ShowEnemyHealth { get; private set; }
public static ConfigEntry<float> HealthShowTimer { get; private set; }
public static ConfigEntry<float> HealthFontSize { get; private set; }
public static ConfigEntry<string> HealthFontColor { get; private set; }
public static ConfigEntry<bool> ShowEnemyDamage { get; private set; }
public static ConfigEntry<float> DamageFontSize { get; private set; }
public static ConfigEntry<string> DamageFontHighlightColor { get; private set; }
public static ConfigEntry<string> DamageFontColor { get; private set; }
public static ConfigEntry<bool> AttemptMultiplayerHealthSync { get; private set; }
public static void Initialize(ConfigFile configFile)
{
ConfigFile = configFile;
BindConfigs();
}
private static void BindConfigs()
{
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Expected O, but got Unknown
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: 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_019d: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Expected O, but got Unknown
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Expected O, but got Unknown
AcceptableValueList<string> val = new AcceptableValueList<string>(new string[10] { "black", "blue", "cyan", "green", "grey", "magenta", "orange", "red", "white", "yellow" });
ShowEnemyHealth = ConfigFile.Bind<bool>("General", "ShowEnemyHealth", true, "");
HealthShowTimer = ConfigFile.Bind<float>("General", "HealthShowTimer", 120f, new ConfigDescription("Max seconds to show enemy health", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), Array.Empty<object>()));
HealthFontSize = ConfigFile.Bind<float>("General", "HealthFontSize", 15f, new ConfigDescription("Enemy health font size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
HealthFontColor = ConfigFile.Bind<string>("General", "HealthFontColor", "grey", new ConfigDescription("Enemy health font color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
ShowEnemyDamage = ConfigFile.Bind<bool>("General", "ShowEnemyDamage", true, "");
DamageFontSize = ConfigFile.Bind<float>("General", "DamageFontSize", 25f, new ConfigDescription("Damage font size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 50f), Array.Empty<object>()));
DamageFontHighlightColor = ConfigFile.Bind<string>("General", "DamageFontHighlightColor", "red", new ConfigDescription("Damage font highlight color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
DamageFontColor = ConfigFile.Bind<string>("General", "DamageFontColor", "orange", new ConfigDescription("Damage font primary color", (AcceptableValueBase)(object)val, Array.Empty<object>()));
AttemptMultiplayerHealthSync = ConfigFile.Bind<bool>("General", "AttemptMultiplayerHealthSync", true, "Sync enemy health across all clients");
}
}
[RequireComponent(typeof(RectTransform))]
[RequireComponent(typeof(TextMeshProUGUI))]
internal class CustomEnemyHealthUI : WorldSpaceUIChild
{
public static CustomEnemyHealthUI instance;
private Vector3 scale;
internal Vector3 newWorldPosition;
private float showTimer;
private Enemy currEnemy;
private EnemyHealth currEnemyHealth;
private EnemyRigidbody enemyRigidBody;
private TextMeshProUGUI text;
private Vector3 worldspaceOffset;
private Vector3 targetWorldspaceOffset;
public int recalcIntervalFrames = 50;
private int frameCounter;
public float worldspaceOffsetLerpRate = 5f;
public AnimationCurve curveIntro = new AnimationCurve();
public AnimationCurve curveOutro = new AnimationCurve();
private bool hasDied;
internal bool hasExploded;
private void Awake()
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
typeof(WorldSpaceUIChild).GetField("positionOffset", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, (object)new Vector3(0f, -0.05f, 0f));
instance = this;
scale = Vector3.one;
text = ((Component)this).GetComponent<TextMeshProUGUI>();
}
public void Show(EnemyHealth enemyHealth, Vector3 screenspaceOffset)
{
//IL_002f: 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_0053: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Expected O, but got Unknown
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Expected O, but got Unknown
//IL_0163: 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)
if (!ConfigManager.ShowEnemyHealth.Value)
{
Patches.healthUIElements.Remove(currEnemyHealth);
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
((Graphic)text).color = Color.gray;
Color32 val = default(Color32);
if (ColorUtility.DoTryParseHtmlColor(ConfigManager.HealthFontColor.Value, ref val))
{
((Graphic)text).color = Color32.op_Implicit(val);
}
((TMP_Text)text).fontSize = ConfigManager.HealthFontSize.Value;
showTimer = ConfigManager.HealthShowTimer.Value;
if (!Object.op_Implicit((Object)(object)currEnemy) || !Object.op_Implicit((Object)(object)currEnemyHealth))
{
typeof(WorldSpaceUIChild).GetField("positionOffset", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, screenspaceOffset);
currEnemyHealth = enemyHealth;
currEnemy = (Enemy)((object)enemyHealth).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(enemyHealth);
newWorldPosition = ((Component)currEnemy).transform.position;
typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(this, newWorldPosition);
enemyRigidBody = (EnemyRigidbody)((object)currEnemy).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemy);
UpdateTargetWorldSpaceOffset();
worldspaceOffset = targetWorldspaceOffset;
UpdateTextValues();
}
}
internal void UpdateTargetWorldSpaceOffset()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: 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_0044: Unknown result type (might be due to invalid IL or missing references)
Bounds bounds = default(Bounds);
((Bounds)(ref bounds))..ctor(Vector3.zero, Vector3.zero);
Collider[] componentsInChildren = ((Component)enemyRigidBody).GetComponentsInChildren<Collider>();
if (componentsInChildren.Length != 0)
{
bounds = componentsInChildren[0].bounds;
}
Collider[] array = componentsInChildren;
foreach (Collider val in array)
{
if (!val.isTrigger)
{
((Bounds)(ref bounds)).Encapsulate(val.bounds);
}
}
float num = ((Bounds)(ref bounds)).max.y / 2f;
targetWorldspaceOffset = new Vector3(0f, num, 0f);
}
internal void UpdateTextValues()
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Invalid comparison between Unknown and I4
if (!((Object)(object)currEnemy == (Object)null) && !((Object)(object)currEnemyHealth == (Object)null))
{
int num = (int)typeof(EnemyHealth).GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemyHealth);
int health = currEnemyHealth.health;
((TMP_Text)text).text = $"{num}/{health}";
bool num2 = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemyHealth);
bool flag = (int)currEnemy.CurrentState == 11;
if ((num2 || flag || hasExploded) && !hasDied)
{
Plugin.Logger.LogDebug((object)"Enemy should have died/despawned, clearing healthbar timer");
showTimer = 0.5f;
hasDied = true;
}
}
}
protected override void Update()
{
//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)
//IL_0048: 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_006f: 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_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: 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_00f3: 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_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Expected O, but got Unknown
((WorldSpaceUIChild)this).Update();
frameCounter++;
if (frameCounter >= recalcIntervalFrames)
{
frameCounter = 0;
UpdateTargetWorldSpaceOffset();
}
worldspaceOffset = Vector3.Lerp(worldspaceOffset, targetWorldspaceOffset, Time.deltaTime * worldspaceOffsetLerpRate);
FieldInfo? field = typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic);
_ = (Vector3)field.GetValue(this);
field.SetValue(this, newWorldPosition + worldspaceOffset);
if ((Object)(object)currEnemy != (Object)null)
{
newWorldPosition = currEnemy.CenterTransform.position;
}
if (showTimer > 0f)
{
showTimer -= Time.deltaTime;
float num = 1f;
float num2 = 5f;
float num3 = 20f;
float num4 = Vector3.Distance(((Component)Camera.main).transform.position, newWorldPosition);
Vector3 localScale = scale;
if (num4 > num2)
{
num4 = Mathf.Clamp(num4, num2, num3);
num = 1f - (num4 - num2) / (num3 - num2);
((Vector3)(ref localScale))..ctor(num, num, num);
}
((TMP_Text)text).alpha = num;
((Component)this).transform.localScale = localScale;
UpdateTextValues();
}
else if (showTimer <= 0f && (Object)(object)currEnemyHealth != (Object)null)
{
EnemyParent val = (EnemyParent)((object)currEnemy).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(currEnemy);
Plugin.Logger.LogDebug((object)("Removing enemy health UI for " + val.enemyName + "..."));
Patches.healthUIElements.Remove(currEnemyHealth);
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
[HarmonyPatch]
public static class Patches
{
[CompilerGenerated]
private sealed class <DelayedSetText>d__7 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public FieldInfo fieldInfo;
public object target;
public string targetText;
private TextMeshProUGUI <text>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedSetText>d__7(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<text>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_00ad: 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_005c: Expected O, but got Unknown
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: 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_00f4: 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)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
<text>5__2 = (TextMeshProUGUI)(fieldInfo?.GetValue(target));
if ((Object)(object)<text>5__2 == (Object)null)
{
<>2__current = null;
<>1__state = 2;
return true;
}
break;
case 2:
<>1__state = -1;
break;
}
((TMP_Text)<text>5__2).text = targetText;
((TMP_Text)<text>5__2).fontSize = ConfigManager.DamageFontSize.Value;
((Graphic)<text>5__2).color = Color.blue;
Color32 val = default(Color32);
if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontHighlightColor.Value, ref val))
{
((Graphic)<text>5__2).color = Color32.op_Implicit(val);
}
Color32 val2 = default(Color32);
if (ColorUtility.DoTryParseHtmlColor(ConfigManager.DamageFontColor.Value, ref val2))
{
Color val3 = Color32.op_Implicit(val2);
typeof(WorldSpaceUIValueLost).GetField("textColor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, val3);
}
else
{
typeof(WorldSpaceUIValueLost).GetField("textColor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(target, Color.cyan);
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <DelayedShowHealthUI>d__8 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public CustomEnemyHealthUI healthBar;
public EnemyHealth enemyHealth;
public Vector3 offset;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedShowHealthUI>d__8(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
try
{
healthBar.Show(enemyHealth, offset);
}
catch (Exception arg)
{
Plugin.Logger.LogDebug((object)$"Handling exception in DelayedShowHealthBar: {arg}");
try
{
healthUIElements.Remove(enemyHealth);
Object.Destroy((Object)(object)healthBar);
}
catch
{
}
}
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
internal static readonly Dictionary<EnemyHealth, CustomEnemyHealthUI> healthUIElements = new Dictionary<EnemyHealth, CustomEnemyHealthUI>();
[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
[HarmonyPrefix]
public static void ShowEnemyHealthOnHurt(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
int num = (int)((object)__instance).GetType().GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
Enemy val = (Enemy)((object)__instance).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
Vector3 position = val.CenterTransform.position;
int num2 = num - _damage;
if (SemiFunc.IsMasterClientOrSingleplayer())
{
try
{
EnemyParent val2 = (EnemyParent)((object)val).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
_ = (EnemyRigidbody)((object)val).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
bool flag = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
Vector3 val3 = default(Vector3);
val3.x = 0f;
val3.y = 0f;
val3.z = 0f;
bool flag2 = num2 <= 0 || flag;
Plugin.Logger.LogDebug((object)$"{val2.enemyName} HURT by {_damage}, currHealth: {num}, will have {num - _damage}, willDie:{flag2} ...");
CreateDamageUI(_damage, position);
if (!flag2)
{
CreateHealthUI(__instance, position);
}
return;
}
catch (Exception arg)
{
Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
return;
}
}
try
{
CreateDamageUI(_damage, val.CenterTransform.position);
}
catch (Exception arg2)
{
Plugin.Logger.LogError((object)$"FAILED TO ADD UI:\n{arg2}");
}
}
[HarmonyPatch(typeof(EnemyHealth), "HurtRPC")]
[HarmonyPrefix]
public static void ShowEnemyHealthOnHurtRPC(int _damage, Vector3 _hurtDirection, EnemyHealth __instance)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
if (SemiFunc.IsMasterClientOrSingleplayer())
{
return;
}
bool flag = false;
int num = Math.Abs(_damage);
if (_damage < 0)
{
flag = true;
}
try
{
Enemy val = (Enemy)((object)__instance).GetType().GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
EnemyParent val2 = (EnemyParent)((object)val).GetType().GetField("EnemyParent", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
_ = (EnemyRigidbody)((object)val).GetType().GetField("Rigidbody", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(val);
bool flag2 = (bool)typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
Vector3 val3 = default(Vector3);
val3.x = 0f;
val3.y = 0f;
val3.z = 0f;
Vector3 position = val.CenterTransform.position;
FieldInfo field = ((object)__instance).GetType().GetField("healthCurrent", BindingFlags.Instance | BindingFlags.NonPublic);
int num2 = (int)field.GetValue(__instance);
int num3 = num2 - num;
if (ConfigManager.AttemptMultiplayerHealthSync.Value && flag)
{
field.SetValue(__instance, num3);
CreateDamageUI(num, position);
}
bool flag3 = num3 <= 0 || flag2;
Plugin.Logger.LogDebug((object)$"{val2.enemyName} HURT by {num}, currHealth: {num2}, will have {num3}, willDie:{flag3} ...");
if (!flag3)
{
CreateHealthUI(__instance, position);
}
}
catch (Exception arg)
{
Plugin.Logger.LogError((object)$"LogEnemyHurt failed:\n{arg}");
}
}
[HarmonyPatch(typeof(EnemyBang), "ExplodeRPC")]
[HarmonyPostfix]
public static void HandleBangerExplode(EnemyBang __instance)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
try
{
Enemy obj = (Enemy)typeof(EnemyBang).GetField("enemy", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
EnemyHealth key = (EnemyHealth)typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
if (healthUIElements.TryGetValue(key, out var value))
{
value.hasExploded = true;
}
}
catch (Exception arg)
{
Plugin.Logger.LogError((object)$"HandleBangerExplode failed:\n{arg}");
}
}
public static void HurtColliderEnemyHurtHook(EnemyHealth enemyHealth, int damage, Vector3 hurtDirection)
{
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: 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)
if (SemiFunc.IsNotMasterClient() || !SemiFunc.IsMultiplayer())
{
enemyHealth.Hurt(damage, hurtDirection);
return;
}
try
{
if (ConfigManager.AttemptMultiplayerHealthSync.Value)
{
((PhotonView)typeof(EnemyHealth).GetField("photonView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(enemyHealth)).RPC("HurtRPC", (RpcTarget)0, new object[2]
{
-damage,
hurtDirection
});
}
}
finally
{
enemyHealth.Hurt(damage, hurtDirection);
}
}
internal static void CreateHealthUI(EnemyHealth enemyHealth, Vector3 enemyPosition)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: 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)
Vector3 val = default(Vector3);
val.x = 0f;
val.y = 0f;
val.z = 0f;
Vector3 val2 = val;
if (!healthUIElements.ContainsKey(enemyHealth))
{
GameObject obj = Object.Instantiate<GameObject>(WorldSpaceUIParent.instance.TTSPrefab, ((Component)WorldSpaceUIParent.instance).transform.position, ((Component)WorldSpaceUIParent.instance).transform.rotation, ((Component)WorldSpaceUIParent.instance).transform);
Object.Destroy((Object)(object)obj.GetComponent<WorldSpaceUITTS>());
CustomEnemyHealthUI customEnemyHealthUI = obj.AddComponent<CustomEnemyHealthUI>();
typeof(WorldSpaceUIChild).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(customEnemyHealthUI, enemyPosition);
healthUIElements.Add(enemyHealth, customEnemyHealthUI);
((MonoBehaviour)enemyHealth).StartCoroutine(DelayedShowHealthUI(healthUIElements[enemyHealth], enemyHealth, val2));
}
else
{
healthUIElements[enemyHealth].Show(enemyHealth, val2);
}
}
internal static void CreateDamageUI(int damage, Vector3 worldPosition)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
if (ConfigManager.ShowEnemyDamage.Value)
{
WorldSpaceUIParent instance = WorldSpaceUIParent.instance;
WorldSpaceUIValueLost component = Object.Instantiate<GameObject>(instance.valueLostPrefab, ((Component)instance).transform.position, ((Component)instance).transform.rotation, ((Component)instance).transform).GetComponent<WorldSpaceUIValueLost>();
typeof(WorldSpaceUIValueLost).GetField("worldPosition", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component, worldPosition);
typeof(WorldSpaceUIValueLost).GetField("value", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component, damage);
FieldInfo field = typeof(WorldSpaceUIValueLost).GetField("text", BindingFlags.Instance | BindingFlags.NonPublic);
((MonoBehaviour)component).StartCoroutine(DelayedSetText(field, component, $"-{damage}"));
((List<WorldSpaceUIValueLost>)((object)instance).GetType().GetField("valueLostList", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance)).Add(component);
}
}
[IteratorStateMachine(typeof(<DelayedSetText>d__7))]
internal static IEnumerator DelayedSetText(FieldInfo fieldInfo, object target, string targetText)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedSetText>d__7(0)
{
fieldInfo = fieldInfo,
target = target,
targetText = targetText
};
}
[IteratorStateMachine(typeof(<DelayedShowHealthUI>d__8))]
internal static IEnumerator DelayedShowHealthUI(CustomEnemyHealthUI healthBar, EnemyHealth enemyHealth, Vector3 offset)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedShowHealthUI>d__8(0)
{
healthBar = healthBar,
enemyHealth = enemyHealth,
offset = offset
};
}
}
[HarmonyPatch(typeof(HurtCollider), "EnemyHurt")]
public static class EnemyHurtTranspilerPatch
{
[CompilerGenerated]
private sealed class <Transpiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
private IEnumerable<CodeInstruction> instructions;
public IEnumerable<CodeInstruction> <>3__instructions;
private MethodInfo <targetHurtMethod>5__2;
private MethodInfo <hookMethod>5__3;
private IEnumerator<CodeInstruction> <>7__wrap3;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Transpiler>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || (uint)(num - 1) <= 1u)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<targetHurtMethod>5__2 = null;
<hookMethod>5__3 = null;
<>7__wrap3 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Expected O, but got Unknown
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<targetHurtMethod>5__2 = AccessTools.Method(typeof(EnemyHealth), "Hurt", new Type[2]
{
typeof(int),
typeof(Vector3)
}, (Type[])null);
<hookMethod>5__3 = AccessTools.Method(typeof(Patches), "HurtColliderEnemyHurtHook", new Type[3]
{
typeof(EnemyHealth),
typeof(int),
typeof(Vector3)
}, (Type[])null);
<>7__wrap3 = instructions.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -3;
break;
case 2:
<>1__state = -3;
break;
}
if (<>7__wrap3.MoveNext())
{
CodeInstruction current = <>7__wrap3.Current;
if (current.opcode == OpCodes.Callvirt && current.operand is MethodInfo methodInfo && methodInfo == <targetHurtMethod>5__2)
{
<>2__current = new CodeInstruction(OpCodes.Call, (object)<hookMethod>5__3);
<>1__state = 1;
return true;
}
<>2__current = current;
<>1__state = 2;
return true;
}
<>m__Finally1();
<>7__wrap3 = null;
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap3 != null)
{
<>7__wrap3.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<Transpiler>d__0 <Transpiler>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<Transpiler>d__ = this;
}
else
{
<Transpiler>d__ = new <Transpiler>d__0(0);
}
<Transpiler>d__.instructions = <>3__instructions;
return <Transpiler>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<Transpiler>d__0))]
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Transpiler>d__0(-2)
{
<>3__instructions = instructions
};
}
}
[BepInPlugin("REPO_ShowEnemyHealth", "ShowEnemyHealth", "1.0.3")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger;
private Harmony _harmony;
private void Awake()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Plugin ShowEnemyHealth by Rozza is loaded!");
ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
_harmony = new Harmony("EnemyHealth");
PatchAll();
}
private void PatchAll()
{
IEnumerable<Type> enumerable;
try
{
enumerable = Assembly.GetExecutingAssembly().GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
enumerable = ex.Types.Where((Type t) => t != null);
}
foreach (Type item in enumerable)
{
_harmony.PatchAll(item);
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "REPO_ShowEnemyHealth";
public const string PLUGIN_NAME = "ShowEnemyHealth";
public const string PLUGIN_VERSION = "1.0.3";
}
}