146 lines
5.2 KiB
C#
146 lines
5.2 KiB
C#
using System.Linq;
|
|
using System.Threading;
|
|
using Code.Infrastructure.Input;
|
|
using Code.Infrastructure.Utils;
|
|
using Code.OfficeGame.BattleMode.Actions.HoloCopy;
|
|
using Code.OfficeGame.BattleMode.HitBoxes;
|
|
using Cysharp.Threading.Tasks;
|
|
using Reflex.Attributes;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace Code.OfficeGame.BattleMode.Actions.Attacks
|
|
{
|
|
public class BattleActionPlayerAttackMMA : BattleAction
|
|
{
|
|
[SerializeField] private HoloCop holoCop;
|
|
[SerializeField] private Animator animator;
|
|
private EntityHitBoxes _entityHitBoxes;
|
|
private AttackActionConfig _attackData;
|
|
public int EntryStateHash => Animator.StringToHash("WalkBlend");
|
|
|
|
private int _currentFrame;
|
|
private IInputService _inputService;
|
|
private CancellationTokenSource _waitForEnterTokenSource;
|
|
private BattleActionDecisionResultCode _decisionResultCode;
|
|
|
|
[Inject]
|
|
public void Construct(MultipleConfig<BattleActionParameters> attackData, IInputService inputService)
|
|
{
|
|
_inputService = inputService;
|
|
|
|
_entityHitBoxes = GetComponent<EntityHitBoxes>();
|
|
|
|
_attackData = (AttackActionConfig) attackData.Configs.SingleOrDefault(x=>x.ActionType == ActionType);
|
|
}
|
|
|
|
public override async UniTask<BattleActionDecisionResult> DecideAction()
|
|
{
|
|
_currentFrame = 0;
|
|
Finished = false;
|
|
|
|
_waitForEnterTokenSource = new CancellationTokenSource();
|
|
_decisionResultCode = BattleActionDecisionResultCode.CancelDecision;
|
|
|
|
_inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm,
|
|
ConfirmAttack);
|
|
_inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel,
|
|
CancelAttack);
|
|
|
|
holoCop.Simulate(TickHoloCopy, _waitForEnterTokenSource.Token).Forget();
|
|
|
|
await UniTask.WaitUntilCanceled(_waitForEnterTokenSource.Token).SuppressCancellationThrow();
|
|
|
|
_inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm,
|
|
ConfirmAttack);
|
|
_inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel,
|
|
CancelAttack);
|
|
|
|
_currentFrame = 0;
|
|
|
|
return new() { ResultCode = _decisionResultCode, FrameDuration = _attackData.TotalFrames};
|
|
}
|
|
|
|
private void CancelAttack(InputAction.CallbackContext obj)
|
|
{
|
|
_decisionResultCode = BattleActionDecisionResultCode.CancelDecision;
|
|
_waitForEnterTokenSource?.Cancel();
|
|
}
|
|
|
|
private void ConfirmAttack(InputAction.CallbackContext obj)
|
|
{
|
|
_decisionResultCode = BattleActionDecisionResultCode.Decided;
|
|
_waitForEnterTokenSource?.Cancel();
|
|
}
|
|
|
|
public override BattleActionType ActionType => BattleActionType.PlayerAttackMMA;
|
|
|
|
public override void Tick(float tickDelta)
|
|
{
|
|
if (Finished) return;
|
|
|
|
if (_currentFrame == 0)
|
|
{
|
|
animator.Play(_attackData.StateHash, 0, 0f);
|
|
}
|
|
|
|
_currentFrame++;
|
|
|
|
if (_currentFrame >= _attackData.HitboxStartFrame && _currentFrame <= _attackData.HitboxEndFrame)
|
|
{
|
|
_entityHitBoxes.EnableHitbox(_attackData.AttackingBodyPart);
|
|
_entityHitBoxes.CheckHitsForCurrentFrame(OnEnemyHit);
|
|
}
|
|
else
|
|
{
|
|
_entityHitBoxes.DisableAllHitboxes();
|
|
}
|
|
|
|
if (_currentFrame >= _attackData.TotalFrames)
|
|
{
|
|
CompleteOrInterruptAction();
|
|
}
|
|
}
|
|
|
|
private void OnEnemyHit(Collider enemyCollider)
|
|
{
|
|
Debug.Log($"Попадание в {enemyCollider.name} на {_currentFrame}-м кадре! Урон: {_attackData.Damage}");
|
|
var entityActor = enemyCollider.GetComponentInParent<EntityTimelineActor>();
|
|
entityActor.ForceDecideAction(BattleActionType.Stugger);
|
|
}
|
|
|
|
public void CompleteOrInterruptAction()
|
|
{
|
|
animator.Play(EntryStateHash, 0, 0f); // Создать None State и кинуть эту штуку туда
|
|
animator.Update(0f);
|
|
_entityHitBoxes.DisableAllHitboxes();
|
|
|
|
// TODO С нормальными анимациями не нужен будет рут моушен
|
|
animator.transform.localPosition = Vector3.zero;
|
|
animator.transform.localRotation = Quaternion.identity;
|
|
|
|
Finished = true;
|
|
}
|
|
|
|
// HoloCopy
|
|
|
|
private bool TickHoloCopy(HoloCop holoCop, float tickDelta)
|
|
{
|
|
if (_currentFrame == 0)
|
|
{
|
|
holoCop.Animator.Play(_attackData.StateHash, 0, 0f);
|
|
}
|
|
|
|
_currentFrame++;
|
|
|
|
if(_currentFrame >= _attackData.TotalFrames)
|
|
{
|
|
_currentFrame = 0;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |