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 Silken Impact v1.6.0
plugins/com.kokomi.silkenimpact.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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.Configuration; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SilkenImpact; using SilkenImpact.Patch; using TMPro; using TeamCherry.Localization; 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("com.kokomi.silkenimpact")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.6.0.0")] [assembly: AssemblyInformationalVersion("1.6.0+051e21b7d3445bf53176ca55e1c2c4b1bc111a0e")] [assembly: AssemblyProduct("Silken Impact")] [assembly: AssemblyTitle("com.kokomi.silkenimpact")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.6.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public class BossHealthBarContainer : MonoBehaviour { [SerializeField] private List<HealthBar> bars = new List<HealthBar>(); [SerializeField] private RectTransform rect; public float interval = 0.3f; public void SetWidth(float width) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)this).GetComponent<RectTransform>(); component.sizeDelta = new Vector2(width, component.sizeDelta.y); OnUpdate(); } public void AddBar(HealthBar bar) { if (!Object.op_Implicit((Object)(object)bars.Find((HealthBar b) => (Object)(object)b == (Object)(object)bar))) { bars.Add(bar); ((Component)bar).transform.SetParent(((Component)this).transform, false); OnUpdate(); } } public void RemoveBar(HealthBar bar) { bars.Remove(bar); OnUpdate(); } private float barWidth() { //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) int count = bars.Count; if (count <= 0) { return 0f; } Rect val = rect.rect; return (((Rect)(ref val)).width - interval * (float)(count - 1)) / (float)count; } private float barCenterX(int index, float barWidth) { return (float)index * (barWidth + interval) + barWidth / 2f; } private void OnUpdate() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) int count = bars.Count; float width = barWidth(); for (int i = 0; i < count; i++) { bars[i].SetWidth(width); ((Component)bars[i]).GetComponent<RectTransform>().anchoredPosition = new Vector2(barCenterX(i, width), 0f); } } internal void TakeDamage(int index, float amount) { int count = bars.Count; if (index < count && index >= 0) { bars[index].TakeDamage(amount); } } internal void Heal(int index, float amount) { int count = bars.Count; if (index < count && index >= 0) { bars[index].Heal(amount); } } } public class ContainerTest : MonoBehaviour { public BossHealthBarContainer container; } namespace System.Runtime.CompilerServices { internal static class IsExternalInit { } } namespace SilkenImpact { internal static class AssetPaths { internal static class Prefabs { internal const string DamageText = "Assets/Addressables/Prefabs/DamageOldText.prefab"; internal const string HealText = "Assets/Addressables/Prefabs/HealOldText.prefab"; internal const string BossContainer = "Assets/Addressables/Prefabs/Container.prefab"; } internal static class HealthBars { internal const string RoundedMob = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab"; internal const string DiamondMob = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab"; internal const string RoundedBoss = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab"; internal const string DiamondBoss = "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab"; internal static string ForMobShape(HealthBarShape shape) { if (shape == HealthBarShape.Diamond) { return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab"; } return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab"; } internal static string ForBossShape(HealthBarShape shape) { if (shape == HealthBarShape.Diamond) { return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab"; } return "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab"; } } } public enum HealthBarShape { Rounded, Diamond } public class Configs : MonoBehaviour { private static Configs __instance; public ConfigEntry<float> shortBarWidth; public ConfigEntry<float> mediumBarWidth; public ConfigEntry<float> longBarWidth; public ConfigEntry<float> bossBarWidth; public ConfigEntry<HealthBarShape> healthBarShape; public ConfigEntry<float> minMobHp; public ConfigEntry<float> minMediumBarHp; public ConfigEntry<float> minLongBarHp; public ConfigEntry<float> minBossBarHp; public ConfigEntry<float> infHp; public ConfigEntry<bool> displayMobHpBar; public ConfigEntry<bool> displayBossHpBar; public ConfigEntry<float> spriteTrackerZOffset; public ConfigEntry<float> maxZPosition; public ConfigEntry<float> visibleCacheSeconds; public ConfigEntry<float> invisibleCacheSeconds; public ConfigEntry<Color> hpColor; public ConfigEntry<Color> delayedEffectColor; public ConfigEntry<Color> hpBarBackgroundColor; public ConfigEntry<Color> hpNumberColor; public ConfigEntry<bool> displayHpNumbers; public ConfigEntry<float> hpNumberFontSizeScaler; public ConfigEntry<float> bossNameFontSizeScaler; public ConfigEntry<Color> defaultColor; public ConfigEntry<Color> poisonColor; public ConfigEntry<Color> fireColor; public ConfigEntry<Color> critHitColor; public ConfigEntry<Color> healTextColor; public ConfigEntry<float> weightOfNewHit; public ConfigEntry<bool> displayDamageText; public ConfigEntry<bool> displayHealText; public ConfigEntry<float> damageFontSizeScaler; public ConfigEntry<FontOption> damageFont; public ConfigEntry<string> damageOsFontName; public ConfigEntry<FontOption> hpBarFont; public ConfigEntry<string> hpBarOsFontName; internal ConfigEntry<LanguageOption> selectedLanguage; public static Configs Instance { get { //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_0027: Expected O, but got Unknown if ((Object)(object)__instance == (Object)null) { GameObject val = new GameObject("Configs"); __instance = val.AddComponent<Configs>(); Object.DontDestroyOnLoad((Object)val); } return __instance; } } private ConfigFile config => ((BaseUnityPlugin)Plugin.Instance).Config; private void Awake() { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } BindLanguage(LanguageOption.English); LoadLanguageConfigs(selectedLanguage.Value); } private void BindLanguage(LanguageOption defaultOption) { new MyConfigSection("Language", config).AddAdvancedEntry(ref selectedLanguage, defaultOption, "Selected Language", "Choose config language (requires reopening the config manager window)"); selectedLanguage.SettingChanged += OnLanguageChanged; } private void OnLanguageChanged(object sender, EventArgs e) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { object boxedValue = ((SettingChangedEventArgs)e).ChangedSetting.BoxedValue; _ = selectedLanguage; config.Clear(); LanguageOption valueOrDefault = (boxedValue as LanguageOption?).GetValueOrDefault(); LoadLanguageConfigs(valueOrDefault); BindLanguage(valueOrDefault); } finally { config.SaveOnConfigSet = saveOnConfigSet; } } private void LoadLanguageConfigs(LanguageOption language) { LocalizedConfigs.Load(this, language); } public float GetHpBarWidth(float maxHp, bool isBoss) { if (isBoss) { return bossBarWidth.Value; } if (maxHp >= minLongBarHp.Value) { return longBarWidth.Value; } if (maxHp >= minMediumBarHp.Value) { return mediumBarWidth.Value; } return shortBarWidth.Value; } } internal sealed class ConfigurationManagerAttributes { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); public bool? ShowRangeAsPercent; public Action<ConfigEntryBase> CustomDrawer; public CustomHotkeyDrawerFunc CustomHotkeyDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func<object, string> ObjToStr; public Func<string, object> StrToObj; } internal class MyConfigEntry<T> { public string Section; public string Key; public T DefaultValue; public string Description; public bool IsAdvanced; public int Order; public bool Browsable; public ConfigEntry<T> Bind(ConfigFile config) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown return config.Bind<T>(Section, Key, DefaultValue, new ConfigDescription(Description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { IsAdvanced = IsAdvanced, Order = Order, Browsable = Browsable } })); } } internal class MyConfigSliderEntry<T> : MyConfigEntry<T> where T : IComparable { public T MinValue; public T MaxValue; public new ConfigEntry<T> Bind(ConfigFile config) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown return config.Bind<T>(Section, Key, DefaultValue, new ConfigDescription(Description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(MinValue, MaxValue), new object[1] { new ConfigurationManagerAttributes { IsAdvanced = IsAdvanced, Order = Order, Browsable = Browsable } })); } } internal class MyConfigSection { public ConfigFile configFile; private int _nextOrder = int.MaxValue; public string Name { get; } public MyConfigSection(string name, ConfigFile configFile) { Name = name; this.configFile = configFile; } public MyConfigSection AddEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool isAdvanced = false, bool browsable = true) { int order = _nextOrder--; MyConfigEntry<T> myConfigEntry = new MyConfigEntry<T> { Section = Name, Key = key, DefaultValue = defaultValue, Description = description, IsAdvanced = isAdvanced, Order = order, Browsable = browsable }; entry = myConfigEntry.Bind(configFile); return this; } public MyConfigSection AddSliderEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, T minValue, T maxValue, bool isAdvanced = false, bool browsable = true) where T : IComparable { int order = _nextOrder--; MyConfigSliderEntry<T> myConfigSliderEntry = new MyConfigSliderEntry<T> { Section = Name, Key = key, DefaultValue = defaultValue, Description = description, IsAdvanced = isAdvanced, Order = order, Browsable = browsable, MinValue = minValue, MaxValue = maxValue }; entry = myConfigSliderEntry.Bind(configFile); return this; } public MyConfigSection AddEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool isAdvanced = false, bool browsable = true) { return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced, browsable); } public MyConfigSection AddSliderEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, T minValue, T maxValue, bool isAdvanced = false, bool browsable = true) where T : IComparable { return AddSliderEntry(ref entry, defaultValue, config.key, config.description, minValue, maxValue, isAdvanced, browsable); } public MyConfigSection AddHiddenEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool isAdvanced = false) { return AddEntry(ref entry, defaultValue, key, description, isAdvanced, browsable: false); } public MyConfigSection AddHiddenEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool isAdvanced = false) { return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced, browsable: false); } public MyConfigSection AddAdvancedEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description, bool browsable = true) { return AddEntry(ref entry, defaultValue, key, description, isAdvanced: true, browsable); } public MyConfigSection AddAdvancedEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config, bool browsable = true) { return AddEntry(ref entry, defaultValue, config.key, config.description, isAdvanced: true, browsable); } public MyConfigSection AddDebugOnlyEntry<T>(ref ConfigEntry<T> entry, T defaultValue, string key, string description) { return AddHiddenEntry(ref entry, defaultValue, key, description); } public MyConfigSection AddDebugOnlyEntry<T>(ref ConfigEntry<T> entry, T defaultValue, (string key, string description) config) { return AddHiddenEntry(ref entry, defaultValue, config.key, config.description); } } internal enum LanguageOption { English, 简体中文, Deutsch, Español, Français, Italiano, 日本語, 한국어, Português, Русский } [Serializable] public class ConfigEntry { [JsonProperty] public string key; [JsonProperty] public string description; } [Serializable] public class ConfigSection { [JsonProperty] public string name; [JsonProperty] public Dictionary<string, ConfigEntry> entries = new Dictionary<string, ConfigEntry>(); public ConfigEntry this[string key] => entries[key]; public (string key, string description) Get(string key) { ConfigEntry configEntry = entries[key]; return (configEntry.key, configEntry.description); } } [Serializable] public class LocalizationData { [JsonProperty("sections")] private Dictionary<string, ConfigSection> sections = new Dictionary<string, ConfigSection>(); public ConfigSection this[string sectionName] => sections[sectionName]; } internal class LocalizedConfigs { private static LocalizationData localization; private static LanguageOption? loadedLanguage; protected static string JsonFileName(LanguageOption option) { return option switch { LanguageOption.English => "en.json", LanguageOption.简体中文 => "zh.json", LanguageOption.Deutsch => "de.json", LanguageOption.Español => "es.json", LanguageOption.Français => "fr.json", LanguageOption.Italiano => "it.json", LanguageOption.日本語 => "ja.json", LanguageOption.한국어 => "ko.json", LanguageOption.Português => "pt.json", LanguageOption.Русский => "ru.json", _ => "en.json", }; } private static void LoadLocalizationIfNeeded(LanguageOption option) { if (!loadedLanguage.HasValue || loadedLanguage != option) { loadedLanguage = option; } try { localization = JsonConvert.DeserializeObject<LocalizationData>(File.ReadAllText(Path.Combine(Plugin.AssetsFolder, "Localization", JsonFileName(loadedLanguage.Value)))); } catch (Exception ex) { loadedLanguage = null; throw ex; } } public static void Load(Configs configs, LanguageOption option) { //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) try { LoadLocalizationIfNeeded(option); } catch (Exception arg) { PluginLogger.LogFatal($"[LocalizedConfigs][Load] Load failed, language={option} error={arg}"); return; } ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; ConfigSection configSection = localization["User: Health Bar Sizes"]; new MyConfigSection(configSection.name, ((BaseUnityPlugin)Plugin.Instance).Config).AddEntry(ref configs.shortBarWidth, 2f, configSection.Get("Short Bar Width")).AddEntry(ref configs.mediumBarWidth, 4f, configSection.Get("Medium Bar Width")).AddEntry(ref configs.longBarWidth, 6f, configSection.Get("Long Bar Width")) .AddEntry(ref configs.bossBarWidth, 13f, configSection.Get("Boss Bar Width")); ConfigSection configSection2 = localization["User: Visibility Control"]; new MyConfigSection(configSection2.name, config).AddEntry(ref configs.displayMobHpBar, defaultValue: true, configSection2.Get("Display Mob HP Bar")).AddEntry(ref configs.displayBossHpBar, defaultValue: true, configSection2.Get("Display Boss HP Bar")).AddEntry(ref configs.displayDamageText, defaultValue: true, configSection2.Get("Display Damage Text")) .AddEntry(ref configs.displayHealText, defaultValue: true, configSection2.Get("Display Heal Text")) .AddEntry(ref configs.displayHpNumbers, defaultValue: false, configSection2.Get("Display Health Numbers")); ConfigSection configSection3 = localization["User: Health Bar Thresholds"]; new MyConfigSection(configSection3.name, config).AddAdvancedEntry(ref configs.minMobHp, 5f, configSection3.Get("Min Mob HP")).AddAdvancedEntry(ref configs.minMediumBarHp, 50f, configSection3.Get("Min Medium Bar HP")).AddAdvancedEntry(ref configs.minLongBarHp, 100f, configSection3.Get("Min Long Bar HP")) .AddAdvancedEntry(ref configs.minBossBarHp, 120f, configSection3.Get("Min Boss Bar HP")); ConfigSection configSection4 = localization["User: Health Bar Shapes"]; new MyConfigSection(configSection4.name, config).AddEntry(ref configs.healthBarShape, HealthBarShape.Diamond, configSection4.Get("Health Bar Shape")); ConfigSection configSection5 = localization["User: Health Bar Colors"]; new MyConfigSection(configSection5.name, config).AddEntry(ref configs.hpColor, ColourPalette.HP, configSection5.Get("HP Color")).AddEntry(ref configs.delayedEffectColor, ColourPalette.DelayedEffect, configSection5.Get("Delayed Effect Color")).AddEntry(ref configs.hpBarBackgroundColor, ColourPalette.HpBarBackground, configSection5.Get("HP Bar Background Color")) .AddEntry(ref configs.hpNumberColor, ColourPalette.HpNumber, configSection5.Get("HP Number Color")); ConfigSection configSection6 = localization["User: Health Bar Font Size"]; new MyConfigSection(configSection6.name, config).AddSliderEntry(ref configs.hpNumberFontSizeScaler, 1f, configSection6.Get("HP Number Font Size Scaler"), 0.1f, 2f).AddSliderEntry(ref configs.bossNameFontSizeScaler, 1f, configSection6.Get("Boss Name Font Size Scaler"), 0.1f, 2f); ConfigSection configSection7 = localization["User: Damage Text Colors"]; new MyConfigSection(configSection7.name, config).AddEntry(ref configs.defaultColor, ColourPalette.HornetDress, configSection7.Get("Default Color")).AddEntry(ref configs.critHitColor, ColourPalette.Geo, configSection7.Get("Crit Hit Color")).AddEntry(ref configs.poisonColor, ColourPalette.Electro, configSection7.Get("Poison Color")) .AddEntry(ref configs.fireColor, ColourPalette.Pyro, configSection7.Get("Fire Color")) .AddEntry(ref configs.healTextColor, ColourPalette.HealTextColor, configSection7.Get("Heal Color")); ConfigSection configSection8 = localization["User: Damage Text Settings"]; new MyConfigSection(configSection8.name, config).AddSliderEntry(ref configs.damageFontSizeScaler, 1f, configSection8.Get("Damage Font Scaler"), 0.1f, 2f).AddDebugOnlyEntry(ref configs.weightOfNewHit, 0.2f, configSection8.Get("Weight Of New Hit")); ConfigSection configSection9 = localization["User: Font Settings"]; new MyConfigSection(configSection9.name, config).AddEntry(ref configs.damageFont, FontOption.SmileySans, configSection9.Get("Damage Font")).AddEntry(ref configs.damageOsFontName, "Arial", configSection9.Get("Damage OS Font Name")).AddEntry(ref configs.hpBarFont, FontOption.SmileySans, configSection9.Get("HP Bar Font")) .AddEntry(ref configs.hpBarOsFontName, "Arial", configSection9.Get("HP Bar OS Font Name")); ConfigSection configSection10 = localization["Dev: Visibility Controller Settings"]; new MyConfigSection(configSection10.name, config).AddDebugOnlyEntry(ref configs.maxZPosition, 1f, configSection10.Get("Max Z Position")).AddDebugOnlyEntry(ref configs.visibleCacheSeconds, 0.5f, configSection10.Get("Visible Cache Seconds")).AddDebugOnlyEntry(ref configs.invisibleCacheSeconds, 0.5f, configSection10.Get("Invisible Cache Seconds")) .AddDebugOnlyEntry(ref configs.infHp, 10000f, configSection10.Get("Infinite HP Threshold")) .AddDebugOnlyEntry(ref configs.spriteTrackerZOffset, -1.5f, configSection10.Get("Sprite Tracker Z Offset")); } } public static class DamageTextSpawnUtils { public static float avgDamagePerHit = -1f; public static float weightOfNew => Configs.Instance.weightOfNewHit.Value; private static void spawnTextOn(HealthManager hm, GameObject textGO, string content, float horizontalOffsetScale, float verticalOffsetScale, float sizeScale, Color color) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_00bf: Unknown result type (might be due to invalid IL or missing references) ((Object)textGO).name = content + " -> " + ((Object)((Component)hm).gameObject).name; Renderer component = ((Component)hm).gameObject.GetComponent<Renderer>(); ? val; if (!Object.op_Implicit((Object)(object)component)) { val = new Vector3(1f, 1f, 0f); } else { Bounds bounds = component.bounds; val = ((Bounds)(ref bounds)).size; } Vector3 val2 = (Vector3)val; val2.x *= horizontalOffsetScale / 2f; val2.y *= verticalOffsetScale / 2f; textGO.transform.position = ((Component)hm).gameObject.transform.position + val2; textGO.transform.SetParent(((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform, true); DamageText component2 = textGO.GetComponent<DamageText>(); component2.DamageString = content; component2.TextColor = color; component2.TextFont = Singleton<FontManager>.instance.DamageFontLoader.Load(); component2.ResetForSpawn(sizeScale); } public static void SpawnDamageText(HealthManager hm, float damage, bool isCritHit, NailElements element = 0, Color? color = null) { //IL_00e4: 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_00db: Unknown result type (might be due to invalid IL or missing references) if (!(damage <= 0f) && Configs.Instance.displayDamageText.Value) { float horizontalOffsetScale = Random.Range(-1f, 1f); float verticalOffsetScale = Random.Range(-0.4f, 0.7f); float num = Random.Range(1f, 1.1f) * (isCritHit ? Mathf.Clamp(damageScale(damage), 2f, 2.5f) : Mathf.Clamp(damageScale(damage), 0.5f, 1.5f)); num *= Configs.Instance.damageFontSizeScaler.Value; updateAvgDamagePerHit(damage); GameObject val = PooledObjectService.Instance.Acquire("Assets/Addressables/Prefabs/DamageOldText.prefab", "DamageText", ((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform); if (!((Object)(object)val == (Object)null)) { spawnTextOn(hm, val, ((int)damage).ToString(), horizontalOffsetScale, verticalOffsetScale, num, (Color)(((??)color) ?? textColor(element, isCritHit))); } } } public static void SpawnHealText(HealthManager hm, float amount, Color? color = null) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (!(amount <= 0f) && Configs.Instance.displayHealText.Value) { float horizontalOffsetScale = Random.Range(-0.5f, 0.5f); float verticalOffsetScale = Random.Range(0f, 0.8f); float num = Random.Range(1.5f, 1.8f); num *= Configs.Instance.damageFontSizeScaler.Value; GameObject val = PooledObjectService.Instance.Acquire("Assets/Addressables/Prefabs/HealOldText.prefab", "HealText", ((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform); if (!((Object)(object)val == (Object)null)) { spawnTextOn(hm, val, $"+{(int)amount}", horizontalOffsetScale, verticalOffsetScale, num, (Color)(((??)color) ?? Configs.Instance.healTextColor.Value)); } } } private static void updateAvgDamagePerHit(float damage) { if (!(damage <= 0f) && !(damage >= 9999f)) { if (avgDamagePerHit <= 0f) { avgDamagePerHit = damage; } else { avgDamagePerHit = weightOfNew * damage + (1f - weightOfNew) * avgDamagePerHit; } } } private static float damageScale(float damage) { if (avgDamagePerHit <= 0f) { return 1f; } float num = damage / avgDamagePerHit; return 0.5f + 0.5f * Mathf.Pow(num, 0.5f); } private static Color textColor(NailElements element, bool isCritHit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0050: Unknown result type (might be due to invalid IL or missing references) //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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((int)element != 1) { if ((int)element == 2) { return Configs.Instance.poisonColor.Value; } return isCritHit ? Configs.Instance.critHitColor.Value : Configs.Instance.defaultColor.Value; } return Configs.Instance.fireColor.Value; } } public abstract class ConfigFontLoaderAdapter : IFontLoader { private FontArgs cachedArgs; private IFontLoader fontLoader; private IFontLoader fallbackLoader = new SmileySansLoader(); protected abstract FontArgs CurrentArgs { get; } public Font Load() { FontArgs currentArgs = CurrentArgs; Font val = null; if (cachedArgs == null || !cachedArgs.Equals(currentArgs)) { fontLoader = FontLoaderFactory.CreateFontLoader(currentArgs); cachedArgs = currentArgs; } val = fontLoader.Load(); if ((Object)(object)val == (Object)null) { return fallbackLoader.Load(); } return val; } } public class DamageFontLoader : ConfigFontLoaderAdapter { protected override FontArgs CurrentArgs => Configs.Instance.damageFont.Value switch { FontOption.SmileySans => new SmileySansFontArgs(), FontOption.InGameFont => new InGameFontArgs(), FontOption.OSFont => new OSFontArgs(Configs.Instance.damageOsFontName.Value), _ => throw new ArgumentOutOfRangeException(), }; } public class HpBarFontLoader : ConfigFontLoaderAdapter { protected override FontArgs CurrentArgs => Configs.Instance.hpBarFont.Value switch { FontOption.SmileySans => new SmileySansFontArgs(), FontOption.InGameFont => new InGameFontArgs(), FontOption.OSFont => new OSFontArgs(Configs.Instance.hpBarOsFontName.Value), _ => throw new ArgumentOutOfRangeException(), }; } public static class FontLoaderFactory { private static IFontLoader FallbackFontLoader(FontArgs args) { return new SmileySansLoader(); } public static IFontLoader CreateFontLoader(FontArgs args) { return args.FontOption switch { FontOption.SmileySans => new SmileySansLoader(), FontOption.InGameFont => new GameFontLoader(), FontOption.OSFont => new OSFontLoader(((OSFontArgs)args).FontName), _ => FallbackFontLoader(args), }; } } public class FontManager : Singleton<FontManager> { public IFontLoader DamageFontLoader { get; private set; } = new DamageFontLoader(); public IFontLoader HpBarFontLoader { get; private set; } = new HpBarFontLoader(); } public interface IFontLoader { Font Load(); } public enum FontOption { SmileySans, InGameFont, OSFont } public abstract record FontArgs(FontOption FontOption); public sealed record SmileySansFontArgs : FontArgs { public SmileySansFontArgs() : base(FontOption.SmileySans) { } } public sealed record InGameFontArgs : FontArgs { public InGameFontArgs() : base(FontOption.InGameFont) { } } public sealed record OSFontArgs(string FontName) : FontArgs(FontOption.OSFont); public abstract class CachedFontLoader : IFontLoader { protected Font cachedFont; protected abstract Font DoLoad(); public Font Load() { if ((Object)(object)cachedFont == (Object)null) { cachedFont = DoLoad(); } return cachedFont; } } public class GameFontLoader : CachedFontLoader { private string fontName = "TrajanPro-Regular"; protected override Font DoLoad() { Font? obj = ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => ((Object)f).name.Contains(fontName))); _ = (Object)(object)obj == (Object)null; return obj; } } public class OSFontLoader : CachedFontLoader { public string FontName { get; set; } public OSFontLoader(string fontName) { FontName = fontName; } protected override Font DoLoad() { string[] oSInstalledFontNames = Font.GetOSInstalledFontNames(); bool flag = false; string[] array = oSInstalledFontNames; for (int i = 0; i < array.Length; i++) { if (array[i] == FontName) { flag = true; break; } } return Font.CreateDynamicFontFromOSFont(FontName, 16); } } public class SmileySansLoader : CachedFontLoader { protected override Font DoLoad() { AssetBundle bundle = Plugin.bundle; if ((Object)(object)bundle == (Object)null) { return null; } return bundle.LoadAsset<Font>("Assets/Addressables/Fonts/SmileySans-Oblique.ttf"); } } public abstract class BaseHealthBarController<EventType, OwnerType> : MonoBehaviour where OwnerType : MonoBehaviour, IHealthBarOwner { protected Dictionary<GameObject, HealthBar> healthBarOf = new Dictionary<GameObject, HealthBar>(); protected LinkBuffer linkBuffer; public abstract GameObject GetNewHealthBar { get; } public abstract Canvas BarCanvas { get; } protected void RegisterEventHandlers() { EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Spawn, OnEnemySpawn); EventHandle<EventType>.Register<GameObject, GameObject>(HealthBarOwnerEventType.Link, LinkEnemy); EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Die, OnEnemyDie); EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Heal, OnEnemyHeal); EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.Damage, OnEnemyDamage); EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Hide, OnEnemyHide); EventHandle<EventType>.Register<GameObject>(HealthBarOwnerEventType.Show, OnEnemyShow); EventHandle<EventType>.Register<GameObject, float>(HealthBarOwnerEventType.SetHP, OnEnemySetHP); EventHandle<EventType>.Register(HealthBarOwnerEventType.CheckHP, delegate(GameObject go) { OnCheckHP(go); }); } protected virtual void Awake() { RegisterEventHandlers(); linkBuffer = new LinkBuffer(TryLinkEnemy); ((MonoBehaviour)this).InvokeRepeating("MatchVisualsWithConfigs", 0f, 1f); } protected void OnCheckHP(GameObject enemyGO, bool fixMismatch = false) { float num = 0f; HealthManager component = enemyGO.GetComponent<HealthManager>(); num = ((!((Object)(object)component.SendDamageTo != (Object)null)) ? ((float)component.hp) : ((float)component.SendDamageTo.hp)); if (!guardExist(enemyGO)) { return; } HealthBar healthBar = healthBarOf[enemyGO]; if (!(Mathf.Abs(healthBar.CurrentHealth - num) > 0.01f)) { return; } float num2 = healthBar.CurrentHealth - num; if (fixMismatch) { if (num2 > 0f) { healthBar.TakeDamage(num2); } else { healthBar.Heal(0f - num2); } } } protected bool guardExist(GameObject enemyGO) { if (!healthBarOf.ContainsKey(enemyGO)) { return false; } return true; } public GameObject GetRandomEnemyGO() { foreach (KeyValuePair<GameObject, HealthBar> item in healthBarOf) { if ((Object)(object)item.Key != (Object)null) { return item.Key.gameObject; } } return null; } protected virtual void OnEnemyShow(GameObject enemyGO) { if (guardExist(enemyGO)) { healthBarOf[enemyGO].SetVisibility(visible: true); } } protected abstract float BarWidth(float maxHp); protected bool TryLinkEnemy(GameObject originGO, GameObject relayGO) { if (!guardExist(originGO)) { return false; } if (healthBarOf.ContainsKey(relayGO)) { GameObject gameObject = ((Component)healthBarOf[relayGO]).gameObject; PooledObjectService.Instance.Release(gameObject); } healthBarOf[relayGO] = healthBarOf[originGO]; IHealthBarOwner healthBarOwner = default(IHealthBarOwner); if (relayGO.TryGetComponent<IHealthBarOwner>(ref healthBarOwner)) { healthBarOwner.RemoveVisibilityController(); } IHealthBarOwner healthBarOwner2 = default(IHealthBarOwner); if (originGO.TryGetComponent<IHealthBarOwner>(ref healthBarOwner2)) { healthBarOwner2.LinkVisibilityControl(relayGO); } return true; } protected void LinkEnemy(GameObject sourceGO, GameObject withGO) { if (!Object.op_Implicit((Object)(object)withGO.GetComponent<OwnerType>())) { withGO.AddComponent<OwnerType>().RemoveVisibilityController(); } linkBuffer.RegisterRelay(sourceGO, withGO); } protected void MatchVisualsWithConfigs(HealthBar bar) { //IL_0014: 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_003e: 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) if (Object.op_Implicit((Object)(object)bar)) { bar.SetHpColor(Configs.Instance.hpColor.Value); bar.SetDelayedEffectColor(Configs.Instance.delayedEffectColor.Value); bar.SetBackgroundColor(Configs.Instance.hpBarBackgroundColor.Value); bar.SetWidth(BarWidth(bar.MaxHealth)); UIHealthBar component = ((Component)bar).GetComponent<UIHealthBar>(); if ((Object)(object)component != (Object)null) { component.SetHpTextEnabled(Configs.Instance.displayHpNumbers.Value); component.SetHpTextColor(Configs.Instance.hpNumberColor.Value); component.SetFont(Singleton<FontManager>.instance.HpBarFontLoader.Load()); component.SetNameScale(Configs.Instance.bossNameFontSizeScaler.Value); component.SetHpNumberScale(Configs.Instance.hpNumberFontSizeScaler.Value); } } } protected virtual void MatchVisualsWithConfigs() { foreach (KeyValuePair<GameObject, HealthBar> item in healthBarOf) { MatchVisualsWithConfigs(item.Value); } } protected virtual void OnEnemySpawn(GameObject enemyGO, float maxHp) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (healthBarOf.ContainsKey(enemyGO)) { HealthBar healthBar = healthBarOf[enemyGO]; healthBar.SetMaxHealth(maxHp); return; } GameObject getNewHealthBar = GetNewHealthBar; ((Object)getNewHealthBar).name = "HealthBar_" + ((Object)enemyGO).name; if (!((Object)(object)getNewHealthBar == (Object)null)) { getNewHealthBar.transform.SetParent(((Component)BarCanvas).transform); getNewHealthBar.transform.localScale = Vector3.one; HealthBar healthBar = getNewHealthBar.GetComponent<HealthBar>(); healthBar.SetMaxHealth(maxHp); MatchVisualsWithConfigs(healthBar); healthBarOf[enemyGO] = healthBar; if (!Object.op_Implicit((Object)(object)enemyGO.GetComponent<OwnerType>())) { enemyGO.AddComponent<OwnerType>(); } ApplySpecialPatches(enemyGO); linkBuffer.RegisterOrigin(enemyGO); } } protected void ApplySpecialPatches(GameObject enemyGO) { if (DeathWatcher.IngameGameObjectNames.Contains(((Object)enemyGO).name.ToLower()) && !Object.op_Implicit((Object)(object)enemyGO.GetComponent<DeathWatcher>())) { enemyGO.AddComponent<DeathWatcher>().Init(enemyGO); } if (!Object.op_Implicit((Object)(object)enemyGO.GetComponent<InitHpWatcher>())) { enemyGO.AddComponent<InitHpWatcher>(); } } protected void OnEnemyDamage(GameObject enemyGO, float amount) { if (guardExist(enemyGO)) { healthBarOf[enemyGO].TakeDamage(amount); OnCheckHP(enemyGO); } } protected void OnEnemyHeal(GameObject enemyGO, float amount) { if (guardExist(enemyGO)) { healthBarOf[enemyGO].Heal(amount); OnCheckHP(enemyGO); } } protected virtual void OnEnemyHide(GameObject enemyGO) { if (guardExist(enemyGO)) { healthBarOf[enemyGO].SetVisibility(visible: false); } } protected virtual void OnEnemyDie(GameObject enemyGO) { if (guardExist(enemyGO)) { HealthBar healthBar = healthBarOf[enemyGO]; PooledObjectService.Instance.Release(((Component)healthBar).gameObject); healthBarOf.Remove(enemyGO); } } protected void OnEnemySetHP(GameObject enemyGO, float hp) { if (guardExist(enemyGO)) { healthBarOf[enemyGO].ResetHealth(hp); OnCheckHP(enemyGO, fixMismatch: true); } } } public class BaseHealthBarOwner<EventType> : MonoBehaviour, IHealthBarOwner { private IVisibilityController visibilityController; public Dispatcher Dispatcher { get; private set; } private void Awake() { HealthManager component = ((Component)this).GetComponent<HealthManager>(); visibilityController = new VisibilityController(component); Dispatcher = new Dispatcher(this); } private void Update() { if (visibilityController != null) { if (!visibilityController.Update()) { return; } CheckHP(); if (visibilityController.IsVisible) { Show(); } else { Hide(); } } ((Component)this).GetComponent<HealthManager>(); } private void OnDisable() { updateVisibilityImmediate(); } private void OnEnable() { updateVisibilityImmediate(); } private void OnDestroy() { Die(); } private void updateVisibilityImmediate() { if (visibilityController != null && visibilityController.Update(forceCheck: true)) { if (visibilityController.IsVisible) { Show(); } else { Hide(); } } } public void Heal(float amount) { EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Heal, ((Component)this).gameObject, amount); updateVisibilityImmediate(); } public void TakeDamage(float amount) { updateVisibilityImmediate(); EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Damage, ((Component)this).gameObject, amount); updateVisibilityImmediate(); } public void Die() { EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Die, ((Component)this).gameObject); updateVisibilityImmediate(); } public void Hide() { EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)this).gameObject); } public void Show() { EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.Show, ((Component)this).gameObject); } public void SetHP(float hp) { EventHandle<EventType>.SendEvent<GameObject, float>(HealthBarOwnerEventType.SetHP, ((Component)this).gameObject, hp); updateVisibilityImmediate(); } public void CheckHP() { EventHandle<EventType>.SendEvent<GameObject>(HealthBarOwnerEventType.CheckHP, ((Component)this).gameObject); } public void RemoveVisibilityController() { visibilityController = null; } public void LinkVisibilityControl(GameObject go) { if (visibilityController == null || visibilityController is VisibilityController) { visibilityController = new LinkedVisibilityController(); visibilityController.Inspect(((Component)this).GetComponent<HealthManager>()); } HealthManager healthManager = default(HealthManager); if (go.TryGetComponent<HealthManager>(ref healthManager)) { visibilityController.Inspect(healthManager); } } } public static class BossResolver { public static bool IsBoss(HealthManager healthManager) { DisplayBossTitle bossTitleAction = GetBossTitleAction(((Component)healthManager).gameObject); if (bossTitleAction == null) { Transform parent = ((Component)healthManager).gameObject.transform.parent; bossTitleAction = GetBossTitleAction((parent != null) ? ((Component)parent).gameObject : null, searchInChildren: true); } return bossTitleAction != null; } public static string BossName(HealthManager healthManager) { string text = null; if (((Object)((Component)healthManager).gameObject).name == "Dock Guard Thrower") { text = "DOCK_GUARD_DUO"; } else { DisplayBossTitle bossTitleAction = GetBossTitleAction(((Component)healthManager).gameObject); if (bossTitleAction == null) { Transform parent = ((Component)healthManager).gameObject.transform.parent; bossTitleAction = GetBossTitleAction((parent != null) ? ((Component)parent).gameObject : null, searchInChildren: true); } text = ((bossTitleAction != null) ? bossTitleAction.bossTitle.Value : null); } if (string.IsNullOrEmpty(text)) { return null; } return LocalizedDisplayName(text); } private static string Localized(string titleKey) { string text = "Titles"; string text2 = Language.Get(titleKey, text); if (text2.StartsWith("#")) { return null; } if (string.IsNullOrEmpty(text2)) { return null; } return text2; } private static string LocalizedDisplayName(string titleKey) { string text; if (titleKey == "DOCK_GUARD_DUO") { text = Localized(titleKey + "_MAIN").Split("&").Last().Trim(); text = Localized(titleKey + "_SUPER") + text; } else { text = Localized(titleKey + "_SUPER") + Localized(titleKey + "_MAIN") + Localized(titleKey + "_SUB"); } if (string.IsNullOrEmpty(text)) { return null; } return text; } private static DisplayBossTitle GetBossTitleAction(GameObject gameObject, bool searchInChildren = false) { if ((Object)(object)gameObject == (Object)null) { return null; } PlayMakerFSM[] array = (searchInChildren ? gameObject.GetComponentsInChildren<PlayMakerFSM>() : gameObject.GetComponents<PlayMakerFSM>()); for (int i = 0; i < array.Length; i++) { FsmState[] fsmStates = array[i].FsmStates; for (int j = 0; j < fsmStates.Length; j++) { FsmStateAction[] actions = fsmStates[j].Actions; foreach (FsmStateAction val in actions) { if (val is DisplayBossTitle) { return (DisplayBossTitle)(object)((val is DisplayBossTitle) ? val : null); } } } } return null; } } public class BossHealthBarController : BaseHealthBarController<BossOwnerEvent, BossHealthBarOwner> { private BossHealthBarContainer container; protected string containerPrefabPath = "Assets/Addressables/Prefabs/Container.prefab"; protected string healthBarPrefabPath => AssetPaths.HealthBars.ForBossShape(Configs.Instance.healthBarShape.Value); public override GameObject GetNewHealthBar => PooledObjectService.Instance.Acquire(healthBarPrefabPath, "BossHealthBar", ((Component)BarCanvas).transform); public override Canvas BarCanvas => ScreenSpaceCanvas.GetScreenSpaceCanvas; private void UpdateContainerWidth() { float value = Configs.Instance.bossBarWidth.Value; container.SetWidth(value); } private void prepareContainer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_00a6: Unknown result type (might be due to invalid IL or missing references) GameObject val = Plugin.InstantiateFromAssetsBundle(containerPrefabPath, "BossHealthBarContainer"); container = val.GetComponent<BossHealthBarContainer>(); ((Component)container).transform.SetParent(((Component)ScreenSpaceCanvas.GetScreenSpaceCanvas).transform); RectTransform component = ((Component)container).GetComponent<RectTransform>(); component.anchoredPosition = new Vector2(0f, 1.3f); component.sizeDelta = new Vector2(Configs.Instance.bossBarWidth.Value, component.sizeDelta.y); Image component2 = ((Component)container).GetComponent<Image>(); if (Object.op_Implicit((Object)(object)component2)) { ((Graphic)component2).color = new Color(1f, 1f, 1f, 0f); } } protected override void Awake() { base.Awake(); prepareContainer(); } protected override void MatchVisualsWithConfigs() { base.MatchVisualsWithConfigs(); UpdateContainerWidth(); } protected override void OnEnemyShow(GameObject enemyGO) { if (guardExist(enemyGO)) { base.OnEnemyShow(enemyGO); HealthBar bar = healthBarOf[enemyGO]; container.AddBar(bar); } } protected override void OnEnemySpawn(GameObject bossGO, float maxHp) { base.OnEnemySpawn(bossGO, maxHp); UIHealthBar component = ((Component)healthBarOf[bossGO]).GetComponent<UIHealthBar>(); if (Object.op_Implicit((Object)(object)component)) { string nameText = HealthManagerPatch.LocalisedName(bossGO.GetComponent<HealthManager>()); component.SetNameText(nameText); } } protected override void OnEnemyHide(GameObject bossGO) { if (guardExist(bossGO)) { base.OnEnemyHide(bossGO); HealthBar bar = healthBarOf[bossGO]; container.RemoveBar(bar); } } protected override void OnEnemyDie(GameObject bossGO) { if (guardExist(bossGO)) { HealthBar bar = healthBarOf[bossGO]; container.RemoveBar(bar); base.OnEnemyDie(bossGO); } } protected override float BarWidth(float maxHp) { return Configs.Instance.bossBarWidth.Value; } } public class BossHealthBarOwner : BaseHealthBarOwner<BossOwnerEvent> { } public class HealthBarEventArgs { public HealthBarOwnerEventType type { get; protected set; } public HealthBarEventArgs(HealthBarOwnerEventType type) { this.type = type; } } public class HealEventArgs : HealthBarEventArgs { public float amount; public HealEventArgs(float amount = 0f) : base(HealthBarOwnerEventType.Heal) { this.amount = amount; } } public class SetHpEventArgs : HealthBarEventArgs { public float amount; public SetHpEventArgs(float amount = 0f) : base(HealthBarOwnerEventType.SetHP) { this.amount = amount; } } public class DamageEventArgs : HealthBarEventArgs { public float amount; public DamageEventArgs(float amount = 0f) : base(HealthBarOwnerEventType.Damage) { this.amount = amount; } } public class Dispatcher { private class EventEntry { public HealthBarEventArgs args; public bool ready; public EventEntry(HealthBarEventArgs args) { this.args = args; } } private LinkedList<EventEntry> queue = new LinkedList<EventEntry>(); private Dictionary<HealthBarOwnerEventType, Action<HealthBarEventArgs>> handlers = new Dictionary<HealthBarOwnerEventType, Action<HealthBarEventArgs>>(); private int counter; private Dictionary<int, EventEntry> pendingEntries = new Dictionary<int, EventEntry>(); private void Dispatch() { while (queue.Count > 0) { EventEntry value = queue.First.Value; if (value.ready) { if (handlers.TryGetValue(value.args.type, out var value2)) { value2(value.args); } queue.RemoveFirst(); continue; } break; } } public Dispatcher(IHealthBarOwner owner) { handlers[HealthBarOwnerEventType.Heal] = delegate(HealthBarEventArgs evt) { owner.Heal(((HealEventArgs)evt).amount); }; handlers[HealthBarOwnerEventType.SetHP] = delegate(HealthBarEventArgs evt) { owner.SetHP(((SetHpEventArgs)evt).amount); }; handlers[HealthBarOwnerEventType.Damage] = delegate(HealthBarEventArgs evt) { owner.TakeDamage(((DamageEventArgs)evt).amount); }; } public int Enqueue<T>() where T : HealthBarEventArgs { EventEntry eventEntry = new EventEntry(null); queue.AddLast(eventEntry); eventEntry.ready = false; pendingEntries[counter] = eventEntry; return counter++; } public void EnqueueReady<T>(T args) where T : HealthBarEventArgs { EventEntry eventEntry = new EventEntry(args); eventEntry.ready = true; queue.AddLast(eventEntry); Dispatch(); } public void Submit<T>(int id, T args) where T : HealthBarEventArgs { if (pendingEntries.TryGetValue(id, out var value)) { value.ready = true; value.args = args; pendingEntries.Remove(id); Dispatch(); } } public void Cancel(int id) { if (pendingEntries.TryGetValue(id, out var value)) { queue.Remove(value); pendingEntries.Remove(id); Dispatch(); } } } public static class EventHandle<E> { private static readonly Dictionary<HealthBarOwnerEventType, Delegate> affairDict = new Dictionary<HealthBarOwnerEventType, Delegate>(); private static void beforeAdd(HealthBarOwnerEventType eventType, Delegate handler) { affairDict.TryAdd(eventType, null); Delegate @delegate = affairDict[eventType]; if ((object)@delegate != null && @delegate.GetType() != handler.GetType()) { throw new Exception($"Handler type mismatch for event '{eventType}'. Expected: {@delegate.GetType().Name}, Actual: {handler.GetType().Name}"); } } public static void Register(HealthBarOwnerEventType eventType, Action handler) { beforeAdd(eventType, handler); affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler); } public static void Register<T>(HealthBarOwnerEventType eventType, Action<T> handler) { beforeAdd(eventType, handler); affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler); } public static void Register<T1, T2>(HealthBarOwnerEventType eventType, Action<T1, T2> handler) { beforeAdd(eventType, handler); affairDict[eventType] = Delegate.Combine(affairDict[eventType], handler); } public static void Deregister(HealthBarOwnerEventType eventType, Action handler) { if (affairDict.TryGetValue(eventType, out var value)) { affairDict[eventType] = Delegate.Remove(value, handler); } } public static void Deregister<T>(HealthBarOwnerEventType eventType, Action<T> handler) { if (affairDict.TryGetValue(eventType, out var value)) { affairDict[eventType] = Delegate.Remove(value, handler); } } public static void Deregister<T1, T2>(HealthBarOwnerEventType eventType, Action<T1, T2> handler) { if (affairDict.TryGetValue(eventType, out var value)) { affairDict[eventType] = Delegate.Remove(value, handler); } } public static void SendEvent(HealthBarOwnerEventType type) { if (affairDict.TryGetValue(type, out var value)) { if (!(value is Action action)) { throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action"); } action(); } } public static void SendEvent<T>(HealthBarOwnerEventType type, T args) { if (affairDict.TryGetValue(type, out var value)) { if (!(value is Action<T> action)) { throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action<{typeof(T).Name}>"); } action(args); } } public static void SendEvent<T1, T2>(HealthBarOwnerEventType type, T1 arg1, T2 arg2) { if (affairDict.TryGetValue(type, out var value)) { if (!(value is Action<T1, T2> action)) { throw new Exception($"Handler type mismatch when sending event '{type}'. Expected: {value.GetType().Name}, Actual: Action<{typeof(T1).Name}, {typeof(T2).Name}>"); } action(arg1, arg2); } } } public enum HealthBarOwnerEventType { Spawn, Link, Show, Hide, Die, Damage, Heal, SetHP, CheckHP } public class BossOwnerEvent { public HealthBarOwnerEventType EventType; } public class MobOwnerEvent { public HealthBarOwnerEventType eventType; } public interface IHealthBarOwner { Dispatcher Dispatcher { get; } void Heal(float amount); void TakeDamage(float amount); void SetHP(float hp); void Die(); void Hide(); void Show(); void CheckHP(); void RemoveVisibilityController(); void LinkVisibilityControl(GameObject go); } public static class JournalRecordResolver { public static string ResolveLocalizedEnemyName(HealthManager healthManager) { if ((Object)(object)healthManager == (Object)null) { return null; } string text = ResolveFromDeathEffect(healthManager); if (text != null) { return text; } string text2 = ResolveFromFsm(healthManager); if (text2 != null) { return text2; } return FallBack(healthManager); } private static string ResolveFromDeathEffect(HealthManager healthManager) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) EnemyDeathEffects component = ((Component)healthManager).gameObject.GetComponent<EnemyDeathEffects>(); if ((Object)(object)component != (Object)null) { EnemyJournalRecord value = Traverse.Create((object)component).Field<EnemyJournalRecord>("journalRecord").Value; if (Object.op_Implicit((Object)(object)value)) { return LocalisedString.op_Implicit(value.DisplayName); } } return null; } private static string ResolveFromFsm(HealthManager healthManager) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) PlayMakerFSM[] components = ((Component)healthManager).gameObject.GetComponents<PlayMakerFSM>(); for (int i = 0; i < components.Length; i++) { FsmState[] fsmStates = components[i].FsmStates; for (int j = 0; j < fsmStates.Length; j++) { FsmStateAction[] actions = fsmStates[j].Actions; foreach (FsmStateAction val in actions) { if (val is RecordJournalKill) { Object value = ((RecordJournalKill)((val is RecordJournalKill) ? val : null)).Record.Value; EnemyJournalRecord val2 = (EnemyJournalRecord)(object)((value is EnemyJournalRecord) ? value : null); if (Object.op_Implicit((Object)(object)val2)) { return LocalisedString.op_Implicit(val2.DisplayName); } } } } } return null; } private static string FallBack(HealthManager healthManager) { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) List<EnemyJournalRecord> allEnemies = EnemyJournalManager.GetAllEnemies(); string text = ((Object)((Component)healthManager).gameObject).name; if (text.EndsWith("NPC")) { text = "Shakra"; } string[] array = text.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries); foreach (EnemyJournalRecord item in allEnemies) { if ((Object)(object)item == (Object)null || string.IsNullOrEmpty(((Object)item).name)) { continue; } string[] array2 = ((Object)item).name.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries); int num = 0; string[] array3 = array; foreach (string text2 in array3) { if (string.IsNullOrEmpty(text2) || text2.Length < 2) { continue; } string[] array4 = array2; foreach (string text3 in array4) { if (!string.IsNullOrEmpty(text3) && text3.Length >= 2 && string.Equals(text2, text3, StringComparison.OrdinalIgnoreCase)) { num++; break; } } } if (num >= 2 && !string.IsNullOrEmpty(LocalisedString.op_Implicit(item.DisplayName))) { return LocalisedString.op_Implicit(item.DisplayName); } } foreach (EnemyJournalRecord item2 in allEnemies) { if ((Object)(object)item2 == (Object)null || string.IsNullOrEmpty(((Object)item2).name)) { continue; } string[] array5 = ((Object)item2).name.Split(new char[5] { ' ', '(', ')', '_', '-' }, StringSplitOptions.RemoveEmptyEntries); string[] array3 = array; foreach (string text4 in array3) { if (string.IsNullOrEmpty(text4) || text4.Length < 3) { continue; } string[] array4 = array5; foreach (string text5 in array4) { if (!string.IsNullOrEmpty(text5) && text5.Length >= 3 && string.Equals(text4, text5, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(LocalisedString.op_Implicit(item2.DisplayName))) { return LocalisedString.op_Implicit(item2.DisplayName); } } } } return CleanGameObjectName(((Object)((Component)healthManager).gameObject).name); static string CleanGameObjectName(string originalName) { if (string.IsNullOrEmpty(originalName)) { return "未知Boss"; } int num2 = originalName.IndexOf('('); if (num2 >= 0) { originalName = originalName.Substring(0, num2).Trim(); } string[] array6 = new string[4] { " Clone", "(Clone)", " Instance", "(Instance)" }; foreach (string text6 in array6) { if (originalName.EndsWith(text6)) { originalName = originalName.Substring(0, originalName.Length - text6.Length).Trim(); } } if (!string.IsNullOrEmpty(originalName)) { return originalName; } return "未知Boss"; } } } public class LinkBuffer { private Dictionary<GameObject, Queue<GameObject>> relaysOfOrigin = new Dictionary<GameObject, Queue<GameObject>>(); private Func<GameObject, GameObject, bool> TryLink; public LinkBuffer(Func<GameObject, GameObject, bool> tryLinkFunc) { TryLink = tryLinkFunc; } private void WaitForLink(GameObject origin, GameObject relay) { if (!relaysOfOrigin.ContainsKey(origin)) { relaysOfOrigin[origin] = new Queue<GameObject>(); } relaysOfOrigin[origin].Enqueue(relay); } public void RegisterRelay(GameObject origin, GameObject relay) { if (!TryLink(origin, relay)) { WaitForLink(origin, relay); } } public void RegisterOrigin(GameObject origin) { if (relaysOfOrigin.ContainsKey(origin)) { Queue<GameObject> queue = relaysOfOrigin[origin]; while (queue.Count > 0) { GameObject arg = queue.Dequeue(); TryLink(origin, arg); } relaysOfOrigin.Remove(origin); } } } public class MobHealthBarController : BaseHealthBarController<MobOwnerEvent, MobHealthBarOwner> { private string prefabPath => AssetPaths.HealthBars.ForMobShape(Configs.Instance.healthBarShape.Value); public override GameObject GetNewHealthBar => PooledObjectService.Instance.Acquire(prefabPath, "MobHealthBar", ((Component)BarCanvas).transform); public override Canvas BarCanvas => WorldSpaceCanvas.GetWorldSpaceCanvas; protected override float BarWidth(float maxHp) { return Configs.Instance.GetHpBarWidth(maxHp, isBoss: false); } protected override void OnEnemySpawn(GameObject enemyGO, float maxHp) { base.OnEnemySpawn(enemyGO, maxHp); GameObject gameObject = ((Component)healthBarOf[enemyGO]).gameObject; SpriteTracker spriteTracker = default(SpriteTracker); if (!gameObject.TryGetComponent<SpriteTracker>(ref spriteTracker)) { spriteTracker = gameObject.AddComponent<SpriteTracker>(); } spriteTracker.SetTarget(enemyGO); spriteTracker.zOffset = Configs.Instance.spriteTrackerZOffset.Value; } } public class MobHealthBarOwner : BaseHealthBarOwner<MobOwnerEvent> { } public class SpawnManager : Singleton<SpawnManager> { public bool IsBoss(HealthManager hm, float? overrideHp = null) { if ((overrideHp ?? ((float)hm.hp)) >= Configs.Instance.minBossBarHp.Value) { return true; } return false; } private void DoLink(HealthManager origin, HealthManager relay) { float? overrideHpIfAny = LinkPolicy.Instance.GetOverrideHpIfAny(origin); if (IsBoss(origin, overrideHpIfAny)) { if (Configs.Instance.displayBossHpBar.Value) { EventHandle<BossOwnerEvent>.SendEvent<GameObject, GameObject>(HealthBarOwnerEventType.Link, ((Component)origin).gameObject, ((Component)relay).gameObject); } } else if (Configs.Instance.displayMobHpBar.Value) { EventHandle<MobOwnerEvent>.SendEvent<GameObject, GameObject>(HealthBarOwnerEventType.Link, ((Component)origin).gameObject, ((Component)relay).gameObject); } } private void DoSpawnHealthBar(HealthManager hm, float? overrideHp = null) { float arg = overrideHp ?? ((float)hm.hp); if (IsBoss(hm, overrideHp)) { if (Configs.Instance.displayBossHpBar.Value) { EventHandle<BossOwnerEvent>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Spawn, ((Component)hm).gameObject, arg); EventHandle<BossOwnerEvent>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)hm).gameObject); } } else if (Configs.Instance.displayMobHpBar.Value) { EventHandle<MobOwnerEvent>.SendEvent<GameObject, float>(HealthBarOwnerEventType.Spawn, ((Component)hm).gameObject, arg); EventHandle<MobOwnerEvent>.SendEvent<GameObject>(HealthBarOwnerEventType.Hide, ((Component)hm).gameObject); } } public void SpawnHealthBar(HealthManager hm) { if (LinkPolicy.Instance.TryGetOriginHealthManager(hm, out var originHm)) { if (!((Object)(object)originHm == (Object)null)) { DoLink(originHm, hm); } } else { float? overrideHpIfAny = LinkPolicy.Instance.GetOverrideHpIfAny(hm); DoSpawnHealthBar(hm, overrideHpIfAny); } } } internal class DeathWatcher : MonoBehaviour { public static HashSet<string> IngameGameObjectNames = new HashSet<string> { "garmond fighter" }; private HealthManager hm; private IHealthBarOwner hpBarOwner; private void Start() { float value = Configs.Instance.visibleCacheSeconds.Value; ((MonoBehaviour)this).InvokeRepeating("CheckHealth", 0f, value); } private void CheckHealth() { if (Object.op_Implicit((Object)(object)hm) && hm.hp <= 0) { hpBarOwner?.Die(); ((MonoBehaviour)this).CancelInvoke("CheckHealth"); Object.Destroy((Object)(object)this); } } internal void Init(GameObject enemyGO) { hm = enemyGO.GetComponent<HealthManager>(); hpBarOwner = enemyGO.GetComponent<IHealthBarOwner>(); } } internal class InitHpWatcher : MonoBehaviour { private int? previousInitHp; private Traverse<int> initHpGetter; private IHealthBarOwner owner; private HealthManager hm; private void Awake() { hm = ((Component)this).GetComponent<HealthManager>(); owner = ((Component)this).GetComponent<IHealthBarOwner>(); if (!((Object)(object)hm == (Object)null) && owner != null) { initHpGetter = Traverse.Create((object)hm).Field<int>("initHp"); previousInitHp = initHpGetter.Value; } } private void Update() { MonitorInitHp(); } private void MonitorInitHp() { if ((Object)(object)hm == (Object)null || owner == null || initHpGetter == null) { return; } if (!previousInitHp.HasValue) { previousInitHp = initHpGetter.Value; return; } int value = initHpGetter.Value; if (value != previousInitHp) { owner.SetHP(value); previousInitHp = value; } } } public class LinkPolicy { private enum EndpointType { RelayEndpoint, OriginEndpoint } private class Endpoint { internal string gameObjectName; internal EndpointType type; internal float? overrideOriginHp; private Func<HealthManager> findHealthManager; internal static Endpoint RelayEndpoint(string name) { return new Endpoint { gameObjectName = name, type = EndpointType.RelayEndpoint, overrideOriginHp = null }; } internal Endpoint SetHealthManagerFinder(Func<HealthManager> finder) { findHealthManager = finder; return this; } internal HealthManager FindHealthManager() { if (findHealthManager == null) { return null; } return findHealthManager(); } internal static Endpoint OriginEndpoint(string name, float? overrideHp = null) { return new Endpoint { gameObjectName = name, type = EndpointType.OriginEndpoint, overrideOriginHp = overrideHp }; } } private static LinkPolicy __instance; private Dictionary<string, Endpoint> endpointOfName; private Dictionary<Endpoint, Endpoint> originOfRelayEndpoint = new Dictionary<Endpoint, Endpoint> { { Endpoint.RelayEndpoint("Giant Centipede Butt"), Endpoint.OriginEndpoint("Giant Centipede Head", 800f).SetHealthManagerFinder(delegate { GameObject obj = GameObject.Find("Giant Centipede Head"); return (obj == null) ? null : obj.GetComponent<HealthManager>(); }) } }; public static LinkPolicy Instance { get { if (__instance == null) { __instance = new LinkPolicy(); __instance.endpointOfName = new Dictionary<string, Endpoint>(); foreach (KeyValuePair<Endpoint, Endpoint> item in __instance.originOfRelayEndpoint) { __instance.endpointOfName[item.Key.gameObjectName] = item.Key; __instance.endpointOfName[item.Value.gameObjectName] = item.Value; } } return __instance; } } public bool TryGetOriginHealthManager(HealthManager relayHm, out HealthManager originHm) { originHm = null; if ((Object)(object)relayHm.SendDamageTo != (Object)null) { originHm = relayHm.SendDamageTo; return true; } endpointOfName.TryGetValue(((Object)((Component)relayHm).gameObject).name, out var value); if (value == null) { return false; } originHm = originOfRelayEndpoint.GetValueOrDefault(value, null)?.FindHealthManager() ?? null; return (Object)(object)originHm != (Object)null; } public float? GetOverrideHpIfAny(HealthManager hm) { if (!endpointOfName.TryGetValue(((Object)((Component)hm).gameObject).name, out var value)) { return null; } if (value != null) { _ = value.type; _ = 1; } return value?.overrideOriginHp ?? null; } } internal class SpawnPreventionPolicy { public static float minMobHealth => Configs.Instance.minMobHp.Value; public static float INF => Configs.Instance.infHp.Value; public static bool ShouldPreventSpawn(HealthManager hm) { if ((float)hm.hp < minMobHealth) { return ((Object)hm).name != "Driller B"; } if ((float)hm.hp >= INF) { return true; } return false; } } internal interface IVisibilityController { bool IsVisible { get; set; } void Inspect(HealthManager healthManager); bool Update(bool forceCheck = false); } internal class LinkedVisibilityController : IVisibilityController { private List<IVisibilityController> controllers = new List<IVisibilityController>(); private bool visibilityCache; public bool IsVisible { get { for (int i = 0; i < controllers.Count; i++) { if (controllers[i].IsVisible) { return true; } } return false; } set { } } public void Inspect(HealthManager healthManager) { VisibilityController item = new VisibilityController(healthManager); controllers.Add(item); } public bool Update(bool forceCheck = false) { bool flag = false; for (int i = 0; i < controllers.Count; i++) { if (controllers[i].Update(forceCheck)) { flag = true; } } if (flag) { bool isVisible = IsVisible; if (isVisible != visibilityCache) { visibilityCache = isVisible; return true; } } return false; } } internal class VisibilityController : IVisibilityController { private static readonly int enemyLayer = LayerMask.NameToLayer("Enemies"); private static readonly float maxZ = Configs.Instance.maxZPosition.Value; private static readonly float visibleCacheTime = Configs.Instance.visibleCacheSeconds.Value; private static readonly float invisibleCacheTime = Configs.Instance.invisibleCacheSeconds.Value; private GameObject gameObject; private HealthManager hm; private Collider2D defaultCollider; private Renderer renderer; private Collider2D physicalPusherCollider; private bool visibilityCache; private float timeSinceLastCheck; public bool IsVisible { get { return visibilityCache; } set { visibilityCache = value; timeSinceLastCheck = 0f; } } private void tryGetColliders() { if (!Object.op_Implicit((Object)(object)defaultCollider)) { defaultCollider = ((Component)hm).GetComponent<Collider2D>(); } if (!Object.op_Implicit((Object)(object)physicalPusherCollider)) { GameObject physicalPusher = hm.GetPhysicalPusher(); physicalPusherCollider = ((physicalPusher != null) ? physicalPusher.GetComponent<Collider2D>() : null); } } private void tryGetRenderer() { if (!Object.op_Implicit((Object)(object)renderer)) { renderer = ((Component)hm).GetComponent<Renderer>(); } if (Object.op_Implicit((Object)(object)renderer)) { return; } Renderer[] componentsInChildren = ((Component)hm).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (val.enabled) { renderer = val; break; } } } public VisibilityController(HealthManager healthManager) { Inspect(healthManager); } public bool Update(bool forceCheck = false) { if (!forceCheck && timeSinceLastCheck < (visibilityCache ? visibleCacheTime : invisibleCacheTime)) { timeSinceLastCheck += Time.deltaTime; return false; } timeSinceLastCheck = 0f; tryGetColliders(); tryGetRenderer(); bool flag = mobIsShowing(); if (flag == visibilityCache) { return false; } visibilityCache = flag; return true; } private bool mobIsShowing() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)hm).isActiveAndEnabled || hm.isDead) { return false; } if (gameObject.layer != enemyLayer) { return false; } if (Mathf.Abs(gameObject.transform.position.z) > maxZ) { return false; } if (Object.op_Implicit((Object)(object)physicalPusherCollider) && Object.op_Implicit((Object)(object)defaultCollider)) { if (!((Behaviour)physicalPusherCollider).isActiveAndEnabled && !((Behaviour)defaultCollider).isActiveAndEnabled) { return false; } } else { if (Object.op_Implicit((Object)(object)physicalPusherCollider) && !((Behaviour)physicalPusherCollider).isActiveAndEnabled) { return false; } if (Object.op_Implicit((Object)(object)defaultCollider) && !((Behaviour)defaultCollider).isActiveAndEnabled) { return false; } } if (Object.op_Implicit((Object)(object)renderer) && (!renderer.enabled || !renderer.isVisible)) { return false; } return true; } public void Inspect(HealthManager healthManager) { hm = healthManager; gameObject = ((Component)hm).gameObject; defaultCollider = ((Component)hm).GetComponent<Collider2D>(); renderer = ((Component)hm).GetComponent<Renderer>(); GameObject physicalPusher = hm.GetPhysicalPusher(); physicalPusherCollider = ((physicalPusher != null) ? physicalPusher.GetComponent<Collider2D>() : null); } } public class Playground : MonoBehaviour { public HealthBarController target; public GameObject bean; public GameObject bean2; private GameObject _player; private List<Color> colors = ColourPalette.AllElementColors; private GameObject _stubTemplate; private static Playground _instance; public GameObject Player { get { if ((Object)(object)_player == (Object)null) { _player = GameObject.Find("Hero_Hornet(Clone)"); } return _player; } } public static Playground Instance { get { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance == (Object)null) { _instance = Object.FindFirstObjectByType<Playground>(); if ((Object)(object)_instance != (Object)null) { return _instance; } _instance = new GameObject(typeof(Playground).Name).AddComponent<Playground>(); } return _instance; } } private GameObject Stub { get { if ((Object)(object)_stubTemplate == (Object)null) { GameObject val = null; val = Object.FindFirstObjectByType<MobHealthBarController>()?.GetRandomEnemyGO(); if (!Object.op_Implicit((Object)(object)val)) { return null; } _stubTemplate = Object.Instantiate<GameObject>(val); ((Object)_stubTemplate).name = "Stub Template"; _stubTemplate.SetActive(false); makeCleanStubTemplate(_stubTemplate); Object.DontDestroyOnLoad((Object)(object)_stubTemplate); } GameObject val2 = Object.Instantiate<GameObject>(_stubTemplate); ((Object)val2).name = "Stub"; val2.SetActive(true); List<MonoBehaviour> list = new List<MonoBehaviour>(); list.AddRange((IEnumerable<MonoBehaviour>)(object)val2.GetComponents<tk2dSpriteAnimator>()); list.AddRange((IEnumerable<MonoBehaviour>)(object)val2.GetComponents<DamageHero>()); foreach (MonoBehaviour item in list) { ((Behaviour)item).enabled = false; } return val2; } } protected virtual void Awake() { if ((Object)(object)_instance == (Object)null) { _instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } else if ((Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void makeCleanStubTemplate(GameObject go) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if ((Object)(object)_stubTemplate == (Object)null) { return; } List<GameObject> list = new List<GameObject>(); foreach (Transform item in go.transform) { Transform val = item; list.Add(((Component)val).gameObject); } foreach (GameObject item2 in list) { Object.DestroyImmediate((Object)(object)item2); } Type[] array = new Type[15] { typeof(Transform), typeof(MeshFilter), typeof(MeshRenderer), typeof(tk2dSprite), typeof(tk2dSpriteAnimator), typeof(Rigidbody2D), typeof(Collider2D), typeof(HealthManager), typeof(MobHealthBarOwner), typeof(DamageHero), typeof(EnemyDeathEffects), typeof(EnemyHitEffectsRegular), typeof(TagDamageTaker), typeof(PlayMakerProxyBase), typeof(PlayMakerFSM) }; Component[] components = go.GetComponents<Component>(); List<Component> list2 = new List<Component>(); Component[] array2 = components; foreach (Component val2 in array2) { bool flag = false; if ((Object)(object)val2 == (Object)null) { continue; } Type type = ((object)val2).GetType(); Type[] array3 = array; for (int j = 0; j < array3.Length; j++) { if (array3[j].IsAssignableFrom(type)) { flag = true; break; } } if (!flag) { list2.Add(val2); } } foreach (Component item3 in list2) { try { Object.DestroyImmediate((Object)(object)item3); } catch (Exception) { } } } } [BepInPlugin("com.kokomi.silkenimpact", "Silken Impact", "1.6.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private Harmony _harmony; private static Plugin __instance; public static string PluginFolder { get; private set; } public static string AssetsFolder => Path.Combine(PluginFolder, "Assets"); public static AssetBundle bundle { get; private set; } public static Plugin Instance => __instance; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0041: 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_0052: Expected O, but got Unknown __instance = this; Logger = ((BaseUnityPlugin)this).Logger; LoadAssetBundle(); PooledObjectService.Instance.InitializeAndPrewarm(); _harmony = new Harmony("com.kokomi.silkenimpact"); _harmony.PatchAll(); GameObject val = new GameObject("Playground"); val.AddComponent<Playground>(); Object.DontDestroyOnLoad((Object)val); summon(); } private void summon() { //IL_0005: 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) //IL_0016: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown GameObject val = new GameObject("MobHealthManager"); val.AddComponent<MobHealthBarController>(); Object.DontDestroyOnLoad((Object)val); GameObject val2 = new GameObject("BossHealthManager"); val2.AddComponent<BossHealthBarController>(); Object.DontDestroyOnLoad((Object)val2); } private void OnDestroy() { PooledObjectService.Instance.ClearAll(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { if (Input.GetKeyDown((KeyCode)286)) { PooledObjectService.Instance.ClearAll(); LoadAssetBundle(); PooledObjectService.Instance.InitializeAndPrewarm(); } } public string LatestBundleInFolder(string folderPath) { return (from f in new DirectoryInfo(folderPath).GetFiles("default*.bundle") orderby f.LastWriteTime descending select f).FirstOrDefault()?.FullName; } public void LoadAssetBundle() { if ((Object)(object)bundle != (Object)null) { bundle.Unload(true); } PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); bundle = AssetBundle.LoadFromFile(LatestBundleInFolder(AssetsFolder)); } public static GameObject InstantiateFromAssetsBundle(string path, string name) { GameObject val = bundle.LoadAsset<GameObject>(path); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = null; try { val2 = Object.Instantiate<GameObject>(val); } catch (Exception ex) { PluginLogger.LogFatal(ex.ToString()); return null; } ((Object)val2).name = name; return val2; } } public static class PluginLogger { [Conditional("DEBUG")] public static void LogInfo(string message) { Plugin.Logger.LogInfo((object)message); } [Conditional("DEBUG")] public static void LogWarning(string message) { Plugin.Logger.LogWarning((object)message); } [Conditional("DEBUG")] public static void LogError(string message) { Plugin.Logger.LogError((object)message); } [Conditional("DEBUG")] public static void LogDebug(string message) { Plugin.Logger.LogDebug((object)message); } public static void LogFatal(string message) { Plugin.Logger.LogFatal((object)message); } [Conditional("DETAIL")] public static void LogDetail(string message) { Plugin.Logger.LogInfo((object)message); } } internal interface IPoolable { void OnAcquireFromPool(); void OnReleaseToPool(); } internal struct ObjectPoolSettings { public int initialSize; public int maxSize; public ObjectPoolSettings(int initialSize, int maxSize) { this.initialSize = initialSize; this.maxSize = maxSize; } } internal class PooledObject : MonoBehaviour { internal string PoolKey { get; set; } internal PooledObjectService Owner { get; set; } } internal class PooledObjectService { private class PoolBucket { internal readonly Stack<GameObject> inactive = new Stack<GameObject>(); internal ObjectPoolSettings settings; internal string prefabPath; } private static PooledObjectService _instance; private readonly Dictionary<string, PoolBucket> _buckets = new Dictionary<string, PoolBucket>(); private readonly Dictionary<string, ObjectPoolSettings> _defaultSettings = new Dictionary<string, ObjectPoolSettings> { ["Assets/Addressables/Prefabs/DamageOldText.prefab"] = new ObjectPoolSettings(4, 24), ["Assets/Addressables/Prefabs/HealOldText.prefab"] = new ObjectPoolSettings(2, 8), ["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab"] = new ObjectPoolSettings(8, 64), ["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab"] = new ObjectPoolSettings(8, 64), ["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab"] = new ObjectPoolSettings(2, 12), ["Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab"] = new ObjectPoolSettings(2, 12) }; private Transform _poolRoot; internal static PooledObjectService Instance => _instance ?? (_instance = new PooledObjectService()); private PooledObjectService() { } private void EnsureRoot() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!((Object)(object)_poolRoot != (Object)null)) { GameObject val = new GameObject("SilkenImpact.ObjectPool"); Object.DontDestroyOnLoad((Object)(object)val); _poolRoot = val.transform; } } private PoolBucket GetOrCreateBucket(string prefabPath) { if (_buckets.TryGetValue(prefabPath, out var value)) { return value; } ObjectPoolSettings value2; ObjectPoolSettings settings = (_defaultSettings.TryGetValue(prefabPath, out value2) ? value2 : new ObjectPoolSettings(0, 32)); PoolBucket poolBucket = new PoolBucket { prefabPath = prefabPath, settings = settings }; _buckets[prefabPath] = poolBucket; return poolBucket; } private GameObject InstantiateForPool(string prefabPath, string displayName) { GameObject val = Plugin.InstantiateFromAssetsBundle(prefabPath, displayName); if ((Object)(object)val == (Object)null) { return null; } PooledObject pooledObject = val.GetComponent<PooledObject>(); if ((Object)(object)pooledObject == (Object)null) { pooledObject = val.AddComponent<PooledObject>(); } pooledObject.PoolKey = prefabPath; pooledObject.Owner = this; return val; } internal void InitializeAndPrewarm() { EnsureRoot(); foreach (KeyValuePair<string, ObjectPoolSettings> defaultSetting in _defaultSettings) { string key = defaultSetting.Key; PoolBucket orCreateBucket = GetOrCreateBucket(key); for (int i = orCreateBucket.inactive.Count; i < orCreateBucket.settings.initialSize; i++) { GameObject val = InstantiateForPool(key, "Pooled"); if ((Object)(object)val == (Object)null) { break; } Release(val); } } } internal GameObject Acquire(string prefabPath, string displayName, Transform parent = null) { if (string.IsNullOrEmpty(prefabPath)) { return null; } EnsureRoot(); PoolBucket orCreateBucket = GetOrCreateBucket(prefabPath); GameObject val = null; while (orCreateBucket.inactive.Count > 0 && (Object)(object)val == (Object)null) { orCreateBucket.inactive.AsEnumerable().ToList().ForEach(delegate { }); val = orCreateBucket.inactive.Pop(); } if ((Object)(object)val == (Object)null) { val = InstantiateForPool(prefabPath, displayName); if ((Object)(object)val == (Object)null) { return null; } } ((Object)val).name = displayName; val.transform.SetParent(parent, false); val.SetActive(true); IPoolable poolable = default(IPoolable); if (val.TryGetComponent<IPoolable>(ref poolable)) { poolable.OnAcquireFromPool(); } return val; } internal void Release(GameObject go) { if ((Object)(object)go == (Object)null) { return; } PooledObject component = go.GetComponent<PooledObject>(); if ((Object)(object)component == (Object)null || component.Owner != this || string.IsNullOrEmpty(component.PoolKey)) { Object.Destroy((Object)(object)go); return; } PoolBucket orCreateBucket = GetOrCreateBucket(component.PoolKey); if (orCreateBucket.inactive.Count >= orCreateBucket.settings.maxSize) { Object.Destroy((Object)(object)go); } else if (!orCreateBucket.inactive.Contains(go)) { IPoolable poolable = default(IPoolable); if (go.TryGetComponent<IPoolable>(ref poolable)) { poolable.OnReleaseToPool(); } go.SetActive(false); go.transform.SetParent(_poolRoot, false); orCreateBucket.inactive.Push(go); } } internal void ClearAll() { foreach (PoolBucket value in _buckets.Values) { while (value.inactive.Count > 0) { GameObject val = value.inactive.Pop(); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } _buckets.Clear(); if ((Object)(object)_poolRoot != (Object)null) { Object.Destroy((Object)(object)((Component)_poolRoot).gameObject); _poolRoot = null; } } } public class CameraFollow : MonoBehaviour { public Transform target; public float smoothSpeed = 5f; public Vector3 offset = new Vector3(0f, 0f, -10f); private void LateUpdate() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) if (!((Object)(object)target == (Object)null)) { Vector3 val = target.position + offset; Vector3 position = Vector3.Lerp(((Component)this).transform.position, val, smoothSpeed * Time.deltaTime); ((Component)this).transform.position = position; } } } public static class ColourPalette { public static Color Hydro => FromHexString("#1EC5E3"); public static Color Cryo => FromHexString("#78FDFF"); public static Color Pyro => FromHexString("#FF6400"); public static Color Anemo => FromHexString("#24FFD3"); public static Color Geo => FromHexString("#FFE064"); public static Color Electro => FromHexString("#D272FF"); public static Color Dendro => FromHexString("#00C94E"); public static Color Physical => FromHexString("#FFFFFF"); public static Color HornetDress => FromHexString("#A83448"); public static Color HealTextColor => FromHexString("#BDFF37"); public static Color HP => FromHexString("#FC5A49"); public static Color DelayedEffect => FromHexString("#FFCE89"); public static Color HpBarBackground => FromHexString("#00000059"); public static Color HpNumber => FromHexString("#bfbfbfff"); public static List<Color> AllElementColors => new List<Color> { Hydro, Cryo, Pyro, Anemo, Geo, Electro, Dendro, Physical, HornetDress }; public static Color FromHexString(string hex) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((hex.Length != 7 && hex.Length != 9) || hex[0] != '#') { throw new ArgumentException("Invalid hex color format. Expected format: #RRGGBB or #RRGGBBAA"); } float num = 1f; if (hex.Length == 9) { num = (float)int.Parse(hex.Substring(7, 2), NumberStyles.HexNumber) / 255f; } return new Color((float)int.Parse(hex.Substring(1, 2), NumberStyles.HexNumber) / 255f, (float)int.Parse(hex.Substring(3, 2), NumberStyles.HexNumber) / 255f, (float)int.Parse(hex.Substring(5, 2), NumberStyles.HexNumber) / 255f, num); } } public class DamageOldText : DamageText { public Text textComponent; public override string DamageString { get { return textComponent.text; } set { textComponent.text = value; } } public override Color TextColor { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Graphic)textComponent).color; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((Graphic)textComponent).color = value; } } public override Font TextFont { set { if (!((Object)(object)value == (Object)null)) { textComponent.font = value; } } } } public abstract class DamageText : MonoBehaviour, IPoolable { public DamageTextAnimationConfig config; public float maxWidth; public float maxHeight; public RectTransform rectTransform; public Material fontMaterial; [SerializeField] private float secondsElapsed; [SerializeField] private Vector3 startPosition; [SerializeField] private Vector3 baseScale; [SerializeField] private Vector3 prefabScale; [SerializeField] private Color baseColor; [SerializeField] private Vector2 baseSize => new Vector2(maxWidth, maxHeight); [SerializeField] public Vector3 BaseScale { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Component)this).transform.localScale; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localScale = value; baseScale = value; } } public abstract string DamageString { get; set; } public abstract Color TextColor { get; set; } public abstract Font TextFont { set; } private void Awake() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) prefabScale = ((Component)this).transform.localScale; } private void Start() { ResetAnimationState(); } public void ResetForSpawn(float sizeScale) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) ((Component)this).transform.localScale = prefabScale; BaseScale = prefabScale * sizeScale; ResetAnimationState(); } private void ResetAnimationState() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) startPosition = ((Component)this).transform.position; secondsElapsed = 0f; baseColor = TextColor; baseScale = ((Component)this).transform.localScale; } private void Update() { secondsElapsed += Time.deltaTime; if ((double)secondsElapsed < 1.1 * (double)config.durationSeconds) { DoAnimation(); } else { PooledObjectService.Instance.Release(((Component)this).gameObject); } } private void DoAnimation() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) float num = secondsElapsed / config.durationSeconds; Color val = baseColor; val.a = 0f; val.r = Mathf.Clamp01(val.r - 0.5f); val.g = Mathf.Clamp01(val.g - 0.5f); val.b = Mathf.Clamp01(val.b - 0.5f); TextColor = Color.Lerp(val, baseColor, config.alphaCurve.Evaluate(num)); ((Transform)rectTransform).localScale = baseScale * config.scaleCurve.Evaluate(num); ((Component)this).transform.position = startPosition + new Vector3(0f, baseScale.y * config.verticalOffsetCurve.Evaluate(num) * maxHeight, 0f); } public void OnAcquireFromPool() { ResetAnimationState(); } public void OnReleaseToPool() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) secondsElapsed = 0f; ((Component)this).transform.localScale = prefabScale; ((Transform)rectTransform).localScale = Vector3.one; } } [CreateAssetMenu(fileName = "DamageTextAnimationConfig", menuName = "ScriptableObjects/DamageTextAnimationConfig")] public class DamageTextAnimationConfig : ScriptableObject { public AnimationCurve alphaCurve; public AnimationCurve blurCurve; public AnimationCurve scaleCurve; public AnimationCurve verticalOffsetCurve; public float durationSeconds = 0.9f; } public class DamageTextTMPro : DamageText { public TextMeshProUGUI textComponent; public override string DamageString { get { return ((TMP_Text)textComponent).text; } set { ((TMP_Text)textComponent).text = DamageString; } } public override Color TextColor { get { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Graphic)textComponent).color; } set { //IL_0006: Unknown result type (might be due to invalid IL or missing references) ((Graphic)textComponent).color = value; } } public override Font TextFont { set { if (!((Object)(object)value == (Object)null)) { TMP_FontAsset font = TMP_FontAsset.CreateFontAsset(value); ((TMP_Text)textComponent).font = font; } } } } public class HealthBarController : MonoBehaviour { } public abstract class Bar : MonoBehaviour { [CompilerGenerated] private sealed class <AnimateTo>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float duration; public float startPercentage; public float targetPercentage; public Bar <>4__this; private float <elapsedTime>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AnimateTo>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; Bar bar = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <elapsedTime>5__2 = 0f; break; case 1: <>1__state = -1; break; } if (<elapsedTime>5__2 < duration) { <elapsedTime>5__2 += Time.deltaTime; float num2 = Mathf.Clamp01(<elapsedTime>5__2 / duration); float percentage = Mathf.Lerp(startPercentage, targetPercentage, num2); bar.MatchWithPercentage(percentage); <>2__current = null; <>1__state = 1; return true; } bar.MatchWithPercentage(targetPercentage); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public float verticalMargin; public float h