sasalka/Code/Player/Dedugan.Inventory.cs
2025-06-26 23:24:52 +03:00

227 lines
6.0 KiB
C#

using Sandbox.Citizen;
using Sandbox.Weapons;
using Sasalka;
public sealed partial class Dedugan : Component
{
[Property] public Inventar Inventory { get; private set; }
private Dictionary<Inventar.InventorySlot, (GameObject obj, IUseable useable)> _useableCache = new();
[Sync] private bool InAds { get; set; } = false;
private AttachmentSlotResolver _resolver;
void InventoryStart()
{
if (!Network.IsOwner) return;
// Создаем инвентарь как компонент
Inventory = GameObject.Components.GetOrCreate<Inventar>();
_resolver = new AttachmentSlotResolver(Renderer.GetAttachmentObject);
// Добавляем тестовые предметы (раскомментируйте для тестирования)
var clothingItem = new InventoryItem
{
Definition = ResourceLibrary.Get<ClothingItemDefinition>("Items/Cloth/cloth_pijama.clitem")
};
Inventory.AddItem(clothingItem);
var weaponItem = new InventoryItem
{
Definition = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol_test.weapon")
};
Inventory.AddItem(weaponItem);
var ammoItem = new InventoryItem
{
Definition = ResourceLibrary.Get<AmmoItemDefinition>("Items/pistol_ammo.inv")
};
ammoItem.Count = 30;
Inventory.AddItem(ammoItem);
Inventory.OnEquipped += OnItemEquipped;
Inventory.OnUnEquipped += OnItemUnEquipped;
Inventory.OnItemAdded += OnItemAdded;
Inventory.OnItemRemoved += OnItemRemoved;
}
private void OnItemEquipped(InventoryItem item)
{
// Очищаем кэши при экипировке предмета
_useableCache.Clear();
_resolver?.ClearCache();
if (item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid())
{
var go = weaponDef.Prefab.Clone();
AnimationHelper.HoldType = weaponDef.HoldType;
switch (weaponDef.Slot)
{
case Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.RightHand:
go.Parent = Renderer.GetAttachmentObject("hold_R");
break;
case Inventar.InventorySlot.LeftHand:
go.Parent = Renderer.GetAttachmentObject("hold_L");
break;
default:
go.Parent = Renderer.GetAttachmentObject("forward_reference_modelspace");
break;
}
go.LocalPosition = weaponDef.WeaponDefinition.Position;
go.LocalRotation = weaponDef.WeaponDefinition.Rotation;
go.LocalScale = weaponDef.WeaponDefinition.Scale;
if (go.Components.TryGet<UseableBase>(out var useable))
{
useable.Equipped = true;
}
go.NetworkSpawn();
var hand = weaponDef.Slot switch
{
Inventar.InventorySlot.LeftHand => CitizenAnimationHelper.Hand.Left,
Inventar.InventorySlot.RightHand => CitizenAnimationHelper.Hand.Right,
Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand => CitizenAnimationHelper.Hand.Both,
_ => CitizenAnimationHelper.Hand.Both
};
AnimationHelper.Handedness = hand;
RpcSetHoldAnimation(weaponDef.HoldType, hand);
InAds = true;
}
else if (item?.Definition is ClothingItemDefinition clothingDef)
{
WearWorkshop(new List<string>() { clothingDef.ClothUrl });
}
}
private void OnItemUnEquipped(InventoryItem item)
{
// Очищаем кэши при снятии предмета
_useableCache.Clear();
_resolver?.ClearCache();
if (item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid())
{
switch (weaponDef.Slot)
{
case Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.LeftHand:
var attachmentName = !weaponDef.Slot.HasFlag(Inventar.InventorySlot.RightHand)
? "hold_L"
: "hold_R";
Renderer.GetAttachmentObject(attachmentName).Children.ForEach(child => child.Destroy());
RpcSetHoldAnimation(CitizenAnimationHelper.HoldTypes.None, CitizenAnimationHelper.Hand.Both);
break;
default:
Renderer.GetAttachmentObject("forward_reference_modelspace").Children
.ForEach(child => child.Destroy());
break;
}
InAds = false;
}
else if (item?.Definition is ClothingItemDefinition clothingDef)
{
StripByName(clothingDef.Description);
}
}
private void OnItemAdded(InventoryItem item)
{
// Очищаем кэши при добавлении предмета
_useableCache.Clear();
_resolver?.ClearCache();
}
private void OnItemRemoved(InventoryItem item)
{
// Очищаем кэши при удалении предмета
_useableCache.Clear();
_resolver?.ClearCache();
}
[Rpc.Broadcast]
public void RpcSetHoldAnimation(CitizenAnimationHelper.HoldTypes HoldType, CitizenAnimationHelper.Hand hand)
{
AnimationHelper.HoldType = HoldType;
AnimationHelper.Handedness = hand;
}
void InventoryUpdate()
{
if (!Network.IsOwner) return;
if (Input.Pressed("Attack1"))
{
if (UseSystem.TryUse(this))
{
Attack();
}
}
}
public IEnumerable<IUseable> GetUsables()
{
// Кэшируем слоты для избежания повторного создания массива
var slots = new[] { Inventar.InventorySlot.LeftHand, Inventar.InventorySlot.RightHand };
foreach (var slot in slots)
{
if (!Inventory.EquippedItems.TryGetValue(slot, out var item))
{
continue;
}
var holder = _resolver.GetSlotObject(slot);
if (holder == null) continue;
var heldObject = holder.Children.FirstOrDefault();
if (heldObject == null)
{
continue;
}
// Проверяем кэш
if (_useableCache.TryGetValue(slot, out var cached) && cached.obj == heldObject)
{
if (cached.useable != null)
yield return cached.useable;
}
else
{
var useable = heldObject.Components.Get<IUseable>();
_useableCache[slot] = (heldObject, useable);
if (useable != null)
yield return useable;
}
}
}
[Rpc.Broadcast]
void Attack()
{
Renderer.Set("b_attack", true);
}
}
// if ( !Network.IsOwner ) return;
//
// InAds = Input.Down( "Attack2" );
//
// if ( Input.Pressed( "Attack1" ) && _weapon != null )
// {
// _weapon.Attack();
// Attack();
// }
// }
//