using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting.Messaging; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using Comfort.Common; using EFT; using EFT.InventoryLogic; using HarmonyLib; using UnityEngine; namespace armorMod { [BepInPlugin("com.armorMod.ASS", "armorMod.ASS", "1.0.0")] public class ASS : BaseUnityPlugin { private ConfigEntry ArmorServiceMode { get; set; } private static ConfigEntry TimeDelayRepairInSec { get; set; } private static ConfigEntry ArmorRepairRateOverTime { get; set; } private static ConfigEntry MaxDurabilityDegradationRateOverTime { get; set; } private AbstractGame game; private bool runOnceAlready = false; private bool newGame = true; private float newRepairRate; private float newMaxDurabilityDrainRate; private ArmorComponent armor; private static float timeSinceLastHit = 0f; private readonly Dictionary> equipmentSlotDictionary = new Dictionary> { { EquipmentSlot.ArmorVest, new List() }, { EquipmentSlot.TacticalVest, new List() }, { EquipmentSlot.Eyewear, new List() }, { EquipmentSlot.FaceCover, new List() }, { EquipmentSlot.Headwear, new List() } }; internal void Awake() { ArmorServiceMode = Config.Bind("Armor Repair Settings", "Enable/Disable Mod", true, "Enables the Armor Repairing Options Below"); TimeDelayRepairInSec = Config.Bind("Armor Repair Settings", "Time Delay Repair in Sec", 60f, "How Long Before you were last hit that it repairs armor"); ArmorRepairRateOverTime = Config.Bind("Armor Repair Settings", "Armor Repair Rate", 0.5f, "How much durability per second is repaired"); MaxDurabilityDegradationRateOverTime = Config.Bind("Armor Repair Settings", "Max Durability Drain Rate", 0.025f, "How much max durability per second of repairs is drained"); } private void Update() { try { game = Singleton.Instance; if (game.InRaid && Camera.main.transform.position != null && newGame && ArmorServiceMode.Value) { var player = Singleton.Instance.MainPlayer; timeSinceLastHit += Time.deltaTime; if (!runOnceAlready && game.Status == GameStatus.Started) { Logger.LogDebug("ASS: Attaching events"); player.BeingHitAction += Player_BeingHitAction; player.OnPlayerDeadOrUnspawn += Player_OnPlayerDeadOrUnspawn; runOnceAlready = true; } RepairArmor(); } } catch { } } private void RepairArmor() { //if the time since we were last hit exceeds TimeDelayRepairInSec.Value then repair all armor if (timeSinceLastHit >= TimeDelayRepairInSec.Value) { //Logger.LogInfo($"Repairing Armor Block Reached Because TimeSinceLastHitReached: " + timeSinceLastHit); //repair the armor divided by the time.unfixed rate newRepairRate = ArmorRepairRateOverTime.Value * Time.deltaTime; newMaxDurabilityDrainRate = MaxDurabilityDegradationRateOverTime.Value * Time.deltaTime; foreach (EquipmentSlot slot in equipmentSlotDictionary.Keys.ToArray()) { Logger.LogInfo("ASS: Checking EquipmentSlot: " + slot); 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 armor = item.GetItemComponent(); //check if it needs repair for the current item in loop of all items for the slot if (armor != null && (armor.Repairable.Durability < armor.Repairable.MaxDurability)) { //increase armor durability by newRepairRate until maximum then set as maximum durability if (armor.Repairable.Durability + newRepairRate >= armor.Repairable.MaxDurability) { armor.Repairable.Durability = armor.Repairable.MaxDurability; //Logger.LogInfo("ASS: Setting MaxDurability for " + item.LocalizedName()); } else { armor.Repairable.Durability += newRepairRate; armor.Repairable.MaxDurability -= newMaxDurabilityDrainRate; Logger.LogInfo("ASS: Repairing " + item.LocalizedName() + " : " + armor.Repairable.Durability + "/" + armor.Repairable.MaxDurability); } } } } } } private void Player_BeingHitAction(DamageInfo dmgInfo, EBodyPart bodyPart, float hitEffectId) => timeSinceLastHit = 0f; private void Player_OnPlayerDeadOrUnspawn(Player player) { Logger.LogDebug("ASS: Undo all events"); player.BeingHitAction -= Player_BeingHitAction; player.OnPlayerDeadOrUnspawn -= Player_OnPlayerDeadOrUnspawn; runOnceAlready = false; newGame = false; Task.Delay(TimeSpan.FromSeconds(15)).ContinueWith(_ => { // Set newGame = true after the timer is finished so it doesn't execute the events right away newGame = true; }); } private Slot slotContents; private InventoryControllerClass inventoryController; private Slot getEquipSlot(EquipmentSlot slot) { var player = Singleton.Instance.MainPlayer; // 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; } } }