148 lines
6.0 KiB
C#
148 lines
6.0 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using BepInEx.Logging;
|
|
using Comfort.Common;
|
|
using EFT;
|
|
using EFT.InventoryLogic;
|
|
using HarmonyLib;
|
|
using UnityEngine;
|
|
|
|
#pragma warning disable IDE0044
|
|
|
|
namespace armorMod
|
|
{
|
|
internal class AssComponent : MonoBehaviour
|
|
{
|
|
private static GameWorld gameWorld = new GameWorld();
|
|
private static Player player = new Player();
|
|
private static InventoryControllerClass _cachedInventoryController;
|
|
|
|
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 Slot tempSlot;
|
|
|
|
private static Dictionary<EquipmentSlot, List<Item>> equipmentSlotDictionary = new Dictionary<EquipmentSlot, List<Item>>
|
|
{
|
|
{ EquipmentSlot.ArmorVest, new List<Item>() },
|
|
{ EquipmentSlot.TacticalVest, new List<Item>() },
|
|
{ EquipmentSlot.Eyewear, new List<Item>() },
|
|
{ EquipmentSlot.FaceCover, new List<Item>() },
|
|
{ EquipmentSlot.Headwear, new List<Item>() },
|
|
};
|
|
|
|
private static Dictionary<EquipmentSlot, List<Item>> weaponSlotDictionary = new Dictionary<EquipmentSlot, List<Item>>
|
|
{
|
|
{ EquipmentSlot.FirstPrimaryWeapon, new List<Item>() },
|
|
{ EquipmentSlot.SecondPrimaryWeapon, new List<Item>() },
|
|
{ EquipmentSlot.Holster, new List<Item>() },
|
|
};
|
|
protected static ManualLogSource Logger
|
|
{
|
|
get; private set;
|
|
}
|
|
private AssComponent()
|
|
{
|
|
if (Logger == null)
|
|
{
|
|
Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(AssComponent));
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
player = Singleton<GameWorld>.Instance.MainPlayer;
|
|
player.BeingHitAction += Player_BeingHitAction;
|
|
timeSinceLastHit = 0;
|
|
_cachedInventoryController = (InventoryControllerClass)AccessTools.Field(typeof(Player), "_inventoryController").GetValue(player);
|
|
}
|
|
internal static void Enable()
|
|
{
|
|
if (Singleton<IBotGame>.Instantiated)
|
|
{
|
|
gameWorld = Singleton<GameWorld>.Instance;
|
|
gameWorld.GetOrAddComponent<AssComponent>();
|
|
|
|
Logger.LogDebug("AssComponent enabled");
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
timeSinceLastHit += Time.deltaTime;
|
|
|
|
if (AssPlugin.ArmorServiceMode.Value && timeSinceLastHit >= AssPlugin.TimeDelayRepairInSec.Value)
|
|
{
|
|
var armorItems = equipmentSlotDictionary.Values.SelectMany(slot => slot).SelectMany(slot => slot.GetAllItems());
|
|
RepairItems(armorItems, isWeapon: false);
|
|
}
|
|
|
|
if (AssPlugin.WeaponServiceMode.Value && timeSinceLastHit >= AssPlugin.weaponTimeDelayRepairInSec.Value)
|
|
{
|
|
var weaponItems = weaponSlotDictionary.Values.SelectMany(slot => slot).SelectMany(slot => slot.GetAllItems());
|
|
RepairItems(weaponItems, isWeapon: true);
|
|
}
|
|
}
|
|
|
|
private void RepairItems(IEnumerable<Item> items, bool isWeapon)
|
|
{
|
|
float repairRate = isWeapon ? AssPlugin.weaponRepairRateOverTime.Value * Time.deltaTime : AssPlugin.ArmorRepairRateOverTime.Value * Time.deltaTime;
|
|
float maxDurabilityDrainRate = isWeapon ? AssPlugin.weaponMaxDurabilityDegradationRateOverTime.Value * Time.deltaTime : AssPlugin.MaxDurabilityDegradationRateOverTime.Value * Time.deltaTime;
|
|
|
|
foreach (var item in items)
|
|
{
|
|
if (!isWeapon)
|
|
{
|
|
// Specifically for face shields, if the item has a FaceShieldComponent.
|
|
if (item.TryGetItemComponent<FaceShieldComponent>(out var faceShield) && AssPlugin.fixFaceShieldBullets.Value)
|
|
{
|
|
// Check if face shield has been hit and reset hits if so.
|
|
if (faceShield.Hits > 0)
|
|
{
|
|
faceShield.Hits = 0;
|
|
// Assuming faceShield has a method or event to notify changes. If not, adjust as necessary.
|
|
faceShield.HitsChanged?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (item.TryGetItemComponent<RepairableComponent>(out var repairable))
|
|
{
|
|
float maxRepairableDurabilityBasedOnCap = ((isWeapon ? AssPlugin.weaponMaxDurabilityCap.Value : AssPlugin.MaxDurabilityCap.Value) / 100) * repairable.MaxDurability;
|
|
|
|
if (repairable.Durability < maxRepairableDurabilityBasedOnCap)
|
|
{
|
|
repairable.Durability = Mathf.Min(repairable.Durability + repairRate, repairable.MaxDurability);
|
|
repairable.MaxDurability = Mathf.Max(repairable.MaxDurability - maxDurabilityDrainRate, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
if (_cachedInventoryController != null)
|
|
{
|
|
var slotContents = _cachedInventoryController.Inventory.Equipment.GetSlot(slot);
|
|
return slotContents.ContainedItem == null ? null : slotContents;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|