Weapons/Rpg/RpgProjectile.cs
/// <summary>
/// An RPG projectile. It supports either being fired in a set direction, or continuously updated with an end target.
/// </summary>
public sealed partial class RpgProjectile : ProjectileEntity
{
[Property] public SoundEvent LoopingSound { get; set; }
[Property] public float ExplosionRadius { get; set; } = 256f;
[Property] public float ExplosionDamage { get; set; } = 150f;
[Property] public float ExplosionForce { get; set; } = 1.5f;
SoundHandle LoopingSoundHandle;
protected override void OnEnabled()
{
base.OnEnabled();
if ( LoopingSound.IsValid() )
{
LoopingSoundHandle = Sound.Play( LoopingSound, WorldPosition );
}
if ( IsProxy )
return;
Rigidbody.Gravity = false;
}
protected override void OnDisabled()
{
LoopingSoundHandle?.Stop();
}
protected override void OnUpdate()
{
LoopingSoundHandle?.Position = WorldPosition;
}
protected override void OnHit( Collision collision = default )
{
Explode();
}
void Explode()
{
var explosionPrefab = ResourceLibrary.Get<PrefabFile>( "/prefabs/engine/explosion_med.prefab" );
if ( explosionPrefab == null )
{
Log.Warning( "RpgProjectile: Can't find /prefabs/engine/explosion_med.prefab" );
GameObject.Destroy();
return;
}
var go = GameObject.Clone( explosionPrefab, new CloneConfig { Transform = WorldTransform.WithScale( 1 ), StartEnabled = false } );
if ( go.IsValid() )
{
go.RunEvent<RadiusDamage>( x =>
{
x.Radius = ExplosionRadius;
x.PhysicsForceScale = ExplosionForce;
x.DamageAmount = ExplosionDamage;
x.Attacker = Instigator.GameObject;
x.DamageTags ??= new();
x.DamageTags.Add( DamageTags.Explosion );
}, FindMode.EverythingInSelfAndDescendants );
go.Enabled = true;
go.NetworkSpawn( true, null );
}
GameObject.Destroy();
}
/// <summary>
/// This is meant to be called continuously, updates the target, rotates slowly to it and moves at a set speed.
/// </summary>
/// <param name="target"></param>
/// <param name="speed"></param>
[Rpc.Host]
internal void UpdateWithTarget( Vector3 target, float speed )
{
var direction = (target - WorldPosition).Normal;
var targetRotation = Rotation.LookAt( direction, Vector3.Up );
WorldRotation = Rotation.Slerp( WorldRotation, targetRotation, Time.Delta * 6f );
Rigidbody.Velocity = WorldTransform.Forward * (speed * 2f);
}
}