This commit is contained in:
Oscar
2025-06-28 18:13:47 +03:00
parent 875d594038
commit 23a35fe3cd
23 changed files with 2579 additions and 607 deletions

View File

@@ -19,7 +19,7 @@ public class WeaponItemDefinition : BaseItemDefinition, IEquipable
public float Damage { get; set; } = 10f;
[Property, Category( "Weapon Properties" )]
public float FireRate { get; set; } = 1f;
public float FireRate { get; set; } = 10f; // Выстрелов в секунду
[Property, Category( "Weapon Properties" )]
public float Range { get; set; } = 1000f;
@@ -30,6 +30,15 @@ public class WeaponItemDefinition : BaseItemDefinition, IEquipable
[Property, Category( "Weapon Properties" )]
public string AmmoType { get; set; } = "Pistol";
[Property, Category( "Weapon Properties" )]
public float ReloadTime { get; set; } = 2f;
[Property, Category( "Weapon Properties" )]
public float Spread { get; set; } = 0.02f; // Разброс при стрельбе
[Property, Category( "Weapon Properties" )]
public bool IsAutomatic { get; set; } = true; // Всегда автоматический режим
public override Inventar.InventorySlot? GetSlot() => Slot;
public override ItemCategory Category => ItemCategory.Weapon;

View File

@@ -65,36 +65,37 @@ public class Inventar : Component
/// <summary>
/// Добавляет предмет в инвентарь, распределяя по существующим и новым стекам. Возвращает остаток, который не удалось добавить (или 0, если всё добавлено).
/// </summary>
public int AddItem(InventoryItem item)
public int AddItem( InventoryItem item )
{
if (item == null || item.Definition == null || item.Count <= 0)
if ( item == null || item.Definition == null || item.Count <= 0 )
return item.Count;
int toAdd = item.Count;
// 1. Заполняем существующие стаки
foreach (var stack in Items.Where(x => x.Definition == item.Definition && x.Count < x.Definition.MaxCount))
foreach ( var stack in Items.Where( x => x.Definition == item.Definition && x.Count < x.Definition.MaxCount ) )
{
int canAdd = Math.Min(toAdd, stack.Definition.MaxCount - stack.Count);
if (canAdd > 0)
int canAdd = Math.Min( toAdd, stack.Definition.MaxCount - stack.Count );
if ( canAdd > 0 )
{
stack.Count += canAdd;
toAdd -= canAdd;
OnChanged?.Invoke();
OnItemAdded?.Invoke(stack);
OnItemAdded?.Invoke( stack );
}
if (toAdd <= 0) return 0;
if ( toAdd <= 0 ) return 0;
}
// 2. Добавляем новые стаки, если есть место
while (toAdd > 0 && (UnlimitedSlots || Items.Count < MaxInventorySlots))
while ( toAdd > 0 && (UnlimitedSlots || Items.Count < MaxInventorySlots) )
{
int stackCount = Math.Min(toAdd, item.Definition.MaxCount);
int stackCount = Math.Min( toAdd, item.Definition.MaxCount );
var newStack = new InventoryItem { Definition = item.Definition, Count = stackCount };
Items.Add(newStack);
Items.Add( newStack );
toAdd -= stackCount;
OnChanged?.Invoke();
OnItemAdded?.Invoke(newStack);
OnItemAdded?.Invoke( newStack );
}
// 3. Возвращаем остаток, если не всё удалось добавить
@@ -149,6 +150,7 @@ public class Inventar : Component
// Экипировать новый предмет
EquippedItems[slot.Value] = item;
item.Equipped = true;
item.OnEquipped();
OnEquipped?.Invoke( item );
OnChanged?.Invoke();
return true;
@@ -159,23 +161,23 @@ public class Inventar : Component
if ( item == null || !Items.Contains( item ) )
return;
// Создаем копию предмета для выбрасывания
var droppedItem = new InventoryItem
{
Definition = item.Definition,
Count = item.Count // Выбрасываем всю стопку
};
// // Создаем копию предмета для выбрасывания
// var droppedItem = new InventoryItem
// {
// Definition = item.Definition,
// Count = item.Count // Выбрасываем всю стопку
// };
GameObject gO = item.Definition.Prefab.Clone( position );
if ( gO.Components.TryGet<InventoryItem>( out var inventoryItem ) )
{
inventoryItem.Count = droppedItem.Count;
inventoryItem.Definition = droppedItem.Definition;
inventoryItem.Count = item.Count;
inventoryItem.Definition = item.Definition;
}
gO.NetworkSpawn();
// Удаляем весь предмет из инвентаря
RemoveItem( item, item.Count );
}
@@ -191,6 +193,7 @@ public class Inventar : Component
{
EquippedItems.Remove( slotToRemove );
item.Equipped = false;
item.OnUnEquipped();
OnUnEquipped?.Invoke( item );
OnChanged?.Invoke();
}
@@ -240,7 +243,7 @@ public class Inventar : Component
{
if ( UnlimitedSlots )
return int.MaxValue;
return Math.Max( 0, MaxInventorySlots - Items.Count );
}
@@ -248,7 +251,7 @@ public class Inventar : Component
{
if ( UnlimitedSlots )
return false;
return Items.Count >= MaxInventorySlots;
}
@@ -256,7 +259,7 @@ public class Inventar : Component
{
if ( UnlimitedSlots )
return 0f;
return (float)Items.Count / MaxInventorySlots * 100f;
}
}

View File

@@ -13,7 +13,18 @@ public class InventoryItem : Component
{
if ( GameObject.Components.TryGet<PickupItem>( out var item ) )
{
item.Label = Definition?.Name ?? "Unknown Item";
string itemName = Definition?.Name;
if ( string.IsNullOrEmpty( itemName ) )
{
item.Label = "Unknown Item";
}
else
{
item.Label = Count > 1
? $"{itemName} x{Count}"
: itemName;
}
}
}
@@ -58,6 +69,22 @@ public class InventoryItem : Component
return clone;
}
/// <summary>
/// Виртуальный метод для экипировки предмета
/// </summary>
public virtual void OnEquipped()
{
Equipped = true;
}
/// <summary>
/// Виртуальный метод для снятия предмета
/// </summary>
public virtual void OnUnEquipped()
{
Equipped = false;
}
public override string ToString()
{
return $"{Definition?.Name ?? "Unknown"} x{Count}";

View File

@@ -1,85 +1,14 @@
namespace Sasalka;
/// <summary>
/// Базовый класс для предметов, которые используют патроны
/// Теперь используется только для совместимости со старой системой
/// </summary>
public abstract class AmmoUseableBase : UseableBase
{
private WeaponItemDefinition _cachedWeaponDef;
private InventoryItem _cachedAmmoItem;
protected InventoryItem AmmoItem => FindAmmoItem();
private InventoryItem FindAmmoItem()
protected override void OnUse()
{
var player = Dedugan.Local;
if (player?.Inventory == null)
{
return null;
}
// Кэшируем WeaponDefinition для избежания повторных вызовов
if (_cachedWeaponDef == null)
{
_cachedWeaponDef = GetWeaponDefinition();
if (_cachedWeaponDef == null)
{
return null;
}
}
// Проверяем кэшированный результат
if (_cachedAmmoItem != null && _cachedAmmoItem.Count > 0)
{
return _cachedAmmoItem;
}
// Ищем патроны
foreach (var item in player.Inventory.Items)
{
if (item.Definition is AmmoItemDefinition ammoDef && ammoDef.IsCompatibleWith(_cachedWeaponDef.AmmoType))
{
_cachedAmmoItem = item;
return item;
}
}
_cachedAmmoItem = null;
return null;
}
protected virtual WeaponItemDefinition GetWeaponDefinition()
{
// Переопределите в наследниках для возврата определения оружия
return null;
}
public override bool CanUse()
{
var ammo = AmmoItem;
var baseCanUse = base.CanUse();
var hasAmmo = ammo != null && ammo.Count > 0;
return baseCanUse && hasAmmo;
}
public override void Use()
{
if (!CanUse())
return;
OnUse();
var ammo = AmmoItem;
if (ammo != null)
{
// Уменьшаем количество патронов
if (ammo.TryRemoveCount(1))
{
// Если патроны закончились, удаляем предмет из инвентаря
if (ammo.Count <= 0)
{
Dedugan.Local.Inventory.RemoveItem(ammo);
_cachedAmmoItem = null; // Очищаем кэш
}
}
}
// Базовая реализация - ничего не делает
// Логика использования патронов теперь в BaseWeapon
}
}

View File

@@ -18,7 +18,9 @@ public sealed class PickupItem : InteractionButton
// Устанавливаем правильную метку для предмета
if ( GameObject.Components.TryGet<InventoryItem>( out var inventoryItem ) )
{
Label = inventoryItem.Definition?.Name ?? "Подобрать";
Label = inventoryItem.Definition?.Name != ""
? $"{inventoryItem.Definition.Name} x{inventoryItem.Count}"
: "Подобрать";
}
}