upd
This commit is contained in:
22
Code/Inventory/AttachmentSlotResolver.cs
Normal file
22
Code/Inventory/AttachmentSlotResolver.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public class AttachmentSlotResolver
|
||||
{
|
||||
private readonly Func<string, GameObject> _attachmentGetter;
|
||||
|
||||
public AttachmentSlotResolver( Func<string, GameObject> attachmentGetter )
|
||||
{
|
||||
_attachmentGetter = attachmentGetter;
|
||||
}
|
||||
|
||||
public GameObject GetSlotObject( Inventar.InventorySlot slot )
|
||||
{
|
||||
return slot switch
|
||||
{
|
||||
Inventar.InventorySlot.LeftHand => _attachmentGetter.Invoke( "hold_L" ),
|
||||
Inventar.InventorySlot.RightHand => _attachmentGetter.Invoke( "hold_R" ),
|
||||
Inventar.InventorySlot.Body => _attachmentGetter.Invoke( "forward_reference_modelspace" ),
|
||||
_ => _attachmentGetter.Invoke( "forward_reference_modelspace" )
|
||||
};
|
||||
}
|
||||
}
|
||||
69
Code/Inventory/Inventar.cs
Normal file
69
Code/Inventory/Inventar.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public class Inventar
|
||||
{
|
||||
[Flags]
|
||||
public enum InventorySlot
|
||||
{
|
||||
None = 0,
|
||||
LeftHand = 1 << 0, // 1
|
||||
RightHand = 1 << 1, // 2
|
||||
Head = 1 << 2, // 4
|
||||
Body = 1 << 3, // 8
|
||||
Hands = 1 << 4, // 16
|
||||
Bottom = 1 << 5, // 32
|
||||
Feet = 1 << 6 // 64
|
||||
}
|
||||
|
||||
public List<InventoryItem> Items { get; private set; } = new();
|
||||
public static bool IsInventoryOpen = false;
|
||||
|
||||
// public Dictionary<InventorySlot, EquippedItem> EquippedItems { get; private set; } = new();
|
||||
public Dictionary<InventorySlot, InventoryItem> EquippedItems { get; private set; } = new();
|
||||
|
||||
public event Action OnChanged;
|
||||
public event Action<InventoryItem> OnEquipped;
|
||||
public event Action<InventoryItem> OnUnEquipped;
|
||||
|
||||
// public class EquippedItem
|
||||
// {
|
||||
// public InventoryItem Item { get; set; }
|
||||
// public GameObject SpawnedObject { get; set; }
|
||||
// }
|
||||
|
||||
public void AddItem( InventoryItem item )
|
||||
{
|
||||
Items.Add( item );
|
||||
OnChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void RemoveItem( InventoryItem item )
|
||||
{
|
||||
UnEquipItem( item );
|
||||
Items.Remove( item );
|
||||
OnChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void EquipItem( InventoryItem item )
|
||||
{
|
||||
if ( EquippedItems.ContainsValue( item ) )
|
||||
{
|
||||
UnEquipItem( item );
|
||||
}
|
||||
else
|
||||
{
|
||||
EquippedItems.Add( item.Definition.Slot, item );
|
||||
OnEquipped?.Invoke( item );
|
||||
}
|
||||
}
|
||||
|
||||
public void UnEquipItem( InventoryItem item )
|
||||
{
|
||||
foreach ( var kvp in EquippedItems.Where( kvp => kvp.Value == item ).ToList() )
|
||||
{
|
||||
EquippedItems.Remove( kvp.Key );
|
||||
}
|
||||
|
||||
OnUnEquipped?.Invoke( item );
|
||||
}
|
||||
}
|
||||
15
Code/Inventory/InventoryItem.cs
Normal file
15
Code/Inventory/InventoryItem.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Sandbox;
|
||||
|
||||
namespace Sasalka;
|
||||
|
||||
public class InventoryItem : Component
|
||||
{
|
||||
public InventoryItemDefinition Definition { get; set; }
|
||||
|
||||
public int Count { get; set; } = 1;
|
||||
public int MaxCount { get; set; } = 1;
|
||||
|
||||
// public GameObject SpawnedObject { get; set; }
|
||||
}
|
||||
// public int Count { get; set; } = 1;
|
||||
// public int MaxCount { get; set; } = 1;
|
||||
9
Code/Inventory/InventoryItemCountable.cs
Normal file
9
Code/Inventory/InventoryItemCountable.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Sandbox;
|
||||
|
||||
namespace Sasalka;
|
||||
|
||||
public class InventoryItemCountable : InventoryItem
|
||||
{
|
||||
// public int Count { get; set; } = 1;
|
||||
// public int MaxCount { get; set; } = 1;
|
||||
}
|
||||
30
Code/Inventory/InventoryItemDefinition.cs
Normal file
30
Code/Inventory/InventoryItemDefinition.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Sandbox.Citizen;
|
||||
|
||||
namespace Sasalka;
|
||||
|
||||
[GameResource( "Inventory Item Definition", "inv", "", Category = "Sasalka", Icon = "inventory_2" )]
|
||||
public class InventoryItemDefinition : GameResource
|
||||
{
|
||||
public Inventar.InventorySlot Slot { get; set; }
|
||||
|
||||
public CitizenAnimationHelper.HoldTypes HoldType { get; set; } = CitizenAnimationHelper.HoldTypes.None;
|
||||
|
||||
public Texture ImageTexture { get; set; }
|
||||
|
||||
public string ImageUrl { get; set; }
|
||||
public string ClothUrl { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
[ResourceType( "prefab" )] public GameObject Prefab { get; set; }
|
||||
|
||||
[InlineEditor, Space] public WeaponDefinition WeaponDefinition { get; set; }
|
||||
}
|
||||
|
||||
public struct WeaponDefinition
|
||||
{
|
||||
// public CitizenAnimationHelper.Hand Hand { get; set; }
|
||||
public Vector3 Position { get; set; }
|
||||
public Rotation Rotation { get; set; }
|
||||
}
|
||||
43
Code/Inventory/Ui/Inventory.razor
Normal file
43
Code/Inventory/Ui/Inventory.razor
Normal file
@@ -0,0 +1,43 @@
|
||||
@using Sasalka
|
||||
@inherits PanelComponent
|
||||
@namespace Sasalka.Ui
|
||||
|
||||
<root class="@( Inventar.IsInventoryOpen ? "" : "hidden" )">
|
||||
<div class="inventory-panel">
|
||||
@foreach ( var item in PlayerInventory.Items )
|
||||
{
|
||||
<Sasalka.Ui.InventoryItem Item="@item" OnItemClick="@( UseItem )"/>
|
||||
}
|
||||
</div>
|
||||
</root>
|
||||
|
||||
@code {
|
||||
Dedugan Player => Dedugan.Local;
|
||||
Inventar PlayerInventory => Player?.Inventory;
|
||||
|
||||
|
||||
void UseItem( Sasalka.InventoryItem item )
|
||||
{
|
||||
Player?.Inventory?.EquipItem( item );
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if ( Input.Pressed( "Score" ) )
|
||||
{
|
||||
Inventar.IsInventoryOpen = !Inventar.IsInventoryOpen;
|
||||
}
|
||||
}
|
||||
|
||||
protected override int BuildHash()
|
||||
{
|
||||
if ( !Inventar.IsInventoryOpen || PlayerInventory == null )
|
||||
return -1;
|
||||
|
||||
var hash = new HashCode();
|
||||
hash.Add( Inventar.IsInventoryOpen );
|
||||
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
|
||||
}
|
||||
34
Code/Inventory/Ui/Inventory.razor.scss
Normal file
34
Code/Inventory/Ui/Inventory.razor.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
Inventory {
|
||||
background: linear-gradient(135deg, #0a1a2b 0%, #08111f 100%);
|
||||
border: 3px solid #2a3d54;
|
||||
border-radius: 14px;
|
||||
font-family: 'Orbitron', 'Poppins', sans-serif;
|
||||
position: absolute;
|
||||
width: 30%;
|
||||
height: 96vh;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
transition: all 0.2s ease;
|
||||
z-index: 100;
|
||||
overflow: hidden;
|
||||
|
||||
pointer-events: all;
|
||||
|
||||
&.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.inventory-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
38
Code/Inventory/Ui/InventoryItem.razor
Normal file
38
Code/Inventory/Ui/InventoryItem.razor
Normal file
@@ -0,0 +1,38 @@
|
||||
@using Sandbox.UI
|
||||
@using Sasalka
|
||||
@inherits Sandbox.UI.Panel
|
||||
@namespace Sasalka.Ui
|
||||
|
||||
<root class="inventory-item @( Equipped ? "equipped" : "" )" @onclick="@(() => OnItemClick?.Invoke( Item ))">
|
||||
<input type="checkbox" class="equipped-checkbox" checked="@Equipped" disabled/>
|
||||
@if ( Item.Definition.ImageTexture.IsValid() )
|
||||
{
|
||||
<img src="@Item.Definition.ImageTexture.ResourcePath" alt="@Item.Definition.Name"/>
|
||||
}
|
||||
else if ( Item.Definition.ImageUrl.Length > 0 )
|
||||
{
|
||||
<img src="@Item.Definition.ImageUrl" alt="@Item.Definition.Name">
|
||||
}
|
||||
|
||||
<div class="inventory-item__name">@Item?.Definition.Name</div>
|
||||
|
||||
<div class="inventory-item__count">@Item?.Count / @Item?.MaxCount</div>
|
||||
</root>
|
||||
|
||||
@code {
|
||||
public Sasalka.InventoryItem Item { get; set; }
|
||||
public Action<Sasalka.InventoryItem> OnItemClick { get; set; }
|
||||
public bool Equipped { get; set; }
|
||||
|
||||
protected override int BuildHash()
|
||||
{
|
||||
base.BuildHash();
|
||||
|
||||
var hash = new HashCode();
|
||||
|
||||
hash.Add( Item.Count );
|
||||
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
|
||||
}
|
||||
41
Code/Inventory/Ui/InventoryItem.razor.scss
Normal file
41
Code/Inventory/Ui/InventoryItem.razor.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
InventoryItem {
|
||||
width: 100%;
|
||||
//height: 64px;
|
||||
background: #2a3d53;
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
border: 1px solid #666;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
border-radius: 12px;
|
||||
padding: 12px 24px;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: #444;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
&.name {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&.equipped {
|
||||
border: 2px solid #4caf50;
|
||||
background: #2e3e2e;
|
||||
}
|
||||
|
||||
.equipped-checkbox {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
pointer-events: none;
|
||||
accent-color: #4caf50;
|
||||
}
|
||||
}
|
||||
39
Code/Inventory/Usable/AmmoUseableBase.cs
Normal file
39
Code/Inventory/Usable/AmmoUseableBase.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public abstract class AmmoUseableBase : UseableBase
|
||||
{
|
||||
protected InventoryItem AmmoItem => FindAmmoItem();
|
||||
|
||||
private InventoryItem FindAmmoItem()
|
||||
{
|
||||
// var ammoDefinition = new InventoryItemDefinition();
|
||||
|
||||
return Dedugan.Local.Inventory.Items.FirstOrDefault( i => i.Definition.Name == "Pistol Ammo" );
|
||||
}
|
||||
|
||||
public override bool CanUse()
|
||||
{
|
||||
var ammo = AmmoItem;
|
||||
return base.CanUse() && ammo != null && ammo.Count > 0;
|
||||
}
|
||||
|
||||
public override void Use()
|
||||
{
|
||||
if ( !CanUse() )
|
||||
return;
|
||||
|
||||
OnUse();
|
||||
|
||||
var ammo = AmmoItem;
|
||||
if ( ammo != null )
|
||||
{
|
||||
ammo.Count--;
|
||||
Log.Info( $"[AmmoUseableBase] Ammo left: {ammo.Count}" );
|
||||
|
||||
if ( ammo.Count <= 0 )
|
||||
{
|
||||
Dedugan.Local.Inventory.RemoveItem( ammo );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
Code/Inventory/Usable/IUseContext.cs
Normal file
6
Code/Inventory/Usable/IUseContext.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public interface IUseContext
|
||||
{
|
||||
public IEnumerable<IUseable> GetUsables();
|
||||
}
|
||||
8
Code/Inventory/Usable/IUseable.cs
Normal file
8
Code/Inventory/Usable/IUseable.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public interface IUseable
|
||||
{
|
||||
public void Use();
|
||||
bool CanUse();
|
||||
float Cooldown { get; }
|
||||
}
|
||||
15
Code/Inventory/Usable/UseSystem.cs
Normal file
15
Code/Inventory/Usable/UseSystem.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Sasalka;
|
||||
|
||||
public static class UseSystem
|
||||
{
|
||||
public static void TryUse( IUseContext context )
|
||||
{
|
||||
foreach ( var useable in context.GetUsables() )
|
||||
{
|
||||
if ( useable.CanUse() )
|
||||
{
|
||||
useable.Use();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Code/Inventory/Usable/UseableBase.cs
Normal file
31
Code/Inventory/Usable/UseableBase.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Sandbox;
|
||||
|
||||
namespace Sasalka;
|
||||
|
||||
public abstract class UseableBase : Component, IUseable
|
||||
{
|
||||
[Property] public float Cooldown { get; set; } = 0.5f;
|
||||
|
||||
private TimeSince _timeSinceUsed;
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
_timeSinceUsed = Cooldown;
|
||||
}
|
||||
|
||||
public virtual bool CanUse()
|
||||
{
|
||||
return _timeSinceUsed >= Cooldown && !Inventar.IsInventoryOpen;
|
||||
}
|
||||
|
||||
public virtual void Use()
|
||||
{
|
||||
if ( !CanUse() )
|
||||
return;
|
||||
|
||||
OnUse();
|
||||
_timeSinceUsed = 0;
|
||||
}
|
||||
|
||||
protected abstract void OnUse();
|
||||
}
|
||||
Reference in New Issue
Block a user