Move navigational helper functions into ncNavInfo

This commit is contained in:
Marco Cawthorne 2025-01-13 17:03:40 -08:00
parent fd90be879c
commit 6867396b09
8 changed files with 15 additions and 308 deletions

View file

@ -19,3 +19,4 @@
#include "route.h"
#include "node_edit.h"
#include "way_convert.h"
#include "NavInfo.h"

View file

@ -3,4 +3,5 @@ nodes.qc
route.qc
node_edit.qc
way_convert.qc
NavInfo.qc
#endlist

View file

@ -47,63 +47,4 @@ void Nodes_Flush(void);
void Nodes_Init(void);
bool Nodes_Available(void);
vector Nodes_PositionOfClosestNode(vector);
/** Returns the position of a spot that'll provide cover from the specified enemy.
@param targetEnemy The enemy to hide from.
@return Absolute position of a valid cover spot. */
vector Nodes_FindCoverFromEnemy(ncActor targetEnemy);
/** Returns the position of a spot that'll be behind where you're currently standing
@param targetPosition The position to back away from.
@param eulerDirection The direction we're looking in, in euler-angles.
@return Absolute position of a valid cover spot. */
vector Nodes_FindBackFromPosition(vector targetPosition, vector eulerDirection);
/** Returns the position of a spot that'll provide cover from the specified enemy, closest to a specified node.
@param targetEnemy The enemy to hide from.
@param nodePosition The position we should get closest to.
@return Absolute position of a valid cover spot. */
vector Nodes_FindCoverFromEnemyNearNode(ncActor targetEnemy, vector nodePosition);
/** Returns the position of a spot that'll provide cover from the specified enemy, furthest from a specified node.
@param targetEnemy The enemy to hide from.
@param nodePosition The position we should get as far away from as possible from.
@return Absolute position of a valid cover spot. */
vector Nodes_FindCoverFromEnemyFarNode(ncActor targetEnemy, vector nodePosition);
/** Returns the position of a spot that'll provide cover from the specified enemy.
@param traceEntity The entity which will be testing for collisions.
@param targetOrigin The spot to hide from.
@return Absolute position of a valid cover spot. */
vector Nodes_FindCoverFromPosition(entity traceEntity, vector targetOrigin);
/** Returns the position of a spot that is accessible within a specified position.
@param traceEntity The entity which will be testing for collisions.
@param targetOrigin The spot to be near.
@param minRadius The mininum distance / search radius from the targetOrigin.
@param maxRadius The maximum Radius in which we'll look for a free spot.
@return Absolute position of a valid cover spot. */
vector Nodes_FindEmptySpotNearPosition(entity traceEntity, vector position, float minRadius, float maxRadius);
/** Returns the position of a spot that is far away within a specified position.
@param traceEntity The entity which will be testing for collisions.
@param targetOrigin The spot to be near.
@param minRadius The mininum distance / search radius from the targetOrigin.
@param maxRadius The maximum Radius in which we'll look for a free spot.
@return Absolute position of a valid cover spot. */
vector Nodes_FindEmptySpotAwayFromPosition(entity traceEntity, vector position, float minRadius, float maxRadius);
/** @} */ // end of nav

View file

@ -187,235 +187,3 @@ Nodes_Flush(void)
{
NodeEdit_Flush();
}
/* Helper functions for tasks/nav */
vector
Nodes_PositionOfClosestNode(vector pointOrigin)
{
float bestDistance = COST_INFINITE;
int bestNodeID = -1;
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeDistance = distanceSquared(nodePosition, pointOrigin);
if (nodeDistance < bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindCoverFromEnemy(ncActor targetEnemy)
{
float bestDistance = COST_INFINITE;
int bestNodeID = -1i;
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeRadius = g_pNodes[i].m_flRadius;
float nodeDistance = distanceSquared(nodePosition, targetEnemy.origin);
traceline(targetEnemy.origin, nodePosition, MOVE_NORMAL, targetEnemy);
if (trace_fraction < 1.0 && nodeDistance < bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
if (bestNodeID != -1i) {
return g_vec_null;
}
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindBackFromPosition(vector targetPosition, vector eulerDirection)
{
float bestDistance = COST_INFINITE;
int bestNodeID = -1;
vector forwardDir = anglesToForward(eulerDirection);
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeRadius = g_pNodes[i].m_flRadius;
float nodeDistance = distanceSquared(nodePosition, targetPosition);
traceline(targetPosition, nodePosition, MOVE_NORMAL, world);
if (trace_fraction < 1.0 && nodeDistance < bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindCoverFromEnemyNearNode(ncActor targetEnemy, vector targetNode)
{
float bestDistance = COST_INFINITE;
int bestNodeID = -1;
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeDistance = distanceSquared(nodePosition, targetNode);
traceline(targetEnemy.origin, nodePosition, MOVE_NORMAL, targetEnemy);
if (trace_fraction < 1.0 && nodeDistance < bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindCoverFromEnemyFarNode(ncActor targetEnemy, vector targetNode)
{
float bestDistance = 0;
int bestNodeID = -1;
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeDistance = distanceSquared(nodePosition, targetNode);
traceline(targetEnemy.origin, nodePosition, MOVE_NORMAL, targetEnemy);
if (trace_fraction < 1.0 && nodeDistance > bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindCoverFromPosition(entity traceEntity, vector targetOrigin)
{
float bestDistance = COST_INFINITE;
int bestNodeID = -1i;
#if 0
if (g_iNodes <= 0i) {
return Nodes_FindEmptySpotNearPosition(world, targetOrigin, 512.0, 4096.0f);
}
#endif
for (int i = 0; i < g_iNodes; i++) {
vector nodePosition = g_pNodes[i].m_vecOrigin;
float nodeDistance = distanceSquared(nodePosition, traceEntity.origin);
traceline(nodePosition, targetOrigin, MOVE_NORMAL, traceEntity);
if ((trace_ent == world || trace_fraction < 1.0) && nodeDistance < bestDistance) {
bestDistance = nodeDistance;
bestNodeID = i;
}
}
if (bestNodeID) {
return (g_vec_null);
}
NSError("%v", (g_pNodes[bestNodeID].m_vecOrigin));
return (g_pNodes[bestNodeID].m_vecOrigin);
}
vector
Nodes_FindEmptySpotNearPosition(entity traceEntity, vector position, float minRadius, float maxRadius)
{
float bestYaw = 0.0f;
float bestDist = 0.0f;
vector testAngle = g_vec_null;
vector testPos = g_vec_null;
for (float yawTest = 0.0f; yawTest < 360.0f; yawTest += 10.0f) {
vector testPos;
float distSquared;
vector testAngle = traceEntity.angles = [0, yawTest, 0];
testAngle[0] = testAngle[2] = 0.0f;
makevectors(testAngle);
testPos = position + (v_forward * 2048.0f);
tracebox(position, traceEntity.mins, traceEntity.maxs, testPos, MOVE_NORMAL, traceEntity);
distSquared = distance(position, trace_endpos);
if (distSquared > bestDist) {
bestYaw = yawTest;
bestDist = distSquared;
}
}
/* cancel early */
if (bestDist <= minRadius) {
return (g_vec_null);
}
for (float dist = minRadius; dist < maxRadius; dist += ((maxRadius - minRadius) / 16.0f)) {
vector testAngle = [0, bestYaw, 0];
testAngle[0] = testAngle[2] = 0.0f;
makevectors(testAngle);
vector testPos = position + (v_forward * dist);
tracebox(testPos, traceEntity.mins, traceEntity.maxs, testPos, MOVE_NORMAL, traceEntity);
if (!trace_startsolid) {
return (testPos);
}
}
return (g_vec_null);
}
vector
Nodes_FindEmptySpotAwayFromPosition(entity traceEntity, vector position, float minRadius, float maxRadius)
{
float bestYaw = 0.0f;
float bestDist = 0.0f;
vector testAngle = g_vec_null;
vector testPos = g_vec_null;
for (float yawTest = 0.0f; yawTest < 360.0f; yawTest += 10.0f) {
vector testPos;
float distSquared;
vector testAngle = traceEntity.angles = [0, yawTest, 0];
testAngle[0] = testAngle[2] = 0.0f;
makevectors(testAngle);
testPos = position + (v_forward * 2048.0f);
tracebox(position, traceEntity.mins, traceEntity.maxs, testPos, MOVE_NORMAL, traceEntity);
distSquared = distance(position, trace_endpos);
if (distSquared > bestDist) {
bestYaw = yawTest;
bestDist = distSquared;
}
}
/* cancel early */
if (bestDist <= minRadius) {
return (g_vec_null);
}
for (float dist = maxRadius; dist > minRadius; dist -= ((maxRadius - minRadius) / 16.0f)) {
vector testAngle = [0, bestYaw, 0];
testAngle[0] = testAngle[2] = 0.0f;
makevectors(testAngle);
vector testPos = position + (v_forward * dist);
tracebox(testPos, traceEntity.mins, traceEntity.maxs, testPos, MOVE_NORMAL, traceEntity);
if (!trace_startsolid) {
return (testPos);
}
}
return (g_vec_null);
}

View file

@ -147,10 +147,6 @@ ncSchedule::Think(void)
if (!m_controllingActor) {
shouldCancel = true;
} else {
if (m_controllingActor.IsAlive() == false) {
shouldCancel = true;
}
if (m_controllingActor.m_activeSchedule != this) {
shouldCancel = true;
}

View file

@ -167,17 +167,16 @@ Spawn_TeleportToSpawn(entity targetEnt)
}
/* if not set, don't bother teleporting */
if (!STRING_SET(desiredSpawn)) {
return;
}
if (STRING_SET(desiredSpawn)) {
entity spawnPoint = Spawn_SelectRandom(desiredSpawn);
entity spawnPoint = Spawn_SelectRandom(desiredSpawn);
if (spawnPoint) {
targetEnt.origin = spawnPoint.origin;
targetEnt.angles = spawnPoint.angles;
setorigin_safe(targetEnt, targetEnt.origin);
return;
if (spawnPoint) {
targetEnt.origin = spawnPoint.origin;
targetEnt.angles = spawnPoint.angles;
setorigin_safe(targetEnt, targetEnt.origin);
return;
}
}
spawnPoint = Spawn_SelectRandom("info_player_start");

View file

@ -478,7 +478,7 @@ ncActor::Input(entity eAct, string strInput, string strData)
// NSWarning("Task %S unimplemented", strInput);
break;
case "GoToCover":
vector coverPos = Nodes_FindCoverFromPosition(this, GetOrigin());
vector coverPos = ncNavInfo::FindCoverFromPosition(this, GetOrigin());
if (vlen(coverPos) > 0.0f) {
RouteToPosition(coverPos);
@ -487,7 +487,7 @@ ncActor::Input(entity eAct, string strInput, string strData)
}
break;
case "GoToSpotInRadius":
vector t = Nodes_FindEmptySpotNearPosition(this, GetOrigin(), 128.0f, stof(strData));
vector t = ncNavInfo::FindEmptySpotNearPosition(this, GetOrigin(), 128.0f, stof(strData));
if (vlen(t) > 0.0f) {
RouteToPosition(t);
@ -496,7 +496,7 @@ ncActor::Input(entity eAct, string strInput, string strData)
}
break;
case "AvoidSpotInRadius":
vector t = Nodes_FindEmptySpotAwayFromPosition(this, GetOrigin(), 0.0f, stof(strData));
vector t = ncNavInfo::FindEmptySpotAwayFromPosition(this, GetOrigin(), 0.0f, stof(strData));
if (vlen(t) > 0.0f) {
RouteToPosition(t);

View file

@ -1969,6 +1969,7 @@ ncMonster::Death(entity inflictor, entity attacker, int damage, vector dir, vect
}
m_iFlags = 0x0;
CancelSchedule();
switch (hitBody) {
case BODY_HEAD:
@ -2265,7 +2266,7 @@ ncMonster::Input( entity entityActivator, string inputName, string dataField )
}
break;
case "FindCoverFromEnemy":
vector coverPos = Nodes_FindCoverFromEnemy(this);
vector coverPos = ncNavInfo::FindCoverFromEnemy(this);
if (vlen(coverPos) > 0.0f) {
RouteToPosition(coverPos);