using Godot; public partial class ship : CharacterBody2D { public enum ShipType { FIGHTER, INTERCEPTOR, GUARDIAN } public enum ShipFaction {PLAYER, FRIENDLY, ENEMY, ACE} [Signal] public delegate void LaserShotEventHandler(Area2D Laser); //[Export] //public Vector2 ScreenSize; [Export] public int Health { get; set; } [Export] public int MaxHealth { get; set; } [Export] public int MaxSpeed { get; set;} [Export] public int MainSpeed { get; set; } [Export] public int StrafeSpeed { get; set; } [Export] public float RotationSpeed { get; set; } [Export] public int Damage {get; set; } [Export] public float FireCooldown { get; set; } [Export] public ShipType type; [Export] public ShipFaction Faction; public Sprite2D Sprite = new Sprite2D(); public Node2D LaserSpawn = null; protected float fireTimer = 0f; public string spritePath = ""; protected int RotationDirection; protected readonly PackedScene LaserScene = GD.Load("res://scenes/laser.tscn"); public virtual void ShootLaser() { //GD.Print(Name, ": firing laser"); Laser laser = LaserScene.Instantiate(); laser.Position = LaserSpawn.GlobalPosition + -Transform.Y * 25f; laser.Shooter = this; laser.Rotation = Rotation; EmitSignal(SignalName.LaserShot, laser); } protected virtual void SetupVisual() { Sprite = GetNode("ShipSprite"); spritePath = ""; // Have to initialise as "" because of switch statements if (Faction == ShipFaction.PLAYER) { switch (type) { case ShipType.FIGHTER: spritePath = "res://assets/Ships/Fighters/Player/Fighter/"; break; case ShipType.INTERCEPTOR: spritePath = "res://assets/Ships/Fighters/Player/Interceptor/"; break; case ShipType.GUARDIAN: spritePath = "res://assets/Ships/Fighters/Player/Guardian/"; break; } } else if (Faction == ShipFaction.FRIENDLY) { switch (type) { case ShipType.FIGHTER: spritePath = "res://assets/Ships/Fighters/Friendly/friendlyFighter.png/"; break; case ShipType.INTERCEPTOR: spritePath = "res://assets/Ships/Fighters/Friendly/friendlyInterceptor.png/"; break; case ShipType.GUARDIAN: spritePath = "res://assets/Ships/Fighters/Friendly/friendlyGuardian.png/"; break; } } else if (Faction == ShipFaction.ENEMY) { switch (type) { case ShipType.FIGHTER: spritePath = "res://assets/Ships/Fighters/Enemy/enemyFighter.png/"; break; case ShipType.INTERCEPTOR: spritePath = "res://assets/Ships/Fighters/Enemy/enemyInterceptor.png/"; break; case ShipType.GUARDIAN: spritePath = "res://assets/Ships/Fighters/Enemy/enemyGuardian.png/"; break; } } else if (Faction == ShipFaction.ACE) { switch (type) { case ShipType.FIGHTER: spritePath = "res://assets/Ships/Fighters/Ace/aceFighter.png/"; break; case ShipType.INTERCEPTOR: spritePath = "res://assets/Ships/Fighters/Ace/aceInterceptor.png/"; break; case ShipType.GUARDIAN: spritePath = "res://assets/Ships/Fighters/Ace/aceGuardian.png/"; break; } } if (Faction == ShipFaction.ENEMY || Faction == ShipFaction.FRIENDLY) { Sprite.RotationDegrees = 180; } else { Sprite.RotationDegrees = 0; } } public void SetShipStats() { switch (type) { case ShipType.FIGHTER: Health = 100; MaxSpeed = 300; MainSpeed = 20; StrafeSpeed = 10; RotationSpeed = 2f; MaxHealth = 100; Damage = 40; FireCooldown = 0.6f; break; case ShipType.INTERCEPTOR: Health = 75; MaxSpeed = 450; MainSpeed = 35; StrafeSpeed = 15; RotationSpeed = 4f; MaxHealth = 75; Damage = 20; FireCooldown = 0.3f; break; case ShipType.GUARDIAN: Health = 200; MaxSpeed = 200; MainSpeed = 15; StrafeSpeed = 7; RotationSpeed = 1.5f; MaxHealth = 200; Damage = 60; FireCooldown = 1.1f; break; } } public virtual void ShipDamage(int damage) { Health -= damage; if (Health <= 0) { Explode(); } GD.Print(Name, " health: ", Health); } public virtual void Explode() { GD.Print(Name, " exploded"); QueueFree(); } public override void _Ready() { //ScreenSize = GetViewportRect().Size; LaserSpawn = GetNode("LaserSpawn"); } public override void _PhysicsProcess(double delta) { // Common movement logic for all ships Rotation += RotationDirection * RotationSpeed * (float)delta; Velocity.LimitLength(MaxSpeed); MoveAndSlide(); } }