using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using BepInEx.Logging; using Comfort.Common; using EFT; using EFT.Interactive; using EFT.InventoryLogic; using HarmonyLib; using UnityEngine; namespace armorMod { internal class AssComponent : MonoBehaviour { private static GameWorld gameWorld = new GameWorld(); private static Player player = new Player(); private static float newRepairRate; private static float newMaxDurabilityDrainRate; private static float newWeaponRepairRate; private static float newWeaponMaxDurabilityDrainRate; private static RepairableComponent armor; private static FaceShieldComponent faceShield; private static RepairableComponent weapon; private static float maxRepairableDurabilityBasedOnCap; private static float maxWeaponRepairableDurabilityBasedOnCap; private static float timeSinceLastHit = 0f; private static Dictionary> equipmentSlotDictionary = new Dictionary> { { EquipmentSlot.ArmorVest, new List() }, { EquipmentSlot.TacticalVest, new List() }, { EquipmentSlot.Eyewear, new List() }, { EquipmentSlot.FaceCover, new List() }, { EquipmentSlot.Headwear, new List() }, }; private static Dictionary> weaponSlotDictionary = new Dictionary> { { EquipmentSlot.FirstPrimaryWeapon, new List() }, { EquipmentSlot.SecondPrimaryWeapon, new List() }, { EquipmentSlot.Holster, new List() }, }; protected static ManualLogSource Logger { get; private set; } private AssComponent() { if (Logger == null) { Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(AssComponent)); } } private void Start() { player = Singleton.Instance.MainPlayer; player.BeingHitAction += Player_BeingHitAction; } internal static void Enable() { if (Singleton.Instantiated) { gameWorld = Singleton.Instance; gameWorld.GetOrAddComponent(); Logger.LogDebug("AssComponent enabled"); } } private void Update() { timeSinceLastHit += Time.deltaTime; if ((timeSinceLastHit >= AssPlugin.TimeDelayRepairInSec.Value) && AssPlugin.ArmorServiceMode.Value) { RepairArmor(); } if ((timeSinceLastHit >= AssPlugin.weaponTimeDelayRepairInSec.Value) && AssPlugin.WeaponServiceMode.Value) { RepairWeapon(); } if(AssPlugin.faceShieldNoMask.Value || AssPlugin.fixFaceShieldBullets.Value) { faceShieldCheck(); } } private void faceShieldCheck() { var slot = EquipmentSlot.Headwear; Slot tempSlot = getEquipSlot(slot); if (tempSlot == null || tempSlot.ContainedItem == null) { return; } foreach (var item in tempSlot.ContainedItem.GetAllItems()) { item.TryGetItemComponent(out faceShield); //if has faceshield repair bullet damage hits if (faceShield != null) { //Logger.LogDebug("Item has a faceshield component, setting hits to 0"); //use access tools to set property of faceshield.mask to no mask if (faceShield.Mask != FaceShieldComponent.EMask.NoMask && AssPlugin.faceShieldNoMask.Value) { AccessTools.Property(faceShield.GetType(), "Mask").SetValue(faceShield, FaceShieldComponent.EMask.NoMask); } if (faceShield.Hits > 0 && AssPlugin.fixFaceShieldBullets.Value && timeSinceLastHit >= AssPlugin.TimeDelayRepairInSec.Value) { faceShield.Hits = 0; faceShield.HitsChanged.Invoke(); } } } } private void RepairArmor() { newRepairRate = AssPlugin.ArmorRepairRateOverTime.Value * Time.deltaTime; newMaxDurabilityDrainRate = AssPlugin.MaxDurabilityDegradationRateOverTime.Value * Time.deltaTime; foreach (EquipmentSlot slot in equipmentSlotDictionary.Keys.ToArray()) { Slot tempSlot = getEquipSlot(slot); if (tempSlot == null || tempSlot.ContainedItem == null) { continue; } foreach (var item in tempSlot.ContainedItem.GetAllItems()) { //get the armorcomponent of each item in items and check to see if all item componenets (even helmet side ears) are max durability //Logger.LogDebug("Examining the item: " + item.Name.Localized() + " in slot: " + slot.ToString() + " for repairable component"); item.TryGetItemComponent(out armor); if (armor == null) { //Logger.LogDebug("Item: " + item.Name.Localized() + " in slot: " + slot.ToString() + " does not have a repairable component"); continue; } maxRepairableDurabilityBasedOnCap = ((AssPlugin.MaxDurabilityCap.Value / 100) * armor.MaxDurability); //check if it needs repair for the current item in loop of all items for the slot if (armor.Durability < maxRepairableDurabilityBasedOnCap) { //increase armor durability by newRepairRate until maximum then set as maximum durability if (armor.Durability + newRepairRate >= armor.MaxDurability) { armor.Durability = armor.MaxDurability; } else { armor.Durability += newRepairRate; armor.MaxDurability -= newMaxDurabilityDrainRate; } } } } } private void RepairWeapon() { newWeaponRepairRate = AssPlugin.weaponRepairRateOverTime.Value * Time.deltaTime; newWeaponMaxDurabilityDrainRate = AssPlugin.weaponMaxDurabilityDegradationRateOverTime.Value * Time.deltaTime; foreach (EquipmentSlot slot in weaponSlotDictionary.Keys.ToArray()) { Slot tempSlot = getEquipSlot(slot); if (tempSlot == null || tempSlot.ContainedItem == null) { continue; } foreach (var item in tempSlot.ContainedItem.GetAllItems()) { item.TryGetItemComponent(out weapon); if (weapon == null) { //Logger.LogDebug("Item: " + item.Name.Localized() + " in slot: " + slot.ToString() + " does not have a repairable component"); continue; } //Logger.LogDebug("Item: " + item.Name.Localized() + " in slot: " + slot.ToString() + " has a repairable component"); maxWeaponRepairableDurabilityBasedOnCap = ((AssPlugin.weaponMaxDurabilityCap.Value / 100) * weapon.MaxDurability); //check if it needs repair for the current item in loop of all items for the slot if (weapon.Durability < maxWeaponRepairableDurabilityBasedOnCap) { //increase weapon durability by newWeaponRepairRate until maximum then set as maximum durability if (weapon.Durability + newWeaponRepairRate >= weapon.MaxDurability) { weapon.Durability = weapon.MaxDurability; } else { weapon.Durability += newWeaponRepairRate; weapon.MaxDurability -= newWeaponMaxDurabilityDrainRate; } } } } } private void Player_BeingHitAction(DamageInfo dmgInfo, EBodyPart bodyPart, float hitEffectId) => timeSinceLastHit = 0f; private static Slot slotContents; private static InventoryControllerClass inventoryController; private Slot getEquipSlot(EquipmentSlot slot) { // Use AccessTools to get the protected field _inventoryController inventoryController = (InventoryControllerClass)AccessTools.Field(typeof(Player), "_inventoryController").GetValue(player); if (inventoryController != null) { slotContents = inventoryController.Inventory.Equipment.GetSlot(slot); if (slotContents.ContainedItem == null) { return null; } return slotContents; } return null; } } }