sasalka/Code/Weapons/Weapon.cs
2025-06-26 23:24:52 +03:00

119 lines
2.6 KiB
C#

using System.Threading.Tasks;
using Sandbox.UI;
using Sasalka;
namespace Sandbox.Weapons;
public sealed class Weapon : AmmoUseableBase
{
[Property] public SkinnedModelRenderer GunRenderer { get; private set; }
[Property] public GameObject MuzzleLight { get; private set; }
[Property] public GameObject particlePrefab { get; set; }
[Property] public GameObject bloodParticle { get; set; }
[Property] public WeaponItemDefinition WeaponDefinition { get; set; }
private SoundPointComponent _sound;
private Rigidbody _rigidbody;
protected override void OnStart()
{
base.OnStart();
_sound = GameObject.GetComponent<SoundPointComponent>(true);
}
public override void OnEquipped()
{
_rigidbody = GameObject.Components.Get<Rigidbody>();
_rigidbody.Enabled = false;
GameObject.Components.Get<PickupItem>().Enabled = false;
}
protected override WeaponItemDefinition GetWeaponDefinition()
{
return WeaponDefinition;
}
public void Attack()
{
AttackEffects();
Vector3 startPos = Scene.Camera.WorldPosition;
Vector3 dir = Scene.Camera.WorldRotation.Forward;
float maxDistance = WeaponDefinition?.Range ?? 1000f;
var tr = Scene.Trace
.Ray(startPos, startPos + dir * maxDistance)
.IgnoreGameObjectHierarchy(Dedugan.Local.GameObject)
.WithoutTags("weapon")
.UseHitboxes()
.Run();
if (tr.Hit)
{
if (tr.Hitbox != null)
{
var boneIndex = tr.Hitbox.Bone.Index;
var components = tr.GameObject.Components;
// Кэшируем компоненты для избежания повторных поисков
var dedugan = components.Get<Dedugan>();
var enemy = components.Get<Enemy>();
var hasTarget = dedugan.IsValid() || enemy.IsValid();
if (hasTarget)
{
CreateHitEffects(tr.EndPosition, tr.Normal, true);
}
if (dedugan.IsValid())
{
dedugan.ReportHit(dir, boneIndex);
}
if (enemy.IsValid())
{
enemy.ReportHit(dir, boneIndex);
}
}
else
{
CreateHitEffects(tr.EndPosition, tr.Normal);
}
}
}
[Rpc.Broadcast]
private void CreateHitEffects(Vector3 position, Vector3 normal, bool blood = false)
{
var rot = Rotation.LookAt(normal);
DestroyAsync(
blood
? bloodParticle.Clone(position, rot)
: particlePrefab.Clone(position, rot), 0.5f);
}
async void DestroyAsync(GameObject go, float delay)
{
await GameTask.DelaySeconds(delay);
go.Destroy();
}
[Rpc.Broadcast]
public void AttackEffects()
{
_sound?.StartSound();
MuzzleLight.Enabled = true;
GunRenderer.Set("Fire", true);
GameTask.DelaySeconds(0.05f).ContinueWith((_) =>
{
MuzzleLight.Enabled = false;
});
}
protected override void OnUse()
{
Attack();
}
}