Weapons/Base/SingleUseWeapon.cs
namespace Opium;
public partial class SingleUseWeapon : BaseWeapon
{
[Property] public Action OnStartAction { get; set; }
[Property] public Action OnDiscardAction { get; set; }
[Property] public CameraEffect OnStartCameraEffect { get; set; }
[Property] public CameraEffect OnDiscardCameraEffect { get; set; }
[Property, Group( "Basic Shooting" )] public bool DoShoot { get; set; } = false;
[Property, Group( "Basic Shooting" )] public float Range { get; set; } = 100f;
[Property, Group( "Basic Shooting" )] public float InitialDelay { get; set; } = 0f;
[Property, Group( "Basic Shooting" )] public float BulletSize { get; set; } = 5f;
[Property, Group( "Basic Shooting" )] public float Randomization { get; set; } = 0f;
[Property, Group( "Basic Shooting" )] public Vector3 ShotOffset { get; set; } = Vector3.Zero;
[Property] public SoundEvent Sound { get; set; }
public override void OnCreateViewModel()
{
Start();
}
protected override void OnEnabled()
{
TimeUntilDiscard = DiscardTime;
if ( OnStartCameraEffect is not null && Actor is Opium.PlayerController player )
{
OnStartCameraEffect.Enabled = true;
OnStartCameraEffect.Player = player;
}
}
[Property] public float DiscardTime { get; set; } = 3f;
[Property, ReadOnly] public TimeUntil TimeUntilDiscard { get; set; } = 3f;
private bool HasShot { get; set; } = false;
/// <summary>
/// Called when the weapon is created.
/// </summary>
protected virtual void Start()
{
OnStartAction?.Invoke();
if ( Sound is not null )
{
Log.Info( "Playing sound!" );
Sandbox.Sound.Play( Sound );
}
if ( DoShoot )
{
AsyncShoot();
}
}
/// <summary>
/// Runs a trace with all the data we have supplied it, and returns the result
/// </summary>
/// <returns></returns>
protected virtual SceneTraceResult GetShootTrace()
{
var cameraOrigin = Actor.CameraObject.Transform;
var forward = cameraOrigin.Rotation.Forward;
forward += (Vector3.Random + Vector3.Random + Vector3.Random + Vector3.Random) * Randomization;
forward = forward.Normal;
var offset = Vector3.Zero;
offset += cameraOrigin.Rotation.Forward * ShotOffset.x;
offset += cameraOrigin.Rotation.Left * ShotOffset.y;
offset += cameraOrigin.Rotation.Up * ShotOffset.z;
var ray = new Ray( cameraOrigin.Position + offset, forward );
var tr = Scene.Trace.Ray( ray, Range )
.IgnoreGameObjectHierarchy( GameObject.Root )
.Size( BulletSize )
.UseHitboxes()
.Run();
return tr;
}
async void AsyncShoot()
{
if ( HasShot ) return;
HasShot = true;
await GameTask.DelaySeconds( InitialDelay );
var tr = GetShootTrace();
var damageInfo = Opium.DamageInfo.Generic( BaseDamage, Actor.GameObject, GameObject, "melee" );
CalculateDamage( damageInfo );
tr.GameObject?.TakeDamage( damageInfo );
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 );
}
/// <summary>
/// Called when the weapon is discarded.
/// </summary>
public virtual void Discard()
{
Actor.SetupViewModel( this, false );
OnDiscardAction?.Invoke();
// Cya
GameObject.Destroy();
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( TimeUntilDiscard )
{
if ( OnDiscardCameraEffect is not null && Actor is Opium.PlayerController player )
{
OnDiscardCameraEffect.Enabled = true;
OnDiscardCameraEffect.Player = player;
}
Discard();
}
}
}