int CLocalNav::FindDirectPath(Vector &vecStepStart, Vector &vecDest, float flTargetRadius, BOOL fNoMonsters)
{
	Vector vecActualDest;
	Vector vecPathDir;
	Vector vecNodeLoc;
	int nindexLast;

	vecPathDir = (vecDest - vecStepStart).Normalize();
	vecActualDest = vecDest - (vecPathDir * flTargetRadius);

	if (PathTraversable(vecStepStart, vecActualDest, fNoMonsters) == TRAVERSABLE_NO)
		return -1;

	nindexLast = -1;
	vecNodeLoc = vecStepStart;
	m_nindexAvailableNode = 0;

	while ((vecNodeLoc - vecActualDest).Length2D() >= HOSTAGE_STEPSIZE)
	{
		vecNodeLoc = vecNodeLoc + (vecPathDir * HOSTAGE_STEPSIZE);
		nindexLast = AddNode(nindexLast, vecNodeLoc, 0, 0, 0);

		if (nindexLast == -1)
			break;
	}

	return nindexLast;
}
node_index_t CLocalNav::FindDirectPath(Vector &vecStart, Vector &vecDest, float flTargetRadius, int fNoMonsters)
{
	Vector vecActualDest;
	Vector vecPathDir;
	Vector vecNodeLoc;
	node_index_t nindexLast;

	vecPathDir = NormalizeSubtract<float_precision, float, float, float_precision>(vecStart, vecDest);
	vecActualDest = vecDest - (vecPathDir * flTargetRadius);

	if (PathTraversable(vecStart, vecActualDest, fNoMonsters) == PATH_TRAVERSABLE_EMPTY)
	{
		return NODE_INVALID_EMPTY;
	}

	nindexLast = NODE_INVALID_EMPTY;
	vecNodeLoc = vecStart;
	m_nindexAvailableNode = 0;

	while ((vecNodeLoc - vecActualDest).Length2D() >= HOSTAGE_STEPSIZE)
	{
		node_index_t nindexCurrent = nindexLast;

		vecNodeLoc = vecNodeLoc + (vecPathDir * HOSTAGE_STEPSIZE);
		nindexLast = AddNode(nindexCurrent, vecNodeLoc);

		if (nindexLast == NODE_INVALID_EMPTY)
			break;
	}

	return nindexLast;
}
int CLocalNav::GetFurthestTraversableNode(Vector &vecStartingLoc, Vector *vecNodes, int nTotalNodes, int fNoMonsters)
{
	int nCount = 0;
	while (nCount < nTotalNodes)
	{
		if (PathTraversable(vecStartingLoc, vecNodes[nCount], fNoMonsters) != PATH_TRAVERSABLE_EMPTY)
			return nCount;

		++nCount;
	}

	return -1;
}
int CLocalNav::GetFurthestTraversableNode(Vector &vecStartingLoc, Vector *vecNodes, int nTotalNodes, BOOL fNoMonsters)
{
	int nCount = 0;

	while (nCount < nTotalNodes)
	{
		if (PathTraversable(vecStartingLoc, vecNodes[nCount], fNoMonsters) != TRAVERSABLE_NO)
			return nCount;

		nCount++;
	}

	return -1;
}
int CLocalNav::LadderTraversable(Vector &vecSource, Vector &vecDest, BOOL fNoMonsters, TraceResult &tr)
{
	Vector vecStepStart;
	Vector vecStepDest;

	vecStepStart = tr.vecEndPos;
	vecStepDest = vecStepStart;
	vecStepDest.z += HOSTAGE_STEPSIZE;

	if (!PathClear(vecStepStart, vecStepDest, fNoMonsters, tr))
	{
		if (tr.fStartSolid)
			return 0;

		if ((tr.vecEndPos - vecStepStart).Length() < 1)
			return 0;
	}

	vecStepStart = tr.vecEndPos;
	vecDest.z = tr.vecEndPos.z;
	return PathTraversable(vecStepStart, vecDest, fNoMonsters);
}
void CLocalNav::AddPathNode(int nindexSource, int offsetX, int offsetY, BOOL fNoMonsters)
{
	BOOL bDepth;
	Vector vecSource, vecDest;
	int offsetXAbs, offsetYAbs;
	int xRevDir, yRevDir;

	if (nindexSource == -1)
	{
		offsetXAbs = offsetX;
		offsetYAbs = offsetY;
		bDepth = 1;
		vecSource = m_vecStartingLoc;
		vecDest.x = vecSource.x + (offsetX * HOSTAGE_STEPSIZE);
		vecDest.y = vecSource.y + (offsetY * HOSTAGE_STEPSIZE);
		vecDest.z = vecSource.z;
	}
	else
	{
		node_index_t *nodeSource;
		node_index_t *nodeCurrent;
		int nindexCurrent;

		nodeCurrent = GetNode(nindexSource);
		offsetXAbs = offsetX + nodeCurrent->offsetX;
		offsetYAbs = offsetY + nodeCurrent->offsetY;
		nodeSource = GetNode(m_nindexAvailableNode);

		if (NodeExists(offsetXAbs, offsetYAbs) != -1)
			return;

		vecSource = nodeCurrent->vecLoc;
		vecDest.x = vecSource.x + (offsetX * HOSTAGE_STEPSIZE);
		vecDest.y = vecSource.y + (offsetY * HOSTAGE_STEPSIZE);
		vecDest.z = vecSource.z;

		if (m_nindexAvailableNode)
		{
			nindexCurrent = m_nindexAvailableNode;

			do
			{
				nodeSource--;
				nindexCurrent--;
				xRevDir = nodeSource->offsetX - offsetXAbs;

				if (xRevDir >= 0)
				{
					if (xRevDir > 1)
						continue;
				}
				else
				{
					if (-xRevDir > 1)
						continue;
				}

				yRevDir = nodeSource->offsetY - offsetYAbs;

				if (yRevDir >= 0)
				{
					if (yRevDir > 1)
						continue;
				}
				else
				{
					if (-yRevDir > 1)
						continue;
				}

				if (PathTraversable(nodeSource->vecLoc, vecDest, fNoMonsters) != TRAVERSABLE_NO)
				{
					nodeCurrent = nodeSource;
					nindexSource = nindexCurrent;
				}
			}
			while (nindexCurrent);
		}

		vecSource = nodeCurrent->vecLoc;
		bDepth = nodeCurrent->bDepth + 1;
	}

	if (PathTraversable(vecSource, vecDest, fNoMonsters) != TRAVERSABLE_NO)
		AddNode(nindexSource, vecDest, offsetXAbs, offsetYAbs, bDepth);
}
void CLocalNav::AddPathNode(node_index_t nindexSource, int offsetX, int offsetY, int fNoMonsters)
{
	int bDepth;
	Vector vecSource, vecDest;
	int offsetXAbs, offsetYAbs;

	if (nindexSource == NODE_INVALID_EMPTY)
	{
		bDepth = 1;

		offsetXAbs = offsetX;
		offsetYAbs = offsetY;

		vecSource = m_vecStartingLoc;
		vecDest = vecSource + Vector(float_precision(offsetX) * HOSTAGE_STEPSIZE, float_precision(offsetY) * HOSTAGE_STEPSIZE, 0);
	}
	else
	{
		localnode_t *nodeSource;
		localnode_t *nodeCurrent;
		node_index_t nindexCurrent;

		nodeCurrent = GetNode(nindexSource);
		offsetXAbs = offsetX + nodeCurrent->offsetX;
		offsetYAbs = offsetY + nodeCurrent->offsetY;
		nodeSource = GetNode(m_nindexAvailableNode);

		// if there exists a node, then to ignore adding a the new node
		if (NodeExists(offsetXAbs, offsetYAbs) != NODE_INVALID_EMPTY)
		{
			return;
		}

		vecSource = nodeCurrent->vecLoc;
		vecDest = vecSource + Vector((float_precision(offsetX) * HOSTAGE_STEPSIZE), (float_precision(offsetY) * HOSTAGE_STEPSIZE), 0);

		if (m_nindexAvailableNode)
		{
			nindexCurrent = m_nindexAvailableNode;

			do
			{
				nodeSource--;
				nindexCurrent--;

				offsetX = (nodeSource->offsetX - offsetXAbs);

				if (offsetX >= 0)
				{
					if (offsetX > 1)
					{
						continue;
					}
				}
				else
				{
					if (-offsetX > 1)
					{
						continue;
					}
				}

				offsetY = (nodeSource->offsetY - offsetYAbs);

				if (offsetY >= 0)
				{
					if (offsetY > 1)
					{
						continue;
					}
				}
				else
				{
					if (-offsetY > 1)
					{
						continue;
					}
				}

				if (PathTraversable(nodeSource->vecLoc, vecDest, fNoMonsters) != PATH_TRAVERSABLE_EMPTY)
				{
					nodeCurrent = nodeSource;
					nindexSource = nindexCurrent;
				}
			}
			while (nindexCurrent);
		}

		vecSource = nodeCurrent->vecLoc;
		bDepth = int(nodeCurrent->bDepth) + 1;
	}

	if (PathTraversable(vecSource, vecDest, fNoMonsters) != PATH_TRAVERSABLE_EMPTY)
	{
		AddNode(nindexSource, vecDest, offsetXAbs, offsetYAbs, bDepth);
	}
}