Decompiled source of Silken Impact v1.4.1
plugins/com.kokomi.silkenimpact.dll
Decompiled 2 days 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.4.1.0")] [assembly: AssemblyInformationalVersion("1.4.1+aac4ab4bf4e2023b172cf828634e2109aa02d62d")] [assembly: AssemblyProduct("Silken Impact")] [assembly: AssemblyTitle("com.kokomi.silkenimpact")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } 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 SilkenImpact { 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<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; 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 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 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 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_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) try { LoadLocalizationIfNeeded(option); } catch (Exception arg) { PluginLogger.LogFatal($"Failed to load localization: {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: Damage Text Colors"]; new MyConfigSection(configSection6.name, config).AddEntry(ref configs.defaultColor, ColourPalette.HornetDress, configSection6.Get("Default Color")).AddEntry(ref configs.critHitColor, ColourPalette.Geo, configSection6.Get("Crit Hit Color")).AddEntry(ref configs.poisonColor, ColourPalette.Electro, configSection6.Get("Poison Color")) .AddEntry(ref configs.fireColor, ColourPalette.Pyro, configSection6.Get("Fire Color")) .AddEntry(ref configs.healTextColor, ColourPalette.HealTextColor, configSection6.Get("Heal Color")); ConfigSection configSection7 = localization["Dev: Visibility Controller Settings"]; new MyConfigSection(configSection7.name, config).AddDebugOnlyEntry(ref configs.maxZPosition, 1f, configSection7.Get("Max Z Position")).AddDebugOnlyEntry(ref configs.visibleCacheSeconds, 0.5f, configSection7.Get("Visible Cache Seconds")).AddDebugOnlyEntry(ref configs.invisibleCacheSeconds, 0.5f, configSection7.Get("Invisible Cache Seconds")) .AddDebugOnlyEntry(ref configs.infHp, 10000f, configSection7.Get("Infinite HP Threshold")) .AddDebugOnlyEntry(ref configs.spriteTrackerZOffset, -1.5f, configSection7.Get("Sprite Tracker Z Offset")); ConfigSection configSection8 = localization["Dev: Damage Text Settings"]; new MyConfigSection(configSection8.name, config).AddDebugOnlyEntry(ref configs.weightOfNewHit, 0.2f, configSection8.Get("Weight Of New Hit")); } } 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 = enemyGO.GetComponent<HealthManager>().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)) { Object.Destroy((Object)(object)((Component)healthBarOf[relayGO]).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); } } } protected virtual void MatchVisualsWithConfigs() { foreach (KeyValuePair<GameObject, HealthBar> item in healthBarOf) { MatchVisualsWithConfigs(item.Value); } } protected virtual void OnEnemySpawn(GameObject enemyGO, float maxHp) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) HealthBar healthBar; if (healthBarOf.ContainsKey(enemyGO)) { healthBar = healthBarOf[enemyGO]; healthBar.SetMaxHealth(maxHp); return; } GameObject getNewHealthBar = GetNewHealthBar; getNewHealthBar.transform.SetParent(((Component)BarCanvas).transform); getNewHealthBar.transform.localScale = Vector3.one; 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)) { Object.Destroy((Object)(object)((Component)healthBarOf[enemyGO]).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 && visibilityController.Update()) { CheckHP(); if (visibilityController.IsVisible) { Show(); } else { Hide(); } } } 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 class BossHealthBarController : BaseHealthBarController<BossOwnerEvent, BossHealthBarOwner> { private BossHealthBarContainer container; protected string containerPrefabPath = "Assets/Addressables/Prefabs/Container.prefab"; protected string healthBarPrefabPath => Configs.Instance.healthBarShape.Value switch { HealthBarShape.Rounded => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab", HealthBarShape.Diamond => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/DiamondBoss.prefab", _ => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/RoundedBoss.prefab", }; public override GameObject GetNewHealthBar => Plugin.InstantiateFromAssetsBundle(healthBarPrefabPath, "BossHealthBar"); 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 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 => Configs.Instance.healthBarShape.Value switch { HealthBarShape.Rounded => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab", HealthBarShape.Diamond => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Diamond.prefab", _ => "Assets/Addressables/Prefabs/Health Bars/Masked UI Health Bars/Rounded.prefab", }; public override GameObject GetNewHealthBar => Plugin.InstantiateFromAssetsBundle(prefabPath, "MobHealthBar"); 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 (((Component)hm).CompareTag("Boss")) { return true; } 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) { PluginLogger.LogFatal($"Detected initHP change on {((Object)hm).name}: {previousInitHp} -> {value}!"); PluginLogger.LogFatal("Either Team Cherry added a new method to modify initHP after initialization, or another mod is interfering."); PluginLogger.LogFatal($"Current HP: {value}"); PluginLogger.LogFatal("Attempting to make automatic adaptation. Updating health bar accordingly."); 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 true; } 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.4.1")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private static AssetBundle bundle; private Harmony _harmony; private static Plugin __instance; public static string PluginFolder { get; private set; } public static string AssetsFolder => Path.Combine(PluginFolder, "Assets"); public static Plugin Instance => __instance; private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown __instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin com.kokomi.silkenimpact is loaded!"); LoadAssetBundle(); _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() { Logger.LogDebug((object)"Plugin is being unloaded"); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { if (Input.GetKeyDown((KeyCode)286)) { Logger.LogInfo((object)"Reloading AssetBundle..."); LoadAssetBundle(); } } 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); string text = LatestBundleInFolder(AssetsFolder); bundle = AssetBundle.LoadFromFile(text); Logger.LogInfo((object)("Loaded AssetBundle from " + text)); } 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) { Logger.LogFatal((object)ex); 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); } } 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 abstract class DamageText : MonoBehaviour { public DamageTextAnimationConfig config; public float maxWidth; public float maxHeight; private float yScale; public RectTransform rectTransform; public Material fontMaterial; [SerializeField] private float secondsElapsed; [SerializeField] private Vector3 startPosition; [SerializeField] private Color baseColor; [SerializeField] private Vector2 baseSize => new Vector2(maxWidth, maxHeight); public abstract string DamageString { get; set; } public abstract Color TextColor { get; set; } private void Start() { //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) startPosition = ((Component)this).transform.position; secondsElapsed = 0f; baseColor = TextColor; yScale = ((Component)this).transform.lossyScale.y; } private void Update() { secondsElapsed += Time.deltaTime; if ((double)secondsElapsed < 1.1 * (double)config.durationSeconds) { DoAnimation(); } else { Object.Destroy((Object)(object)((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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) 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)); rectTransform.sizeDelta = baseSize * config.scaleCurve.Evaluate(num); ((Component)this).transform.position = startPosition + new Vector3(0f, yScale * config.verticalOffsetCurve.Evaluate(num) * maxHeight, 0f); } } [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 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 horizontalMargin; public float maxHeight; public float maxWidth; public abstract float CurrentPercentage { get; } protected abstract void MatchWithPercentage(float percentage); public abstract void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin); public abstract void SetVisibility(bool visible); public abstract void SetColor(Color color); public void Init(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin) { UpdateSize(maxHeight, maxWidth, verticalMargin, horizontalMargin); MatchWithPercentage(1f); } public void SetPercentage(float percentage, float animationDurationSeconds) { percentage = Mathf.Clamp01(percentage); if (animationDurationSeconds <= 0f) { MatchWithPercentage(percentage); return; } ((MonoBehaviour)this).StopAllCoroutines(); ((MonoBehaviour)this).StartCoroutine(AnimateTo(CurrentPercentage, percentage, animationDurationSeconds)); } [IteratorStateMachine(typeof(<AnimateTo>d__12))] private IEnumerator AnimateTo(float startPercentage, float targetPercentage, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AnimateTo>d__12(0) { <>4__this = this, startPercentage = startPercentage, targetPercentage = targetPercentage, duration = duration }; } } public class HealthBar : MonoBehaviour { [SerializeField] protected HealthBarConfig config; [SerializeField] protected Bar hp; [SerializeField] protected Bar delayedEffect; [SerializeField] protected Bar background; [SerializeField] protected float height; [SerializeField] protected float width; [SerializeField] protected float verticalMargin; [SerializeField] protected float horizontalMargin; [SerializeField] protected float maxHealth = 100f; [SerializeField] protected float currentHealth = 100f; [SerializeField] protected float decayTimer; [SerializeField] protected float DecayingHealth { get { float num = delayedEffect.CurrentPercentage * maxHealth; if ((double)Mathf.Abs(currentHealth - num) < 1E-05) { return currentHealth; } return num; } } public float MaxHealth => maxHealth; public float CurrentHealth => currentHealth; public void SetHpColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) hp.SetColor(color); } public void SetDelayedEffectColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) delayedEffect.SetColor(color); } public void SetBackgroundColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) background.SetColor(color); } public void SetHeight(float height) { this.height = height; Redraw(); } public void SetWidth(float width) { this.width = width; Redraw(); } public void SetMargin(float verticalMargin, float horizontalMargin) { this.verticalMargin = verticalMargin; this.horizontalMargin = horizontalMargin; Redraw(); } public void SetMaxHealth(float maxHealth) { this.maxHealth = maxHealth; currentHealth = Mathf.Clamp(currentHealth, 0f, maxHealth); OnStart(); } protected void Start() { OnStart(); } protected virtual void Redraw() { hp.UpdateSize(height, width, verticalMargin, horizontalMargin); delayedEffect.UpdateSize(height, width, verticalMargin, horizontalMargin); background.UpdateSize(height, width, 0f, 0f); } protected virtual void OnStart() { hp.Init(height, width, verticalMargin, horizontalMargin); delayedEffect.Init(height, width, verticalMargin, horizontalMargin); background.Init(height, width, 0f, 0f); currentHealth = maxHealth; OnHealthChanged(); } protected virtual void OnHealthChanged() { } protected void Update() { if (DecayingHealth > currentHealth) { if (decayTimer < config.decayThresholdSeconds) { decayTimer += Time.deltaTime; return; } delayedEffect.SetPercentage(currentHealth / maxHealth, (DecayingHealth - currentHealth) / maxHealth / config.decayPercentagePerSecond); decayTimer = 0f; } else { decayTimer = 0f; } } public void TakeDamage(float amount) { if (!(amount <= 0f)) { if (decayTimer > 0f) { decayTimer -= config.timerReductionPercentageOnDamage * config.decayThresholdSeconds; } decayTimer = Mathf.Clamp(decayTimer, -0.3f * config.decayThresholdSeconds, config.decayThresholdSeconds); float num = Mathf.Clamp(currentHealth - amount, 0f, maxHealth); currentHealth = num; hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration); OnHealthChanged(); } } public void Heal(float amount) { if (!(amount <= 0f)) { float num = Mathf.Clamp(currentHealth + amount, 0f, maxHealth); currentHealth = num; delayedEffect.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration); hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration); OnHealthChanged(); } } public void ResetHealth(float hp) { currentHealth = hp; maxHealth = hp; delayedEffect.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration); this.hp.SetPercentage(currentHealth / maxHealth, config.healthChangeDuration); OnHealthChanged(); } public virtual void SetVisibility(bool visible) { hp.SetVisibility(visible); delayedEffect.SetVisibility(visible); background.SetVisibility(visible); } private void OnDestroy() { } } [CreateAssetMenu(fileName = "HealthBarConfig", menuName = "ScriptableObjects/HealthBarConfig")] public class HealthBarConfig : ScriptableObject { public float timerReductionPercentageOnDamage = 0.5f; public float decayThresholdSeconds = 0.2f; public float decayPercentagePerSecond = 0.4f; public float healthChangeDuration = 0.2f; } public class MaskedUIBar : UIBar { [SerializeField] private RectMask2D rectMask; private float currentWidth; public override float CurrentPercentage => currentWidth / maxWidth; public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) float currentPercentage = CurrentPercentage; base.maxHeight = maxHeight - 2f * verticalMargin; base.maxWidth = maxWidth - 2f * horizontalMargin; base.verticalMargin = verticalMargin; base.horizontalMargin = horizontalMargin; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.offsetMin = new Vector2(horizontalMargin, verticalMargin); rectTransform.SetSizeWithCurrentAnchors((Axis)1, base.maxHeight); rectTransform.SetSizeWithCurrentAnchors((Axis)0, base.maxWidth); MatchWithPercentage(currentPercentage); } protected override void MatchWithPercentage(float percentage) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) float num = (currentWidth = maxWidth * percentage); rectMask.padding = new Vector4(0f, 0f, maxWidth - num, 0f); } } public class SpriteBar : Bar { private SpriteRenderer spriteRenderer; public override float CurrentPercentage => ((Component)this).transform.localScale.x / (maxWidth - 2f * horizontalMargin); private void Awake() { spriteRenderer = ((Component)this).GetComponent<SpriteRenderer>(); } public override void SetVisibility(bool visible) { ((Renderer)spriteRenderer).enabled = visible; } public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) base.verticalMargin = verticalMargin; base.horizontalMargin = horizontalMargin; base.maxWidth = maxWidth; base.maxHeight = maxHeight; ((Component)this).transform.localScale = new Vector3(maxWidth - 2f * verticalMargin, maxHeight - 2f * horizontalMargin, 1f); } protected override void MatchWithPercentage(float percentage) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Vector3 localScale = ((Component)this).transform.localScale; Vector3 localPosition = ((Component)this).transform.localPosition; localScale.x = (maxWidth - 2f * horizontalMargin) * percentage; localPosition.x = 0f - (maxWidth / 2f - horizontalMargin - localScale.x / 2f); ((Component)this).transform.localScale = localScale; ((Component)this).transform.localPosition = localPosition; } public override void SetColor(Color color) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) spriteRenderer.color = color; } } public class UIBar : Bar { [SerializeField] protected RectTransform rectTransform; [SerializeField] protected CanvasGroup canvasGroup; [SerializeField] protected Image image; public override float CurrentPercentage => rectTransform.sizeDelta.x / maxWidth; public override void UpdateSize(float maxHeight, float maxWidth, float verticalMargin, float horizontalMargin) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) float currentPercentage = CurrentPercentage; base.maxHeight = maxHeight - 2f * verticalMargin; base.maxWidth = maxWidth - 2f * horizontalMargin; base.verticalMargin = verticalMargin; base.horizontalMargin = horizontalMargin; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.offsetMin = new Vector2(horizontalMargin, verticalMargin); rectTransform.SetSizeWithCurrentAnchors((Axis)1, base.maxHeight); rectTransform.SetSizeWithCurrentAnchors((Axis)0, base.maxWidth * currentPercentage); } protected override void MatchWithPercentage(float percentage) { float num = maxWidth * percentage; rectTransform.SetSizeWithCurrentAnchors((Axis)0, num); } public override void SetVisibility(bool visible) { canvasGroup.alpha = (visible ? 1 : 0); } public override void SetColor(Color color) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)image != (Object)null) { ((Graphic)image).color = color; } } } public class UIHealthBar : HealthBar { [SerializeField] protected Text hpText; [SerializeField] protected Text nameText; [SerializeField] protected CanvasGroup canvasGroup; protected override void OnStart() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) base.OnStart(); ((Component)this).GetComponent<RectTransform>().sizeDelta = new Vector2(width, height); } protected override void Redraw() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) base.Redraw(); ((Component)this).GetComponent<RectTransform>().sizeDelta = new Vector2(width, height); OnHealthChanged(); } protected override void OnHealthChanged() { hpText.text = $"{Mathf.CeilToInt(currentHealth)}/{Mathf.CeilToInt(maxHealth)}"; } public void SetNameText(string name) { if (!((Object)(object)nameText == (Object)null)) { nameText.text = name; } } public void SetHpTextColor(Color color) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)hpText == (Object)null)) { ((Graphic)hpText).color = color; } } public void SetHpTextEnabled(bool enabled) { if (!((Object)(object)hpText == (Object)null)) { ((Behaviour)hpText).enabled = enabled; } } public override void SetVisibility(bool visible) { base.SetVisibility(visible); canvasGroup.alpha = (visible ? 1 : 0); } } public static class ScreenSpaceCanvas { private static Canvas _screenSpaceCanvas; public static readonly string name = "SilkenImpactScreenSpaceCanvas"; public static Canvas GetScreenSpaceCanvas { get { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_screenSpaceCanvas == (Object)null) { GameObject val = GameObject.Find(name); if ((Object)(object)val != (Object)null) { return val.GetComponent<Canvas>(); } val = new GameObject(name); Object.DontDestroyOnLoad((Object)(object)val); _screenSpaceCanvas = val.AddComponent<Canvas>(); _screenSpaceCanvas.renderMode = (RenderMode)0; _screenSpaceCanvas.vertexColorAlwaysGammaSpace = false; _screenSpaceCanvas.sortingOrder = 999; CanvasScaler obj = val.AddComponent<CanvasScaler>(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(26f, 14f); obj.screenMatchMode = (ScreenMatchMode)0; obj.matchWidthOrHeight = 0.5f; obj.referencePixelsPerUnit = 100f; } return _screenSpaceCanvas; } } } public class SpriteTracker : MonoBehaviour { public float gapBetweenTop; public float zOffset; [SerializeField] private GameObject target; [SerializeField] private Vector3 basicOffset = Vector3.zero; private Vector3 Offset => basicOffset + new Vector3(0f, gapBetweenTop, zOffset); private void Start() { SetTarget(target); } private Renderer GetEnabledRendererInChildren(GameObject target) { Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(); Renderer result = null; Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (val.enabled) { result = val; break; } } return result; } public void SetTarget(GameObject target) { //IL_0008: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) this.target = target; basicOffset = Vector3.zero; if ((Object)(object)target != (Object)null) { Renderer val = default(Renderer); Renderer val2 = ((!target.TryGetComponent<Renderer>(ref val)) ? GetEnabledRendererInChildren(target) : val); if ((Object)(object)val2 != (Object)null) { Bounds bounds = val2.bounds; float y = ((Bounds)(ref bounds)).extents.y; basicOffset = new Vector3(0f, y, 0f); } } } private void Update() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { ((Component)this).transform.position = target.transform.position + Offset; } } } public static class WorldSpaceCanvas { private static Canvas _worldSpaceCanvas; public static readonly string name = "SilkenImpactWorldSpaceCanvas"; public static readonly float PPU = 100f; public static Canvas GetWorldSpaceCanvas { get { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if ((Object)(object)_worldSpaceCanvas == (Object)null) { GameObject val = GameObject.Find(name); if ((Object)(object)val != (Object)null) { return val.GetComponent<Canvas>(); } val = new GameObject(name); Object.DontDestroyOnLoad((Object)(object)val); _worldSpaceCanvas = val.AddComponent<Canvas>(); _worldSpaceCanvas.renderMode = (RenderMode)2; _worldSpaceCanvas.worldCamera = Camera.main; _worldSpaceCanvas.sortingOrder = 1000; CanvasScaler obj = val.AddComponent<CanvasScaler>(); obj.dynamicPixelsPerUnit = PPU; obj.referencePixelsPerUnit = PPU; } return _worldSpaceCanvas; } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.kokomi.silkenimpact"; public const string PLUGIN_NAME = "Silken Impact"; public const string PLUGIN_VERSION = "1.4.1"; } } namespace SilkenImpact.Deprecated { public class HealthBar : MonoBehaviour { [CompilerGenerated] private sealed class <AnimateHealthChange>d__19 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public HealthBar <>4__this; public float targetHealth; private float <timer>5__2; private float <startHealth>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AnimateHealthChange>d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; HealthBar healthBar = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <timer>5__2 = 0f; <startHealth>5__3 = healthBar.currentHealth; break; case 1: <>1__state = -1; break; } if (<timer>5__2 < healthBar.healthChangeDuration) { <timer>5__2 += Time.deltaTime; float num2 = Mathf.Clamp01(<timer>5__2 / healthBar.healthChangeDuration); healthBar.currentHealth = Mathf.Lerp(<startHealth>5__3, targetHealth, num2); <>2__current = null; <>1__state = 1; return true; } healthBar.currentHealth = targetHealth; healthBar.healthAnimationCoroutine = null; 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 SpriteRenderer hp; public SpriteRenderer delayedEffect; public SpriteRenderer background; public float maxHealth = 100f; [SerializeField] private float currentHealth; [SerializeField] private float delayedHealth; public float timerReductionPercentageOnDamage = 0.5f; public float decayThresholdSeconds = 0.2f; public float decayPercentagePerSecond = 0.4f; [SerializeField] private float decayTimer; public float healthChangeDuration = 0.2f; private Coroutine healthAnimationCoroutine; private void Awake() { //IL_000c: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) hp.size = background.size; delayedEffect.size = background.size; Vector3 localScale = ((Component)background).transform.localScale; ((Component)hp).transform.localScale = localScale; ((Component)delayedEffect).transform.localScale = localScale; Vector3 localPosition = ((Component)background).transform.localPosition; ((Component)hp).transform.localPosition = localPosition; ((Component)delayedEffect).transform.localPosition = localPosition; ((Renderer)hp).sortingOrder = 2; ((Renderer)delayedEffect).sortingOrder = 1; ((Renderer)background).sortingOrder = 0; currentHealth = maxHealth; delayedHealth = maxHealth; } private void SetSpritePercentage(SpriteRenderer sprite, float percentage) { //IL_000e: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) percentage = Mathf.Clamp01(percentage); Vector3 localScale = ((Component)sprite).transform.localScale; localScale.x = ((Component)background).transform.localScale.x * percentage; ((Component)sprite).transform.localScale = localScale; Vector3 localPosition = ((Component)sprite).transform.localPosition; float x = background.size.x; float num = ((Component)background).transform.localScale.x - localScale.x; localPosition.x = ((Component)background).transform.localPosition.x - x * num * 0.5f; ((Component)sprite).transform.localPosition = localPosition; } private void Update() { if (Input.GetKeyDown((KeyCode)97)) { TakeDamage(10f); } if (Input.GetKeyDown((KeyCode)100)) { Heal(10f); } SetSpritePercentage(hp, currentHealth / maxHealth); if (delayedHealth > currentHealth) { if (decayTimer < decayThresholdSeconds) { decayTimer += Time.deltaTime; } else { delayedHealth -= maxHealth * Time.deltaTime * decayPercentagePerSecond; delayedHealth = Mathf.Clamp(delayedHealth, currentHealth, maxHealth); } } else { delayedHealth = currentHealth; decayTimer = 0f; } SetSpritePercentage(delayedEffect, delayedHealth / maxHealth); } public void TakeDamage(float amount) { decayTimer -= timerReductionPercentageOnDamage * decayThresholdSeconds; decayTimer = Mathf.Clamp(decayTimer, -0.3f * decayThresholdSeconds, decayThresholdSeconds); float newHealth = Mathf.Clamp(currentHealth - amount, 0f, maxHealth); AnimateHealthTo(newHealth); } public void Heal(float amount) { float newHealth = Mathf.Clamp(currentHealth + amount, 0f, maxHealth); AnimateHealthTo(newHealth); } public void SetHealth(float percentage) { percentage = Mathf.Clamp01(percentage); float num = percentage * maxHealth; if (num >= currentHealth) { Heal(num - currentHealth); } else { TakeDamage(currentHealth - num); } } private void AnimateHealthTo(float newHealth) { if (healthAnimationCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(healthAnimationCoroutine); } healthAnimationCoroutine = ((MonoBehaviour)this).StartCoroutine(AnimateHealthChange(newHealth)); } [IteratorStateMachine(typeof(<AnimateHealthChange>d__19))] private IEnumerator AnimateHealthChange(float targetHealth) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AnimateHealthChange>d__19(0) { <>4__this = this, targetHealth = targetHealth }; } } } namespace SilkenImpact.Patch { [HarmonyPatch] [HarmonyPatch(typeof(BlackThreadState))] public class BlackThreadStatePatch { private static HealthManager GetPrivateHealthManager(BlackThreadState instance) { return Traverse.Create((object)instance).Field<HealthManager>("healthManager").Value; } [HarmonyPatch("SetupThreaded")] [HarmonyPrefix] public static void BlackThreadState_DoDamage_Prefix(BlackThreadState __instance, ref Tuple<int, int> __state) { HealthManager privateHealthManager = GetPrivateHealthManager(__instance); if (Object.op_Implicit((Object)(object)privateHealthManager)) { int hp = privateHealthManager.hp; int item = ((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Enqueue<SetHpEventArgs>() ?? (-1); __state = new Tuple<int, int>(hp, item); } } [HarmonyPatch("SetupThreaded")] [HarmonyPostfix] public static void BlackThreadState_DoDamage_Postfix(BlackThreadState __instance, ref Tuple<int, int> __state) { HealthManager privateHealthManager = GetPrivateHealthManager(__instance); if (Object.op_Implicit((Object)(object)privateHealthManager)) { int hp = privateHealthManager.hp; var (num3, id) = __state; if (hp != num3) { ((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Submit(id, new SetHpEventArgs(hp)); } else { ((Component)privateHealthManager).GetComponent<IHealthBarOwner>()?.Dispatcher.Cancel(id); } } } } [HarmonyPatch] [HarmonyPatch(typeof(EnemyDeathEffects))] public class EnemyDeathEffectsPatch { } [HarmonyPatch] [HarmonyPatch(typeof(HealthManager))] public class HealthManagerPatch { public static float avgDamagePerHit = -1f; private static MethodInfo isImmuneToMethod = AccessTools.Method(typeof(HealthManager), "IsImmuneTo", (Type[])null, (Type[])null); private static MethodInfo applyDamageScalingMethod = AccessTools.Method(typeof(HealthManager), "ApplyDamageScaling", (Type[])null, (Type[])null); public static float weightOfNew => Configs.Instance.weightOfNewHit.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; } private static void spawnTextOn(HealthManager __instance, 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)__instance).gameObject).name; Renderer component = ((Component)__instance).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)__instance).gameObject.transform.position + val2; textGO.transform.SetParent(((Component)WorldSpaceCanvas.GetWorldSpaceCanvas).transform, true); DamageText component2 = textGO.GetComponent<DamageText>(); component2.DamageString = content; component2.TextColor = color; component2.maxHeight *= sizeScale; component2.maxWidth *= sizeScale; } public static void SpawnDamageText(HealthManager __instance, float damage, bool isCritHit, NailElements element = 0, Color? color = null) { //IL_00b9: 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_00b0: 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 = Ra