ShooterWeapon.cs

A weapon Component for a shooter that handles firing input, raytracing from the camera, playing a pistol sound, and applying impulse to rigidbodies hit by the shot.

Native Interop
using Sandbox;
using System.Linq;

public sealed class ShooterWeapon : Component
{
	[Property] public string WeaponName { get; set; } = "Pistol";
	[Property] public float DamageForce { get; set; } = 800f;
	[Property] public float FireRate { get; set; } = 0.25f;
	[Property] public float Range { get; set; } = 2000f;

	private TimeSince _timeSinceLastShot;

	protected override void OnUpdate()
	{
		if ( Input.Down( "attack1" ) && _timeSinceLastShot >= FireRate )
		{
			Shoot();
			_timeSinceLastShot = 0;
		}
	}

	private void Shoot()
	{
		var cam = Scene.Camera;
		if ( cam == null ) return;

		Vector3 startPos = cam.Transform.Position;
		Vector3 forwardDir = cam.Transform.World.Forward;

		var tr = Scene.Trace.Ray( startPos, startPos + forwardDir * Range )
			.IgnoreGameObjectHierarchy( GameObject )
			.Run();

		Sound.Play( "rust_pistol.shoot", Transform.Position );

		if ( tr.Hit && tr.GameObject != null )
		{
			// 1. Проверяем напрямую точное попадание в Rigidbody
			if ( tr.Body != null )
			{
				tr.Body.ApplyImpulseAt( tr.EndPosition, forwardDir * DamageForce );
				return;
			}

			// 2. Ищем Rigidbody на текущем объекте или у его родителей
			var targetBody = tr.GameObject.Components.Get<Rigidbody>( true ) 
			                 ?? tr.GameObject.Components.GetInAncestors<Rigidbody>();

			if ( targetBody != null )
			{
				targetBody.ApplyImpulse( forwardDir * DamageForce );
			}
		}
	}
}