r2mods/ilspy_dump/ror2_csproj/RoR2/PathFollower.cs

340 lines
8.5 KiB
C#
Raw Normal View History

2024-10-04 07:26:37 +00:00
using System;
using System.Collections.Generic;
using HG;
using RoR2.Navigation;
using UnityEngine;
namespace RoR2;
public class PathFollower
{
public class Drawer : IDisposable
{
private PathFollower _target;
private WireMeshBuilder wireMeshBuilder;
private DebugOverlay.MeshDrawer passDistanceDrawer;
private DebugOverlay.MeshDrawer pathDrawer;
private List<Path.Waypoint> waypointCache;
private int cachedCurrentWaypoint;
public PathFollower target
{
get
{
return _target;
}
set
{
if (_target != value)
{
_target = value;
pathDrawer.enabled = _target != null;
passDistanceDrawer.enabled &= _target != null;
waypointCache.Clear();
}
}
}
public Drawer(PathFollower target)
{
cachedCurrentWaypoint = -1;
waypointCache = new List<Path.Waypoint>();
wireMeshBuilder = new WireMeshBuilder();
passDistanceDrawer = DebugOverlay.GetMeshDrawer();
pathDrawer = DebugOverlay.GetMeshDrawer();
int num = 32;
float sliceSize = 360f / (float)num;
Vector3 halfForward = Vector3.forward * 0.5f;
Vector3 p = GetCirclePosition(-1);
for (int j = 0; j < num; j++)
{
Vector3 vector = GetCirclePosition(j);
wireMeshBuilder.AddLine(p, Color.yellow, vector, Color.yellow);
p = vector;
}
passDistanceDrawer.hasMeshOwnership = true;
passDistanceDrawer.mesh = wireMeshBuilder.GenerateMesh();
wireMeshBuilder.Clear();
pathDrawer.mesh = new Mesh();
RoR2Application.onFixedUpdate += FixedUpdate;
this.target = target;
Vector3 GetCirclePosition(int i)
{
return Quaternion.AngleAxis((float)i * sliceSize, Vector3.up) * halfForward;
}
}
private void SetWaypoints(List<Path.Waypoint> newWaypoints, int newCurrentWaypoint)
{
if (!ListUtils.SequenceEquals(waypointCache, newWaypoints) || !cachedCurrentWaypoint.Equals(newCurrentWaypoint))
{
waypointCache.Clear();
waypointCache.AddRange(newWaypoints);
cachedCurrentWaypoint = newCurrentWaypoint;
RebuildPathMesh();
}
}
private void RebuildPathMesh()
{
List<Path.Waypoint> waypoints = target.waypoints;
Color nodeColor;
Color traversedPathColor;
Color currentPathColor;
Color untraversedPathColor;
Color drawPathColor;
if (waypoints.Count > 1)
{
nodeColor = new Color(1f, 0.5f, 0.5f, 0.25f);
traversedPathColor = new Color(0.5f, 0.5f, 0.5f, 0.25f);
currentPathColor = new Color(1f, 0.5f, 0.5f, 1f);
untraversedPathColor = new Color(0.5f, 0f, 0f, 0.25f);
target.nodeGraph.GetNodePosition(waypoints[0].nodeIndex, out var position2);
drawPathColor = untraversedPathColor;
DrawNode(position2);
for (int j = 1; j < waypoints.Count; j++)
{
UpdateDrawPathColor(j);
target.nodeGraph.GetNodePosition(waypoints[j].nodeIndex, out var position3);
wireMeshBuilder.AddLine(position2, drawPathColor, position3, drawPathColor);
DrawNode(position3);
position2 = position3;
}
}
wireMeshBuilder.GenerateMesh(pathDrawer.mesh);
wireMeshBuilder.Clear();
void DrawNode(Vector3 position)
{
wireMeshBuilder.AddLine(position - Vector3.up, nodeColor, position + Vector3.up, nodeColor);
}
void UpdateDrawPathColor(int i)
{
if (cachedCurrentWaypoint == i)
{
drawPathColor = currentPathColor;
}
else if (cachedCurrentWaypoint < i)
{
drawPathColor = untraversedPathColor;
}
else
{
drawPathColor = traversedPathColor;
}
}
}
private void FixedUpdate()
{
if (target != null)
{
passDistanceDrawer.enabled = target.currentWaypoint < target.waypoints.Count;
if (passDistanceDrawer.enabled)
{
target.nodeGraph.GetNodePosition(target.waypoints[target.currentWaypoint].nodeIndex, out var position);
passDistanceDrawer.transform.position = position;
passDistanceDrawer.transform.localScale = Vector3.one * target.debugPassDistance;
}
SetWaypoints(target.waypoints, target.currentWaypoint);
}
}
public void Dispose()
{
target = null;
RoR2Application.onFixedUpdate -= FixedUpdate;
pathDrawer.Dispose();
passDistanceDrawer.Dispose();
wireMeshBuilder.Dispose();
}
}
private Vector3 currentPosition;
private const float waypointPassDistance = 2f;
private const float waypointPassYTolerance = 2f;
private List<Path.Waypoint> waypoints = new List<Path.Waypoint>();
private int currentWaypoint;
private NodeGraph.NodeIndex previousNode = NodeGraph.NodeIndex.invalid;
private float debugPassDistance;
public NodeGraph nodeGraph { get; private set; }
public NodeGraph.NodeIndex nextNode { get; private set; } = NodeGraph.NodeIndex.invalid;
public bool isFinished => currentWaypoint >= waypoints.Count;
public bool isOnJumpLink => false;
public bool hasPassedFirstWaypoint => currentWaypoint > 0;
public bool nextWaypointNeedsJump
{
get
{
if (waypoints.Count > 0 && currentWaypoint < waypoints.Count)
{
return waypoints[currentWaypoint].minJumpHeight > 0f;
}
return false;
}
}
private static float DistanceXZ(Vector3 a, Vector3 b)
{
a.y = 0f;
b.y = 0f;
return Vector3.Distance(a, b);
}
public float CalculateJumpVelocityNeededToReachNextWaypoint(float moveSpeed)
{
if (!nextWaypointNeedsJump)
{
return 0f;
}
Vector3 a = currentPosition;
if (!GetNextNodePosition(out var nextPosition))
{
return 0f;
}
return Trajectory.CalculateInitialYSpeed(Trajectory.CalculateGroundTravelTime(moveSpeed, DistanceXZ(a, nextPosition)), nextPosition.y - a.y);
}
public void UpdatePosition(Vector3 newPosition)
{
Vector3 vector = currentPosition;
currentPosition = newPosition;
if (GetNextNodePosition(out var nextPosition))
{
Vector3 vector2 = nextPosition - currentPosition;
Vector3 vector3 = vector2;
vector3.y = 0f;
float num = 2f;
Vector3 inNormal = currentPosition - vector;
Plane plane = new Plane(inNormal, nextPosition);
if (plane.GetSide(currentPosition) != plane.GetSide(vector))
{
num += 2f;
}
if (waypoints.Count > currentWaypoint + 1 && waypoints[currentWaypoint + 1].minJumpHeight > 0f)
{
num = 0.5f;
}
debugPassDistance = num;
if (num * num >= vector3.sqrMagnitude && Mathf.Abs(vector2.y) <= 2f)
{
SetWaypoint(currentWaypoint + 1);
}
}
_ = nextNode != NodeGraph.NodeIndex.invalid;
}
private void SetWaypoint(int newWaypoint)
{
currentWaypoint = Math.Min(newWaypoint, waypoints.Count);
if (currentWaypoint == waypoints.Count)
{
nextNode = NodeGraph.NodeIndex.invalid;
previousNode = NodeGraph.NodeIndex.invalid;
}
else
{
nextNode = waypoints[currentWaypoint].nodeIndex;
previousNode = ((currentWaypoint > 0) ? waypoints[currentWaypoint - 1].nodeIndex : NodeGraph.NodeIndex.invalid);
}
}
public void Reset()
{
nodeGraph = null;
nextNode = NodeGraph.NodeIndex.invalid;
previousNode = NodeGraph.NodeIndex.invalid;
waypoints.Clear();
currentWaypoint = 0;
}
public void SetPath(Path newPath)
{
if (nodeGraph != newPath.nodeGraph)
{
Reset();
nodeGraph = newPath.nodeGraph;
}
waypoints.Clear();
newPath.WriteWaypointsToList(waypoints);
currentWaypoint = 0;
for (int i = 1; i < waypoints.Count; i++)
{
if (waypoints[i].nodeIndex == nextNode && waypoints[i - 1].nodeIndex == previousNode)
{
currentWaypoint = i;
break;
}
}
SetWaypoint(currentWaypoint);
}
private void GetPreviousAndNextNodePositions(out Vector3? previousPosition, out Vector3? nextPosition)
{
previousPosition = null;
nextPosition = null;
if (!(nodeGraph == null))
{
if (nodeGraph.GetNodePosition(previousNode, out var position))
{
previousPosition = position;
}
if (nodeGraph.GetNodePosition(nextNode, out position))
{
nextPosition = position;
}
}
}
private bool GetNextNodePosition(out Vector3 nextPosition)
{
if (nodeGraph != null && nextNode != NodeGraph.NodeIndex.invalid && nodeGraph.GetNodePosition(nextNode, out nextPosition))
{
return true;
}
nextPosition = currentPosition;
return false;
}
public Vector3? GetNextPosition()
{
if (GetNextNodePosition(out var nextPosition))
{
return nextPosition;
}
return null;
}
public void DebugDrawPath(Color color, float duration)
{
for (int i = 1; i < waypoints.Count; i++)
{
nodeGraph.GetNodePosition(waypoints[i].nodeIndex, out var position);
nodeGraph.GetNodePosition(waypoints[i - 1].nodeIndex, out var position2);
Debug.DrawLine(position, position2, color, duration);
}
for (int j = 0; j < waypoints.Count; j++)
{
nodeGraph.GetNodePosition(waypoints[j].nodeIndex, out var position3);
Debug.DrawLine(position3 + Vector3.up, position3 - Vector3.up, color, duration);
}
}
}