using Godot; using System; using System.Diagnostics; using Cirno.Scripts; using Cirno.Scripts.Components; using Cirno.Scripts.Resources; public partial class Weapon : Node2D { [Export] public WeaponResource WeaponData { get; set; } [Export] public PackedScene BulletScene { get; set; } [Export] public Marker2D Muzzle { get; set; } public int Ammo { get; set; } = 0; public int LoadedAmmo { get; private set; } public Vector2 ShootDirection { get; set; } = Vector2.Zero; private Timer _cooldownTimer; private Marker2D _muzzle; private Node2D _bulletsContainer; private GameManager _gameManager; private InventoryManager _inventoryManager; // Called when the node enters the scene tree for the first time. public override void _Ready() { _muzzle = GetNode("./Muzzle"); _cooldownTimer = GetNode("./ShootTimer"); _gameManager = this.GetGameManager(); _inventoryManager = this.GetInventoryManager(); } public void Reload() { _cooldownTimer.Start(WeaponData.ReloadTime); if (WeaponData.InfiniteAmmo || string.IsNullOrWhiteSpace(WeaponData.AmmoKey)) { LoadedAmmo = WeaponData.BulletCapacity; } else { // if (_inventoryManager.GetItemCount(WeaponData.AmmoKey) <= 0) return; var ammoToLoad = _inventoryManager.RemoveItem(WeaponData.AmmoKey, WeaponData.BulletCapacity); if (ammoToLoad > 0) { LoadedAmmo = ammoToLoad; } else { GD.Print("Out of ammo"); } } } public void Shoot() { // Waiting on reload or Rate of Fire cooldown? if (!_cooldownTimer.IsStopped()) { return; } // Out of ammo? if (LoadedAmmo <= 0) { if (WeaponData.AutoReload) { Reload(); } return; } // TODO: Shoot at muzzle position, need to provide a way to turn it, on a radius? float halfSpread = WeaponData.SpreadAngle / 2f; float spreadStep = WeaponData.BulletsPerShot > 1 ? WeaponData.SpreadAngle / (WeaponData.BulletsPerShot - 1) : 0; for (int i = 0; i < WeaponData.BulletsPerShot; i++) { // Calculate angle offset for this bullet float spreadOffset = -halfSpread + (spreadStep * i); // Rotate the ShootDirection by the spread angle Vector2 spreadDirection = ShootDirection.Rotated(Mathf.DegToRad(spreadOffset)); var bullet = this.CreateChildOf(_gameManager.BulletsContainer, WeaponData.BulletData.BulletScene, _muzzle.GlobalPosition); if (bullet == null) { GD.PrintErr("Bullet is null, not shooting"); return; }; bullet.Initialize(WeaponData.MakeBullet(_muzzle.GlobalPosition), _gameManager); //bullet.SetDirection(ShootDirection); bullet.SetDirection(spreadDirection); bullet.Speed = WeaponData.BulletData.BulletSpeed; } LoadedAmmo -= 1; _cooldownTimer.Start(WeaponData.RateOfFire); } }