using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; namespace Nox.Game { public class PartyMovementHandler { private readonly PartyReference partyReference; private readonly ICameraController cameraController; private readonly InputSystem_Actions inputActions; private readonly MapLocationsReference mapLocationsReference; private readonly EncounterHandler encounterHandler; private readonly AdventureSettings adventureSettings; private readonly float maxDistance = 100f; private readonly AdventureData adventureData; private bool partyCanMove; private Vector3 targetPosition; private bool shouldHover; private MapLocation currentSelectedPoi; private bool hasClicked; private bool skipNextClick; public LayerMask clickToMoveMask = LayerMask.GetMask("Clickable"); public LayerMask hoverOverMask = LayerMask.GetMask("Hoverable"); public PartyMovementHandler( PartyReference partyReference, ICameraController cameraController, MapLocationsReference mapLocationsReference, Input.InputSettings inputSettings, EncounterHandler encounterHandler, AdventureData adventureData, AdventureSettings adventureSettings) { this.partyReference = partyReference; this.cameraController = cameraController; this.mapLocationsReference = mapLocationsReference; this.encounterHandler = encounterHandler; this.adventureData = adventureData; this.adventureSettings = adventureSettings; inputActions = inputSettings.inputActions; } public void Initialize() { inputActions.Player.ClickOnMap.performed += OnClickOnMap; } public void ConsumeNextClick() { skipNextClick = true; } private void OnClickOnMap(InputAction.CallbackContext obj) { if(!obj.action.WasReleasedThisFrame()) { return; } hasClicked = true; } private void HandleHoverableLocation(RaycastHit hitInfo) { var go = hitInfo.collider.gameObject; if(!go.transform.parent.TryGetComponent(out MapLocation mapLocation)) { return; } currentSelectedPoi = mapLocation; mapLocation.highlight.gameObject.SetActive(true); } private void HandleClickableLocation() { var screenPos = inputActions.Player.Point.ReadValue(); var ray = cameraController.CameraReference.mainCamera.ScreenPointToRay(screenPos); if(!Physics.Raycast(ray, out var clickHit, maxDistance, clickToMoveMask, QueryTriggerInteraction.Ignore)) { return; } if(!clickHit.collider.gameObject.transform.parent.TryGetComponent(out MapReference mapReference)) { return; } if(ValidateMoveLocation(clickHit)) { targetPosition = clickHit.point; partyCanMove = true; } } private bool ValidateMoveLocation(object hitInfoPoint) { return true; } public void Tick() { HandleHover(); if(hasClicked) { hasClicked = false; // should it skip next click to avoid click-through from the pause menu? if(skipNextClick) { skipNextClick = false; return; } if(EventSystem.current.IsPointerOverGameObject()) { return; } HandleClickableLocation(); } if(!partyCanMove) { adventureData.isPartyMoving = false; return; } if(Vector3.Distance(partyReference.transform.position, targetPosition) < 0.05f) { partyReference.transform.position = targetPosition; VerifyPointsOfInterest(); partyCanMove = false; } adventureData.isPartyMoving = true; partyReference.transform.position = Vector3.MoveTowards( new Vector3(partyReference.transform.position.x, 0, partyReference.transform.position.z), targetPosition, Time.deltaTime * adventureSettings.partyBaseSpeed); encounterHandler?.CheckForEncounters(partyReference.transform.position); } private void HandleHover() { if(EventSystem.current.IsPointerOverGameObject()) { return; } var screenPos = inputActions.Player.Point.ReadValue(); var ray = cameraController.CameraReference.mainCamera.ScreenPointToRay(screenPos); if(Physics.Raycast(ray, out var hoverHit, maxDistance, hoverOverMask, QueryTriggerInteraction.Ignore)) { HandleHoverableLocation(hoverHit); } else { currentSelectedPoi?.highlight.gameObject.SetActive(false); currentSelectedPoi = null; } } private void VerifyPointsOfInterest() { foreach(var location in mapLocationsReference.mapLocations) { if(Vector3.Distance(location.mapLocation.transform.position, partyReference.transform.position) < 0.4f) { Debug.Log($"Arrived at {location.locationId}"); break; } } } public void Dispose() { inputActions.Player.ClickOnMap.performed -= OnClickOnMap; } } }