2023-08-05 23:50:08 -07:00
|
|
|
using Godot;
|
|
|
|
|
|
|
|
namespace SupaLidlGame.Items.Weapons;
|
|
|
|
|
|
|
|
public partial class ProjectileSpawner : Ranged
|
|
|
|
{
|
|
|
|
[Export]
|
|
|
|
public PackedScene Projectile { get; set; }
|
|
|
|
|
2023-08-15 17:53:43 -07:00
|
|
|
[ExportGroup("Projectile Overrides")]
|
2023-08-05 23:50:08 -07:00
|
|
|
[Export]
|
|
|
|
public bool ShouldOverrideProjectileDamage { get; set; } = true;
|
|
|
|
|
2023-08-08 00:54:00 -07:00
|
|
|
[Export]
|
|
|
|
public bool ShouldOverrideVelocity { get; set; } = true;
|
|
|
|
|
2023-08-05 23:50:08 -07:00
|
|
|
[Export]
|
|
|
|
public bool ShouldRotate { get; set; } = true;
|
|
|
|
|
2023-08-15 17:53:43 -07:00
|
|
|
[ExportGroup("Multishot")]
|
|
|
|
[Export]
|
|
|
|
public int ProjectileCount { get; set; } = 1;
|
|
|
|
|
|
|
|
[Export]
|
|
|
|
public float ProjectileAngleDeviation { get; set; }
|
|
|
|
|
2024-05-27 12:14:38 -07:00
|
|
|
public string ProjectilePath
|
|
|
|
{
|
|
|
|
get => Projectile?.ResourcePath;
|
|
|
|
set
|
|
|
|
{
|
|
|
|
Projectile = GD.Load<PackedScene>(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-24 16:08:53 -07:00
|
|
|
protected virtual Entities.Projectile SpawnProjectile(Scenes.Map map,
|
2023-11-09 16:22:52 -08:00
|
|
|
Vector2 direction, float velocityModifier = 1)
|
2023-08-05 23:50:08 -07:00
|
|
|
{
|
|
|
|
var projectile = map.SpawnEntity<Entities.Projectile>(Projectile);
|
|
|
|
projectile.Hitbox.Faction = Character.Faction;
|
2023-08-15 17:53:43 -07:00
|
|
|
projectile.Direction = direction;
|
2023-08-05 23:50:08 -07:00
|
|
|
projectile.GlobalPosition = GlobalPosition;
|
2023-08-14 14:07:57 -07:00
|
|
|
|
|
|
|
if (ShouldOverrideVelocity)
|
|
|
|
{
|
2023-11-09 16:22:52 -08:00
|
|
|
projectile.Speed = InitialVelocity * velocityModifier;
|
2023-08-14 14:07:57 -07:00
|
|
|
}
|
2023-08-05 23:50:08 -07:00
|
|
|
|
|
|
|
if (ShouldRotate)
|
|
|
|
{
|
|
|
|
projectile.GlobalRotation = projectile.Direction.Angle();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ShouldOverrideProjectileDamage)
|
|
|
|
{
|
|
|
|
if (projectile.Hitbox is not null)
|
|
|
|
{
|
|
|
|
projectile.Hitbox.Damage = Damage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-03 17:42:32 -07:00
|
|
|
projectile.Hitbox.Inflictor = Character;
|
|
|
|
projectile.Weapon = this;
|
|
|
|
|
2023-08-05 23:50:08 -07:00
|
|
|
if (projectile is Utils.ITarget target)
|
|
|
|
{
|
|
|
|
if (Character is Characters.NPC npc)
|
|
|
|
{
|
|
|
|
target.CharacterTarget = npc.FindBestTarget();
|
|
|
|
}
|
|
|
|
}
|
2023-08-14 14:07:57 -07:00
|
|
|
|
2024-06-24 16:08:53 -07:00
|
|
|
return projectile;
|
2023-08-15 17:53:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void Attack()
|
2023-09-10 17:08:14 -07:00
|
|
|
{
|
|
|
|
Attack(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Attack(float velocityModifier)
|
2023-08-15 17:53:43 -07:00
|
|
|
{
|
2023-08-14 14:07:57 -07:00
|
|
|
Character.Inventory.EmitSignal("UsedItem", this);
|
2023-08-15 17:53:43 -07:00
|
|
|
|
|
|
|
var map = Utils.World.Instance.CurrentMap;
|
|
|
|
|
|
|
|
Vector2 target = Character.Target.Normalized();
|
|
|
|
|
2024-07-06 22:49:17 -07:00
|
|
|
if (AngleDeviation > 0)
|
|
|
|
{
|
|
|
|
float angle = (GD.Randf() - 0.5f) * AngleDeviation;
|
|
|
|
target = target.Rotated(Mathf.DegToRad(angle));
|
|
|
|
}
|
|
|
|
|
2023-08-15 21:49:33 -07:00
|
|
|
if (CharacterRecoil > 0)
|
|
|
|
{
|
|
|
|
Character.ApplyImpulse(-target * CharacterRecoil);
|
|
|
|
}
|
|
|
|
|
2023-08-15 17:53:43 -07:00
|
|
|
// avoid unnecessary math if only spawning 1 projectile
|
|
|
|
if (ProjectileCount == 1)
|
|
|
|
{
|
2023-09-10 17:08:14 -07:00
|
|
|
SpawnProjectile(map, target, velocityModifier);
|
2023-08-15 17:53:43 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// example: 4 projectiles =
|
|
|
|
// i = 0 -> 1.5 theta
|
|
|
|
// i = 1 -> 0.5 theta
|
|
|
|
// i = 2 -> -0.5 theta
|
|
|
|
// i = 3 -> -1.5 theta
|
|
|
|
// i = x -> -x * 0.5 theta + max dev
|
|
|
|
|
|
|
|
float theta = Mathf.DegToRad(ProjectileAngleDeviation);
|
|
|
|
// maaax angle deviation = ((projectile count - 1) / 2) thetas
|
|
|
|
float maxAngleDeviations = ((ProjectileCount - 1) / 2);
|
|
|
|
for (int i = 0; i < ProjectileCount; i++)
|
|
|
|
{
|
|
|
|
float curDeviation = -i + maxAngleDeviations;
|
2023-09-10 17:08:14 -07:00
|
|
|
SpawnProjectile(map,
|
|
|
|
target.Rotated(curDeviation * theta),
|
|
|
|
velocityModifier);
|
2023-08-15 17:53:43 -07:00
|
|
|
}
|
2023-08-05 23:50:08 -07:00
|
|
|
}
|
|
|
|
}
|