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 BattleActionPositionDecider : BattleActionDecider { private CameraStateMachine _cameraStateMachine; private IInputService _inputService; private Vector3 _targetPosition; private LayerMask _navMeshMask; private const float StoppingDistance = 0.15f; public BattleActionPositionDecider( 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.Position; 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 PositionBattleActionDeciderResult() { ResultCode = _decisionResultCode, Position = _targetPosition }; } public override void UnmountDecider() { if (!IsMounted) return; _playerDecisionMarker.Toggle(false); _markerManager.ReleaseMarkerInstance(_playerDecisionMarker); _markerManager.ReleaseMarkerInstance(_playerLockedDecisionMarker); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Select, SelectPosition); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm, ConfirmPosition); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel, CancelPosition); _inputService.UnbindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Watchment, MarkPosition); IsMounted = false; } public override void MountDecider() { if (IsMounted) return; _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Select, SelectPosition); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Confirm, ConfirmPosition); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Cancel, CancelPosition); _inputService.BindActionPerformed((int)ActionMappings.BattleMode, (int)BattleModeActions.Watchment, MarkPosition); _playerLockedDecisionMarker = _markerManager.GetMarkerInstance(); _playerDecisionMarker = _markerManager.GetMarkerInstance(); _playerDecisionMarker.Toggle(true); IsMounted = true; } private MarkerManager _markerManager; private void CancelPosition(InputAction.CallbackContext obj) { _decisionResultCode = BattleActionDecisionResultCode.CancelDecision; _waitForEnterTokenSource?.Cancel(); } private void ConfirmPosition(InputAction.CallbackContext input) { _decisionResultCode = BattleActionDecisionResultCode.Decided; _waitForEnterTokenSource?.Cancel(); } private RaycastHit[] _hitBuffer = new RaycastHit[1]; private Vector3 _lastViewedPosition; private PlayerDecisionMarker _playerDecisionMarker; private PlayerDecisionMarker _playerLockedDecisionMarker; 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) return; var hit = _hitBuffer[0]; _playerDecisionMarker.MoveMarker(hit.point); _lastViewedPosition = hit.point; } private void SelectPosition(InputAction.CallbackContext input) { _targetPosition = _lastViewedPosition; _playerLockedDecisionMarker.MoveMarker(_targetPosition); _playerLockedDecisionMarker.Toggle(true); _waitForEnterTokenSource?.Cancel(); } } }