Weapons/ShotgunWeapon.cs
using Sandbox.Rendering;
using Sandbox.Utility;
public class ShotgunWeapon : BaseBulletWeapon
{
[Property] public float Damage { get; set; } = 12.0f;
[Property] public float AltDamage { get; set; } = 20.0f;
[Property] public int Pellets { get; set; } = 12;
[Property] public Vector2 Spread { get; set; } = new Vector2( 8, 4 );
public override void OnControl( Player player )
{
base.OnControl( player );
if ( Input.Pressed( "attack1" ) )
{
ShootBullet( player );
}
if ( Input.Pressed( "Attack2" ) )
{
ShootBulletAlternate( player );
}
}
[Rpc.Broadcast]
void OneShotEvent( Vector3 hitPos, float shootPitchModifier = 1f )
{
var ev = new IWeaponEvent.AttackEvent( ViewModel.IsValid() );
IWeaponEvent.PostToGameObject( GameObject.Root, x => x.OnAttack( ev ) );
IWeaponEvent.PostToGameObject( GameObject.Root, x => x.CreateRangedEffects( this, hitPos ) );
if ( ShootSound.IsValid() )
{
var snd = GameObject.PlaySound( ShootSound );
// If we're shooting, the sound should not be spatialized
if ( Owner.IsValid() && Owner.IsLocalPlayer && snd.IsValid() )
{
snd.SpacialBlend = 0;
}
snd.Pitch *= shootPitchModifier;
}
}
public void ShootBullet( Player player )
{
if ( !CanShoot() || !TakeAmmo( 1 ) )
{
TryAutoReload();
return;
}
AddShootDelay( 0.9f );
var hitPos = Vector3.Zero;
for ( int i = 0; i < Pellets; i++ )
{
var forward = player.EyeTransform.Rotation.Forward.WithAimCone( Spread.x, Spread.y );
var bulletRadius = GameSettings.ShotgunBulletRadius * GameSettings.BulletRadius;
var tr = Scene.Trace.Ray( player.EyeTransform.ForwardRay with { Forward = forward }, 4096 )
.IgnoreGameObjectHierarchy( player.GameObject )
.WithCollisionRules( "bullet" )
.Radius( bulletRadius )
.UseHitboxes()
.Run();
// DebugOverlay.Line( tr.StartPosition, tr.EndPosition, duration: 30 );
ShootEffects( tr.EndPosition, tr.Hit, tr.Normal, tr.GameObject, tr.Surface, null, true );
TraceAttack( TraceAttackInfo.From( tr, Damage ) );
TimeSinceShoot = 0;
if ( player.IsLocalPlayer )
{
HitMarker.CreateFromTrace( tr );
}
hitPos = tr.EndPosition;
}
OneShotEvent( hitPos );
player.Controller.EyeAngles += new Angles( Random.Shared.Float( -2, -3 ), Random.Shared.Float( -2, 2 ), 0 );
if ( !player.Controller.ThirdPerson && player.IsLocalPlayer )
{
new Sandbox.CameraNoise.Punch( new Vector3( Random.Shared.Float( -50, -65 ), Random.Shared.Float( -20, 0 ), 0 ), 2.0f, 2f, 0.7f );
new Sandbox.CameraNoise.Shake( 3.5f, 1.0f );
}
}
public void ShootBulletAlternate( Player player )
{
if ( !CanShoot() )
{
TryAutoReload();
return;
}
if ( !TakeAmmo( 2 ) )
{
ShootBullet( player );
return;
}
AddShootDelay( 1.5f );
var hitPos = Vector3.Zero;
for ( int i = 0; i < Pellets * 2; i++ )
{
var forward = player.EyeTransform.Rotation.Forward.WithAimCone( Spread.x * 2f, Spread.y * 2f );
var bulletRadius = GameSettings.ShotgunBulletRadius * GameSettings.BulletRadius;
var tr = Scene.Trace.Ray( player.EyeTransform.ForwardRay with { Forward = forward }, 4096 )
.IgnoreGameObjectHierarchy( player.GameObject )
.WithCollisionRules( "bullet" )
.Radius( bulletRadius )
.UseHitboxes()
.Run();
ShootEffects( tr.EndPosition, tr.Hit, tr.Normal, tr.GameObject, tr.Surface, null, true );
TraceAttack( TraceAttackInfo.From( tr, Damage ) );
TimeSinceShoot = 0;
if ( player.IsLocalPlayer )
{
HitMarker.CreateFromTrace( tr );
}
hitPos = tr.EndPosition;
}
OneShotEvent( hitPos, shootPitchModifier: 0.8f );
player.Controller.EyeAngles += new Angles( Random.Shared.Float( -2, -3 ), Random.Shared.Float( -2, 2 ), 0 );
if ( !player.Controller.ThirdPerson && player.IsLocalPlayer )
{
new Sandbox.CameraNoise.Punch( new Vector3( Random.Shared.Float( -50, -65 ), Random.Shared.Float( -20, 0 ), 0 ), 2.0f, 1f, 0.7f );
new Sandbox.CameraNoise.Shake( 6.0f, 1.3f );
}
}
public override void DrawCrosshair( HudPainter hud, Vector2 center )
{
var tss = TimeSinceShoot.Relative.Remap( 0, 0.8f, 1, 0 );
var len = 64 + Easing.BounceIn( tss ) * 128;
Color color = !CanShoot() ? UI.CrosshairInactive : UI.CrosshairActive;
var rect = new Rect( center - len * 0.5f, len );
hud.DrawRect( rect, Color.Transparent, cornerRadius: new Vector4( 512 ), borderWidth: new Vector4( 2 ), borderColor: color );
}
}