diff --git a/Fika.Core/Bundles/Files/playerui.bundle b/Fika.Core/Bundles/Files/playerui.bundle index 3045e9a9..342b78ae 100644 Binary files a/Fika.Core/Bundles/Files/playerui.bundle and b/Fika.Core/Bundles/Files/playerui.bundle differ diff --git a/Fika.Core/Coop/Custom/FikaHealthBar.cs b/Fika.Core/Coop/Custom/FikaHealthBar.cs index 6612a4ed..bf6cedca 100644 --- a/Fika.Core/Coop/Custom/FikaHealthBar.cs +++ b/Fika.Core/Coop/Custom/FikaHealthBar.cs @@ -3,11 +3,14 @@ using Comfort.Common; using EFT; using EFT.Animations; +using EFT.HealthSystem; using EFT.UI; using Fika.Core.Bundles; using Fika.Core.Coop.Players; using Fika.Core.Utils; using System; +using System.Collections.Generic; +using TMPro; using UnityEngine; using UnityEngine.UI; @@ -23,11 +26,15 @@ public class FikaHealthBar : MonoBehaviour private CoopPlayer mainPlayer; private PlayerPlateUI playerPlate; private float screenScale = 1f; + private Dictionary effectIcons; + private List effects; protected void Awake() { currentPlayer = GetComponent(); mainPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; + effectIcons = EFTHardSettings.Instance.StaticIcons.EffectIcons.EffectIcons; + effects = []; CreateHealthBar(); } @@ -172,24 +179,118 @@ private void CreateHealthBar() SetPlayerPlateHealthVisibility(FikaPlugin.HideHealthBar.Value); playerPlate.gameObject.SetActive(FikaPlugin.UseNamePlates.Value); + if (FikaPlugin.ShowEffects.Value) + { + currentPlayer.HealthController.EffectAddedEvent += HealthController_EffectAddedEvent; + currentPlayer.HealthController.EffectRemovedEvent += HealthController_EffectRemovedEvent; + } + FikaPlugin.UsePlateFactionSide.SettingChanged += UsePlateFactionSide_SettingChanged; FikaPlugin.HideHealthBar.SettingChanged += HideHealthBar_SettingChanged; FikaPlugin.UseNamePlates.SettingChanged += UseNamePlates_SettingChanged; + FikaPlugin.UseHealthNumber.SettingChanged += UseHealthNumber_SettingChanged; + FikaPlugin.ShowEffects.SettingChanged += ShowEffects_SettingChanged; currentPlayer.HealthController.HealthChangedEvent += HealthController_HealthChangedEvent; currentPlayer.HealthController.BodyPartDestroyedEvent += HealthController_BodyPartDestroyedEvent; currentPlayer.HealthController.BodyPartRestoredEvent += HealthController_BodyPartRestoredEvent; currentPlayer.HealthController.DiedEvent += HealthController_DiedEvent; + playerPlate.SetHealthNumberText("100%"); + UpdateHealth(); } + #region events + private void UseHealthNumber_SettingChanged(object sender, EventArgs e) + { + UpdateHealth(); + } + + private void HealthController_EffectRemovedEvent(IEffect effect) + { + for (int i = 0; i < effects.Count; i++) + { + HealthBarEffect currentEffect = effects[i]; + if (currentEffect.effectType == effect.Type) + { + currentEffect.DecreaseAmount(); + if (currentEffect.GetAmount() == 0) + { + currentEffect.Remove(); + effects.Remove(currentEffect); + } + break; + } + } + } + + private void HealthController_EffectAddedEvent(IEffect effect) + { + AddEffect(effect); + } + + private void AddEffect(IEffect effect) + { + bool found = false; + foreach (HealthBarEffect currentEffect in effects) + { + if (currentEffect.effectType == effect.Type) + { + currentEffect.IncreaseAmount(); + found = true; + } + } + + if (found) + { + return; + } + + if (effectIcons.TryGetValue(effect.Type, out Sprite effectSprite)) + { + GameObject newEffect = Instantiate(playerPlate.EffectImageTemplate, playerPlate.EffectsBackground.transform); + HealthBarEffect healthBarEffect = new(); + healthBarEffect.Init(newEffect, effect, effectSprite); + effects.Add(healthBarEffect); + } + } + + private void ShowEffects_SettingChanged(object sender, EventArgs e) + { + if (FikaPlugin.ShowEffects.Value) + { + currentPlayer.HealthController.EffectAddedEvent += HealthController_EffectAddedEvent; + currentPlayer.HealthController.EffectRemovedEvent += HealthController_EffectRemovedEvent; + + IEnumerable currentEffects = currentPlayer.HealthController.GetAllActiveEffects(); + foreach (IEffect effect in currentEffects) + { + AddEffect(effect); + } + } + else + { + currentPlayer.HealthController.EffectAddedEvent -= HealthController_EffectAddedEvent; + currentPlayer.HealthController.EffectRemovedEvent -= HealthController_EffectRemovedEvent; + + List tempList = new(effects); + foreach (HealthBarEffect effect in tempList) + { + effect.Remove(); + } + effects.Clear(); + tempList.Clear(); + tempList = null; + } + } + private void HealthController_DiedEvent(EDamageType obj) { Destroy(this); } - private void HealthController_BodyPartRestoredEvent(EBodyPart arg1, EFT.HealthSystem.ValueStruct arg2) + private void HealthController_BodyPartRestoredEvent(EBodyPart arg1, ValueStruct arg2) { UpdateHealth(); } @@ -208,6 +309,7 @@ private void UsePlateFactionSide_SettingChanged(object sender, EventArgs e) { SetPlayerPlateFactionVisibility(FikaPlugin.UsePlateFactionSide.Value); } + private void HideHealthBar_SettingChanged(object sender, EventArgs e) { SetPlayerPlateHealthVisibility(FikaPlugin.HideHealthBar.Value); @@ -216,7 +318,8 @@ private void HideHealthBar_SettingChanged(object sender, EventArgs e) private void UseNamePlates_SettingChanged(object sender, EventArgs e) { playerPlate.gameObject.SetActive(FikaPlugin.UseNamePlates.Value); - } + } + #endregion /// /// Updates the health on the HealthBar, this is invoked from events on the healthcontroller @@ -229,8 +332,7 @@ private void UpdateHealth() { if (!playerPlate.healthNumberBackgroundScreen.gameObject.activeSelf) { - playerPlate.healthNumberBackgroundScreen.gameObject.SetActive(true); - playerPlate.healthBarBackgroundScreen.gameObject.SetActive(false); + SetPlayerPlateHealthVisibility(false); } int healthNumberPercentage = (int)Math.Round(currentHealth / maxHealth * 100); playerPlate.SetHealthNumberText($"{healthNumberPercentage}%"); @@ -239,8 +341,7 @@ private void UpdateHealth() { if (!playerPlate.healthBarBackgroundScreen.gameObject.activeSelf) { - playerPlate.healthNumberBackgroundScreen.gameObject.SetActive(false); - playerPlate.healthBarBackgroundScreen.gameObject.SetActive(true); + SetPlayerPlateHealthVisibility(false); } float normalizedHealth = Mathf.Clamp01(currentHealth / maxHealth); @@ -302,14 +403,71 @@ protected void OnDestroy() FikaPlugin.UsePlateFactionSide.SettingChanged -= UsePlateFactionSide_SettingChanged; FikaPlugin.HideHealthBar.SettingChanged -= HideHealthBar_SettingChanged; FikaPlugin.UseNamePlates.SettingChanged -= UseNamePlates_SettingChanged; + FikaPlugin.UseHealthNumber.SettingChanged -= UseHealthNumber_SettingChanged; + FikaPlugin.ShowEffects.SettingChanged -= ShowEffects_SettingChanged; currentPlayer.HealthController.HealthChangedEvent -= HealthController_HealthChangedEvent; currentPlayer.HealthController.BodyPartDestroyedEvent -= HealthController_BodyPartDestroyedEvent; currentPlayer.HealthController.BodyPartRestoredEvent -= HealthController_BodyPartRestoredEvent; currentPlayer.HealthController.DiedEvent -= HealthController_DiedEvent; + currentPlayer.HealthController.EffectAddedEvent -= HealthController_EffectAddedEvent; + currentPlayer.HealthController.EffectRemovedEvent -= HealthController_EffectRemovedEvent; playerPlate.gameObject.SetActive(false); Destroy(this); } + + private class HealthBarEffect + { + public Type effectType; + private int amount; + private GameObject effectObject; + private Image effectImage; + private TextMeshProUGUI tmpText; + + public void Init(GameObject initObject, IEffect effect, Sprite effectSprite) + { + effectObject = initObject; + effectObject.SetActive(true); + effectImage = effectObject.transform.GetChild(0).GetComponent(); + effectImage.sprite = effectSprite; + tmpText = effectObject.transform.GetChild(1).GetComponent(); + amount = 1; + tmpText.text = amount.ToString(); + effectType = effect.Type; + } + + public void Remove() + { + Destroy(effectImage); + Destroy(tmpText); + Destroy(effectObject); + } + + public int GetAmount() + { + return amount; + } + + public void IncreaseAmount() + { + amount++; + tmpText.text = amount.ToString(); + } + + public void DecreaseAmount() + { + amount = Math.Max(0, amount - 1); + if (amount == 0) + { + Remove(); + return; + } + else + { + tmpText.text = amount.ToString(); + } + } + } } } \ No newline at end of file diff --git a/Fika.Core/Coop/Custom/PlayerPlateUI.cs b/Fika.Core/Coop/Custom/PlayerPlateUI.cs index 217bdaf2..bf12ee56 100644 --- a/Fika.Core/Coop/Custom/PlayerPlateUI.cs +++ b/Fika.Core/Coop/Custom/PlayerPlateUI.cs @@ -31,7 +31,7 @@ public class PlayerPlateUI : MonoBehaviour [SerializeField] public GameObject EffectsBackground; [SerializeField] - public Image EffectImageTemplate; + public GameObject EffectImageTemplate; public void SetNameText(string text) { diff --git a/Fika.Core/FikaPlugin.cs b/Fika.Core/FikaPlugin.cs index 46ff0054..52b1226c 100644 --- a/Fika.Core/FikaPlugin.cs +++ b/Fika.Core/FikaPlugin.cs @@ -118,6 +118,7 @@ public class FikaPlugin : BaseUnityPlugin public static ConfigEntry MaxDistanceToShow { get; set; } public static ConfigEntry MinimumOpacity { get; set; } public static ConfigEntry MinimumNamePlateScale { get; set; } + public static ConfigEntry ShowEffects { get; set; } // Coop | Quest Sharing public static ConfigEntry QuestTypesToShareAndReceive { get; set; } @@ -327,25 +328,27 @@ private void SetupConfig() HideHealthBar = Config.Bind("Coop | Name Plates", "Hide Health Bar", false, new ConfigDescription("Completely hides the health bar.", tags: new ConfigurationManagerAttributes() { Order = 10 })); - UseHealthNumber = Config.Bind("Coop | Name Plates", "Show HP% instead of bar", false, new ConfigDescription("Shows health in % amount instead of using the bar.", tags: new ConfigurationManagerAttributes() { Order = 9 })); + UseHealthNumber = Config.Bind("Coop | Name Plates", "Show HP% instead of bar", false, new ConfigDescription("Shows health in % amount instead of using the bar.", tags: new ConfigurationManagerAttributes() { Order = 10 })); - UsePlateFactionSide = Config.Bind("Coop | Name Plates", "Show Player Faction Icon", true, new ConfigDescription("Shows the player faction icon next to the HP bar.", tags: new ConfigurationManagerAttributes() { Order = 8 })); + UsePlateFactionSide = Config.Bind("Coop | Name Plates", "Show Player Faction Icon", true, new ConfigDescription("Shows the player faction icon next to the HP bar.", tags: new ConfigurationManagerAttributes() { Order = 9 })); - HideNamePlateInOptic = Config.Bind("Coop | Name Plates", "Hide Name Plate in Optic", true, new ConfigDescription("Hides the name plate when viewing through PiP scopes.", tags: new ConfigurationManagerAttributes() { Order = 7 })); + HideNamePlateInOptic = Config.Bind("Coop | Name Plates", "Hide Name Plate in Optic", true, new ConfigDescription("Hides the name plate when viewing through PiP scopes.", tags: new ConfigurationManagerAttributes() { Order = 8 })); - NamePlateUseOpticZoom = Config.Bind("Coop | Name Plates", "Name Plates Use Optic Zoom", true, new ConfigDescription("If name plate location should be displayed using the PiP optic camera.", tags: new ConfigurationManagerAttributes() { Order = 6, IsAdvanced = true })); + NamePlateUseOpticZoom = Config.Bind("Coop | Name Plates", "Name Plates Use Optic Zoom", true, new ConfigDescription("If name plate location should be displayed using the PiP optic camera.", tags: new ConfigurationManagerAttributes() { Order = 7, IsAdvanced = true })); - DecreaseOpacityNotLookingAt = Config.Bind("Coop | Name Plates", "Decrease Opacity In Peripheral", true, new ConfigDescription("Decreases the opacity of the name plates when not looking at a player.", tags: new ConfigurationManagerAttributes() { Order = 5 })); + DecreaseOpacityNotLookingAt = Config.Bind("Coop | Name Plates", "Decrease Opacity In Peripheral", true, new ConfigDescription("Decreases the opacity of the name plates when not looking at a player.", tags: new ConfigurationManagerAttributes() { Order = 6 })); - NamePlateScale = Config.Bind("Coop | Name Plates", "Name Plate Scale", 0.22f, new ConfigDescription("Size of the name plates", new AcceptableValueRange(0.05f, 1f), new ConfigurationManagerAttributes() { Order = 4 })); + NamePlateScale = Config.Bind("Coop | Name Plates", "Name Plate Scale", 0.22f, new ConfigDescription("Size of the name plates", new AcceptableValueRange(0.05f, 1f), new ConfigurationManagerAttributes() { Order = 5 })); - OpacityInADS = Config.Bind("Coop | Name Plates", "Opacity in ADS", 0.75f, new ConfigDescription("The opacity of the name plates when aiming down sights.", new AcceptableValueRange(0.1f, 1f), new ConfigurationManagerAttributes() { Order = 3 })); + OpacityInADS = Config.Bind("Coop | Name Plates", "Opacity in ADS", 0.75f, new ConfigDescription("The opacity of the name plates when aiming down sights.", new AcceptableValueRange(0.1f, 1f), new ConfigurationManagerAttributes() { Order = 4 })); - MaxDistanceToShow = Config.Bind("Coop | Name Plates", "Max Distance to Show", 500f, new ConfigDescription("The maximum distance at which name plates will become invisible, starts to fade at half the input value.", new AcceptableValueRange(10f, 1000f), new ConfigurationManagerAttributes() { Order = 2 })); + MaxDistanceToShow = Config.Bind("Coop | Name Plates", "Max Distance to Show", 500f, new ConfigDescription("The maximum distance at which name plates will become invisible, starts to fade at half the input value.", new AcceptableValueRange(10f, 1000f), new ConfigurationManagerAttributes() { Order = 3 })); - MinimumOpacity = Config.Bind("Coop | Name Plates", "Minimum Opacity", 0.1f, new ConfigDescription("The minimum opacity of the name plates.", new AcceptableValueRange(0.0f, 1f), new ConfigurationManagerAttributes() { Order = 1 })); + MinimumOpacity = Config.Bind("Coop | Name Plates", "Minimum Opacity", 0.1f, new ConfigDescription("The minimum opacity of the name plates.", new AcceptableValueRange(0.0f, 1f), new ConfigurationManagerAttributes() { Order = 2 })); - MinimumNamePlateScale = Config.Bind("Coop | Name Plates", "Minimum Name Plate Scale", 0.01f, new ConfigDescription("The minimum scale of the name plates.", new AcceptableValueRange(0.0f, 1f), new ConfigurationManagerAttributes() { Order = 0 })); + MinimumNamePlateScale = Config.Bind("Coop | Name Plates", "Minimum Name Plate Scale", 0.01f, new ConfigDescription("The minimum scale of the name plates.", new AcceptableValueRange(0.0f, 1f), new ConfigurationManagerAttributes() { Order = 1 })); + + ShowEffects = Config.Bind("Coop | Name Plates", "Show Effects", true, new ConfigDescription("If status effects should be display below the health bar.", tags: new ConfigurationManagerAttributes() { Order = 0 })); // Coop | Quest Sharing