Refactored weapon equipment system

This commit is contained in:
Marco 2025-05-02 15:49:25 +02:00
commit 1a403d163a
10 changed files with 164 additions and 73 deletions

View file

@ -1,6 +1,7 @@
using System;
using System.Linq;
using Cirno.Scripts.Resources;
using Cirno.Scripts.Utils;
using Godot;
using Godot.Collections;
@ -10,7 +11,28 @@ public partial class PlayerWeaponProvider : Node2D
{
[Export] public PackedScene WeaponTemplate { get; private set; }
public Array<Weapon> EquippedWeapons { get; set; } = [];
public int CurrentWeaponIndex { get; set; } = 0;
private int _currentWeaponIndex = 0;
private int CurrentWeaponIndex
{
get => Math.Clamp(_currentWeaponIndex, 0, EquippedWeapons.Count -1);
set
{
if (value > EquippedWeapons.Count)
{
_currentWeaponIndex = 0;
}
if (value < 0)
{
_currentWeaponIndex = EquippedWeapons.Count - 1;
}
_currentWeaponIndex = value;
}
}
private InventoryManager _inventoryManager;
@ -18,78 +40,73 @@ public partial class PlayerWeaponProvider : Node2D
private CharacterBody2D _parent;
//public Vector2 FacingDirection
public override void _Ready()
{
}
public void Init(CharacterBody2D parent)
{
_parent = parent;
_inventoryManager = this.GetInventoryManager();
_inventoryManager.WeaponEquip += this.EquipWeapon;
_inventoryManager.WeaponEquip += this.OnInventoryWeaponEquipped;
_inventoryManager.ItemAdded += (LootItem item, int amount) =>
{
if (item.Item == ItemTypes.Weapon)
{
SpawnPlayerWeapon(item);
}
};
_inventoryManager.ItemAdded += OnInventoryWeaponAdded;
}
private void OnInventoryWeaponEquipped(string itemKey)
{
Equip(itemKey, true);
}
private void OnInventoryWeaponAdded(LootItem item, int amount)
{
if (item.Item is not ItemTypes.Weapon) return;
Equip(item, false);
}
private void EquipStartupWeapon()
{
if (EquippedWeapon is not null) return;
if (!string.IsNullOrWhiteSpace(GlobalState.Session.EquippedWeaponId))
{
// equip it
Equip(GlobalState.Session.EquippedWeaponId, false);
}
else
{
// Try to equip whatever is first
var weaponData = InventoryManager.Instance.Items.FirstOrDefault(x => x.Item.Item is ItemTypes.Weapon);
if (weaponData is null) return;
Equip(weaponData.Item.ItemKey, false);
}
}
// This is a soft equip
public void AddWeapon(Weapon weapon)
{
EquippedWeapons.Add(weapon);
}
public void EquipWeapon(string itemKey)
{
if (string.IsNullOrWhiteSpace(itemKey)) return;
var weapon = EquippedWeapons.FirstOrDefault(x => x.WeaponData.ItemKey == itemKey);
if (weapon is null)
{
// Spawn a weapon
InventoryManager.Instance.TryGetItem(itemKey, out var item);
SpawnPlayerWeapon(item.Item);
return;
};
EquipWeapon(weapon);
}
// Triggered by event in inventorymanager
public void EquipWeapon(Weapon weapon)
private void EquipWeapon(Weapon weapon)
{
EquippedWeapon = weapon;
CurrentWeaponIndex = EquippedWeapons.IndexOf(weapon);
GlobalState.Session.EquippedWeaponId = weapon.WeaponData.ItemKey;
}
public void NextWeapon()
{
CurrentWeaponIndex += 1;
if (CurrentWeaponIndex > EquippedWeapons.Count - 1)
{
CurrentWeaponIndex = EquippedWeapons.Count - 1;
}
EquipWeapon(EquippedWeapons[CurrentWeaponIndex]);
Equip(EquippedWeapons[CurrentWeaponIndex], true);
}
public void PreviousWeapon()
{
CurrentWeaponIndex -= 1;
if (CurrentWeaponIndex < 0)
{
CurrentWeaponIndex = 0;
}
EquipWeapon(EquippedWeapons[CurrentWeaponIndex]);
Equip(EquippedWeapons[CurrentWeaponIndex], true);
}
public void Shoot(Vector2 direction)
@ -100,23 +117,83 @@ public partial class PlayerWeaponProvider : Node2D
EquippedWeapon.Shoot();
}
private void SpawnPlayerWeapon(LootItem startingItem)
// Remastered method
private LootItem GetItemFromInventory(string itemKey)
{
return InventoryManager.Instance.Items.FirstOrDefault(x => x.Item.ItemKey == itemKey)?.Item;
}
private Weapon GetWeaponFromLocal(string itemKey)
{
return EquippedWeapons.FirstOrDefault(x => x.WeaponData.ItemKey == itemKey);
}
// Remastered method
private Weapon SpawnWeapon(string itemKey)
{
return SpawnWeapon(GetItemFromInventory(itemKey));
}
// Remastered method
private Weapon SpawnWeapon(LootItem startingItem)
{
if (WeaponTemplate == null)
{
GD.Print("Could not spawn weapon because template is null");
return;
return null;
}
// Check if it's not spawned already
var maybeExistingWeapon = GetWeaponFromLocal(startingItem.ItemKey);
if (maybeExistingWeapon is not null) return maybeExistingWeapon;
var weapon = this.CreateSibling<Weapon>(WeaponTemplate);
weapon.WeaponData = startingItem.WeaponData;
this.AddWeapon(weapon);
if (this.EquippedWeapon == null)
{
this.EquipWeapon(weapon);
}
return weapon;
}
public Weapon Equip(LootItem item, bool force)
{
var maybeExistingWeapon = GetWeaponFromLocal(item.ItemKey);
if (maybeExistingWeapon is not null) return Equip(maybeExistingWeapon, force);
// Spawn if not present
var spawnedWeapon = SpawnWeapon(item);
return Equip(spawnedWeapon, force);
}
public Weapon Equip(string itemKey, bool force)
{
// Check in local inventory first
var maybeExistingWeapon = GetWeaponFromLocal(itemKey);
if (maybeExistingWeapon is not null) return Equip(maybeExistingWeapon, force);
// Spawn if not present
var spawnedWeapon = SpawnWeapon(itemKey);
return Equip(spawnedWeapon, force);
}
public Weapon Equip(Weapon weapon, bool force)
{
// When we get here we already have a spawned weapon and it's in the list
// Always equip it if there's nothing equipped
if (this.EquippedWeapon is null)
{
this.EquipWeapon(weapon);
return weapon;
}
// If it's a soft equip check for priority
if (!force && this.EquippedWeapon.WeaponData.Priority < weapon.WeaponData.Priority)
{
this.EquipWeapon(weapon);
return weapon;
}
EquipWeapon(weapon);
return weapon;
}
}