using System; using System.Threading; using Code.Infrastructure.Camera; using Code.Infrastructure.Input; using Code.OfficeGame.BattleMode.Actions.Player; using Code.OfficeGame.BattleMode.Marker; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.InputSystem; namespace Code.OfficeGame.BattleMode.Actions.Deciders { public class RotationBattleActionDecider: BattleActionDecider { private CameraStateMachine _cameraStateMachine; private IInputService _inputService; private Quaternion _targetRotation; private LayerMask _navMeshMask; public RotationBattleActionDecider( CameraStateMachine cameraStateMachine, IInputService inputService, MarkerManager markerManager) { _markerManager = markerManager; _cameraStateMachine = cameraStateMachine; _inputService = inputService; _navMeshMask = LayerMask.GetMask("Environment"); } private CancellationTokenSource _waitForEnterTokenSource; private BattleActionDecisionResultCode _decisionResultCode; public override DeciderType DeciderType => DeciderType.Rotation; public override async UniTask GetDecision() { if (!IsMounted) throw new Exception("Decider is not mounted"); // А почему бы и нет? _waitForEnterTokenSource = new CancellationTokenSource(); _decisionResultCode = BattleActionDecisionResultCode.Deciding; await UniTask.WaitUntilCanceled(_waitForEnterTokenSource.Token).SuppressCancellationThrow(); _waitForEnterTokenSource.Dispose(); _waitForEnterTokenSource = null; return new RotationBattleActionDeciderResult() { ResultCode = _decisionResultCode, Rotation = _targetRotation }; } public override void UnmountDecider() { if (!IsMounted) return; _playerDecisionMarker.Toggle(false); _markerManager.ReleaseMarkerInstance(_playerDecisionMarker); _playerLockedDecisionMarker.Toggle(false); _markerManager.ReleaseMarkerInstance(_playerLockedDecisionMarker); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Select, SelectRotation); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm, ConfirmRotation); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel, CancelRotation); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Watchment, MarkPosition); IsMounted = false; } public override void MountDecider(EntityProperties entityProperties) { if (IsMounted) return; _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Select, SelectRotation); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm, ConfirmRotation); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel, CancelRotation); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Watchment, MarkPosition); _playerLockedDecisionMarker = _markerManager.GetMarkerInstance(); _playerDecisionMarker = _markerManager.GetMarkerInstance(); _playerDecisionMarker.Toggle(true); _targetRotation = entityProperties.KinematicCharacterMotor.TransientRotation; _entityPosition = entityProperties.KinematicCharacterMotor.TransientPosition; IsMounted = true; } private MarkerManager _markerManager; private void CancelRotation(InputAction.CallbackContext obj) { _decisionResultCode = BattleActionDecisionResultCode.CancelDecision; _waitForEnterTokenSource?.Cancel(); } private void ConfirmRotation(InputAction.CallbackContext input) { _decisionResultCode = BattleActionDecisionResultCode.Decided; _waitForEnterTokenSource?.Cancel(); } private RaycastHit[] _hitBuffer = new RaycastHit[1]; private PlayerDecisionMarker _playerDecisionMarker; private PlayerDecisionMarker _playerLockedDecisionMarker; private Vector3 _entityPosition; private void MarkPosition(InputAction.CallbackContext input) { var position = _cameraStateMachine.Camera.transform.position; var direction = _cameraStateMachine.Camera.transform.forward; var hitCount = Physics.RaycastNonAlloc( position, direction, _hitBuffer, Mathf.Infinity, _navMeshMask); if (hitCount == 0 || _entityPosition == Vector3.zero) return; var hit = _hitBuffer[0]; var lookDirection = hit.point - _entityPosition; _targetRotation = Quaternion.LookRotation(lookDirection.normalized, Vector3.up); _playerDecisionMarker.transform.rotation = _targetRotation; _playerDecisionMarker.transform.position = hit.point; } private void SelectRotation(InputAction.CallbackContext input) { _playerLockedDecisionMarker.MoveMarker(_entityPosition); _playerLockedDecisionMarker.transform.rotation = _targetRotation; _playerLockedDecisionMarker.Toggle(true); _waitForEnterTokenSource?.Cancel(); } } }