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 ShowDamage HealthBar v2.1.1
Silksong_HealthBar.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.UI; [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("Silksong_HealthBar")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.1.1.0")] [assembly: AssemblyInformationalVersion("2.1.1+06a4c918fba54a77942cb428b6410ae962a688a8")] [assembly: AssemblyProduct("Silksong_HealthBar")] [assembly: AssemblyTitle("Silksong_HealthBar")] [assembly: AssemblyVersion("2.1.1.0")] namespace HealthbarPlugin; public static class BossHealthBarManager { private static readonly List<BossHealthBar> Bars = new List<BossHealthBar>(); private static bool refreshing; public static void Register(BossHealthBar bar) { if ((Object)(object)bar != (Object)null && !Bars.Contains(bar)) { Bars.Add(bar); } RefreshLayout(); } public static void Unregister(BossHealthBar bar) { if ((Object)(object)bar != (Object)null) { Bars.Remove(bar); } RefreshLayout(); } public static void RegisterBossHealthBar(BossHealthBar bar) { Register(bar); } public static void UnregisterBossHealthBar(BossHealthBar bar) { Unregister(bar); } public static void RefreshLayout() { if (refreshing) { return; } refreshing = true; try { for (int num = Bars.Count - 1; num >= 0; num--) { if ((Object)(object)Bars[num] == (Object)null) { Bars.RemoveAt(num); } } int num2 = 0; foreach (BossHealthBar bar in Bars) { if (bar.IsDisplayed) { bar.ApplyManagedPosition(num2); num2++; } } } finally { refreshing = false; } } } public class ConfigGUI : MonoBehaviour { private bool showGUI; private Rect windowRect = new Rect(20f, 20f, 400f, 600f); private Vector2 scrollPosition = Vector2.zero; private bool isEnglish; private CursorLockMode previousCursorLockMode; private bool previousCursorVisible; private Dictionary<string, string> texts = new Dictionary<string, string> { { "window_title_cn", "Silksong HealthBar 配置面板" }, { "window_title_en", "Silksong HealthBar Config Panel" }, { "display_settings_cn", "=== 显示开关配置 ===" }, { "display_settings_en", "=== Display Settings ===" }, { "damage_text_settings_cn", "=== 伤害文本配置 ===" }, { "damage_text_settings_en", "=== Damage Text Settings ===" }, { "healthbar_settings_cn", "=== 血条配置 ===" }, { "healthbar_settings_en", "=== Health Bar Settings ===" }, { "boss_settings_cn", "=== BOSS血条配置 ===" }, { "boss_settings_en", "=== Boss Health Bar Settings ===" }, { "show_enemy_healthbar_cn", "显示普通敌人血条" }, { "show_enemy_healthbar_en", "Show Normal Enemy Health Bars" }, { "show_boss_healthbar_cn", "显示BOSS血条" }, { "show_boss_healthbar_en", "Show Boss Health Bars" }, { "show_damage_text_cn", "显示伤害文本" }, { "show_damage_text_en", "Show Damage Text" }, { "damage_text_use_sign_cn", "显示+/-符号" }, { "damage_text_use_sign_en", "Show +/- Signs" }, { "damage_text_use_sign_label_cn", "伤害文本使用符号:" }, { "damage_text_use_sign_label_en", "Damage Text Use Signs:" }, { "damage_text_duration_cn", "伤害文本持续时间" }, { "damage_text_duration_en", "Damage Text Duration" }, { "damage_text_fontsize_cn", "伤害文本字体大小" }, { "damage_text_fontsize_en", "Damage Text Font Size" }, { "damage_text_color_cn", "伤害文本颜色 (十六进制):" }, { "damage_text_color_en", "Damage Text Color (Hex):" }, { "healthbar_fill_color_cn", "血条填充颜色 (十六进制):" }, { "healthbar_fill_color_en", "Health Bar Fill Color (Hex):" }, { "healthbar_background_color_cn", "血条背景颜色 (十六进制):" }, { "healthbar_background_color_en", "Health Bar Background Color (Hex):" }, { "healthbar_width_cn", "血条宽度" }, { "healthbar_width_en", "Health Bar Width" }, { "healthbar_height_cn", "血条高度" }, { "healthbar_height_en", "Health Bar Height" }, { "show_healthbar_numbers_cn", "显示血量数字" }, { "show_healthbar_numbers_en", "Show Health Numbers" }, { "healthbar_numbers_fontsize_cn", "血量数字字体大小" }, { "healthbar_numbers_fontsize_en", "Health Numbers Font Size" }, { "healthbar_numbers_color_cn", "血量数字颜色 (十六进制):" }, { "healthbar_numbers_color_en", "Health Numbers Color (Hex):" }, { "healthbar_hide_delay_cn", "血条隐藏延迟" }, { "healthbar_hide_delay_en", "Health Bar Hide Delay" }, { "healthbar_numbers_vertical_offset_cn", "血量数字垂直偏移" }, { "healthbar_numbers_vertical_offset_en", "Health Numbers Vertical Offset" }, { "healthbar_numbers_inside_bar_cn", "血量数字显示在血条内部" }, { "healthbar_numbers_inside_bar_en", "Show Health Numbers Inside Bar" }, { "healthbar_numbers_auto_white_cn", "血量低于49%时自动变白" }, { "healthbar_numbers_auto_white_en", "Auto White on Low Health (49%)" }, { "healthbar_fill_margin_top_cn", "血条填充物上边距" }, { "healthbar_fill_margin_top_en", "Health Bar Fill Top Margin" }, { "healthbar_fill_margin_bottom_cn", "血条填充物下边距" }, { "healthbar_fill_margin_bottom_en", "Health Bar Fill Bottom Margin" }, { "boss_health_threshold_cn", "BOSS血量阈值" }, { "boss_health_threshold_en", "Boss Health Threshold" }, { "boss_healthbar_fill_color_cn", "BOSS血条填充颜色 (十六进制):" }, { "boss_healthbar_fill_color_en", "Boss Health Bar Fill Color (Hex):" }, { "boss_healthbar_background_color_cn", "BOSS血条背景颜色 (十六进制):" }, { "boss_healthbar_background_color_en", "Boss Health Bar Background Color (Hex):" }, { "boss_healthbar_width_cn", "BOSS血条宽度" }, { "boss_healthbar_width_en", "Boss Health Bar Width" }, { "boss_healthbar_height_cn", "BOSS血条高度" }, { "boss_healthbar_height_en", "Boss Health Bar Height" }, { "boss_healthbar_bottom_position_cn", "BOSS血条显示在底部" }, { "boss_healthbar_bottom_position_en", "Show Boss Health Bar at Bottom" }, { "boss_healthbar_name_color_cn", "BOSS名字颜色 (十六进制):" }, { "boss_healthbar_name_color_en", "Boss Name Color (Hex):" }, { "show_boss_healthbar_numbers_cn", "显示BOSS血量数字" }, { "show_boss_healthbar_numbers_en", "Show Boss Health Numbers" }, { "boss_healthbar_numbers_color_cn", "BOSS血量数字颜色 (十六进制):" }, { "boss_healthbar_numbers_color_en", "Boss Health Numbers Color (Hex):" }, { "boss_healthbar_fill_margin_top_cn", "BOSS血条填充物上边距" }, { "boss_healthbar_fill_margin_top_en", "Boss Health Bar Fill Top Margin" }, { "boss_healthbar_fill_margin_bottom_cn", "BOSS血条填充物下边距" }, { "boss_healthbar_fill_margin_bottom_en", "Boss Health Bar Fill Bottom Margin" }, { "boss_healthbar_fill_margin_left_cn", "BOSS血条填充物左边距" }, { "boss_healthbar_fill_margin_left_en", "Boss Health Bar Fill Left Margin" }, { "boss_healthbar_fill_margin_right_cn", "BOSS血条填充物右边距" }, { "boss_healthbar_fill_margin_right_en", "Boss Health Bar Fill Right Margin" }, { "healthbar_shape_cn", "敌人血条形状" }, { "healthbar_shape_en", "Enemy Health Bar Shape" }, { "boss_healthbar_shape_cn", "BOSS血条形状" }, { "boss_healthbar_shape_en", "Boss Health Bar Shape" }, { "shape_rectangle_cn", "长方形" }, { "shape_rectangle_en", "Rectangle" }, { "shape_rounded_cn", "圆角" }, { "shape_rounded_en", "Rounded" }, { "corner_radius_cn", "圆角半径" }, { "corner_radius_en", "Corner Radius" }, { "boss_corner_radius_cn", "BOSS血条圆角半径" }, { "boss_corner_radius_en", "Boss Health Bar Corner Radius" }, { "custom_texture_settings_cn", "=== 自定义材质配置 ===" }, { "custom_texture_settings_en", "=== Custom Texture Settings ===" }, { "use_custom_textures_cn", "启用自定义血条材质" }, { "use_custom_textures_en", "Enable Custom Health Bar Textures" }, { "trim_transparent_margins_cn", "自动裁剪填充贴图外围透明区域" }, { "trim_transparent_margins_en", "Trim Transparent Margins from Fill Textures" }, { "use_custom_enemy_background_cn", "启用自定义普通敌人血条背景" }, { "use_custom_enemy_background_en", "Enable Custom Enemy Background" }, { "use_custom_boss_background_cn", "启用自定义BOSS血条背景" }, { "use_custom_boss_background_en", "Enable Custom Boss Background" }, { "custom_texture_scale_mode_cn", "材质缩放模式" }, { "custom_texture_scale_mode_en", "Texture Scale Mode" }, { "scale_mode_stretch_cn", "拉伸适应" }, { "scale_mode_stretch_en", "Stretch to Fit" }, { "scale_mode_aspect_cn", "保持比例" }, { "scale_mode_aspect_en", "Keep Aspect Ratio" }, { "reload_textures_cn", "重新加载材质" }, { "reload_textures_en", "Reload Textures" }, { "texture_path_info_cn", "材质路径: DLL目录/Texture/\nHpBar.png (敌人填充) | BG_Enemy.png (敌人背景)\nHpBar_Boss.png (BOSS填充) | BG_Boss.png (BOSS背景)" }, { "texture_path_info_en", "Texture Path: DLL Directory/Texture/\nHpBar.png (Enemy Fill) | BG_Enemy.png (Enemy Background)\nHpBar_Boss.png (Boss Fill) | BG_Boss.png (Boss Background)" }, { "performance_settings_cn", "=== 性能优化配置 ===" }, { "performance_settings_en", "=== Performance Settings ===" }, { "use_simplified_corners_cn", "使用简化圆角算法(推荐)" }, { "use_simplified_corners_en", "Use Simplified Corner Algorithm (Recommended)" }, { "save_config_cn", "保存配置" }, { "save_config_en", "Save Config" }, { "reset_defaults_cn", "恢复默认值" }, { "reset_defaults_en", "Reset to Defaults" }, { "close_panel_cn", "关闭面板" }, { "close_panel_en", "Close Panel" }, { "seconds_cn", "秒" }, { "seconds_en", "s" }, { "display_tips_cn", "修改后点击“保存配置”立即应用;关闭的血条会被清理。" }, { "display_tips_en", "Click Save Config to apply changes immediately; disabled bars are removed." } }; private string GetText(string key) { string text = (isEnglish ? "_en" : "_cn"); if (!texts.ContainsKey(key + text)) { return key; } return texts[key + text]; } private void Update() { //IL_0005: 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_002e: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(Plugin.ConfigGUI_Hotkey.Value)) { showGUI = !showGUI; if (showGUI) { previousCursorLockMode = Cursor.lockState; previousCursorVisible = Cursor.visible; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { RestoreCursor(); } } if (showGUI) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void OnDestroy() { if (showGUI) { RestoreCursor(); } } private void RestoreCursor() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Cursor.lockState = previousCursorLockMode; Cursor.visible = previousCursorVisible; } private void OnGUI() { //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_002d: Expected O, but got Unknown //IL_0028: 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) if (showGUI) { windowRect = GUI.Window(0, windowRect, new WindowFunction(ConfigWindow), GetText("window_title")); } } private void ConfigWindow(int windowID) { //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_00ab: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("中文", isEnglish ? GUI.skin.button : GUI.skin.box, Array.Empty<GUILayoutOption>())) { isEnglish = false; } if (GUILayout.Button("ENGLISH", isEnglish ? GUI.skin.box : GUI.skin.button, Array.Empty<GUILayoutOption>())) { isEnglish = true; } GUILayout.EndHorizontal(); GUILayout.Label(GetText("display_tips"), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); scrollPosition = GUILayout.BeginScrollView(scrollPosition, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("display_settings"), GUI.skin.box, Array.Empty<GUILayoutOption>()); Plugin.ShowEnemyHealthBar.Value = GUILayout.Toggle(Plugin.ShowEnemyHealthBar.Value, GetText("show_enemy_healthbar"), Array.Empty<GUILayoutOption>()); Plugin.ShowBossHealthBar.Value = GUILayout.Toggle(Plugin.ShowBossHealthBar.Value, GetText("show_boss_healthbar"), Array.Empty<GUILayoutOption>()); Plugin.ShowDamageText.Value = GUILayout.Toggle(Plugin.ShowDamageText.Value, GetText("show_damage_text"), Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("damage_text_use_sign_label"), Array.Empty<GUILayoutOption>()); Plugin.DamageTextUseSign.Value = GUILayout.Toggle(Plugin.DamageTextUseSign.Value, GetText("damage_text_use_sign"), Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); GUILayout.Label(GetText("damage_text_settings"), GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}{2}", GetText("damage_text_duration"), Plugin.DamageTextDuration.Value, GetText("seconds")), Array.Empty<GUILayoutOption>()); Plugin.DamageTextDuration.Value = GUILayout.HorizontalSlider(Plugin.DamageTextDuration.Value, 0.5f, 5f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1}", GetText("damage_text_fontsize"), Plugin.DamageTextFontSize.Value), Array.Empty<GUILayoutOption>()); Plugin.DamageTextFontSize.Value = (int)GUILayout.HorizontalSlider((float)Plugin.DamageTextFontSize.Value, 10f, 100f, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("damage_text_color"), Array.Empty<GUILayoutOption>()); Plugin.DamageTextColor.Value = GUILayout.TextField(Plugin.DamageTextColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); GUILayout.Label(GetText("healthbar_settings"), GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("healthbar_fill_color"), Array.Empty<GUILayoutOption>()); Plugin.HealthBarFillColor.Value = GUILayout.TextField(Plugin.HealthBarFillColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("healthbar_background_color"), Array.Empty<GUILayoutOption>()); Plugin.HealthBarBackgroundColor.Value = GUILayout.TextField(Plugin.HealthBarBackgroundColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F0}", GetText("healthbar_width"), Plugin.HealthBarWidth.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarWidth.Value = GUILayout.HorizontalSlider(Plugin.HealthBarWidth.Value, 50f, 500f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F0}", GetText("healthbar_height"), Plugin.HealthBarHeight.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarHeight.Value = GUILayout.HorizontalSlider(Plugin.HealthBarHeight.Value, 10f, 100f, Array.Empty<GUILayoutOption>()); Plugin.ShowHealthBarNumbers.Value = GUILayout.Toggle(Plugin.ShowHealthBarNumbers.Value, GetText("show_healthbar_numbers"), Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1}", GetText("healthbar_numbers_fontsize"), Plugin.HealthBarNumbersFontSize.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarNumbersFontSize.Value = (int)GUILayout.HorizontalSlider((float)Plugin.HealthBarNumbersFontSize.Value, 1f, 100f, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("healthbar_numbers_color"), Array.Empty<GUILayoutOption>()); Plugin.HealthBarNumbersColor.Value = GUILayout.TextField(Plugin.HealthBarNumbersColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}{2}", GetText("healthbar_hide_delay"), Plugin.HealthBarHideDelay.Value, GetText("seconds")), Array.Empty<GUILayoutOption>()); Plugin.HealthBarHideDelay.Value = GUILayout.HorizontalSlider(Plugin.HealthBarHideDelay.Value, 0.5f, 5f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F2}", GetText("healthbar_numbers_vertical_offset"), Plugin.HealthBarNumbersVerticalOffset.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarNumbersVerticalOffset.Value = GUILayout.HorizontalSlider(Plugin.HealthBarNumbersVerticalOffset.Value, -5f, 5f, Array.Empty<GUILayoutOption>()); Plugin.HealthBarNumbersInsideBar.Value = GUILayout.Toggle(Plugin.HealthBarNumbersInsideBar.Value, GetText("healthbar_numbers_inside_bar"), Array.Empty<GUILayoutOption>()); Plugin.HealthBarNumbersAutoWhiteOnLowHealth.Value = GUILayout.Toggle(Plugin.HealthBarNumbersAutoWhiteOnLowHealth.Value, GetText("healthbar_numbers_auto_white"), Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("healthbar_fill_margin_top"), Plugin.HealthBarFillMarginTop.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarFillMarginTop.Value = GUILayout.HorizontalSlider(Plugin.HealthBarFillMarginTop.Value, 0f, 40f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("healthbar_fill_margin_bottom"), Plugin.HealthBarFillMarginBottom.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarFillMarginBottom.Value = GUILayout.HorizontalSlider(Plugin.HealthBarFillMarginBottom.Value, 0f, 40f, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("healthbar_shape"), Array.Empty<GUILayoutOption>()); if (!((Object)(object)CustomTextureManager.GetEnemyHealthBarTexture() != (Object)null)) { GUILayout.Label("(原始材质仅支持长方形样式)", GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Toggle(true, GetText("shape_rectangle"), Array.Empty<GUILayoutOption>()); GUI.enabled = false; GUILayout.Toggle(false, GetText("shape_rounded"), Array.Empty<GUILayoutOption>()); GUI.enabled = true; GUILayout.EndHorizontal(); Plugin.HealthBarShape.Value = 1; } else { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Toggle(Plugin.HealthBarShape.Value == 1, GetText("shape_rectangle"), Array.Empty<GUILayoutOption>())) { Plugin.HealthBarShape.Value = 1; } if (GUILayout.Toggle(Plugin.HealthBarShape.Value == 2, GetText("shape_rounded"), Array.Empty<GUILayoutOption>())) { Plugin.HealthBarShape.Value = 2; } GUILayout.EndHorizontal(); if (Plugin.HealthBarShape.Value == 2) { GUILayout.Label(string.Format("{0}: {1}", GetText("corner_radius"), Plugin.HealthBarCornerRadius.Value), Array.Empty<GUILayoutOption>()); Plugin.HealthBarCornerRadius.Value = (int)GUILayout.HorizontalSlider((float)Plugin.HealthBarCornerRadius.Value, 5f, 50f, Array.Empty<GUILayoutOption>()); } } GUILayout.Space(10f); GUILayout.Label(GetText("boss_settings"), GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1}", GetText("boss_health_threshold"), Plugin.BossHealthThreshold.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthThreshold.Value = (int)GUILayout.HorizontalSlider((float)Plugin.BossHealthThreshold.Value, 50f, 1000f, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("boss_healthbar_fill_color"), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarFillColor.Value = GUILayout.TextField(Plugin.BossHealthBarFillColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("boss_healthbar_background_color"), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarBackgroundColor.Value = GUILayout.TextField(Plugin.BossHealthBarBackgroundColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F0}", GetText("boss_healthbar_width"), Plugin.BossHealthBarWidth.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarWidth.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarWidth.Value, 500f, 1200f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F0}", GetText("boss_healthbar_height"), Plugin.BossHealthBarHeight.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarHeight.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarHeight.Value, 10f, 50f, Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarBottomPosition.Value = GUILayout.Toggle(Plugin.BossHealthBarBottomPosition.Value, GetText("boss_healthbar_bottom_position"), Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("boss_healthbar_name_color"), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarNameColor.Value = GUILayout.TextField(Plugin.BossHealthBarNameColor.Value, Array.Empty<GUILayoutOption>()); Plugin.ShowBossHealthBarNumbers.Value = GUILayout.Toggle(Plugin.ShowBossHealthBarNumbers.Value, GetText("show_boss_healthbar_numbers"), Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("boss_healthbar_numbers_color"), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarNumbersColor.Value = GUILayout.TextField(Plugin.BossHealthBarNumbersColor.Value, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("boss_healthbar_fill_margin_top"), Plugin.BossHealthBarFillMarginTop.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarFillMarginTop.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarFillMarginTop.Value, 0f, 80f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("boss_healthbar_fill_margin_bottom"), Plugin.BossHealthBarFillMarginBottom.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarFillMarginBottom.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarFillMarginBottom.Value, 0f, 80f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("boss_healthbar_fill_margin_left"), Plugin.BossHealthBarFillMarginLeft.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarFillMarginLeft.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarFillMarginLeft.Value, 0f, 80f, Array.Empty<GUILayoutOption>()); GUILayout.Label(string.Format("{0}: {1:F1}", GetText("boss_healthbar_fill_margin_right"), Plugin.BossHealthBarFillMarginRight.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarFillMarginRight.Value = GUILayout.HorizontalSlider(Plugin.BossHealthBarFillMarginRight.Value, 0f, 80f, Array.Empty<GUILayoutOption>()); GUILayout.Label(GetText("boss_healthbar_shape"), Array.Empty<GUILayoutOption>()); if (!((Object)(object)CustomTextureManager.GetBossHealthBarTexture() != (Object)null)) { GUILayout.Label("(原始材质仅支持长方形样式)", GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Toggle(true, GetText("shape_rectangle"), Array.Empty<GUILayoutOption>()); GUI.enabled = false; GUILayout.Toggle(false, GetText("shape_rounded"), Array.Empty<GUILayoutOption>()); GUI.enabled = true; GUILayout.EndHorizontal(); Plugin.BossHealthBarShape.Value = 1; } else { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Toggle(Plugin.BossHealthBarShape.Value == 1, GetText("shape_rectangle"), Array.Empty<GUILayoutOption>())) { Plugin.BossHealthBarShape.Value = 1; } if (GUILayout.Toggle(Plugin.BossHealthBarShape.Value == 2, GetText("shape_rounded"), Array.Empty<GUILayoutOption>())) { Plugin.BossHealthBarShape.Value = 2; } GUILayout.EndHorizontal(); if (Plugin.BossHealthBarShape.Value == 2) { GUILayout.Label(string.Format("{0}: {1}", GetText("boss_corner_radius"), Plugin.BossHealthBarCornerRadius.Value), Array.Empty<GUILayoutOption>()); Plugin.BossHealthBarCornerRadius.Value = (int)GUILayout.HorizontalSlider((float)Plugin.BossHealthBarCornerRadius.Value, 5f, 50f, Array.Empty<GUILayoutOption>()); } } GUILayout.Space(10f); GUILayout.Label(GetText("custom_texture_settings"), GUI.skin.box, Array.Empty<GUILayoutOption>()); Plugin.UseCustomTextures.Value = GUILayout.Toggle(Plugin.UseCustomTextures.Value, GetText("use_custom_textures"), Array.Empty<GUILayoutOption>()); Plugin.UseCustomEnemyBackground.Value = GUILayout.Toggle(Plugin.UseCustomEnemyBackground.Value, GetText("use_custom_enemy_background"), Array.Empty<GUILayoutOption>()); Plugin.UseCustomBossBackground.Value = GUILayout.Toggle(Plugin.UseCustomBossBackground.Value, GetText("use_custom_boss_background"), Array.Empty<GUILayoutOption>()); if (Plugin.UseCustomTextures.Value) { GUILayout.Label(GetText("custom_texture_scale_mode"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Toggle(Plugin.CustomTextureScaleMode.Value == 1, GetText("scale_mode_stretch"), Array.Empty<GUILayoutOption>())) { Plugin.CustomTextureScaleMode.Value = 1; } if (GUILayout.Toggle(Plugin.CustomTextureScaleMode.Value == 2, GetText("scale_mode_aspect"), Array.Empty<GUILayoutOption>())) { Plugin.CustomTextureScaleMode.Value = 2; } GUILayout.EndHorizontal(); Plugin.TrimCustomTextureMargins.Value = GUILayout.Toggle(Plugin.TrimCustomTextureMargins.Value, GetText("trim_transparent_margins"), Array.Empty<GUILayoutOption>()); } if (Plugin.UseCustomTextures.Value || Plugin.UseCustomEnemyBackground.Value || Plugin.UseCustomBossBackground.Value) { if (GUILayout.Button(GetText("reload_textures"), Array.Empty<GUILayoutOption>())) { CustomTextureManager.ReloadTextures(); RecreateAllHealthBars(); } GUILayout.Label(GetText("texture_path_info"), GUI.skin.textArea, Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); GUILayout.Space(10f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button(GetText("save_config"), Array.Empty<GUILayoutOption>())) { ((BaseUnityPlugin)Plugin.Instance).Config.Save(); RecreateAllHealthBars(); } if (GUILayout.Button(GetText("reset_defaults"), Array.Empty<GUILayoutOption>())) { ResetToDefaults(); } GUILayout.EndHorizontal(); if (GUILayout.Button(GetText("close_panel"), Array.Empty<GUILayoutOption>())) { showGUI = false; RestoreCursor(); } GUI.DragWindow(); } private void RecreateAllHealthBars() { try { if ((Object)(object)DamageTextManager.Instance != (Object)null) { DamageTextManager.Instance.ClearAllDamageTexts(); } HealthBarCoordinator.RefreshAllViews(); } catch (Exception ex) { Plugin.logger.LogError((object)("重新创建血条时发生错误: " + ex.Message)); } } private void ResetToDefaults() { try { Plugin.ShowEnemyHealthBar.Value = true; Plugin.ShowBossHealthBar.Value = true; Plugin.ShowDamageText.Value = true; Plugin.ConfigGUI_Hotkey.Value = (KeyCode)278; Plugin.DamageTextDuration.Value = 2f; Plugin.DamageTextFontSize.Value = 55; Plugin.DamageTextColor.Value = "#DC143CFF"; Plugin.DamageTextUseSign.Value = true; Plugin.HealthBarFillColor.Value = "#beb8b8ff"; Plugin.HealthBarWidth.Value = 135f; Plugin.HealthBarHeight.Value = 25f; Plugin.ShowHealthBarNumbers.Value = true; Plugin.HealthBarNumbersFontSize.Value = 32; Plugin.HealthBarNumbersColor.Value = "#0e0404ff"; Plugin.HealthBarHideDelay.Value = 1.5f; Plugin.HealthBarNumbersVerticalOffset.Value = 0.3f; Plugin.HealthBarNumbersInsideBar.Value = false; Plugin.HealthBarNumbersAutoWhiteOnLowHealth.Value = true; Plugin.HealthBarFillMarginTop.Value = 2f; Plugin.HealthBarFillMarginBottom.Value = 2f; Plugin.HealthBarBackgroundColor.Value = "#00000085"; Plugin.BossHealthThreshold.Value = 105; Plugin.BossHealthBarFillColor.Value = "#beb8b8ff"; Plugin.BossHealthBarBackgroundColor.Value = "#00000080"; Plugin.BossHealthBarWidth.Value = 900f; Plugin.BossHealthBarHeight.Value = 25f; Plugin.BossHealthBarBottomPosition.Value = true; Plugin.BossHealthBarNameColor.Value = "#0e0404ff"; Plugin.ShowBossHealthBarNumbers.Value = true; Plugin.BossMaxHealth.Value = 3000f; Plugin.BossHealthBarNumbersColor.Value = "#0e0404ff"; Plugin.BossHealthBarFillMarginTop.Value = 2f; Plugin.BossHealthBarFillMarginBottom.Value = 2f; Plugin.BossHealthBarFillMarginLeft.Value = 2f; Plugin.BossHealthBarFillMarginRight.Value = 2f; Plugin.HealthBarShape.Value = 1; Plugin.BossHealthBarShape.Value = 1; Plugin.HealthBarCornerRadius.Value = 30; Plugin.BossHealthBarCornerRadius.Value = 30; Plugin.UseCustomTextures.Value = false; Plugin.TrimCustomTextureMargins.Value = true; Plugin.UseCustomEnemyBackground.Value = false; Plugin.UseCustomBossBackground.Value = false; Plugin.CustomTextureScaleMode.Value = 1; ((BaseUnityPlugin)Plugin.Instance).Config.Save(); RecreateAllHealthBars(); } catch (Exception ex) { Plugin.logger.LogError((object)("恢复默认配置时发生错误: " + ex.Message)); } } } public sealed class DamageTextManager : MonoBehaviour { private sealed class Slot { internal GameObject Root; internal Text Label; internal Vector3 StartPosition; internal float StartedAt; internal float Duration; internal bool Active; } private const int MaximumActiveTexts = 32; private const float RiseDistance = 1.4f; private readonly List<Slot> slots = new List<Slot>(32); public static DamageTextManager Instance { get; private set; } public static Font SharedFont { get; private set; } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; SharedFont = LoadFont(); } public void ShowDamageText(Vector3 worldPosition, int damage) { //IL_0019: 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) //IL_001f: 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_00b5: 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_00d0: Unknown result type (might be due to invalid IL or missing references) if (damage > 0 && Plugin.ShowDamageText.Value) { Slot slot = AcquireSlot(); slot.StartPosition = worldPosition + Vector3.up; slot.StartedAt = Time.unscaledTime; slot.Duration = Plugin.DamageTextDuration.Value; slot.Active = true; slot.Label.text = (Plugin.DamageTextUseSign.Value ? ("-" + damage) : damage.ToString()); slot.Label.fontSize = Plugin.DamageTextFontSize.Value; ((Graphic)slot.Label).color = HealthBarView.ParseColor(Plugin.DamageTextColor.Value, new Color(0.86f, 0.08f, 0.24f, 1f)); slot.Root.transform.position = slot.StartPosition; slot.Root.SetActive(true); } } public void ClearAllDamageTexts() { foreach (Slot slot in slots) { slot.Active = false; if ((Object)(object)slot.Root != (Object)null) { slot.Root.SetActive(false); } } } private void Update() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_006b: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) float unscaledTime = Time.unscaledTime; foreach (Slot slot in slots) { if (slot.Active) { float num = Mathf.Clamp01((unscaledTime - slot.StartedAt) / Mathf.Max(0.01f, slot.Duration)); slot.Root.transform.position = slot.StartPosition + Vector3.up * (1.4f * num); Color color = ((Graphic)slot.Label).color; color.a = 1f - num; ((Graphic)slot.Label).color = color; if (num >= 1f) { slot.Active = false; slot.Root.SetActive(false); } } } } private void OnDestroy() { ClearAllDamageTexts(); slots.Clear(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; SharedFont = null; } } private Slot AcquireSlot() { foreach (Slot slot3 in slots) { if (!slot3.Active) { return slot3; } } if (slots.Count < 32) { Slot slot = CreateSlot(slots.Count); slots.Add(slot); return slot; } Slot slot2 = slots[0]; for (int i = 1; i < slots.Count; i++) { if (slots[i].StartedAt < slot2.StartedAt) { slot2 = slots[i]; } } return slot2; } private Slot CreateSlot(int index) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_004f: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DamageText." + index, new Type[2] { typeof(RectTransform), typeof(Canvas) }); val.transform.SetParent(((Component)this).transform, false); val.transform.localScale = Vector3.one * 0.01f; Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)2; component.sortingOrder = 110; GameObject val2 = new GameObject("Label", new Type[2] { typeof(RectTransform), typeof(Text) }); RectTransform component2 = val2.GetComponent<RectTransform>(); ((Transform)component2).SetParent(val.transform, false); component2.sizeDelta = new Vector2(500f, 140f); Text component3 = val2.GetComponent<Text>(); component3.font = SharedFont; component3.alignment = (TextAnchor)4; component3.fontStyle = (FontStyle)1; ((Graphic)component3).raycastTarget = false; component3.horizontalOverflow = (HorizontalWrapMode)1; component3.verticalOverflow = (VerticalWrapMode)1; val.SetActive(false); return new Slot { Root = val, Label = component3 }; } private static Font LoadFont() { string[] array = new string[2] { "LegacyRuntime.ttf", "Arial.ttf" }; foreach (string text in array) { try { Font builtinResource = Resources.GetBuiltinResource<Font>(text); if ((Object)(object)builtinResource != (Object)null) { return builtinResource; } } catch (UnityException) { } } Font[] array2 = Resources.FindObjectsOfTypeAll<Font>(); if (array2.Length == 0) { return null; } return array2[0]; } } internal static class HealthBarCoordinator { internal static void OnHeroHealthChanged(HealthManager target, int beforeHealth, int afterHealth) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) int num = beforeHealth - afterHealth; if (num > 0 && Plugin.ShowDamageText.Value && (Object)(object)DamageTextManager.Instance != (Object)null) { DamageTextManager.Instance.ShowDamageText(((Component)target).transform.position, num); } int num2 = Mathf.Max(beforeHealth, afterHealth); EnemyHealthBar component = ((Component)target).GetComponent<EnemyHealthBar>(); BossHealthBar component2 = ((Component)target).GetComponent<BossHealthBar>(); if ((Object)(object)component != (Object)null) { num2 = Mathf.Max(num2, component.MaxHealth); } if ((Object)(object)component2 != (Object)null) { num2 = Mathf.Max(num2, component2.MaxHealth); } if (num2 <= 0 || (float)num2 > Plugin.BossMaxHealth.Value) { RemoveView(component); RemoveView(component2); return; } bool flag = num2 > Plugin.BossHealthThreshold.Value; if (!(flag ? Plugin.ShowBossHealthBar.Value : Plugin.ShowEnemyHealthBar.Value)) { RemoveView(component); RemoveView(component2); return; } HealthBarView healthBarView; if (flag) { RemoveView(component); healthBarView = (((Object)(object)component2 != (Object)null) ? component2 : ((Component)target).gameObject.AddComponent<BossHealthBar>()); } else { RemoveView(component2); healthBarView = (((Object)(object)component != (Object)null) ? component : ((Component)target).gameObject.AddComponent<EnemyHealthBar>()); } healthBarView.Initialize(target, num2); if (num > 0) { healthBarView.OnDamageTaken(); } else { healthBarView.RefreshValues(); } } internal static void RefreshAllViews() { EnemyHealthBar[] array = Object.FindObjectsByType<EnemyHealthBar>((FindObjectsInactive)1, (FindObjectsSortMode)0); BossHealthBar[] array2 = Object.FindObjectsByType<BossHealthBar>((FindObjectsInactive)1, (FindObjectsSortMode)0); EnemyHealthBar[] array3 = array; for (int i = 0; i < array3.Length; i++) { RefreshView(array3[i]); } BossHealthBar[] array4 = array2; for (int i = 0; i < array4.Length; i++) { RefreshView(array4[i]); } BossHealthBarManager.RefreshLayout(); } internal static void RemoveAllViews() { EnemyHealthBar[] array = Object.FindObjectsByType<EnemyHealthBar>((FindObjectsInactive)1, (FindObjectsSortMode)0); BossHealthBar[] array2 = Object.FindObjectsByType<BossHealthBar>((FindObjectsInactive)1, (FindObjectsSortMode)0); EnemyHealthBar[] array3 = array; for (int i = 0; i < array3.Length; i++) { RemoveView(array3[i]); } BossHealthBar[] array4 = array2; for (int i = 0; i < array4.Length; i++) { RemoveView(array4[i]); } } private static void RefreshView(HealthBarView view) { if ((Object)(object)view == (Object)null || (Object)(object)view.Manager == (Object)null) { RemoveView(view); return; } int num = Mathf.Max(view.MaxHealth, view.Manager.hp); bool flag = num > Plugin.BossHealthThreshold.Value; if (!(flag ? Plugin.ShowBossHealthBar.Value : Plugin.ShowEnemyHealthBar.Value) || (float)num > Plugin.BossMaxHealth.Value) { RemoveView(view); } else if (view.BossStyle != flag) { HealthManager manager = view.Manager; bool isDisplayed = view.IsDisplayed; RemoveView(view); HealthBarView healthBarView = (flag ? ((HealthBarView)((Component)manager).gameObject.AddComponent<BossHealthBar>()) : ((HealthBarView)((Component)manager).gameObject.AddComponent<EnemyHealthBar>())); healthBarView.Initialize(manager, num); if (isDisplayed) { healthBarView.OnDamageTaken(); } } else { view.RecreateHealthBar(); } } private static void RemoveView(HealthBarView view) { if (!((Object)(object)view == (Object)null)) { view.HideImmediately(); ((Behaviour)view).enabled = false; Object.Destroy((Object)(object)view); } } } public abstract class HealthBarView : MonoBehaviour { private HealthManager healthManager; private int maximumHealth; private int lastHealth; private float hideAt; private float worldOffsetY = 1.5f; private bool activated; private GameObject uiRoot; private RectTransform panelRect; private Image backgroundImage; private Image fillImage; private Text healthText; private Text nameText; public HealthManager Manager => healthManager; public int MaxHealth => maximumHealth; public bool BossStyle => IsBossStyle; public bool IsDisplayed { get { if ((Object)(object)uiRoot != (Object)null) { return uiRoot.activeSelf; } return false; } } protected abstract bool IsBossStyle { get; } public void Initialize(HealthManager manager, int observedMaximum) { if (!((Object)(object)manager == (Object)null)) { healthManager = manager; maximumHealth = Mathf.Max(maximumHealth, observedMaximum); lastHealth = manager.hp; if (!IsBossStyle) { CacheWorldOffset(); } EnsureUi(); RefreshValues(); } } public void RecordMaxHealth(int health) { maximumHealth = Mathf.Max(maximumHealth, health); RefreshValues(); } public void OnDamageTaken() { EnsureInitialized(); if ((Object)(object)healthManager == (Object)null || healthManager.hp <= 0) { HideImmediately(); return; } activated = true; SetVisible(visible: true); hideAt = Time.unscaledTime + Plugin.HealthBarHideDelay.Value; RefreshValues(); } public void RecreateHealthBar() { bool isDisplayed = IsDisplayed; DestroyUi(); EnsureUi(); RefreshValues(); SetVisible(isDisplayed && IsStyleEnabled()); } public void RefreshValues() { //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_00fc: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)healthManager == (Object)null) && !((Object)(object)fillImage == (Object)null)) { int hp = healthManager.hp; if (hp > maximumHealth && (float)hp <= Plugin.BossMaxHealth.Value) { maximumHealth = hp; } float num = ((maximumHealth > 0) ? Mathf.Clamp01((float)hp / (float)maximumHealth) : 0f); fillImage.fillAmount = num; if ((Object)(object)healthText != (Object)null) { healthText.text = $"{Mathf.Max(0, hp)}/{maximumHealth}"; ((Graphic)healthText).color = ((!IsBossStyle && Plugin.HealthBarNumbersAutoWhiteOnLowHealth.Value && num < 0.49f) ? Color.white : ParseColor(IsBossStyle ? Plugin.BossHealthBarNumbersColor.Value : Plugin.HealthBarNumbersColor.Value, Color.white)); } if (hp <= 0) { HideImmediately(); } } } public void HideImmediately() { SetVisible(visible: false); } public void ApplyManagedPosition(int visibleIndex) { //IL_0046: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (IsBossStyle && !((Object)(object)panelRect == (Object)null)) { bool value = Plugin.BossHealthBarBottomPosition.Value; panelRect.anchorMin = (value ? new Vector2(0.5f, 0f) : new Vector2(0.5f, 1f)); panelRect.anchorMax = panelRect.anchorMin; panelRect.pivot = (value ? new Vector2(0.5f, 0f) : new Vector2(0.5f, 1f)); float num = (value ? 1f : (-1f)); float num2 = Plugin.BossHealthBarHeight.Value + 54f; panelRect.anchoredPosition = new Vector2(0f, num * (42f + (float)visibleIndex * num2)); } } private void Start() { EnsureInitialized(); if ((Object)(object)uiRoot != (Object)null && !activated) { uiRoot.SetActive(false); } } private void Update() { if (!((Object)(object)healthManager == (Object)null)) { int hp = healthManager.hp; if (hp != lastHealth) { lastHealth = hp; RefreshValues(); } if (IsDisplayed && Time.unscaledTime >= hideAt) { SetVisible(visible: false); } } } private void LateUpdate() { //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_0052: 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_006c: Unknown result type (might be due to invalid IL or missing references) if (!IsBossStyle && IsDisplayed && (Object)(object)uiRoot != (Object)null && (Object)(object)healthManager != (Object)null) { uiRoot.transform.position = ((Component)healthManager).transform.position + Vector3.up * worldOffsetY; uiRoot.transform.rotation = Quaternion.identity; } } private void OnDestroy() { if (IsBossStyle) { BossHealthBarManager.Unregister(this as BossHealthBar); } DestroyUi(); } private void EnsureInitialized() { if ((Object)(object)healthManager == (Object)null) { healthManager = ((Component)this).GetComponent<HealthManager>(); } if ((Object)(object)healthManager != (Object)null) { maximumHealth = Mathf.Max(maximumHealth, healthManager.hp); lastHealth = healthManager.hp; } EnsureUi(); } private void EnsureUi() { if (!((Object)(object)uiRoot != (Object)null) && !((Object)(object)healthManager == (Object)null)) { if (IsBossStyle) { CreateBossUi(); BossHealthBarManager.Register(this as BossHealthBar); } else { CreateEnemyUi(); } SetVisible(visible: false); } } private void CreateEnemyUi() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0054: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) uiRoot = new GameObject("EnemyHealthBar.Canvas", new Type[2] { typeof(RectTransform), typeof(Canvas) }); Canvas component = uiRoot.GetComponent<Canvas>(); component.renderMode = (RenderMode)2; component.sortingOrder = 100; uiRoot.transform.localScale = Vector3.one * 0.01f; uiRoot.transform.position = ((Component)healthManager).transform.position + Vector3.up * worldOffsetY; panelRect = CreatePanel(uiRoot.transform, Plugin.HealthBarWidth.Value, Plugin.HealthBarHeight.Value); ConfigureImages(boss: false); CreateHealthText(boss: false); } private void CreateBossUi() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) uiRoot = new GameObject("BossHealthBar.Canvas", new Type[3] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler) }); Canvas component = uiRoot.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 100; CanvasScaler component2 = uiRoot.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.matchWidthOrHeight = 0.5f; panelRect = CreatePanel(uiRoot.transform, Plugin.BossHealthBarWidth.Value, Plugin.BossHealthBarHeight.Value); ConfigureImages(boss: true); CreateBossName(); CreateHealthText(boss: true); } private RectTransform CreatePanel(Transform parent, float width, float height) { //IL_0018: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject("Panel", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.sizeDelta = new Vector2(width, height); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); component.anchorMax = val; component.anchorMin = val; return component; } private void ConfigureImages(bool boss) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_00e5: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) Sprite roundedSprite = TextureResources.GetRoundedSprite(boss); Sprite val = (boss ? CustomTextureManager.GetBossBackgroundTexture() : CustomTextureManager.GetEnemyBackgroundTexture()); GameObject val2 = new GameObject("Background", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val2.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)panelRect, false); Stretch(component, 0f, 0f, 0f, 0f); backgroundImage = val2.GetComponent<Image>(); backgroundImage.sprite = (((Object)(object)val != (Object)null) ? val : (roundedSprite ?? TextureResources.SolidSprite)); ((Graphic)backgroundImage).color = (((Object)(object)val != (Object)null) ? Color.white : ParseColor(boss ? Plugin.BossHealthBarBackgroundColor.Value : Plugin.HealthBarBackgroundColor.Value, new Color(0f, 0f, 0f, 0.5f))); ((Graphic)backgroundImage).raycastTarget = false; backgroundImage.preserveAspect = (Object)(object)val != (Object)null && Plugin.CustomTextureScaleMode.Value == 2; GameObject val3 = new GameObject("Fill", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component2 = val3.GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); float top = (boss ? Plugin.BossHealthBarFillMarginTop.Value : Plugin.HealthBarFillMarginTop.Value); float bottom = (boss ? Plugin.BossHealthBarFillMarginBottom.Value : Plugin.HealthBarFillMarginBottom.Value); float left = (boss ? Plugin.BossHealthBarFillMarginLeft.Value : 0f); float right = (boss ? Plugin.BossHealthBarFillMarginRight.Value : 0f); Stretch(component2, left, right, top, bottom); fillImage = val3.GetComponent<Image>(); Sprite val4 = (boss ? CustomTextureManager.GetBossHealthBarTexture() : CustomTextureManager.GetEnemyHealthBarTexture()); fillImage.sprite = (((Object)(object)val4 != (Object)null) ? val4 : (roundedSprite ?? TextureResources.SolidSprite)); fillImage.type = (Type)3; fillImage.fillMethod = (FillMethod)0; fillImage.fillOrigin = 0; fillImage.fillAmount = 1f; ((Graphic)fillImage).color = (((Object)(object)val4 != (Object)null) ? Color.white : ParseColor(boss ? Plugin.BossHealthBarFillColor.Value : Plugin.HealthBarFillColor.Value, Color.white)); ((Graphic)fillImage).raycastTarget = false; fillImage.preserveAspect = (Object)(object)val4 != (Object)null && Plugin.CustomTextureScaleMode.Value == 2; } private void CreateHealthText(bool boss) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0065: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00b6: Unknown result type (might be due to invalid IL or missing references) if (boss ? Plugin.ShowBossHealthBarNumbers.Value : Plugin.ShowHealthBarNumbers.Value) { GameObject val = new GameObject("Health", new Type[2] { typeof(RectTransform), typeof(Text) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)panelRect, false); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = component.anchorMin; component.sizeDelta = new Vector2(panelRect.sizeDelta.x, 60f); float num = 0f; if (!boss && !Plugin.HealthBarNumbersInsideBar.Value) { num = panelRect.sizeDelta.y * 0.5f + Plugin.HealthBarNumbersVerticalOffset.Value * 100f; } component.anchoredPosition = new Vector2(0f, num); healthText = val.GetComponent<Text>(); healthText.font = DamageTextManager.SharedFont; healthText.fontSize = (boss ? 24 : Plugin.HealthBarNumbersFontSize.Value); healthText.alignment = (TextAnchor)4; ((Graphic)healthText).raycastTarget = false; healthText.horizontalOverflow = (HorizontalWrapMode)1; healthText.verticalOverflow = (VerticalWrapMode)1; } } private void CreateBossName() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0051: 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_0064: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Name", new Type[2] { typeof(RectTransform), typeof(Text) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)panelRect, false); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.sizeDelta = new Vector2(panelRect.sizeDelta.x, 50f); component.anchoredPosition = new Vector2(0f, panelRect.sizeDelta.y * 0.5f + 28f); nameText = val.GetComponent<Text>(); nameText.font = DamageTextManager.SharedFont; nameText.fontSize = 28; nameText.alignment = (TextAnchor)4; ((Graphic)nameText).color = ParseColor(Plugin.BossHealthBarNameColor.Value, Color.white); ((Graphic)nameText).raycastTarget = false; nameText.text = ResolveDisplayName(); } private string ResolveDisplayName() { try { EnemyDeathEffects val = ((Component)this).GetComponent<EnemyDeathEffects>(); if ((Object)(object)val == (Object)null) { val = ((Component)this).GetComponentInChildren<EnemyDeathEffects>(); } if ((Object)(object)val == (Object)null) { val = ((Component)this).GetComponentInParent<EnemyDeathEffects>(); } object obj = (((Object)(object)val != (Object)null) ? AccessTools.Field(((object)val).GetType(), "journalRecord") : null)?.GetValue(val); string text = (obj?.GetType().GetProperty("DisplayName", BindingFlags.Instance | BindingFlags.Public))?.GetValue(obj, null)?.ToString(); if (!string.IsNullOrWhiteSpace(text)) { return text; } } catch (Exception ex) { ManualLogSource logger = Plugin.logger; if (logger != null) { logger.LogDebug((object)("无法读取敌人本地化名称: " + ex.Message)); } } return ((Object)((Component)this).gameObject).name.Replace("(Clone)", string.Empty).Replace('_', ' ').Trim(); } private void CacheWorldOffset() { //IL_0012: 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_001a: Unknown result type (might be due to invalid IL or missing references) Renderer componentInChildren = ((Component)this).GetComponentInChildren<Renderer>(); if ((Object)(object)componentInChildren != (Object)null) { Bounds bounds = componentInChildren.bounds; worldOffsetY = Mathf.Clamp(((Bounds)(ref bounds)).extents.y + 0.5f, 1f, 6f); } } private bool IsStyleEnabled() { if (!IsBossStyle) { return Plugin.ShowEnemyHealthBar.Value; } return Plugin.ShowBossHealthBar.Value; } private void SetVisible(bool visible) { if (!((Object)(object)uiRoot == (Object)null)) { bool num = uiRoot.activeSelf != visible; uiRoot.SetActive(visible); if (num && IsBossStyle) { BossHealthBarManager.RefreshLayout(); } } } private void DestroyUi() { if ((Object)(object)uiRoot != (Object)null) { Object.Destroy((Object)(object)uiRoot); } uiRoot = null; panelRect = null; backgroundImage = null; fillImage = null; healthText = null; nameText = null; } private static void Stretch(RectTransform rect, float left, float right, float top, float bottom) { //IL_0001: 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_001a: 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) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = new Vector2(left, bottom); rect.offsetMax = new Vector2(0f - right, 0f - top); } internal static Color ParseColor(string value, Color fallback) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!ColorUtility.TryParseHtmlString(value, ref result)) { return fallback; } return result; } } public sealed class EnemyHealthBar : HealthBarView { protected override bool IsBossStyle => false; } public sealed class BossHealthBar : HealthBarView { protected override bool IsBossStyle => true; } [BepInPlugin("com.Xiaohai.HealthbarAndDamageShow", "Healthbar&DamageShow", "2.1.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.Xiaohai.HealthbarAndDamageShow"; public const string PluginName = "Healthbar&DamageShow"; public const string PluginVersion = "2.1.1"; internal const float EnemyFillMarginMaximum = 40f; internal const float BossFillMarginMaximum = 80f; public const string PLUGIN_GUID = "com.Xiaohai.HealthbarAndDamageShow"; public const string PLUGIN_NAME = "Healthbar&DamageShow"; public const string PLUGIN_VERSION = "2.1.1"; public static ManualLogSource logger; public static ConfigEntry<bool> ShowEnemyHealthBar; public static ConfigEntry<bool> ShowBossHealthBar; public static ConfigEntry<bool> ShowDamageText; public static ConfigEntry<KeyCode> ConfigGUI_Hotkey; public static ConfigEntry<float> DamageTextDuration; public static ConfigEntry<int> DamageTextFontSize; public static ConfigEntry<string> DamageTextColor; public static ConfigEntry<bool> DamageTextUseSign; public static ConfigEntry<string> HealthBarFillColor; public static ConfigEntry<string> HealthBarBackgroundColor; public static ConfigEntry<float> HealthBarWidth; public static ConfigEntry<float> HealthBarHeight; public static ConfigEntry<bool> ShowHealthBarNumbers; public static ConfigEntry<int> HealthBarNumbersFontSize; public static ConfigEntry<string> HealthBarNumbersColor; public static ConfigEntry<float> HealthBarHideDelay; public static ConfigEntry<float> HealthBarNumbersVerticalOffset; public static ConfigEntry<bool> HealthBarNumbersInsideBar; public static ConfigEntry<bool> HealthBarNumbersAutoWhiteOnLowHealth; public static ConfigEntry<float> HealthBarFillMarginTop; public static ConfigEntry<float> HealthBarFillMarginBottom; public static ConfigEntry<int> BossHealthThreshold; public static ConfigEntry<string> BossHealthBarFillColor; public static ConfigEntry<string> BossHealthBarBackgroundColor; public static ConfigEntry<float> BossHealthBarWidth; public static ConfigEntry<float> BossHealthBarHeight; public static ConfigEntry<bool> BossHealthBarBottomPosition; public static ConfigEntry<string> BossHealthBarNameColor; public static ConfigEntry<bool> ShowBossHealthBarNumbers; public static ConfigEntry<string> BossHealthBarNumbersColor; public static ConfigEntry<float> BossMaxHealth; public static ConfigEntry<float> BossHealthBarFillMarginTop; public static ConfigEntry<float> BossHealthBarFillMarginBottom; public static ConfigEntry<float> BossHealthBarFillMarginLeft; public static ConfigEntry<float> BossHealthBarFillMarginRight; public static ConfigEntry<int> HealthBarShape; public static ConfigEntry<int> BossHealthBarShape; public static ConfigEntry<int> HealthBarCornerRadius; public static ConfigEntry<int> BossHealthBarCornerRadius; public static ConfigEntry<bool> UseCustomTextures; public static ConfigEntry<int> CustomTextureScaleMode; public static ConfigEntry<bool> TrimCustomTextureMargins; public static ConfigEntry<bool> UseCustomEnemyBackground; public static ConfigEntry<bool> UseCustomBossBackground; private Harmony harmony; private GameObject runtimeRoot; public static Plugin Instance { get; private set; } private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) Instance = this; logger = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; BindConfiguration(); ((BaseUnityPlugin)this).Config.Save(); try { ValidateGameApi(); harmony = new Harmony("com.Xiaohai.HealthbarAndDamageShow"); harmony.PatchAll(typeof(Plugin).Assembly); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"补丁初始化失败,模组已停止工作: {arg}"); ((Behaviour)this).enabled = false; return; } runtimeRoot = new GameObject("HealthBar.Runtime"); Object.DontDestroyOnLoad((Object)(object)runtimeRoot); runtimeRoot.AddComponent<DamageTextManager>(); runtimeRoot.AddComponent<ConfigGUI>(); CustomTextureManager.Initialize(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} 已加载;按 {2} 打开设置。", "Healthbar&DamageShow", "2.1.1", ConfigGUI_Hotkey.Value)); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } HealthBarCoordinator.RemoveAllViews(); CustomTextureManager.Dispose(); RoundedSpriteCache.Dispose(); if ((Object)(object)runtimeRoot != (Object)null) { Object.Destroy((Object)(object)runtimeRoot); } runtimeRoot = null; logger = null; Instance = null; } private static void ValidateGameApi() { MethodInfo methodInfo = AccessTools.Method(typeof(HealthManager), "TakeDamage", new Type[1] { typeof(HitInstance) }, (Type[])null); PropertyInfo propertyInfo = AccessTools.Property(typeof(HealthManager), "SendDamageTo"); FieldInfo fieldInfo = AccessTools.Field(typeof(HealthManager), "hp"); if (methodInfo == null || propertyInfo == null || fieldInfo == null) { throw new MissingMemberException("当前游戏的 HealthManager API 与本模组不兼容。需要 TakeDamage(HitInstance)、SendDamageTo 和 hp。"); } } private void BindConfiguration() { ShowEnemyHealthBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowEnemyHealthBar", true, "是否显示普通敌人血条 / Show normal enemy health bars"); ShowBossHealthBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBossHealthBar", true, "是否显示 BOSS 血条 / Show boss health bars"); ShowDamageText = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowDamageText", true, "是否显示伤害数字 / Show damage numbers"); ConfigGUI_Hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Display", "ConfigGUI_Hotkey", (KeyCode)278, "配置面板热键 / Configuration panel hotkey"); DamageTextDuration = BindRange("DamageText", "Duration", 2f, 0.1f, 10f, "伤害数字持续时间 / Damage number duration"); DamageTextFontSize = BindRange("DamageText", "FontSize", 55, 10, 160, "伤害数字字号 / Damage number font size"); DamageTextColor = ((BaseUnityPlugin)this).Config.Bind<string>("DamageText", "DamageColor", "#DC143CFF", "伤害数字颜色 / Damage number color"); DamageTextUseSign = ((BaseUnityPlugin)this).Config.Bind<bool>("DamageText", "UseSign", true, "伤害数字是否显示符号 / Prefix damage numbers with a sign"); HealthBarFillColor = ((BaseUnityPlugin)this).Config.Bind<string>("HealthBar", "FillColor", "#BEB8B8FF", "普通血条填充颜色 / Enemy bar fill color"); HealthBarBackgroundColor = ((BaseUnityPlugin)this).Config.Bind<string>("HealthBar", "BackgroundColor", "#00000085", "普通血条背景颜色 / Enemy bar background color"); HealthBarWidth = BindRange("HealthBar", "Width", 135f, 32f, 1000f, "普通血条宽度 / Enemy bar width"); HealthBarHeight = BindRange("HealthBar", "Height", 25f, 6f, 160f, "普通血条高度 / Enemy bar height"); ShowHealthBarNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("HealthBar", "ShowNumbers", true, "显示当前/最大血量 / Show current/max health"); HealthBarNumbersFontSize = BindRange("HealthBar", "NumbersFontSize", 32, 8, 120, "普通血条字号 / Enemy health text size"); HealthBarNumbersColor = ((BaseUnityPlugin)this).Config.Bind<string>("HealthBar", "NumbersColor", "#0E0404FF", "普通血量文字颜色 / Enemy health text color"); HealthBarHideDelay = BindRange("HealthBar", "HideDelay", 1.5f, 0.1f, 60f, "无变化后隐藏延迟 / Hide delay after a hit"); HealthBarNumbersVerticalOffset = BindRange("HealthBar", "NumbersVerticalOffset", 0.3f, -3f, 3f, "血量文字垂直偏移 / Health text vertical offset"); HealthBarNumbersInsideBar = ((BaseUnityPlugin)this).Config.Bind<bool>("HealthBar", "NumbersInsideBar", false, "在血条内部显示数值 / Put health text inside the bar"); HealthBarNumbersAutoWhiteOnLowHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("HealthBar", "NumbersAutoWhiteOnLowHealth", true, "低血量时使用白字 / Use white text at low health"); HealthBarFillMarginTop = BindRange("HealthBar", "FillMarginTop", 2f, 0f, 40f, "填充上边距 / Fill top margin"); HealthBarFillMarginBottom = BindRange("HealthBar", "FillMarginBottom", 2f, 0f, 40f, "填充下边距 / Fill bottom margin"); HealthBarShape = BindRange("HealthBar", "Shape", 1, 1, 2, "形状:1=矩形,2=圆角 / 1=rectangle, 2=rounded"); HealthBarCornerRadius = BindRange("HealthBar", "CornerRadius", 30, 0, 128, "普通血条圆角半径 / Enemy bar corner radius"); BossHealthThreshold = BindRange("BossHealthBar", "HealthThreshold", 105, 1, 1000000, "初始血量大于此值时使用 BOSS 血条 / Boss threshold"); BossHealthBarFillColor = ((BaseUnityPlugin)this).Config.Bind<string>("BossHealthBar", "FillColor", "#BEB8B8FF", "BOSS 血条填充颜色 / Boss bar fill color"); BossHealthBarBackgroundColor = ((BaseUnityPlugin)this).Config.Bind<string>("BossHealthBar", "BackgroundColor", "#00000080", "BOSS 血条背景颜色 / Boss bar background color"); BossHealthBarWidth = BindRange("BossHealthBar", "Width", 900f, 100f, 3000f, "BOSS 血条宽度 / Boss bar width"); BossHealthBarHeight = BindRange("BossHealthBar", "Height", 25f, 6f, 200f, "BOSS 血条高度 / Boss bar height"); BossHealthBarBottomPosition = ((BaseUnityPlugin)this).Config.Bind<bool>("BossHealthBar", "BottomPosition", true, "BOSS 血条位于屏幕下方 / Put boss bars at the bottom"); BossHealthBarNameColor = ((BaseUnityPlugin)this).Config.Bind<string>("BossHealthBar", "NameColor", "#0E0404FF", "BOSS 名称颜色 / Boss name color"); ShowBossHealthBarNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("BossHealthBar", "ShowNumbers", true, "显示 BOSS 当前/最大血量 / Show boss health numbers"); BossHealthBarNumbersColor = ((BaseUnityPlugin)this).Config.Bind<string>("BossHealthBar", "NumbersColor", "#0E0404FF", "BOSS 血量文字颜色 / Boss health text color"); BossMaxHealth = BindRange("BossHealthBar", "BossMaxHealth", 3000f, 1f, 10000000f, "血条跟踪的最大合理血量 / Maximum health accepted by the overlay"); BossHealthBarFillMarginTop = BindRange("BossHealthBar", "FillMarginTop", 2f, 0f, 80f, "BOSS 填充上边距 / Boss fill top margin"); BossHealthBarFillMarginBottom = BindRange("BossHealthBar", "FillMarginBottom", 2f, 0f, 80f, "BOSS 填充下边距 / Boss fill bottom margin"); BossHealthBarFillMarginLeft = BindRange("BossHealthBar", "FillMarginLeft", 2f, 0f, 80f, "BOSS 填充左边距 / Boss fill left margin"); BossHealthBarFillMarginRight = BindRange("BossHealthBar", "FillMarginRight", 2f, 0f, 80f, "BOSS 填充右边距 / Boss fill right margin"); BossHealthBarShape = BindRange("BossHealthBar", "Shape", 1, 1, 2, "形状:1=矩形,2=圆角 / 1=rectangle, 2=rounded"); BossHealthBarCornerRadius = BindRange("BossHealthBar", "CornerRadius", 30, 0, 128, "BOSS 血条圆角半径 / Boss bar corner radius"); UseCustomTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("CustomTexture", "Enabled", false, "使用 Texture 文件夹中的自定义材质 / Use custom textures"); CustomTextureScaleMode = BindRange("CustomTexture", "ScaleMode", 1, 1, 2, "1=拉伸,2=保持比例 / 1=stretch, 2=preserve aspect"); TrimCustomTextureMargins = ((BaseUnityPlugin)this).Config.Bind<bool>("CustomTexture", "TrimTransparentMargins", true, "自动裁剪填充贴图外围透明像素 / Trim transparent outer pixels from fill textures"); UseCustomEnemyBackground = ((BaseUnityPlugin)this).Config.Bind<bool>("CustomTexture", "EnemyBackgroundEnabled", false, "使用 BG_Enemy.png / Use BG_Enemy.png"); UseCustomBossBackground = ((BaseUnityPlugin)this).Config.Bind<bool>("CustomTexture", "BossBackgroundEnabled", false, "使用 BG_Boss.png / Use BG_Boss.png"); } private ConfigEntry<int> BindRange(string section, string key, int value, int min, int max, string description) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<int>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); } private ConfigEntry<float> BindRange(string section, string key, float value, float min, float max, string description) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } } [HarmonyPatch] internal static class HealthManagerTakeDamagePatch { private sealed class DamageSnapshot { internal HealthManager Target; internal int BeforeHealth; } private static MethodBase TargetMethod() { return AccessTools.Method(typeof(HealthManager), "TakeDamage", new Type[1] { typeof(HitInstance) }, (Type[])null); } private static void Prefix(HealthManager __instance, HitInstance hitInstance, out DamageSnapshot __state) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) __state = null; if (!((Object)(object)__instance == (Object)null) && hitInstance.IsHeroDamage) { HealthManager val = __instance.SendDamageTo; if ((Object)(object)val == (Object)null) { val = __instance; } if (!((Object)(object)val == (Object)null)) { __state = new DamageSnapshot { Target = val, BeforeHealth = val.hp }; } } } private static void Postfix(DamageSnapshot __state) { if (__state != null && !((Object)(object)__state.Target == (Object)null)) { int hp = __state.Target.hp; if (hp != __state.BeforeHealth) { HealthBarCoordinator.OnHeroHealthChanged(__state.Target, __state.BeforeHealth, hp); } } } } internal static class TextureResources { private static Sprite solidSprite; internal static Sprite SolidSprite { get { //IL_0011: 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_0021: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0068: Expected O, but got Unknown if ((Object)(object)solidSprite == (Object)null) { Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false) { name = "HealthBar.Solid" }; val.SetPixel(0, 0, Color.white); val.Apply(false, true); solidSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f); } return solidSprite; } } internal static Sprite GetRoundedSprite(bool boss) { if ((boss ? Plugin.BossHealthBarShape.Value : Plugin.HealthBarShape.Value) != 2) { return null; } float requestedWidth = (boss ? Plugin.BossHealthBarWidth.Value : Plugin.HealthBarWidth.Value); float requestedHeight = (boss ? Plugin.BossHealthBarHeight.Value : Plugin.HealthBarHeight.Value); int requestedRadius = (boss ? Plugin.BossHealthBarCornerRadius.Value : Plugin.HealthBarCornerRadius.Value); return RoundedSpriteCache.Get(requestedWidth, requestedHeight, requestedRadius); } internal static void Dispose() { if ((Object)(object)solidSprite != (Object)null) { Texture2D texture = solidSprite.texture; Object.Destroy((Object)(object)solidSprite); if ((Object)(object)texture != (Object)null) { Object.Destroy((Object)(object)texture); } solidSprite = null; } } } internal static class RoundedSpriteCache { private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>(); internal static Sprite Get(float requestedWidth, float requestedHeight, int requestedRadius) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) int num = 128; int num2 = Mathf.Clamp(Mathf.RoundToInt((float)num * requestedHeight / Mathf.Max(1f, requestedWidth)), 8, 64); int radius = Mathf.Clamp(Mathf.RoundToInt((float)(requestedRadius * num) / Mathf.Max(1f, requestedWidth)), 0, num2 / 2); string text = num + "x" + num2 + ":" + radius; if (Cache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false); ((Object)val).name = "HealthBar.Rounded." + text; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color32[] array = (Color32[])(object)new Color32[num * num2]; Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)0); for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { bool flag = IsInsideRoundedRectangle(j, i, num, num2, radius); array[i * num + j] = (flag ? val2 : val3); } } val.SetPixels32(array); val.Apply(false, true); Sprite val4 = Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), 100f); ((Object)val4).name = ((Object)val).name; Cache[text] = val4; return val4; } internal static void Dispose() { foreach (Sprite value in Cache.Values) { if (!((Object)(object)value == (Object)null)) { Texture2D texture = value.texture; Object.Destroy((Object)(object)value); if ((Object)(object)texture != (Object)null) { Object.Destroy((Object)(object)texture); } } } Cache.Clear(); TextureResources.Dispose(); } private static bool IsInsideRoundedRectangle(int x, int y, int width, int height, int radius) { if (radius <= 0 || (x >= radius && x < width - radius) || (y >= radius && y < height - radius)) { return true; } float num = ((x < radius) ? ((float)radius - 0.5f) : ((float)(width - radius) - 0.5f)); float num2 = ((y < radius) ? ((float)radius - 0.5f) : ((float)(height - radius) - 0.5f)); float num3 = (float)x - num; float num4 = (float)y - num2; return num3 * num3 + num4 * num4 <= (float)(radius * radius); } } public static class CustomTextureManager { private const int MaximumFileBytes = 8388608; private const int MaximumDimension = 4096; private const byte MinimumVisibleAlpha = 4; private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); private static string textureFolderPath; public static void Initialize() { textureFolderPath = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? string.Empty, "Texture"); } public static Sprite GetEnemyHealthBarTexture() { if (!Plugin.UseCustomTextures.Value) { return null; } return Load("HpBar.png", Plugin.TrimCustomTextureMargins.Value); } public static Sprite GetBossHealthBarTexture() { if (!Plugin.UseCustomTextures.Value) { return null; } return Load("HpBar_Boss.png", Plugin.TrimCustomTextureMargins.Value); } public static Sprite GetEnemyBackgroundTexture() { if (!Plugin.UseCustomEnemyBackground.Value) { return null; } return Load("BG_Enemy.png", trimTransparentMargins: false); } public static Sprite GetBossBackgroundTexture() { if (!Plugin.UseCustomBossBackground.Value) { return null; } return Load("BG_Boss.png", trimTransparentMargins: false); } public static void ApplyCustomTexture(Image image, Sprite sprite, Vector2 size) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)image == (Object)null) && !((Object)(object)sprite == (Object)null)) { image.sprite = sprite; ((Graphic)image).color = Color.white; image.preserveAspect = Plugin.CustomTextureScaleMode.Value == 2; } } public static void ReloadTextures() { Dispose(); Initialize(); ManualLogSource logger = Plugin.logger; if (logger != null) { logger.LogInfo((object)"自定义血条材质缓存已重新加载。"); } } public static void Dispose() { foreach (Sprite value in Cache.Values) { if (!((Object)(object)value == (Object)null)) { Texture2D texture = value.texture; Object.Destroy((Object)(object)value); if ((Object)(object)texture != (Object)null) { Object.Destroy((Object)(object)texture); } } } Cache.Clear(); } private static Sprite Load(string fileName, bool trimTransparentMargins) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) string key = fileName + (trimTransparentMargins ? "|trim" : "|full"); Texture2D val = null; if (Cache.TryGetValue(key, out var value)) { return value; } if (string.IsNullOrEmpty(textureFolderPath)) { Initialize(); } string text = Path.Combine(textureFolderPath, fileName); try { FileInfo fileInfo = new FileInfo(text); if (!fileInfo.Exists) { Cache[key] = null; return null; } if (fileInfo.Length <= 0 || fileInfo.Length > 8388608) { ManualLogSource logger = Plugin.logger; if (logger != null) { logger.LogWarning((object)("忽略尺寸异常的材质文件: " + text)); } Cache[key] = null; return null; } byte[] array = File.ReadAllBytes(text); if (!TryReadPngDimensions(array, out var width, out var height) || width > 4096 || height > 4096) { ManualLogSource logger2 = Plugin.logger; if (logger2 != null) { logger2.LogWarning((object)("忽略无效或分辨率过大的 PNG: " + text)); } Cache[key] = null; return null; } val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).name = "HealthBar.Custom." + fileName; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; if (!ImageConversion.LoadImage(val, array, false)) { Object.Destroy((Object)(object)val); Cache[key] = null; return null; } Rect rect = default(Rect); ((Rect)(ref rect))..ctor(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height); if (trimTransparentMargins) { if (!TryGetVisibleRect(val, out rect, out var trimmed)) { ManualLogSource logger3 = Plugin.logger; if (logger3 != null) { logger3.LogWarning((object)("忽略完全透明的填充材质: " + text)); } Object.Destroy((Object)(object)val); Cache[key] = null; return null; } if (trimmed) { ManualLogSource logger4 = Plugin.logger; if (logger4 != null) { logger4.LogInfo((object)$"已裁剪填充材质透明边距: {fileName} -> {((Rect)(ref rect)).width:F0}x{((Rect)(ref rect)).height:F0}"); } } } Sprite val2 = Sprite.Create(val, rect, new Vector2(0.5f, 0.5f), 100f); ((Object)val2).name = ((Object)val).name; Cache[key] = val2; return val2; } catch (Exception ex) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } ManualLogSource logger5 = Plugin.logger; if (logger5 != null) { logger5.LogWarning((object)("读取材质失败 " + text + ": " + ex.Message)); } Cache[key] = null; return null; } } private static bool TryGetVisibleRect(Texture2D texture, out Rect rect, out bool trimmed) { //IL_0001: 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_00d1: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); trimmed = false; if ((Object)(object)texture == (Object)null || ((Texture)texture).width <= 0 || ((Texture)texture).height <= 0) { return false; } Color32[] pixels = texture.GetPixels32(); int num = ((Texture)texture).width; int num2 = ((Texture)texture).height; int num3 = -1; int num4 = -1; for (int i = 0; i < ((Texture)texture).height; i++) { int num5 = i * ((Texture)texture).width; for (int j = 0; j < ((Texture)texture).width; j++) { if (pixels[num5 + j].a >= 4) { num = Mathf.Min(num, j); num2 = Mathf.Min(num2, i); num3 = Mathf.Max(num3, j); num4 = Mathf.Max(num4, i); } } } if (num3 < num || num4 < num2) { return false; } rect = new Rect((float)num, (float)num2, (float)(num3 - num + 1), (float)(num4 - num2 + 1)); trimmed = num != 0 || num2 != 0 || num3 != ((Texture)texture).width - 1 || num4 != ((Texture)texture).height - 1; return true; } private static bool TryReadPngDimensions(byte[] data, out int width, out int height) { width = 0; height = 0; if (data == null || data.Length < 24 || data[0] != 137 || data[1] != 80 || data[2] != 78 || data[3] != 71) { return false; } width = ReadBigEndianInt32(data, 16); height = ReadBigEndianInt32(data, 20); if (width > 0) { return height > 0; } return false; } private static int ReadBigEndianInt32(byte[] data, int offset) { return (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]; } }