124 lines
5.9 KiB
C#
124 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Grid;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace Actions {
|
|
public class MoveAction : BaseAction {
|
|
private const float moveSpeed = 4f;
|
|
private const float rotationSpeed = 10f;
|
|
private const float stoppingDistance = 0.1f;
|
|
private const int pathfindingDistanceMultiplier = 10;
|
|
private const float DIFFERENT_FLOORS_TELEPORT_TIMER_MAX = .5f;
|
|
|
|
[FormerlySerializedAs("MaxMoveDistance")] [SerializeField]
|
|
private int maxMoveDistance = 4;
|
|
|
|
private int currentPositionIndex;
|
|
private float differentFloorsTeleportTimer;
|
|
private bool isChangingFloors;
|
|
private List<Vector3> PositionList { get; set; }
|
|
|
|
|
|
protected override void Awake() {
|
|
base.Awake();
|
|
ActionName = "Move";
|
|
}
|
|
|
|
private void Update() {
|
|
if (!IsActive) return;
|
|
|
|
Vector3 targetPosition = PositionList[currentPositionIndex];
|
|
if (isChangingFloors) {
|
|
//Stop and teleport logic
|
|
differentFloorsTeleportTimer -= Time.deltaTime;
|
|
Vector3 targetSameFloorPosition = targetPosition;
|
|
targetSameFloorPosition.y = transform.position.y;
|
|
Vector3 rotateDirection = (targetSameFloorPosition - Unit.GetWorldPosition()).normalized;
|
|
transform.forward = Vector3.Slerp(transform.forward, rotateDirection, rotationSpeed * Time.deltaTime);
|
|
if (differentFloorsTeleportTimer < 0f) {
|
|
isChangingFloors = false;
|
|
transform.position = targetPosition;
|
|
}
|
|
}
|
|
else {
|
|
//Regular move logic
|
|
Vector3 moveDirection = (targetPosition - Unit.GetWorldPosition()).normalized;
|
|
transform.forward = Vector3.Slerp(transform.forward, moveDirection, rotationSpeed * Time.deltaTime); //Rotate towards targetPosition
|
|
transform.position += moveSpeed * Time.deltaTime * moveDirection; //Move towards targetPosition
|
|
}
|
|
|
|
if (!(Vector3.Distance(targetPosition, Unit.GetWorldPosition()) < stoppingDistance)) return;
|
|
|
|
currentPositionIndex++;
|
|
if (currentPositionIndex >= PositionList.Count) {
|
|
OnStopMoving?.Invoke(this, EventArgs.Empty);
|
|
ActionComplete();
|
|
}
|
|
else {
|
|
targetPosition = PositionList[currentPositionIndex];
|
|
GridPosition targetGridPosition = LevelGrid.Instance.GetGridPosition(targetPosition);
|
|
GridPosition unitGridPosition = LevelGrid.Instance.GetGridPosition(transform.position);
|
|
if (targetGridPosition.Floor == unitGridPosition.Floor) return; //Same floor
|
|
isChangingFloors = true;
|
|
differentFloorsTeleportTimer = DIFFERENT_FLOORS_TELEPORT_TIMER_MAX;
|
|
OnChangeFloorsStarted?.Invoke(this, new() { unitGridPosition = unitGridPosition, targetGridPosition = targetGridPosition });
|
|
}
|
|
}
|
|
|
|
public event EventHandler OnStartMoving;
|
|
public event EventHandler OnStopMoving;
|
|
public event EventHandler<ChangeFloorsStartedEventArgs> OnChangeFloorsStarted;
|
|
|
|
public override List<GridPosition> GetValidActionGridPositionList() {
|
|
List<GridPosition> validGridPositionList = new();
|
|
GridPosition unitGridPosition = Unit.GridPosition;
|
|
|
|
for (int xPosition = -maxMoveDistance; xPosition <= maxMoveDistance; xPosition++) {
|
|
for (int zPosition = -maxMoveDistance; zPosition <= maxMoveDistance; zPosition++) {
|
|
for (int floor = -maxMoveDistance; floor < maxMoveDistance; floor++) {
|
|
GridPosition offsetGridPosition = new(xPosition, zPosition, floor);
|
|
GridPosition testGridPosition = unitGridPosition + offsetGridPosition;
|
|
|
|
if (!LevelGrid.Instance.IsValidGridPosition(testGridPosition)) continue; //Only return valid grid positions
|
|
if (unitGridPosition == testGridPosition) continue; //Same grid position where the unit is already at
|
|
if (LevelGrid.Instance.HasAnyUnitOnGridPosition(testGridPosition)) continue; //Grid position already occopied with anther unit
|
|
if (!Pathfinding.Instance.IsWalkableGridPosition(testGridPosition)) continue; //Obstacle on path
|
|
if (!Pathfinding.Instance.HasPath(unitGridPosition, testGridPosition)) continue; //No path available
|
|
|
|
if (Pathfinding.Instance.GetPathLength(unitGridPosition, testGridPosition) > maxMoveDistance * pathfindingDistanceMultiplier) continue; //Pathlength is to long
|
|
|
|
validGridPositionList.Add(testGridPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
return validGridPositionList;
|
|
}
|
|
|
|
public override void TakeAction(GridPosition gridPosition, Action onMoveCompleted) {
|
|
List<GridPosition> pathGridPositionList = Pathfinding.Instance.FindPath(Unit.GridPosition, gridPosition, out _);
|
|
|
|
currentPositionIndex = 0;
|
|
PositionList = new();
|
|
|
|
foreach (GridPosition pathGridPosition in pathGridPositionList) {
|
|
PositionList.Add(LevelGrid.Instance.GetWorldPosition(pathGridPosition));
|
|
}
|
|
|
|
OnStartMoving?.Invoke(this, EventArgs.Empty);
|
|
ActionStart(onMoveCompleted);
|
|
}
|
|
|
|
protected override EnemyAIAction GetEnemyAIAction(GridPosition gridPosition) {
|
|
int targetCountAtGridPosition = Unit.GetAction<ShootAction>().GetTargetCountAtPosition(gridPosition);
|
|
return new(gridPosition, targetCountAtGridPosition * 10);
|
|
}
|
|
|
|
public class ChangeFloorsStartedEventArgs : EventArgs {
|
|
public GridPosition targetGridPosition;
|
|
public GridPosition unitGridPosition;
|
|
}
|
|
}
|
|
} |