Combat/Projectile.cs
namespace Prototype;
public sealed class Projectile : Component
{
[Sync] public Vector3 Velocity { get; set; }
[Sync] public float Damage { get; set; }
[Sync] public GameObject Instigator { get; set; }
[Sync] public float Lifetime { get; set; } = 2.5f;
protected override void OnUpdate()
{
// Clients display the replicated transform; only the host hits/despawns.
if ( IsProxy ) return;
Lifetime -= Time.Delta;
if ( Lifetime <= 0f ) { DestroyGameObject(); return; }
var next = WorldPosition + Velocity * Time.Delta;
var trace = Scene.Trace.Ray( WorldPosition, next ).WithoutTags( "projectile" ).Run();
if ( trace.Hit && trace.GameObject != Instigator )
{
var targetPlayer = trace.GameObject.Components.Get<FpsPlayer>( FindMode.EverythingInSelfAndAncestors );
var targetEnemy = trace.GameObject.Components.Get<EnemyBrain>( FindMode.EverythingInSelfAndAncestors );
var sourceIsPlayer = Instigator?.Components.Get<FpsPlayer>() is not null;
if ( sourceIsPlayer && targetEnemy is not null ) targetEnemy.Vitality?.ApplyDamage( Damage, Instigator );
else if ( !sourceIsPlayer && targetPlayer is not null ) targetPlayer.ReceiveDamage( Damage, Instigator );
DestroyGameObject();
return;
}
WorldPosition = next;
}
}