using 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.Logging;
using Configgy;
using HarmonyLib;
using Healthbars;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Healthbars")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+acbf77da764365b6043b3af683c417bb84afbc2a")]
[assembly: AssemblyProduct("Healthbars")]
[assembly: AssemblyTitle("Healthbars")]
[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;
}
}
}
public class BarSegment : MonoBehaviour
{
public Image bar;
public Image DPSBar;
public LayoutElement layoutElement;
}
public enum SegmentMode
{
Disabled,
Segmented
}
public class Healthbar : MonoBehaviour
{
private const float SEGMENT_GAP_RATIO = 0.1875f;
protected static Dictionary<EnemyIdentifier, Healthbar> activeHealthbars;
public TextMeshProUGUI label;
public HorizontalLayoutGroup barLayout;
public BarSegment bar;
public CanvasGroup canvasGroup;
public TextMeshProUGUI damageLabel;
public Image staminaBar;
public Image bg1;
public Image bg2;
[HideInInspector]
public bool setupStamina;
public float[] segmentValues;
public BarSegment[] barSegments;
public EnemyType enemyType;
public RectTransform rectTransform;
public EnemyIdentifier enemy;
public Enemy enemyScript;
public Transform head;
public Mask mask;
public float enemyHeight;
private const int BUFFER = 6;
private float timeSinceDamaged = 99.9f;
private float lastHealth = 0f;
private float maxHealth = 0f;
private float damage = 0f;
private float healthMultiplier = 1f;
private float dpsFill = 1f;
public void Start()
{
//IL_003b: 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_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Invalid comparison between Unknown and I4
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: 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)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: 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_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
enemyScript = ((Component)enemy).GetComponent<Enemy>();
mask = ((Component)bar).GetComponent<Mask>();
ref RectTransform reference = ref rectTransform;
Transform transform = ((Component)this).transform;
reference = (RectTransform)(object)((transform is RectTransform) ? transform : null);
enemyType = enemy.enemyType;
if ((int)enemyType == 1 && (Object)(object)((Component)enemy).GetComponent<Mandalore>() != (Object)null)
{
enemyType = (EnemyType)25;
}
healthMultiplier = enemy.totalHealthModifier;
Material material = Object.Instantiate<Material>(((Graphic)bar.bar).material);
((Graphic)bar.bar).material = material;
Material material2 = Object.Instantiate<Material>(((Graphic)bar.DPSBar).material);
((Graphic)bar.DPSBar).material = material2;
if (enemy.isBoss)
{
switch (enemy.GetPrivateField<int>("difficulty"))
{
case 4:
healthMultiplier *= 1.5f;
break;
case 5:
healthMultiplier *= 2f;
break;
}
}
Collider component = ((Component)enemy).GetComponent<Collider>();
Bounds bounds = component.bounds;
float y = (((Bounds)(ref bounds)).center - ((Component)enemy).transform.position).y;
bounds = component.bounds;
enemyHeight = y + ((Bounds)(ref bounds)).extents.y;
setupStamina = false;
UpdateSegments();
SeasonalHats componentInChildren = ((Component)enemy).GetComponentInChildren<SeasonalHats>(true);
head = ((componentInChildren != null) ? ((Component)componentInChildren).transform : null);
if ((Object)(object)head == (Object)null)
{
head = ((Component)enemy).transform;
}
}
private void UpdateSegments()
{
//IL_00cd: 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_011b: Unknown result type (might be due to invalid IL or missing references)
float segments = GetSegments();
int value = ((ConfigValueElement<int>)(object)Plugin.height).Value;
int num = 0;
float num2 = 25f * (float)((ConfigValueElement<int>)(object)Plugin.width).Value;
int num3 = value + num;
float num4 = Mathf.Floor(segments) + segments % 1f * 0.8125f;
if (num4 % 1f < 0.005f || num4 % 1f > 0.9f)
{
num4 -= 0.1875f;
}
float num5 = ((ConfigValueElement<int>)(object)Plugin.width).Value;
if (maxHealth * healthMultiplier > 100f)
{
num5 -= 8f;
}
float num6 = num4 * num5;
num6 = Mathf.CeilToInt(num6);
num6 = Mathf.Min(num6, 1200f);
rectTransform.sizeDelta = new Vector2(num6, (float)value);
((Graphic)bar.bar).material.SetTextureScale("_MainTex", new Vector2(num4, 1f));
((Graphic)bar.DPSBar).material.SetTextureScale("_MainTex", new Vector2(num4, 1f));
((Graphic)bar.bar).SetMaterialDirty();
((Graphic)bar.DPSBar).SetMaterialDirty();
((Behaviour)mask).enabled = false;
((Behaviour)mask).enabled = true;
}
private void Update()
{
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0278: Unknown result type (might be due to invalid IL or missing references)
//IL_0574: Unknown result type (might be due to invalid IL or missing references)
//IL_0579: Unknown result type (might be due to invalid IL or missing references)
//IL_0591: Unknown result type (might be due to invalid IL or missing references)
//IL_0596: Unknown result type (might be due to invalid IL or missing references)
//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
if (maxHealth == 0f)
{
lastHealth = enemy.health;
maxHealth = enemy.health;
UpdateSegments();
if (maxHealth < ((ConfigValueElement<float>)(object)Plugin.minMaxHealth).Value)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
if (enemyScript.originalHealth != 0f)
{
maxHealth = enemyScript.originalHealth;
}
timeSinceDamaged += Time.deltaTime;
canvasGroup.alpha = Mathf.InverseLerp(5f, 4.5f, timeSinceDamaged);
if ((Object)(object)enemy == (Object)null || (enemy.health <= 0f && canvasGroup.alpha <= 0f))
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
if ((Object)(object)head == (Object)null)
{
head = ((Component)enemy).transform;
}
Vector3 val = MonoSingleton<CameraController>.Instance.cam.WorldToScreenPoint(GetHealthbarPosition());
if (val.z < 0f)
{
canvasGroup.alpha = 0f;
}
((Component)bar).gameObject.SetActive(canvasGroup.alpha > 0f);
((Component)bg1).gameObject.SetActive(canvasGroup.alpha > 0f);
((Component)bg2).gameObject.SetActive(canvasGroup.alpha > 0f);
int privateField = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("width");
int privateField2 = MonoSingleton<PostProcessV2_Handler>.Instance.GetPrivateField<int>("height");
val.x *= Screen.width;
val.y *= Screen.height;
val.x /= privateField;
val.y /= privateField2;
val.x = Mathf.Round(val.x);
val.y = Mathf.Round(val.y);
((Transform)rectTransform).position = val + new Vector3(0f, 12f, 0f);
float totalHealthModifier = enemy.totalHealthModifier;
if (totalHealthModifier != healthMultiplier)
{
healthMultiplier = totalHealthModifier;
UpdateSegments();
}
if (lastHealth != enemy.health && (lastHealth > 0f || enemy.health > 0f))
{
float num = Mathf.Max(lastHealth, 0f);
if (timeSinceDamaged <= 4f)
{
damage += Mathf.Min(lastHealth - enemy.health, num) * healthMultiplier;
}
else
{
damage = Mathf.Min(lastHealth - enemy.health, num) * healthMultiplier;
}
UpdateDamageLabel();
lastHealth = enemy.health;
timeSinceDamaged = 0f;
}
dpsFill = Mathf.Max(enemy.health * healthMultiplier, Mathf.MoveTowards(dpsFill, enemy.health * healthMultiplier, Time.deltaTime * Mathf.Lerp(1f, 10f, (dpsFill - enemy.health * healthMultiplier) / 10f)));
float segments = GetSegments();
float num2 = Mathf.Floor(segments) + segments % 1f * 0.8125f;
if (num2 % 1f < 0.005f || num2 % 1f > 0.9f)
{
num2 -= 0.1875f;
}
float num3 = maxHealth * healthMultiplier / segments;
float num4 = enemy.health * healthMultiplier / num3;
float num5 = dpsFill / num3;
float num6 = 1f / num2;
float num7 = Mathf.Floor(num4) + num4 % 1f * 0.8125f;
float num8 = Mathf.Floor(num5) + num5 % 1f * 0.8125f;
bar.bar.fillAmount = num7 * num6;
bar.DPSBar.fillAmount = num8 * num6;
string text = ((float)Mathf.CeilToInt(maxHealth * 100f * healthMultiplier) / 100f).ToString();
string text2 = ((float)Mathf.CeilToInt(Mathf.Max(enemy.health * 100f * healthMultiplier, 0f)) / 100f).ToString("0.00");
((TMP_Text)label).text = text2 + "<space=0.25em><size=75%><color=#FFFA>" + text;
Color value = ((ConfigValueElement<Color>)(object)Plugin.normalColor).Value;
if (enemy.isBoss)
{
value = ((ConfigValueElement<Color>)(object)Plugin.bossColor).Value;
}
if (enemy.blessed)
{
value = ((ConfigValueElement<Color>)(object)Plugin.blessedColor).Value;
}
((Graphic)bg1).color = ((ConfigValueElement<Color>)(object)Plugin.outlineColor).Value;
((Graphic)bg2).color = ((ConfigValueElement<Color>)(object)Plugin.bgColor).Value;
((Graphic)bar.bar).color = value;
}
private Vector3 GetHealthbarPosition()
{
//IL_000c: 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_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)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
return ((Component)enemy).transform.position + enemyHeight * Vector3.up;
}
private void UpdateDamageLabel()
{
if (!((ConfigValueElement<bool>)(object)Plugin.showDamageLabel).Value)
{
((TMP_Text)damageLabel).text = "";
return;
}
float num = Mathf.Sign(damage);
float num2 = num;
if (num2 != 1f)
{
if (num2 != 0f)
{
if (num2 == -1f)
{
((TMP_Text)damageLabel).text = $"<color=#0F0>+{(float)Mathf.FloorToInt(damage * -100f) / 100f}";
}
}
else
{
((TMP_Text)damageLabel).text = "-0";
}
}
else
{
((TMP_Text)damageLabel).text = $"<color=#F00>-{(float)Mathf.FloorToInt(damage * 100f) / 100f}";
}
}
private void OnDestroy()
{
}
private float GetSegments()
{
float num = maxHealth * healthMultiplier;
SegmentMode value = ((ConfigValueElement<SegmentMode>)(object)Plugin.segmentedBars).Value;
SegmentMode segmentMode = value;
if (segmentMode != SegmentMode.Disabled && segmentMode == SegmentMode.Segmented)
{
float num2 = 5f / healthMultiplier;
float num3 = maxHealth / num2;
if (num3 > 250f)
{
return 1f;
}
return num3;
}
return 1f;
}
}
namespace Healthbars
{
[BepInPlugin("Healthbars", "Healthbars", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public const bool ENABLE_STAMINA_BAR = false;
public const bool PER_PHASE_SEGMENTING = false;
public static Plugin instance;
public static GameObject ob;
public static GameObject healthbar;
public static Canvas canvas;
internal static ConfigBuilder config;
internal static ManualLogSource Log;
[Configgable("", null, 0, null)]
public static ConfigColor bgColor = new ConfigColor(new Color(1f, 1f, 1f));
[Configgable("", null, 0, null)]
public static ConfigColor outlineColor = new ConfigColor(new Color(0.213f, 0.213f, 0.213f));
[Configgable("", null, 0, null)]
public static ConfigColor bossColor = new ConfigColor(new Color(1f, 0.28f, 0.28f));
[Configgable("", null, 0, null)]
public static ConfigColor normalColor = new ConfigColor(new Color(1f, 0.82f, 0.28f));
[Configgable("", null, 0, null)]
public static ConfigColor blessedColor = new ConfigColor(new Color(0.28f, 0.82f, 1f));
[Configgable("", null, 0, null)]
public static IntegerSlider width = new IntegerSlider(24, 16, 32);
[Configgable("", null, 0, null)]
public static IntegerSlider height = new IntegerSlider(10, 6, 14);
[Configgable("", null, 0, "The minimum BASE health (inclusive) of an enemy to display a healthbar.\r\nPersonal Recommendations:\r\n5 - Schisms and above display healthbar\r\n4.5 - Streetcleaners and above display healthbar\r\n0 - All enemies display healthbar")]
public static ConfigInputField<float> minMaxHealth = new ConfigInputField<float>(5f, (Func<float, bool>)null, (Func<string, ValueTuple<bool, float>>)null);
public static ConfigInputField<float> offsetLeft = new ConfigInputField<float>(0.8f, (Func<float, bool>)null, (Func<string, ValueTuple<bool, float>>)null);
public static ConfigInputField<float> offsetRight = new ConfigInputField<float>(1.99f, (Func<float, bool>)null, (Func<string, ValueTuple<bool, float>>)null);
[Configgable("", "Segmented Bars", 0, null)]
public static ConfigDropdown<SegmentMode> segmentedBars = new ConfigDropdown<SegmentMode>(new SegmentMode[2]
{
SegmentMode.Disabled,
SegmentMode.Segmented
}, SegmentMode.Segmented, (string[])null);
[Configgable("", "Show Health Text", 0, null)]
public static ConfigToggle showHealthLabel = new ConfigToggle(true);
[Configgable("", "Show Damage Text", 0, null)]
public static ConfigToggle showDamageLabel = new ConfigToggle(true);
[Configgable("", "Show Max Health Text", 0, null)]
public static ConfigToggle showMaxHealth = new ConfigToggle(true);
private void Awake()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Expected O, but got Unknown
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
Harmony val = new Harmony("me.eladnlg.healthbars");
val.PatchAll();
ob = ((Component)this).gameObject;
instance = this;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Healthbars is loaded!");
AssetBundle val2 = AssetUtils.LoadAssetBundleFromResources("healthbars", Assembly.GetExecutingAssembly());
healthbar = val2.LoadAsset<GameObject>("Healthbar");
if ((Object)(object)healthbar == (Object)null)
{
throw new NullReferenceException("Healthbar asset is null!");
}
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Healthbars is loade2d!");
canvas = Object.Instantiate<GameObject>(val2.LoadAsset<GameObject>("HealthbarCanvas")).GetComponent<Canvas>();
Object.DontDestroyOnLoad((Object)(object)((Component)canvas).gameObject);
((Object)((Component)canvas).gameObject).hideFlags = (HideFlags)61;
config = new ConfigBuilder("Healthbars", "me.eladnlg.healthbars");
config.BuildAll();
Log = ((BaseUnityPlugin)this).Logger;
}
}
internal static class ReflectionUtils
{
public static T GetPrivateField<T>(this object obj, string field)
{
Type type = obj.GetType();
if (type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic) == null)
{
throw new ArgumentException("The field " + field + " does not exist in target class " + type.Name + "!");
}
return (T)type.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
}
public static class PluginInfo
{
public const string PLUGIN_GUID = "Healthbars";
public const string PLUGIN_NAME = "Healthbars";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace Healthbars.Patches
{
[HarmonyPatch(typeof(EnemyIdentifier))]
public class EnemyPatch
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
public static void EnemySpawned(EnemyIdentifier __instance)
{
if (!(__instance.health * __instance.totalHealthModifier < ((ConfigValueElement<float>)(object)Plugin.minMaxHealth).Value))
{
GameObject val = Object.Instantiate<GameObject>(Plugin.healthbar, ((Component)Plugin.canvas).transform);
val.GetComponent<Healthbar>().enemy = __instance;
}
}
}
}
namespace Jotunn.Utils
{
public static class AssetUtils
{
public const char AssetBundlePathSeparator = '$';
public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Expected O, but got Unknown
string text = texturePath;
if (relativePath)
{
text = Path.Combine(Paths.PluginPath, texturePath);
}
if (!File.Exists(text))
{
return null;
}
if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
{
throw new Exception("LoadTexture can only load png or jpg textures");
}
byte[] array = File.ReadAllBytes(text);
Texture2D val = new Texture2D(2, 2);
val.LoadRawTextureData(array);
return val;
}
public static Sprite LoadSpriteFromFile(string spritePath)
{
//IL_002e: 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_003b: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = LoadTexture(spritePath);
if ((Object)(object)val != (Object)null)
{
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), default(Vector2), 100f);
}
return null;
}
public static AssetBundle LoadAssetBundle(string bundlePath)
{
string text = Path.Combine(Paths.PluginPath, bundlePath);
if (!File.Exists(text))
{
return null;
}
return AssetBundle.LoadFromFile(text);
}
public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
{
if (resourceAssembly == null)
{
throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
}
string text = null;
try
{
text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
}
catch (Exception)
{
}
if (text == null)
{
Debug.LogError((object)("AssetBundle " + bundleName + " not found in assembly manifest"));
return null;
}
AssetBundle result;
using (Stream stream = resourceAssembly.GetManifestResourceStream(text))
{
result = AssetBundle.LoadFromStream(stream);
}
return result;
}
public static string LoadText(string path)
{
string text = Path.Combine(Paths.PluginPath, path);
if (!File.Exists(text))
{
Debug.LogError((object)("Error, failed to load contents from non-existant path: $" + text));
return null;
}
return File.ReadAllText(text);
}
public static Sprite LoadSprite(string assetPath)
{
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
string text = Path.Combine(Paths.PluginPath, assetPath);
if (!File.Exists(text))
{
return null;
}
if (text.Contains('$'.ToString()))
{
string[] array = text.Split('$');
string text2 = array[0];
string text3 = array[1];
AssetBundle val = AssetBundle.LoadFromFile(text2);
Sprite result = val.LoadAsset<Sprite>(text3);
val.Unload(false);
return result;
}
Texture2D val2 = LoadTexture(text, relativePath: false);
if (!Object.op_Implicit((Object)(object)val2))
{
return null;
}
return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), Vector2.zero);
}
}
}