canto/Assets/Scripts/Item/Firearm.cs
2025-08-16 16:17:16 -04:00

126 lines
3 KiB
C#

using System;
using KitsuneCafe.Entities;
using KitsuneCafe.Extension;
using KitsuneCafe.SOAP;
using R3;
using UnityEngine;
namespace KitsuneCafe.ItemSystem
{
public class Firearm : MonoBehaviour, IEquippable, IDamaging
{
[SerializeField]
private BoolValue ready;
[SerializeField]
private BoolValue fire;
[SerializeField]
private BoolValue reload;
[SerializeField]
private Transform projectileOrigin;
[SerializeField]
private DamageSource damageSource;
[SerializeField]
private float projectileLength = 15;
[SerializeField]
private LayerMask layerMask;
public event EventHandler<bool> Readied;
public event EventHandler Attacked;
public event EventHandler Reloaded;
private InventoryInstance inventory;
private readonly RaycastHit[] hits = new RaycastHit[1];
private void OnValidate()
{
if (damageSource == null)
{
damageSource = GetComponent<DamageSource>();
}
}
public void OnEquip(InventoryInstance inventory)
{
this.inventory = inventory;
}
public void OnUnequip() { }
private void Start()
{
if (projectileOrigin == null)
{
projectileOrigin = transform;
}
var d = Disposable.CreateBuilder();
ready
.AsObservable()
.Subscribe(Ready)
.AddTo(ref d);
fire
.AsObservable()
.CombineLatest(ready.AsObservable(), (ready, fire) => ready && fire)
.WhereTrue()
.AsUnitObservable()
.Subscribe(_ => Fire())
.AddTo(ref d);
reload
.AsObservable()
.WhereTrue()
.Subscribe(_ => Reload())
.AddTo(ref d);
d.RegisterTo(destroyCancellationToken);
}
private void Ready(bool isReady)
{
Readied?.Invoke(this, isReady);
}
private void Fire()
{
var count = Physics.RaycastNonAlloc(
projectileOrigin.position,
projectileOrigin.forward,
hits,
projectileLength,
layerMask
);
if (count > 0)
{
damageSource.ApplyDamage(hits[0].collider);
}
Attacked?.Invoke(this, EventArgs.Empty);
}
private void Reload()
{
Reloaded?.Invoke(this, EventArgs.Empty);
Debug.Log("rewowd");
}
public void ApplyDamage(int amount, IDamageable target)
{
damageSource.ApplyDamage(amount, target);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawRay(projectileOrigin.position, projectileOrigin.forward * projectileLength);
}
}
}