Weapons/RangedWeapon.cs
using Opium;
public partial class RangedWeapon : BaseWeapon
{
[Property, Category( "Ranged" )] public int BulletCount { get; set; } = 1;
[Property, Category( "Ranged" )] public float BulletSpread { get; set; } = 0.1f;
[Property, Category( "Ranged" )] public float MaxRange { get; set; } = 4096f;
[Property, Category( "Ranged" )] public float BulletSize { get; set; } = 1f;
//
[Property, Category( "FX" )] public GameObject MuzzleFlashPrefab { get; set; }
[Property, Category( "FX" )] public GameObject EjectPrefab { get; set; }
[Property, Category( "FX" )] public SoundEvent FireSound { get; set; }
[Property] public CameraEffect ShootCameraEffect { get; set; }
[Property] public CameraEffect AimingCameraEffect { get; set; }
[Property] public int CurrentAmmo { get; set; } = 2;
[Property] public int MaximumAmmo { get; set; } = 2;
/// <summary>
/// Runs a trace with all the data we have supplied it, and returns the result
/// </summary>
/// <returns></returns>
protected virtual IEnumerable<SceneTraceResult> GetShootTrace()
{
for ( int i = 0; i < BulletCount; i++ )
{
var cameraOrigin = Actor.CameraObject.Transform;
var forward = cameraOrigin.Rotation.Forward;
forward += (Vector3.Random + Vector3.Random + Vector3.Random + Vector3.Random) * BulletSpread * 0.25f;
forward = forward.Normal;
var ray = new Ray( cameraOrigin.Position, forward );
var tr = Scene.Trace.Ray( ray, MaxRange )
.IgnoreGameObjectHierarchy( GameObject.Root )
.Size( BulletSize )
.UseHitboxes()
.Run();
yield return tr;
}
}
void DryFire()
{
// TODO - animation
// TODO - effects
}
public bool IsAiming { get; set; }
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
if ( Input.Down( "Attack2" ) )
{
IsAiming = true;
if ( !AimingCameraEffect.Enabled && Actor is Opium.PlayerController player )
{
AimingCameraEffect.Player = player;
AimingCameraEffect.Enabled = true;
}
}
else
{
IsAiming = false;
}
}
public override void Shoot()
{
if ( CurrentAmmo <= 0 )
{
DryFire();
return;
}
base.Shoot();
foreach ( var tr in GetShootTrace() )
{
// Inflict damage on whatever we find.
var damageInfo = Opium.DamageInfo.Bullet( BaseDamage, Actor.GameObject, GameObject, tr.Hitbox );
CalculateDamage( damageInfo );
tr.GameObject.TakeDamage( damageInfo );
var rb = tr.GameObject.Components.Get<Rigidbody>( FindMode.EnabledInSelfAndChildren );
if ( rb is not null )
{
rb.ApplyImpulseAt( tr.EndPosition, tr.Normal * -10000f );
}
var skinnedModelRenderer = tr.GameObject.Components.Get<SkinnedModelRenderer>();
if ( skinnedModelRenderer is not null && tr.Hitbox is not null )
{
CreateImpactEffects( skinnedModelRenderer.GetBoneObject( tr.Hitbox.Bone ), GetSurfaceFromTrace( tr ), tr.EndPosition, tr.Normal );
}
else
CreateImpactEffects( tr.GameObject, GetSurfaceFromTrace( tr ), tr.EndPosition, tr.Normal );
}
EventListener?.Invoke( "shoot" );
var gameObject = Actor.CameraObject ?? GameObject;
gameObject.PlaySound( FireSound, true );
CurrentAmmo--;
Actor.TriggerEvent( "ammo_loss", CurrentAmmo );
if ( ShootCameraEffect is not null && Actor is Opium.PlayerController player )
{
ShootCameraEffect.Player = player;
ShootCameraEffect.Enabled = true;
}
}
}