using System; using KitsuneCafe.Entities; using KitsuneCafe.Extension; using R3; using UnityAtoms.BaseAtoms; using UnityEngine; namespace KitsuneCafe.ItemSystem { public class Firearm : MonoBehaviour, IEquippable, IDamaging { [SerializeField] private BoolVariable ready; [SerializeField] private BoolVariable fire; [SerializeField] private BoolVariable reload; [SerializeField] private Transform projectileOrigin; [SerializeField] private DamageSource damageSource; [SerializeField] private float projectileLength = 15; [SerializeField] private LayerMask layerMask; public event EventHandler 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(); } } public void OnEquip(InventoryInstance inventory) { this.inventory = inventory; } public void OnUnequip() { } private void Start() { if (projectileOrigin == null) { projectileOrigin = transform; } var d = Disposable.CreateBuilder(); var readyObs = ready.ObserveChange().ToObservable(); readyObs .Subscribe(Ready) .AddTo(ref d); fire .ObserveChange() .ToObservable() .CombineLatest(readyObs, (ready, fire) => ready && fire) .WhereTrue() .AsUnitObservable() .Subscribe(_ => Fire()) .AddTo(ref d); reload .ObserveChange() .ToObservable() .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); } 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); } } }