using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using HarmonyLib;
using MelonLoader;
using MimesisHealth;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(HealthMod), "Health & Damage Indicators", "1.0.0", "Xomik", null)]
[assembly: MelonGame("ReLUGames", "MIMESIS")]
[assembly: AssemblyTitle("mimesisMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mimesisMod")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c15bb9a0-acc9-4201-9026-c0303e372288")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MimesisHealth;
public class HealthMod : MelonMod
{
public override void OnInitializeMelon()
{
((MelonBase)this).LoggerInstance.Msg("Health & Damage Indicators 1.0.0 Loaded Successfully!");
}
}
[HarmonyPatch(typeof(VMonster), "Update")]
public static class MonsterHealthPatch
{
private static Dictionary<int, GameObject> _cachedBodies = new Dictionary<int, GameObject>();
private static Dictionary<int, long> _previousHp = new Dictionary<int, long>();
private static float _nextScanTime = 0f;
[HarmonyPostfix]
public static void Postfix(VMonster __instance)
{
if (__instance == null)
{
return;
}
long num = 0L;
long num2 = 100L;
try
{
object value = Traverse.Create((object)__instance).Property("StatControlUnit", (object[])null).GetValue();
if (value != null)
{
num = (long)Traverse.Create(value).Method("GetCurrentHP", Array.Empty<object>()).GetValue();
object value2 = Traverse.Create(value).Method("GetMaxHP", Array.Empty<object>()).GetValue();
if (value2 != null)
{
num2 = (long)value2;
}
}
}
catch
{
return;
}
if (num2 <= 0)
{
num2 = 1L;
}
GameObject bodyForMonster = GetBodyForMonster(__instance);
if (!((Object)(object)bodyForMonster != (Object)null))
{
return;
}
if (_previousHp.TryGetValue(((VActor)__instance).ObjectID, out var value3))
{
if (num < value3)
{
long damageAmount = value3 - num;
SpawnDamageNumber(bodyForMonster, damageAmount);
_previousHp[((VActor)__instance).ObjectID] = num;
}
else if (num > value3)
{
_previousHp[((VActor)__instance).ObjectID] = num;
}
}
else
{
_previousHp[((VActor)__instance).ObjectID] = num;
}
UpdateHealthUI(bodyForMonster, num, num2);
}
private static void SpawnDamageNumber(GameObject body, long damageAmount)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: 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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: 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)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Expected O, but got Unknown
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = body.transform.position;
float num = 1.6f * body.transform.localScale.y;
Vector3 val = position + Vector3.up * num;
float num2 = Random.Range(-0.3f, 0.3f);
float num3 = Random.Range(-0.2f, 0.2f);
float num4 = Random.Range(-0.3f, 0.3f);
Vector3 position2 = val + new Vector3(num2, num3, num4);
GameObject val2 = new GameObject("DamagePopup");
val2.transform.position = position2;
val2.transform.localScale = Vector3.one * 0.003f;
Canvas val3 = val2.AddComponent<Canvas>();
val3.renderMode = (RenderMode)2;
GameObject val4 = new GameObject("Text");
val4.transform.SetParent(val2.transform, false);
Text val5 = val4.AddComponent<Text>();
val5.text = "-" + damageAmount;
val5.alignment = (TextAnchor)4;
val5.fontSize = 80;
val5.horizontalOverflow = (HorizontalWrapMode)1;
val5.verticalOverflow = (VerticalWrapMode)1;
val5.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
((Graphic)val5).color = new Color(1f, 0.5f, 0f, 1f);
Outline val6 = val4.AddComponent<Outline>();
((Shadow)val6).effectColor = Color.black;
((Shadow)val6).effectDistance = new Vector2(2f, -2f);
val2.AddComponent<DamagePopup>();
}
private static void UpdateHealthUI(GameObject body, long currentHp, long maxHp)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: 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_00d2: Expected O, but got Unknown
//IL_0123: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
Transform val = body.transform.Find("ModHealthCanvas");
HealthBarLifecycle healthBarLifecycle;
Text val5;
if ((Object)(object)val == (Object)null)
{
GameObject val2 = new GameObject("ModHealthCanvas");
val2.transform.SetParent(body.transform);
float num = 1.6f * body.transform.localScale.y + 0.4f;
val2.transform.localPosition = new Vector3(0f, num, 0f);
val2.transform.localScale = Vector3.one * 0.005f;
val2.transform.localRotation = Quaternion.identity;
Canvas val3 = val2.AddComponent<Canvas>();
val3.renderMode = (RenderMode)2;
val2.AddComponent<FaceCameraScript>();
healthBarLifecycle = val2.AddComponent<HealthBarLifecycle>();
GameObject val4 = new GameObject("HP_Text");
val4.transform.SetParent(val2.transform, false);
val5 = val4.AddComponent<Text>();
val5.alignment = (TextAnchor)4;
val5.horizontalOverflow = (HorizontalWrapMode)1;
val5.fontSize = 60;
val5.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
Outline val6 = val4.AddComponent<Outline>();
((Shadow)val6).effectColor = Color.black;
((Shadow)val6).effectDistance = new Vector2(1f, -1f);
}
else
{
GameObject val2 = ((Component)val).gameObject;
val5 = ((Component)val).GetComponentInChildren<Text>();
healthBarLifecycle = val2.GetComponent<HealthBarLifecycle>();
if ((Object)(object)healthBarLifecycle == (Object)null)
{
healthBarLifecycle = val2.AddComponent<HealthBarLifecycle>();
}
}
if ((Object)(object)val5 != (Object)null)
{
long num2 = ((currentHp < 0) ? 0 : currentHp);
string text = $"{num2}/{maxHp}";
if (val5.text != text)
{
val5.text = text;
float num3 = (float)num2 / (float)maxHp;
num3 = Mathf.Clamp01(num3);
float num4 = Mathf.Lerp(0f, 0.33f, num3);
((Graphic)val5).color = Color.HSVToRGB(num4, 1f, 1f);
}
if ((Object)(object)healthBarLifecycle != (Object)null)
{
healthBarLifecycle.UpdateStatus(num2);
}
}
}
private static GameObject GetBodyForMonster(VMonster logic)
{
//IL_006a: 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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
if (_cachedBodies.TryGetValue(((VActor)logic).ObjectID, out var value))
{
if ((Object)(object)value != (Object)null)
{
return value;
}
_cachedBodies.Remove(((VActor)logic).ObjectID);
}
if (Time.time < _nextScanTime)
{
return null;
}
_nextScanTime = Time.time + 0.5f;
Vector3 positionVector = ((VActor)logic).PositionVector;
Animator[] array = Object.FindObjectsByType<Animator>((FindObjectsSortMode)0);
Animator[] array2 = array;
foreach (Animator val in array2)
{
if (Vector3.Distance(((Component)val).transform.position, positionVector) < 0.5f)
{
_cachedBodies[((VActor)logic).ObjectID] = ((Component)val).gameObject;
return ((Component)val).gameObject;
}
}
return null;
}
}
public class FaceCameraScript : MonoBehaviour
{
private void LateUpdate()
{
//IL_001d: 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_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Camera.main != (Object)null)
{
((Component)this).transform.rotation = Quaternion.LookRotation(((Component)this).transform.position - ((Component)Camera.main).transform.position);
}
}
}
public class DamagePopup : MonoBehaviour
{
private float _lifeTime = 0.8f;
private float _timer = 0f;
private float _moveSpeed = 1f;
private void Start()
{
//IL_001c: 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_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Camera.main != (Object)null)
{
((Component)this).transform.rotation = Quaternion.LookRotation(((Component)this).transform.position - ((Component)Camera.main).transform.position);
}
}
private void Update()
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_0066: 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_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Camera.main != (Object)null)
{
((Component)this).transform.rotation = Quaternion.LookRotation(((Component)this).transform.position - ((Component)Camera.main).transform.position);
}
Transform transform = ((Component)this).transform;
transform.position += Vector3.up * _moveSpeed * Time.deltaTime;
_timer += Time.deltaTime;
if (_timer > _lifeTime)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
public class HealthBarLifecycle : MonoBehaviour
{
private float _deathTimer = 0f;
private bool _isDead = false;
private const float TIME_TO_DESTROY = 4f;
public void UpdateStatus(long currentHp)
{
if (currentHp <= 0)
{
if (!_isDead)
{
_isDead = true;
_deathTimer = 0f;
}
}
else
{
_isDead = false;
_deathTimer = 0f;
}
}
private void Update()
{
if (_isDead)
{
_deathTimer += Time.deltaTime;
if (_deathTimer > 4f)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
}