This commit is contained in:
Oscar
2025-06-10 23:24:50 +03:00
parent de85b85b13
commit 5c9be94aba
24 changed files with 1187 additions and 580 deletions

View File

@@ -9,4 +9,6 @@ public class BaseItemDefinition : GameResource
[ResourceType( "prefab" )] public GameObject Prefab { get; set; }
public Texture ImageTexture { get; set; }
public string ImageUrl { get; set; }
public int MaxCount { get; set; } = 1;
}

View File

@@ -36,34 +36,50 @@ public class Inventar
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 EquipItem( InventoryItem item )
{
if ( item.Definition is not IEquipable equipable ) return;
if ( item.Definition is not IEquipable equipable )
return;
// Если уже экипирован этот же предмет — снять его
if ( EquippedItems.ContainsValue( item ) )
{
UnEquipItem( item );
return;
}
else
// Если на этом слоте уже что-то есть — снять старый предмет
if ( EquippedItems.TryGetValue( equipable.Slot, out var oldItem ) )
{
EquippedItems[equipable.Slot] = item;
OnEquipped?.Invoke( item );
UnEquipItem( oldItem );
// Вернуть снятый предмет обратно в инвентарь, если его там нет
if ( !Items.Contains( oldItem ) )
Items.Add( oldItem );
}
// Экипировать новый предмет
EquippedItems[equipable.Slot] = item;
OnEquipped?.Invoke( item );
}
public void DropItem( InventoryItem item, Vector3 position )
{
var gO = item.Definition.Prefab.Clone( position );
if ( gO.Components.TryGet<InventoryItem>( out var inventoryItem ) )
{
inventoryItem.Count = item.Count;
}
gO.NetworkSpawn( null );
RemoveItem( item );
// Items.Remove( item );
// OnChanged?.Invoke();
}
public void UnEquipItem( InventoryItem item )
{
foreach ( var kvp in EquippedItems.Where( kvp => kvp.Value == item ).ToList() )

View File

@@ -4,7 +4,6 @@ namespace Sasalka;
public class InventoryItem : Component
{
public BaseItemDefinition Definition { get; set; }
public int Count { get; set; } = 1;
public int MaxCount { get; set; } = 1;
[Property] public BaseItemDefinition Definition { get; set; }
[Property] public int Count { get; set; } = 1;
}

View File

@@ -4,9 +4,12 @@
<root class="@( Inventar.IsInventoryOpen ? "" : "hidden" )">
<div class="inventory-panel">
@foreach ( var item in PlayerInventory.Items )
@if ( PlayerInventory.Items.Count > 0 )
{
<Sasalka.Ui.InventoryItem Item="@item" OnItemClick="@( UseItem )"/>
@foreach ( var item in PlayerInventory.Items )
{
<Sasalka.Ui.InventoryItem Item="@item" OnItemClick="@( UseItem )" OnItemRightClick="@( DropItem )"/>
}
}
</div>
</root>
@@ -21,6 +24,11 @@
Player?.Inventory?.EquipItem( item );
}
void DropItem( Sasalka.InventoryItem item )
{
Player?.Inventory?.DropItem( item, Player.CameraPivot.WorldPosition + Player.Camera.LocalRotation.Right * 50 );
}
protected override void OnUpdate()
{
if ( Input.Pressed( "Score" ) )

View File

@@ -3,8 +3,10 @@
@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/>
<root class="inventory-item @( Equipped ? "equipped" : "" )" @onclick="@(() => OnItemClick?.Invoke( Item ))" @onrightclick=@( () => OnItemRightClick?.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"/>
@@ -16,12 +18,17 @@
<div class="inventory-item__name">@Item?.Definition.Name</div>
<div class="inventory-item__count">@Item?.Count / @Item?.MaxCount</div>
@if ( Item?.Definition.MaxCount > 1 )
{
<div class="inventory-item__count">@Item?.Count / @Item?.Definition.MaxCount</div>
}
</root>
@code {
public Sasalka.InventoryItem Item { get; set; }
public Action<Sasalka.InventoryItem> OnItemClick { get; set; }
public Action<Sasalka.InventoryItem> OnItemRightClick { get; set; }
public bool Equipped { get; set; }
protected override int BuildHash()

View File

@@ -6,8 +6,7 @@ public abstract class AmmoUseableBase : UseableBase
private InventoryItem FindAmmoItem()
{
// var ammoDefinition = new InventoryItemDefinition();
//По типу патрон поиск + енум типа патрон
return Dedugan.Local.Inventory.Items.FirstOrDefault( i => i.Definition.Name == "Pistol Ammo" );
}
@@ -28,7 +27,6 @@ public abstract class AmmoUseableBase : UseableBase
if ( ammo != null )
{
ammo.Count--;
Log.Info( $"[AmmoUseableBase] Ammo left: {ammo.Count}" );
if ( ammo.Count <= 0 )
{

View File

@@ -0,0 +1,29 @@
using Sandbox.Gravity;
using Sasalka;
namespace Sandbox.UI;
[Icon( "skip_next" )]
public sealed class PickupItem : InteractionButton
{
[Property] public override string Label { get; set; } = "E";
public override bool Press( IPressable.Event e )
{
base.Press( e );
if ( e.Source.Components.TryGet<Dedugan>( out var dedugan ) )
{
dedugan.Inventory.AddItem( Components.Get<InventoryItem>() );
RpcDestroy();
}
return true;
}
[Rpc.Broadcast]
void RpcDestroy()
{
GameObject.Destroy();
}
}

View File

@@ -2,14 +2,17 @@
public static class UseSystem
{
public static void TryUse( IUseContext context )
public static bool TryUse( IUseContext context )
{
foreach ( var useable in context.GetUsables() )
{
if ( useable.CanUse() )
{
useable.Use();
return true;
}
}
return false;
}
}

View File

@@ -6,11 +6,38 @@ public abstract class UseableBase : Component, IUseable
{
[Property] public float Cooldown { get; set; } = 0.5f;
private TimeSince _timeSinceUsed;
private bool _equipped;
protected override void OnStart()
[Property]
public bool Equipped
{
get => _equipped;
set
{
if ( _equipped != value )
{
_equipped = value;
if ( _equipped )
{
OnEquip?.Invoke();
}
}
}
}
private TimeSince _timeSinceUsed;
public Action OnEquip { get; set; }
protected override void OnAwake()
{
_timeSinceUsed = Cooldown;
OnEquip += OnEquipped;
}
public virtual void OnEquipped()
{
Log.Info( $"OnEquip {this}" );
}
public virtual bool CanUse()