forked from Shardstone/trail-into-darkness
151 lines
5.7 KiB
C#
151 lines
5.7 KiB
C#
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 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,
|
|
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<Vector2>();
|
|
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<Vector2>();
|
|
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;
|
|
}
|
|
}
|
|
}
|