using Jovian.ZoneSystem; 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 ZoneSystem zoneSystem; private readonly AdventureSettings adventureSettings; private readonly float maxDistance = 100f; private AdventureData adventureData; private bool partyCanMove; private Vector3 targetPosition; private bool shouldHover; private MapLocation currentSelectedPoi; private string previousZoneId; 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, ZoneSystem zoneSystem, AdventureData adventureData, AdventureSettings adventureSettings) { this.partyReference = partyReference; this.cameraController = cameraController; this.mapLocationsReference = mapLocationsReference; this.zoneSystem = zoneSystem; 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(mapReference.ValidateMoveLocation(hitInfoPoint)) { targetPosition = clickHit.point; partyCanMove = 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); VerifyZones(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 VerifyZones(Vector3 position) { var zoneContext = zoneSystem.QueryZone(position); var currentZoneId = zoneContext.resolvedZoneId; if(currentZoneId != previousZoneId) { if(!string.IsNullOrEmpty(currentZoneId)) { Debug.Log($"Entered zone: {currentZoneId} (encounter: {zoneContext.encounterTableId}, safe: {zoneContext.isSafe})"); } else if(!string.IsNullOrEmpty(previousZoneId)) { Debug.Log($"Left zone: {previousZoneId}"); } previousZoneId = currentZoneId; } } 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; } } }