2024-08-15 14:40:37 +00:00
|
|
|
using Godot;
|
|
|
|
|
|
|
|
|
|
public partial class ship : CharacterBody2D
|
|
|
|
|
{
|
|
|
|
|
public enum ShipType { FIGHTER, INTERCEPTOR, GUARDIAN }
|
2025-04-17 18:24:50 +00:00
|
|
|
|
|
|
|
|
public enum ShipFaction {PLAYER, FRIENDLY, ENEMY, ACE}
|
2024-08-15 14:40:37 +00:00
|
|
|
|
|
|
|
|
[Signal]
|
2025-04-19 22:33:53 +00:00
|
|
|
public delegate void LaserShotEventHandler(Area2D laser);
|
2024-08-15 14:40:37 +00:00
|
|
|
|
|
|
|
|
//[Export]
|
|
|
|
|
//public Vector2 ScreenSize;
|
|
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public int Health { get; set; }
|
2024-08-15 17:12:48 +00:00
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public int MaxHealth { get; set; }
|
2024-08-15 17:12:48 +00:00
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public int MaxSpeed { get; set;}
|
2024-08-15 14:40:37 +00:00
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public int MainSpeed { get; set; }
|
2024-08-15 14:40:37 +00:00
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public int StrafeSpeed { get; set; }
|
2024-08-15 14:40:37 +00:00
|
|
|
[Export]
|
2025-04-18 01:07:51 +00:00
|
|
|
public float RotationSpeed { get; set; }
|
|
|
|
|
[Export]
|
2025-04-18 23:21:19 +00:00
|
|
|
public int Damage {get; set; }
|
|
|
|
|
[Export]
|
|
|
|
|
public float FireCooldown { get; set; }
|
2024-08-15 14:40:37 +00:00
|
|
|
[Export]
|
2025-04-19 22:33:53 +00:00
|
|
|
public ShipType Type;
|
2025-04-17 18:24:50 +00:00
|
|
|
[Export]
|
2025-04-19 22:24:46 +00:00
|
|
|
public ShipFaction Faction;
|
2025-04-22 04:43:03 +00:00
|
|
|
[Export]
|
|
|
|
|
public float StatModifier = 1f;
|
2025-04-17 18:24:50 +00:00
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected Sprite2D Sprite = new Sprite2D();
|
2024-08-15 14:40:37 +00:00
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected Node2D LaserSpawn;
|
2025-04-18 23:21:19 +00:00
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected float FireTimer = 0f;
|
2024-08-15 14:40:37 +00:00
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected string SpritePath;
|
2025-04-17 18:24:50 +00:00
|
|
|
|
2025-04-19 22:24:46 +00:00
|
|
|
protected int RotationDirection;
|
2025-04-22 04:43:03 +00:00
|
|
|
|
2025-04-23 16:20:00 +00:00
|
|
|
protected readonly PackedScene LaserScene = GD.Load<PackedScene>("res://scenes/entities/laser.tscn");
|
2024-08-15 14:40:37 +00:00
|
|
|
|
|
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected virtual void ShootLaser()
|
2024-08-15 14:40:37 +00:00
|
|
|
{
|
2025-04-20 17:27:34 +00:00
|
|
|
GD.Print(Name, ": firing laser");
|
2025-04-18 23:21:19 +00:00
|
|
|
|
2025-04-19 22:24:46 +00:00
|
|
|
Laser laser = LaserScene.Instantiate<Laser>();
|
|
|
|
|
laser.Position = LaserSpawn.GlobalPosition + -Transform.Y * 25f;
|
|
|
|
|
laser.Shooter = this;
|
|
|
|
|
laser.Rotation = Rotation;
|
2025-04-23 16:20:00 +00:00
|
|
|
GetNode<AudioStreamPlayer2D>("LaserSFX").Play();
|
2025-04-19 22:24:46 +00:00
|
|
|
EmitSignal(SignalName.LaserShot, laser);
|
2024-08-15 14:40:37 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-22 04:43:03 +00:00
|
|
|
public void SetupVisual()
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
Sprite = GetNode<Sprite2D>("ShipSprite");
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = ""; // Have to initialise as "" because of switch statements
|
2025-04-17 18:24:50 +00:00
|
|
|
|
2025-04-19 22:24:46 +00:00
|
|
|
if (Faction == ShipFaction.PLAYER)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
2025-04-19 22:33:53 +00:00
|
|
|
switch (Type)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
case ShipType.FIGHTER:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Player/Fighter/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.INTERCEPTOR:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Player/Interceptor/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.GUARDIAN:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Player/Guardian/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-19 22:24:46 +00:00
|
|
|
else if (Faction == ShipFaction.FRIENDLY)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
2025-04-19 22:33:53 +00:00
|
|
|
switch (Type)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
case ShipType.FIGHTER:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyFighter.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.INTERCEPTOR:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyInterceptor.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.GUARDIAN:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyGuardian.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-19 22:24:46 +00:00
|
|
|
else if (Faction == ShipFaction.ENEMY)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
2025-04-19 22:33:53 +00:00
|
|
|
switch (Type)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
case ShipType.FIGHTER:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Enemy/enemyFighter.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.INTERCEPTOR:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Enemy/enemyInterceptor.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.GUARDIAN:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Enemy/enemyGuardian.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-19 22:24:46 +00:00
|
|
|
else if (Faction == ShipFaction.ACE)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
2025-04-19 22:33:53 +00:00
|
|
|
switch (Type)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
case ShipType.FIGHTER:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Ace/aceFighter.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.INTERCEPTOR:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Ace/aceInterceptor.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.GUARDIAN:
|
2025-04-19 22:33:53 +00:00
|
|
|
SpritePath = "res://assets/Ships/Fighters/Ace/aceGuardian.png/";
|
2025-04-17 18:24:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-19 22:24:46 +00:00
|
|
|
if (Faction == ShipFaction.ENEMY || Faction == ShipFaction.FRIENDLY)
|
2025-04-17 18:24:50 +00:00
|
|
|
{
|
|
|
|
|
Sprite.RotationDegrees = 180;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Sprite.RotationDegrees = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-19 22:33:53 +00:00
|
|
|
|
|
|
|
|
protected void SetShipStats()
|
2024-08-15 17:12:48 +00:00
|
|
|
{
|
2025-04-19 22:33:53 +00:00
|
|
|
switch (Type)
|
2024-08-15 17:12:48 +00:00
|
|
|
{
|
2025-04-18 01:07:51 +00:00
|
|
|
case ShipType.FIGHTER:
|
2025-04-22 04:43:03 +00:00
|
|
|
Health = (int)(100 * StatModifier);
|
|
|
|
|
MaxSpeed = (int)(300 * StatModifier);
|
|
|
|
|
MainSpeed = (int)(20 * StatModifier);
|
|
|
|
|
StrafeSpeed = (int)(10 * StatModifier);
|
|
|
|
|
RotationSpeed = 2f * StatModifier;
|
|
|
|
|
MaxHealth = (int)(100 * StatModifier);
|
|
|
|
|
Damage = (int)(30 * StatModifier);
|
|
|
|
|
FireCooldown = 0.6f * StatModifier;
|
2025-04-18 01:07:51 +00:00
|
|
|
break;
|
|
|
|
|
|
2024-08-15 17:12:48 +00:00
|
|
|
case ShipType.INTERCEPTOR:
|
2025-04-22 04:43:03 +00:00
|
|
|
Health = (int)(75 * StatModifier);
|
|
|
|
|
MaxSpeed = (int)(450 * StatModifier);
|
|
|
|
|
MainSpeed = (int)(35 * StatModifier);
|
|
|
|
|
StrafeSpeed = (int)(15 * StatModifier);
|
|
|
|
|
RotationSpeed = 4f * StatModifier;
|
|
|
|
|
MaxHealth = (int)(75 * StatModifier);
|
|
|
|
|
Damage = (int)(10 * StatModifier);
|
|
|
|
|
FireCooldown = 0.3f * StatModifier;
|
2024-08-15 17:12:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ShipType.GUARDIAN:
|
2025-04-22 04:43:03 +00:00
|
|
|
Health = (int)(200 * StatModifier);
|
|
|
|
|
MaxSpeed = (int)(200 * StatModifier);
|
|
|
|
|
MainSpeed = (int)(15 * StatModifier);
|
|
|
|
|
StrafeSpeed = (int)(7 * StatModifier);
|
|
|
|
|
RotationSpeed = 1.5f * StatModifier;
|
|
|
|
|
MaxHealth = (int)(200 * StatModifier);
|
|
|
|
|
Damage = (int)(50 * StatModifier);
|
|
|
|
|
FireCooldown = 1.1f * StatModifier;
|
2024-08-15 17:12:48 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public virtual void ShipDamage(int damage)
|
|
|
|
|
{
|
|
|
|
|
Health -= damage;
|
2025-04-19 22:24:46 +00:00
|
|
|
if (Health <= 0)
|
|
|
|
|
{
|
2025-04-23 16:20:00 +00:00
|
|
|
Health = 0;
|
2025-04-19 22:24:46 +00:00
|
|
|
Explode();
|
|
|
|
|
}
|
2025-04-23 16:20:00 +00:00
|
|
|
//GD.Print(Name, " health: ", Health);
|
|
|
|
|
GetNode<AudioStreamPlayer2D>("DamageSFX").Play();
|
|
|
|
|
|
2025-04-19 22:24:46 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-19 22:33:53 +00:00
|
|
|
protected virtual void Explode()
|
2025-04-19 22:24:46 +00:00
|
|
|
{
|
|
|
|
|
GD.Print(Name, " exploded");
|
|
|
|
|
QueueFree();
|
2024-08-15 17:12:48 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-15 14:40:37 +00:00
|
|
|
public override void _Ready()
|
|
|
|
|
{
|
|
|
|
|
//ScreenSize = GetViewportRect().Size;
|
|
|
|
|
LaserSpawn = GetNode<Node2D>("LaserSpawn");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
|
|
|
{
|
|
|
|
|
// Common movement logic for all ships
|
2025-04-19 22:24:46 +00:00
|
|
|
Rotation += RotationDirection * RotationSpeed * (float)delta;
|
2024-08-15 14:40:37 +00:00
|
|
|
Velocity.LimitLength(MaxSpeed);
|
|
|
|
|
|
|
|
|
|
MoveAndSlide();
|
|
|
|
|
}
|
2024-08-16 10:18:44 +00:00
|
|
|
}
|