using Sandbox.Citizen; using Sandbox.Weapons; using Sasalka; public sealed partial class Dedugan : Component { [Property] public Inventar Inventory { get; private set; } private Dictionary _useableCache = new(); [Sync] private bool InAds { get; set; } = false; private AttachmentSlotResolver _resolver; void InventoryStart() { if (!Network.IsOwner) return; // Создаем инвентарь как компонент Inventory = GameObject.Components.GetOrCreate(); _resolver = new AttachmentSlotResolver(Renderer.GetAttachmentObject); // Добавляем тестовые предметы (раскомментируйте для тестирования) var clothingItem = new InventoryItem { Definition = ResourceLibrary.Get("Items/Cloth/cloth_pijama.clitem") }; Inventory.AddItem(clothingItem); var weaponItem = new InventoryItem { Definition = ResourceLibrary.Get("Items/pistol_test.weapon") }; Inventory.AddItem(weaponItem); var ammoItem = new InventoryItem { Definition = ResourceLibrary.Get("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(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() { 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 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(); _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(); // } // } //