110 lines
2.9 KiB
C#
110 lines
2.9 KiB
C#
using Godot;
|
|
|
|
namespace SupaLidlGame.Items.Weapons;
|
|
|
|
public partial class ProjectileSpawner : Ranged
|
|
{
|
|
[Export]
|
|
public PackedScene Projectile { get; set; }
|
|
|
|
[ExportGroup("Projectile Overrides")]
|
|
[Export]
|
|
public bool ShouldOverrideProjectileDamage { get; set; } = true;
|
|
|
|
[Export]
|
|
public bool ShouldOverrideVelocity { get; set; } = true;
|
|
|
|
[Export]
|
|
public bool ShouldRotate { get; set; } = true;
|
|
|
|
[ExportGroup("Multishot")]
|
|
[Export]
|
|
public int ProjectileCount { get; set; } = 1;
|
|
|
|
[Export]
|
|
public float ProjectileAngleDeviation { get; set; }
|
|
|
|
protected virtual void SpawnProjectile(Scenes.Map map,
|
|
Vector2 direction, float velocityModifier = 1)
|
|
{
|
|
var projectile = map.SpawnEntity<Entities.Projectile>(Projectile);
|
|
projectile.Hitbox.Faction = Character.Faction;
|
|
projectile.Direction = direction;
|
|
projectile.GlobalPosition = GlobalPosition;
|
|
|
|
if (ShouldOverrideVelocity)
|
|
{
|
|
projectile.Speed = InitialVelocity * velocityModifier;
|
|
}
|
|
|
|
if (ShouldRotate)
|
|
{
|
|
projectile.GlobalRotation = projectile.Direction.Angle();
|
|
}
|
|
|
|
if (ShouldOverrideProjectileDamage)
|
|
{
|
|
if (projectile.Hitbox is not null)
|
|
{
|
|
projectile.Hitbox.Damage = Damage;
|
|
}
|
|
}
|
|
|
|
projectile.Hitbox.Inflictor = Character;
|
|
projectile.Weapon = this;
|
|
|
|
if (projectile is Utils.ITarget target)
|
|
{
|
|
if (Character is Characters.NPC npc)
|
|
{
|
|
target.CharacterTarget = npc.FindBestTarget();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public override void Attack()
|
|
{
|
|
Attack(1);
|
|
}
|
|
|
|
public override void Attack(float velocityModifier)
|
|
{
|
|
Character.Inventory.EmitSignal("UsedItem", this);
|
|
|
|
var map = Utils.World.Instance.CurrentMap;
|
|
|
|
Vector2 target = Character.Target.Normalized();
|
|
|
|
if (CharacterRecoil > 0)
|
|
{
|
|
Character.ApplyImpulse(-target * CharacterRecoil);
|
|
}
|
|
|
|
// avoid unnecessary math if only spawning 1 projectile
|
|
if (ProjectileCount == 1)
|
|
{
|
|
SpawnProjectile(map, target, velocityModifier);
|
|
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;
|
|
SpawnProjectile(map,
|
|
target.Rotated(curDeviation * theta),
|
|
velocityModifier);
|
|
}
|
|
}
|
|
}
|