Weapons/Rpg/RpgWeapon.cs
using Sandbox.Rendering;
using Sandbox.Utility;
public class RpgWeapon : BaseWeapon
{
[Property] public float TimeBetweenShots { get; set; } = 2f;
[Property] public GameObject ProjectilePrefab { get; set; }
[Property] public GameObject LaserEnd { get; set; }
[Sync, Change( nameof( OnLaserChanged ) )] public bool Laser { get; set; }
[Sync( SyncFlags.FromHost )] RpgProjectile Projectile { get; set; }
private void OnLaserChanged( bool before, bool after )
{
LaserEnd.Enabled = after;
}
protected override void OnEnabled()
{
LaserEnd.Enabled = false;
base.OnEnabled();
}
public override void OnControl( Player player )
{
base.OnControl( player );
if ( Input.Down( "attack1" ) )
{
Shoot( player );
}
if ( Input.Released( "Attack2" ) )
{
Laser = !Laser;
}
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( Laser )
{
var player = Owner;
if ( !player.IsValid() )
return;
var forward = player.EyeTransform.Rotation.Forward;
forward = forward.Normal;
var tr = Scene.Trace.Ray( player.EyeTransform.ForwardRay with { Forward = forward }, 4096 )
.IgnoreGameObjectHierarchy( player.GameObject )
.WithoutTags( "projectile" )
.UseHitboxes()
.Run();
LaserEnd.WorldPosition = tr.EndPosition + (-tr.Direction * 2f);
LaserEnd.WorldRotation = Rotation.LookAt( -tr.Normal );
if ( !Projectile.IsValid() ) return;
if ( !IsProxy )
{
Projectile.UpdateWithTarget( tr.EndPosition, 1024 );
}
}
}
private Vector3 CheckThrowPosition( Player player, Vector3 eyePosition, Vector3 grenadePosition )
{
var tr = Scene.Trace.Box( BBox.FromPositionAndSize( Vector3.Zero, 8.0f ), eyePosition, grenadePosition )
.WithoutTags( "trigger", "ragdoll", "player", "effect" )
.IgnoreGameObjectHierarchy( player.GameObject )
.Run();
if ( tr.Hit )
{
Log.Info( tr.GameObject );
return tr.EndPosition;
}
return grenadePosition;
}
TimeSince TimeSinceShoot;
public void Shoot( Player player )
{
if ( !CanShoot() || !TakeAmmo( 1 ) )
{
TryAutoReload();
return;
}
TimeSinceShoot = 0;
AddShootDelay( TimeBetweenShots );
var ev = new IWeaponEvent.AttackEvent( ViewModel.IsValid() );
IWeaponEvent.PostToGameObject( GameObject.Root, x => x.OnAttack( ev ) );
var transform = player.EyeTransform;
transform.Position = transform.Position + Vector3.Down * 8f + transform.Right * 8f;
var forward = transform.Forward;
var right = transform.Right;
var initialPos = transform.ForwardRay.Position + (forward * 64.0f);
initialPos = CheckThrowPosition( player, transform.Position + (forward * 0.0f), initialPos );
CreateProjectile( initialPos, transform.Forward, 1024 );
player.Controller.EyeAngles += new Angles( Random.Shared.Float( -0.2f, -0.3f ), Random.Shared.Float( -0.1f, 0.1f ), 0 );
if ( !player.Controller.ThirdPerson && player.IsLocalPlayer )
{
new Sandbox.CameraNoise.Punch( new Vector3( Random.Shared.Float( 45, 35 ), Random.Shared.Float( -10, -5 ), 0 ), 1.5f, 2, 0.5f );
new Sandbox.CameraNoise.Shake( 1f, 0.6f );
if ( HasAmmo() )
{
IWeaponEvent.PostToGameObject( ViewModel, x => x.OnReloadStart() );
}
}
}
/// <summary>
/// Creates the projectile with the host's permission
/// </summary>
/// <param name="start"></param>
/// <param name="direction"></param>
/// <param name="speed"></param>
[Rpc.Host]
void CreateProjectile( Vector3 start, Vector3 direction, float speed )
{
if ( !Owner.IsValid() ) return;
var go = ProjectilePrefab?.Clone( start );
var projectile = go.GetComponent<RpgProjectile>();
Assert.True( projectile.IsValid(), "RpgProjectile not on projectile prefab" );
projectile.Instigator = Owner.PlayerData;
projectile.Explosive.Instigator = Owner.PlayerData;
go.NetworkSpawn();
Projectile = projectile;
projectile.UpdateDirection( direction, speed );
}
public override void DrawCrosshair( HudPainter hud, Vector2 center )
{
var tss = TimeSinceShoot.Relative.Remap( 0, 0.2f, 1, 0 );
var gap = 6 + Easing.EaseOut( tss ) * 32;
var len = 6;
var w = 2;
Color color = !CanShoot() ? UI.CrosshairInactive : UI.CrosshairActive;
// Define the size of the square
var squareSize = 64f;
// Draw the four edges of the square
hud.DrawLine( center + new Vector2( -squareSize / 2, -squareSize / 2 ), center + new Vector2( squareSize / 2, -squareSize / 2 ), w, color ); // Top edge
hud.DrawLine( center + new Vector2( squareSize / 2, -squareSize / 2 ), center + new Vector2( squareSize / 2, squareSize / 2 ), w, color ); // Right edge
hud.DrawLine( center + new Vector2( squareSize / 2, squareSize / 2 ), center + new Vector2( -squareSize / 2, squareSize / 2 ), w, color ); // Bottom edge
hud.DrawLine( center + new Vector2( -squareSize / 2, squareSize / 2 ), center + new Vector2( -squareSize / 2, -squareSize / 2 ), w, color ); // Left edge
if ( Laser )
{
gap += 32f;
len = 16;
hud.DrawLine( center + Vector2.Left * (len + gap), center + Vector2.Left * gap, w, color );
hud.DrawLine( center - Vector2.Left * (len + gap), center - Vector2.Left * gap, w, color );
hud.DrawLine( center + Vector2.Up * (len + gap), center + Vector2.Up * gap, w, color );
hud.DrawLine( center - Vector2.Up * (len + gap), center - Vector2.Up * gap, w, color );
}
}
}