using System; using System.Collections.Generic; using Cirno.Scripts.Resources; using Cirno.Scripts.Weapons; using Godot; using Godot.Collections; namespace Cirno.Scripts.Components; public partial class BulletSpawner : Node2D { [Export] public PackedScene BulletScene; private GameManager _gameManager; public override void _Ready() { _gameManager = this.GetGameManager(); } public void SpawnBullet(BulletInfo bulletInfo) { var bulletScene = bulletInfo.BulletScene ?? BulletScene; Bullet bullet; for (int i = 0; i < bulletInfo.BulletCount; i++) { if (bulletInfo.IsLaser) bullet = this.CreateChildOf(_gameManager.BulletsContainer, bulletScene, bulletInfo.Position); else bullet = this.CreateChildOf(_gameManager.BulletsContainer, bulletScene, bulletInfo.Position); // var bullet = this.CreateChildOf(_gameManager.BulletsContainer, bulletInfo.BulletScene ?? BulletScene, bulletInfo.Position); if (bulletInfo.Modifier is not null) { bulletInfo = bulletInfo.Modifier.ModifyBullet(bulletInfo, i, bulletInfo.BulletCount); } bullet.Initialize(bulletInfo, _gameManager); // float modifiedSpeed = bulletInfo.Modifier?.ModifySpeed(bulletInfo.Speed, i, bulletInfo.BulletCount) ?? bulletInfo.Speed; // bullet.Speed = modifiedSpeed; Vector2 baseDirection = bulletInfo.Direction == Vector2.Zero ? Vector2.Right : bulletInfo.Direction.Normalized(); float baseAngle = Mathf.Atan2(baseDirection.Y, baseDirection.X); float offsetRadians = Mathf.DegToRad(bulletInfo.RotationOffset); float spreadStep = Mathf.DegToRad(bulletInfo.Spread) / Mathf.Max(1, bulletInfo.BulletCount - 1); // Ensure proper spread spacing, also add 1 if 0 float angle = baseAngle + offsetRadians + (spreadStep * i); // float angle = baseAngle + Mathf.DegToRad(bulletInfo.RotationOffset + (bulletInfo.Spread / bulletInfo.BulletCount) * i); Vector2 bulletDirection = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); bullet.SetDirection(bulletDirection); } } // public void SpawnBullet(Vector2 position, Vector2 direction, float speed, BulletOwner owner, int count = 1, float angleOffset = 0, float spread = 0, PackedScene bulletScene = null, IBulletModifier modifier = null) // { // for (int i = 0; i < count; i++) // { // var bullet = this.CreateChildOf(_gameManager.BulletsContainer, bulletScene ?? BulletScene, position); // // //var bullet = BulletScene.Instantiate(); // bullet.Position = position; // //bullet.Speed = speed; // // if (modifier is not null) // { // bullet.BulletInfo = modifier.ModifyBullet(bullet.BulletInfo, i, count); // } // // //float modifiedSpeed = modifier?.ModifySpeed(speed, i, count) ?? speed; // //bullet.Speed = modifiedSpeed; // // Vector2 baseDirection = direction == Vector2.Zero ? Vector2.Right : direction.Normalized(); // float baseAngle = Mathf.Atan2(baseDirection.Y, baseDirection.X); // //float angle = angleOffset + (360 / count) * i; // float angle = baseAngle + Mathf.DegToRad(angleOffset + (spread / count) * i); // Vector2 bulletDirection = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); // //Vector2 bulletDirection = new Vector2(Mathf.Cos(Mathf.DegToRad(angle)), Mathf.Sin(Mathf.DegToRad(angle))); // // bullet.SetDirection(bulletDirection); // //GetParent().AddChild(bullet); // } // } // public void SpawnTargetedBullet(Vector2 position, Vector2 target, float speed, BulletOwner owner, PackedScene bulletScene = null, int burstCount = 1, float spread = 0, IBulletModifier modifier = null) // { // Vector2 direction = (target - position).Normalized(); // SpawnBullet(position, direction, speed, owner, burstCount, spread: spread, bulletScene: bulletScene, modifier: modifier); // } } public class BulletInfo(BulletResource originalBulletResource) { public BulletResource OriginalBulletResource { get; set; } = originalBulletResource; public Vector2 Position { get; set; } public Vector2 Direction { get; set; } public float Speed { get; set; } public float LifeTime { get; set; } public bool DestroyOnCollision { get; set; } public BulletOwner Owner { get; set; } public DamageType DamageType { get; set; } public float Damage { get; set; } public float Knockback { get; set; } public int BulletCount { get; set; } public float RotationSpeed { get; set; } public float RotationOffset { get; set; } //public double Time { get; set; } public float Spread { get; set; } public bool RotateSprite { get; set; } = false; public bool Controllabe { get; set; } = false; public bool Freezable { get; set; } = true; public PackedScene BulletScene { get; set; } public PackedScene DestructionParticlesScene { get; set; } public IBulletModifier Modifier { get; set; } public List TimeModifiers { get; set; } = new List(); public bool Grazeable { get; set; } public float GrazeValue { get; set; } #region Laser public bool IsLaser { get; set; } public float SpawnDelay { get; set; } = 0.3f; // Delay before beam appears public float PreFireTime { get; set; } = 0.5f; // Time before laser becomes lethal public float LethalTime { get; set; } = 1.5f; // Time laser remains lethal public Color PreFireColor { get; set; } = new Color(1, 0, 0, 0.5f); // Thin red beam public Color LethalColor { get; set; } = new Color(1, 0, 0, 1.0f); // Thicker beam #endregion }