SupaLidlGame/Items/Weapons/ProjectileSpawner.cs

126 lines
3.3 KiB
C#
Raw Permalink Normal View History

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; }
[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;
[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;
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;
}
public override void Attack()
2023-09-10 17:08:14 -07:00
{
Attack(1);
}
public override void Attack(float velocityModifier)
{
2023-08-14 14:07:57 -07:00
Character.Inventory.EmitSignal("UsedItem", this);
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);
}
// avoid unnecessary math if only spawning 1 projectile
if (ProjectileCount == 1)
{
2023-09-10 17:08:14 -07:00
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;
2023-09-10 17:08:14 -07:00
SpawnProjectile(map,
target.Rotated(curDeviation * theta),
velocityModifier);
}
2023-08-05 23:50:08 -07:00
}
}