Files
BITFALL/Assets/Artists/Scripts/Equip/BITGun.cs
CortexCore cd02761be7 init
2023-06-08 14:09:50 +08:00

214 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITKit.Entities;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;
using BITKit.Animations;
using BITKit.StateMachine;
using Net.Client;
using Unity.Mathematics;
using UnityEngine.VFX;
using System.Diagnostics;
using BITFALL.Guns;
namespace BITFALL
{
public interface IGunState : IState { }
[System.Serializable]
public abstract class GunState : IGunState
{
public BITGun root;
public virtual void Initialize()
{
}
public virtual void OnStateEnter(IState old)
{
}
public virtual void OnStateExit(IState old, IState newState)
{
}
public virtual void OnStateUpdate()
{
}
public virtual void OnMovementCallback(IMovementCallback callback) { }
}
[System.Serializable]
public class GunStateMachine : MonoStateMachine<GunState> { }
public class BITGun : BITEquipBase<GunState>
{
// 常数引用
public const string _Movement = "Movement";
public const string _Run = "Run";
public const string _Aim = "Aim";
public const string _Interactive = "Interactive";
public const string _Equip = "Equip";
public const string _Fire = "Fire";
// 输入系统
[Header(Constant.Header.Input)]
public InputActionReference fireAction;
public InputActionReference aimAction;
public InputActionGroup actionGroup = new();
// 状态机
[Header(Constant.Header.State)]
public GunStateMachine stateMachine;
// 引用组件
[Header(Constant.Header.Components)]
public Renderer[] rendererComponents;
public VFXPlayer vfxPlayer;
// 引用预制体
[Header(Constant.Header.Prefabs)]
public AssetableGun assetable;
[Header(Constant.Header.Reference)]
// 内部变量
[Header(Constant.Header.InternalVariables)]
public ExpectState<bool> isFiring;
public ExpectState<bool> isAiming;
internal IntervalUpdate fireUpdater = new(0.32f);
internal IntervalUpdate brustFireUpdater = new(0.1f);
internal int burstFireCount;
#region
public override string AddressablePath => assetable.AdressablePath;
#endregion
public override void Entry()
{
animator.animator.enabled = true;
actionGroup.allowInput.SetElements(this, true);
foreach (var x in rendererComponents)
{
x.enabled = true;
}
isFiring.Reset();
stateMachine.StateMachine.TransitionState(stateMachine.states[0]);
entity.AddListener<IMovementCallback>(OnMovementCallback);
fireUpdater.updateInterval = 1f / assetable.FireMode.FireRate;
fireUpdater.Reset();
if(assetable.FireMode is BurstFireMode burstFireMode)
{
brustFireUpdater.updateInterval = burstFireMode.BurstFireInterval;
brustFireUpdater.Reset();
}
}
public override void Exit()
{
actionGroup.allowInput.SetElements(this, false);
foreach (var x in rendererComponents)
{
x.enabled = false;
}
isFiring.Reset();
animator.animator.enabled = false;
entity.RemoveListener<IMovementCallback>(OnMovementCallback);
}
public override void OnAwake()
{
actionGroup.RegisterCallback(fireAction, OnFire);
actionGroup.RegisterCallback(aimAction, OnAim);
stateMachine.OnStart();
}
public override void OnStart()
{
base.OnStart();
foreach (var x in rendererComponents)
{
x.enabled = false;
}
}
public override void OnUpdate(float deltaTime)
{
stateMachine?.CurrentState?.OnStateUpdate();
if(assetable.FireMode is BurstFireMode && isFiring.being)
{
if(brustFireUpdater)
{
Fire();
}
}
}
public void Fire()
{
//如果启用了指针则不开火
if(BITAppForUnity.AllowCursor)
{
return;
}
//播放射击动画
animator.Play(BITGun._Fire);
//调用IMovementCancenAction接口取消奔跑或冲刺
Entity.Invoke<IMovementCancelAction>(new CancelRunOrSprint());
//调用BulletManager生成子弹
BulletService.Spawn(new()
{
initiator = entity.Id,
pos = transform.position.Fix(),
rot = transform.rotation,
forward = transform.forward.Fix(),
//pos=transform.position,
//rot=transform.rotation,
});
//播放枪口MuzzleFlash
vfxPlayer.Excute();
//开火模式逻辑判断
switch (assetable.FireMode)
{
case AutoFireMode:
break;
case SemiFireMode:
//如果是半自动开火,则取消射击
isFiring.Reset();
break;
case BurstFireMode burstFireMode:
burstFireCount++;
isFiring.being = true;
if(burstFireCount > burstFireMode.BurstRound)
{
burstFireCount = 0;
isFiring.Reset();
}
break;
}
}
void OnFire(InputAction.CallbackContext context)
{
switch (assetable.FireMode)
{
case AutoFireMode:
case SemiFireMode:
isFiring.shouldBe = context.ReadValueAsButton();
break;
case BurstFireMode:
if(isFiring.being is false)
isFiring.shouldBe = context.ReadValueAsButton();//|| context.action.triggered;
break;
}
}
void OnAim(InputAction.CallbackContext context)
{
isAiming.shouldBe = context.ReadValueAsButton();
}
void OnMovementCallback(IMovementCallback callback)
{
stateMachine?.CurrentState?.OnMovementCallback(callback);
}
}
}