mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-01 11:15:33 +00:00
286 lines
No EOL
7.8 KiB
C#
286 lines
No EOL
7.8 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Cirno.Scripts.Resources;
|
|
using Cirno.Scripts.Weapons;
|
|
using Godot;
|
|
using Godot.Collections;
|
|
|
|
namespace Cirno.Scripts.Components.FSM._3DPlayer;
|
|
|
|
public partial class PlayerWeaponProvider3D : Node
|
|
{
|
|
[Export] public IsoPlayerStorageModule StorageModule { get; set; }
|
|
[Export] public PackedScene WeaponTemplate { get; private set; }
|
|
|
|
[Export] public double WeaponSwitchCooldown { get; private set; } = 0.5d;
|
|
|
|
[Export] public Marker3D WeaponRightOffset { get; private set; } // local offset when facing right
|
|
[Export] public Marker3D WeaponLeftOffset { get; private set; } // local offset when facing left
|
|
|
|
public Array<Weapon3D> EquippedWeapons { get; set; } = [];
|
|
|
|
private int _currentWeaponIndex = 0;
|
|
|
|
private double _switchCooldown = 0d;
|
|
private bool _switching = false;
|
|
|
|
private int CurrentWeaponIndex
|
|
{
|
|
get => Math.Clamp(_currentWeaponIndex, 0, EquippedWeapons.Count -1);
|
|
|
|
set
|
|
{
|
|
if (value > EquippedWeapons.Count - 1)
|
|
{
|
|
_currentWeaponIndex = 0;
|
|
return;
|
|
}
|
|
|
|
if (value < 0)
|
|
{
|
|
_currentWeaponIndex = EquippedWeapons.Count - 1;
|
|
return;
|
|
}
|
|
|
|
_currentWeaponIndex = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public Weapon3D EquippedWeapon { get; set; }
|
|
|
|
private CharacterBody3D _parent;
|
|
|
|
public void Init(CharacterBody3D parent)
|
|
{
|
|
_parent = parent;
|
|
|
|
InventoryManager.Instance.WeaponEquip += this.OnInventoryWeaponEquipped;
|
|
|
|
InventoryManager.Instance.ItemAdded += OnInventoryWeaponAdded;
|
|
|
|
EquipStartupWeapon();
|
|
}
|
|
|
|
public void Update(double delta)
|
|
{
|
|
RotateWeapon();
|
|
|
|
if (!_switching) return;
|
|
_switchCooldown += delta;
|
|
if (_switchCooldown >= WeaponSwitchCooldown)
|
|
{
|
|
_switching = false;
|
|
_switchCooldown = 0d;
|
|
}
|
|
}
|
|
|
|
private void RotateWeapon()
|
|
{
|
|
if (EquippedWeapon is null) return;
|
|
|
|
//EquippedWeapon.RotateWeapon(StorageModule.FacingDirection, WeaponLeftOffset.Position, WeaponRightOffset.Position);
|
|
|
|
|
|
|
|
// EquippedWeapon.SetRotation(angle + Mathf.Pi / 2.0f);
|
|
//
|
|
//
|
|
//
|
|
// EquippedWeapon.FlipH = facingLeft;
|
|
//
|
|
// // 3. Position on correct side (assuming EquippedWeapon is a child of the Player node)
|
|
// EquippedWeapon.Position = facingLeft ? WeaponLeftOffset : WeaponRightOffset;
|
|
}
|
|
|
|
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(Weapon3D weapon)
|
|
{
|
|
EquippedWeapons.Add(weapon);
|
|
}
|
|
|
|
// Triggered by event in inventorymanager
|
|
private void EquipWeapon(Weapon3D weapon)
|
|
{
|
|
if (EquippedWeapon == weapon)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Need to start cooldown
|
|
EquippedWeapon?.Hide();
|
|
|
|
EquippedWeapon = weapon;
|
|
CurrentWeaponIndex = EquippedWeapons.IndexOf(weapon);
|
|
GlobalState.Session.EquippedWeaponId = weapon.WeaponData.ItemKey;
|
|
|
|
EquippedWeapon.Show();
|
|
|
|
_switching = true;
|
|
_switchCooldown = 0d;
|
|
|
|
InventoryManager.Instance.UpdateEquippedWeapon(weapon.WeaponData.ItemKey);
|
|
}
|
|
|
|
public void NextWeapon()
|
|
{
|
|
CurrentWeaponIndex += 1;
|
|
|
|
Equip(EquippedWeapons[CurrentWeaponIndex], true);
|
|
}
|
|
|
|
public void PreviousWeapon()
|
|
{
|
|
CurrentWeaponIndex -= 1;
|
|
|
|
Equip(EquippedWeapons[CurrentWeaponIndex], true);
|
|
}
|
|
|
|
public void Shoot(Vector2 direction)
|
|
{
|
|
if (EquippedWeapon == null) return;
|
|
if (_switching) return;
|
|
|
|
EquippedWeapon.ShootDirection = direction;
|
|
EquippedWeapon.Shoot();
|
|
}
|
|
|
|
public void Reload()
|
|
{
|
|
if (EquippedWeapon == null) return;
|
|
if (_switching) return;
|
|
|
|
EquippedWeapon.Reload();
|
|
}
|
|
|
|
// Remastered method
|
|
private LootItem GetItemFromInventory(string itemKey)
|
|
{
|
|
return InventoryManager.Instance.Items.FirstOrDefault(x => x.Item.ItemKey == itemKey)?.Item;
|
|
}
|
|
|
|
private Weapon3D GetWeaponFromLocal(string itemKey)
|
|
{
|
|
return EquippedWeapons.FirstOrDefault(x => x.WeaponData.ItemKey == itemKey);
|
|
}
|
|
|
|
// Remastered method
|
|
private Weapon3D SpawnWeapon(string itemKey)
|
|
{
|
|
return SpawnWeapon(GetItemFromInventory(itemKey));
|
|
}
|
|
|
|
// Remastered method
|
|
private Weapon3D SpawnWeapon(LootItem startingItem)
|
|
{
|
|
if (startingItem is null)
|
|
{
|
|
GD.Print($"Could not spawn weapon was not in the inventory.");
|
|
return null;
|
|
}
|
|
|
|
if (WeaponTemplate == null)
|
|
{
|
|
GD.Print("Could not spawn weapon because template is null");
|
|
return null;
|
|
}
|
|
|
|
// Check if it's not spawned already
|
|
var maybeExistingWeapon = GetWeaponFromLocal(startingItem.ItemKey);
|
|
if (maybeExistingWeapon is not null) return maybeExistingWeapon;
|
|
|
|
var weapon = WeaponTemplate.Instantiate<Weapon3D>();
|
|
this.AddChild(weapon);
|
|
//this.CreateSibling<Weapon>(WeaponTemplate);
|
|
weapon.WeaponData = startingItem.WeaponData;
|
|
|
|
weapon.Sprite.Texture = startingItem.InventorySprite;
|
|
|
|
this.AddWeapon(weapon);
|
|
return weapon;
|
|
}
|
|
|
|
public Weapon3D 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 Weapon3D 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);
|
|
if (spawnedWeapon is null)
|
|
{
|
|
GD.Print($"Tried to spawn weapon {itemKey} but failed because it was null.");
|
|
return null;
|
|
};
|
|
return Equip(spawnedWeapon, force);
|
|
}
|
|
|
|
public Weapon3D Equip(Weapon3D weapon, bool force)
|
|
{
|
|
// When we get here we already have a spawned weapon and it's in the list
|
|
|
|
if (weapon is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
} |