2022-07-25 16:39:07 +02:00
//=============================================================================//
//
// Purpose: Shared AI utility.
//
//=============================================================================//
// ai_utility_shared.cpp: requires server.dll and client.dll!
//
/////////////////////////////////////////////////////////////////////////////////
# include "core/stdafx.h"
# include "tier1/cvar.h"
# include "mathlib/color.h"
# include "mathlib/vector.h"
2023-04-01 20:54:10 +02:00
# include "mathlib/ssemath.h"
2022-07-25 16:39:07 +02:00
# include "engine/debugoverlay.h"
# include "game/shared/ai_utility_shared.h"
# include "game/server/ai_utility.h"
# include "game/server/ai_networkmanager.h"
2022-09-29 10:59:27 +02:00
# include "game/server/ai_network.h"
2022-11-10 00:53:12 +01:00
# include "game/client/viewrender.h"
2023-04-08 18:52:33 +02:00
# include "thirdparty/recast/Detour/Include/DetourCommon.h"
# include "thirdparty/recast/Detour/Include/DetourNavMesh.h"
2022-07-25 16:39:07 +02:00
2024-02-24 02:15:09 +01:00
static ConVar ai_script_nodes_draw_range ( " ai_script_nodes_draw_range " , " 0 " , FCVAR_DEVELOPMENTONLY , " Debug draw AIN script nodes ranging from shift index to this cvar " ) ;
static ConVar ai_script_nodes_draw_nearest ( " ai_script_nodes_draw_nearest " , " 1 " , FCVAR_DEVELOPMENTONLY , " Debug draw AIN script node links to nearest node (build order is used if null) " ) ;
static ConVar navmesh_debug_type ( " navmesh_debug_type " , " 0 " , FCVAR_DEVELOPMENTONLY , " NavMesh debug draw hull index " , true , 0.f , true , 4.f , nullptr , " 0 = small, 1 = med_short, 2 = medium, 3 = large, 4 = extra large " ) ;
static ConVar navmesh_debug_tile_range ( " navmesh_debug_tile_range " , " 0 " , FCVAR_DEVELOPMENTONLY , " NavMesh debug draw tiles ranging from shift index to this cvar " , true , 0.f , false , 0.f ) ;
static ConVar navmesh_debug_camera_range ( " navmesh_debug_camera_range " , " 2000 " , FCVAR_DEVELOPMENTONLY , " Only debug draw tiles within this distance from camera origin " , true , 0.f , false , 0.f ) ;
static ConVar navmesh_draw_bvtree ( " navmesh_draw_bvtree " , " -1 " , FCVAR_DEVELOPMENTONLY , " Draws the BVTree of the NavMesh tiles " , false , 0.f , false , 0.f , nullptr , " Index: >= 0 && < mesh->m_tileCount " ) ;
static ConVar navmesh_draw_portal ( " navmesh_draw_portal " , " -1 " , FCVAR_DEVELOPMENTONLY , " Draws the portal of the NavMesh tiles " , false , 0.f , false , 0.f , nullptr , " Index: >= 0 && < mesh->m_tileCount " ) ;
static ConVar navmesh_draw_polys ( " navmesh_draw_polys " , " -1 " , FCVAR_DEVELOPMENTONLY , " Draws the polys of the NavMesh tiles " , false , 0.f , false , 0.f , nullptr , " Index: >= 0 && < mesh->m_tileCount " ) ;
static ConVar navmesh_draw_poly_bounds ( " navmesh_draw_poly_bounds " , " -1 " , FCVAR_DEVELOPMENTONLY , " Draws the bounds of the NavMesh polys " , false , 0.f , false , 0.f , nullptr , " Index: >= 0 && < mesh->m_tileCount " ) ;
static ConVar navmesh_draw_poly_bounds_inner ( " navmesh_draw_poly_bounds_inner " , " 0 " , FCVAR_DEVELOPMENTONLY , " Draws the inner bounds of the NavMesh polys (requires navmesh_draw_poly_bounds) " ) ;
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2022-09-30 01:16:26 +02:00
// Purpose:
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2022-09-30 01:16:26 +02:00
CAI_Utility : : CAI_Utility ( void )
: m_BoxColor ( 0 , 255 , 0 , 255 )
, m_LinkColor ( 255 , 0 , 0 , 255 )
2022-07-25 16:39:07 +02:00
{
2022-09-30 01:16:26 +02:00
}
2023-04-01 20:54:10 +02:00
static const VectorAligned s_vMaxs = { 50.0f , 50.0f , 50.0f } ;
static const VectorAligned s_vSubMask = { 25.0f , 25.0f , 25.0f } ;
static const fltx4 s_xMins = LoadZeroSIMD ( ) ;
static const fltx4 s_xMaxs = LoadAlignedSIMD ( s_vMaxs ) ;
static const fltx4 s_xSubMask = LoadAlignedSIMD ( s_vSubMask ) ;
2023-09-23 14:01:53 +02:00
//------------------------------------------------------------------------------
// Purpose: run the NavMesh renderer
//------------------------------------------------------------------------------
void CAI_Utility : : RunRenderFrame ( void )
{
const int iScriptNodeIndex = ai_script_nodes_draw - > GetInt ( ) ;
2024-02-24 02:15:09 +01:00
const int iNavMeshBVTreeIndex = navmesh_draw_bvtree . GetInt ( ) ;
const int iNavMeshPortalIndex = navmesh_draw_portal . GetInt ( ) ;
const int iNavMeshPolyIndex = navmesh_draw_polys . GetInt ( ) ;
const int iNavMeshPolyBoundIndex = navmesh_draw_poly_bounds . GetInt ( ) ;
2023-09-23 14:01:53 +02:00
if ( iScriptNodeIndex < = - 1 & &
iNavMeshBVTreeIndex < = - 1 & &
iNavMeshPortalIndex < = - 1 & &
iNavMeshPolyIndex < = - 1 & &
iNavMeshPolyBoundIndex < = - 1 )
{
// Nothing to render.
return ;
}
const Vector3D & vCamera = MainViewOrigin ( ) ;
const QAngle & aCamera = MainViewAngles ( ) ;
const Vector3D vNormal = vCamera - aCamera . GetNormal ( ) * 256.0f ;
const VPlane vCullPlane ( vNormal , aCamera ) ;
2024-02-24 02:15:09 +01:00
const float flCameraRange = navmesh_debug_camera_range . GetFloat ( ) ;
const int nTileRange = navmesh_debug_tile_range . GetInt ( ) ;
const bool bUseDepthBuffer = r_debug_draw_depth_test . GetBool ( ) ;
2023-09-23 14:01:53 +02:00
if ( iScriptNodeIndex > - 1 )
g_pAIUtility - > DrawAIScriptNetwork ( * g_pAINetwork , vCamera , iScriptNodeIndex , flCameraRange , bUseDepthBuffer ) ;
if ( iNavMeshBVTreeIndex > - 1 )
g_pAIUtility - > DrawNavMeshBVTree ( nullptr , vCamera , vCullPlane , iNavMeshBVTreeIndex , flCameraRange , nTileRange , bUseDepthBuffer ) ;
if ( iNavMeshPortalIndex > - 1 )
g_pAIUtility - > DrawNavMeshPortals ( nullptr , vCamera , vCullPlane , iNavMeshPortalIndex , flCameraRange , nTileRange , bUseDepthBuffer ) ;
if ( iNavMeshPolyIndex > - 1 )
g_pAIUtility - > DrawNavMeshPolys ( nullptr , vCamera , vCullPlane , iNavMeshPolyIndex , flCameraRange , nTileRange , bUseDepthBuffer ) ;
if ( iNavMeshPolyBoundIndex > - 1 )
g_pAIUtility - > DrawNavMeshPolyBoundaries ( nullptr , vCamera , vCullPlane , iNavMeshPolyBoundIndex , flCameraRange , nTileRange , bUseDepthBuffer ) ;
}
2022-09-30 01:16:26 +02:00
//------------------------------------------------------------------------------
2022-10-01 00:25:21 +02:00
// Purpose: draw AI script network
2023-09-23 14:01:53 +02:00
// Input : *pNetwork -
// &vCameraPos -
// iNodeIndex -
// flCameraRange -
// bUseDepthBuffer -
2022-09-30 01:16:26 +02:00
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
void CAI_Utility : : DrawAIScriptNetwork (
const CAI_Network * pNetwork ,
const Vector3D & vCameraPos ,
const int iNodeIndex ,
const float flCameraRange ,
const bool bUseDepthBuffer ) const
2022-09-30 01:16:26 +02:00
{
2022-10-04 23:00:33 +02:00
if ( ! pNetwork )
return ; // AI Network not build or loaded.
2022-09-29 15:59:48 +02:00
2024-02-24 02:15:09 +01:00
const bool bDrawNearest = ai_script_nodes_draw_nearest . GetBool ( ) ;
const int nNodeRange = ai_script_nodes_draw_range . GetInt ( ) ;
2022-10-11 01:20:59 +02:00
2022-10-03 01:15:29 +02:00
OverlayBox_t : : Transforms vTransforms ;
2022-10-11 01:20:59 +02:00
std : : unordered_set < int64_t > uLinkSet ;
2022-07-25 16:39:07 +02:00
2023-09-23 14:01:53 +02:00
for ( int i = iNodeIndex , ns = pNetwork - > NumScriptNodes ( ) ; i < ns ; i + + )
2022-10-03 01:15:29 +02:00
{
2022-11-17 20:49:23 +01:00
if ( nNodeRange & & i > nNodeRange )
2022-10-03 01:15:29 +02:00
break ;
2022-09-29 10:59:27 +02:00
2022-10-04 23:00:33 +02:00
const CAI_ScriptNode * pScriptNode = & pNetwork - > m_ScriptNode [ i ] ;
2023-09-23 14:01:53 +02:00
const fltx4 xOrigin = SubSIMD ( // Subtract 25.f from our scalars to align box with node.
LoadUnaligned3SIMD ( & pScriptNode - > m_vOrigin ) , s_xSubMask ) ;
2022-07-25 16:39:07 +02:00
2022-11-17 20:49:23 +01:00
if ( flCameraRange > 0.0f )
{
// Flip the script node Z axis with that of the camera, so that it won't be used for
// the final distance computation. This allows for viewing the AI Network from above.
2023-09-23 14:01:53 +02:00
const fltx4 xOriginCamZ = SetComponentSIMD ( xOrigin , 2 , vCameraPos . z ) ;
2022-11-17 20:49:23 +01:00
2023-09-23 14:01:53 +02:00
if ( vCameraPos . DistTo ( * reinterpret_cast < const Vector3D * > ( & xOriginCamZ ) ) > flCameraRange )
2022-11-17 20:49:23 +01:00
continue ; // Do not render if node is not within range set by cvar 'navmesh_debug_camera_range'.
}
2023-04-01 20:54:10 +02:00
// Construct box matrix transforms.
vTransforms . mat . Init (
{ 1.0f , 0.0f , 0.0f } ,
{ 0.0f , 1.0f , 0.0f } ,
{ 0.0f , 0.0f , 1.0f } ,
2023-09-23 14:01:53 +02:00
* reinterpret_cast < const Vector3D * > ( & xOrigin ) ) ;
2022-09-28 00:14:33 +02:00
2023-04-01 20:54:10 +02:00
v_RenderBox ( vTransforms . mat , * reinterpret_cast < const Vector3D * > ( & s_xMins ) ,
* reinterpret_cast < const Vector3D * > ( & s_xMaxs ) , m_BoxColor , bUseDepthBuffer ) ;
2022-10-03 01:15:29 +02:00
2022-10-11 01:20:59 +02:00
if ( bDrawNearest ) // Render links to the nearest node.
2022-10-03 01:15:29 +02:00
{
2023-04-01 17:39:22 +02:00
int nNearest = GetNearestNodeToPos ( pNetwork , & pScriptNode - > m_vOrigin ) ;
2022-10-03 01:15:29 +02:00
if ( nNearest ! = NO_NODE ) // NO_NODE = -1
2022-09-28 00:14:33 +02:00
{
2023-09-23 16:34:37 +02:00
shortx8 packedLinks = PackNodeLink ( i , nNearest ) ;
packedLinks = _mm_srli_si128 ( packedLinks , 8 ) ; // Only the upper 64bits are used.
auto p = uLinkSet . insert ( reinterpret_cast < int64_t & > ( packedLinks ) ) ;
2022-11-17 20:49:23 +01:00
if ( p . second ) // Only render if link hasn't already been rendered.
2022-09-28 00:14:33 +02:00
{
2022-10-04 23:00:33 +02:00
const CAI_ScriptNode * pNearestNode = & pNetwork - > m_ScriptNode [ nNearest ] ;
2022-10-03 01:15:29 +02:00
v_RenderLine ( pScriptNode - > m_vOrigin , pNearestNode - > m_vOrigin , m_LinkColor , bUseDepthBuffer ) ;
2022-09-28 00:14:33 +02:00
}
}
2022-07-25 16:39:07 +02:00
}
2022-10-03 01:15:29 +02:00
else if ( i > 0 ) // Render links in the order the AI Network was build.
v_RenderLine ( ( pScriptNode - 1 ) - > m_vOrigin , pScriptNode - > m_vOrigin , m_LinkColor , bUseDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
}
//------------------------------------------------------------------------------
2022-09-30 01:16:26 +02:00
// Purpose: draw NavMesh BVTree
2023-09-23 14:01:53 +02:00
// Input : *pMesh -
// &vCameraPos -
// &vCullPlane -
// iBVTreeIndex -
// flCameraRange -
// nTileRange -
// bDepthBuffer -
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
void CAI_Utility : : DrawNavMeshBVTree (
const dtNavMesh * pMesh ,
const Vector3D & vCameraPos ,
const VPlane & vCullPlane ,
const int iBVTreeIndex ,
const float flCameraRange ,
const int nTileRange ,
const bool bDepthBuffer ) const
2022-07-25 16:39:07 +02:00
{
2022-10-24 00:52:32 +02:00
if ( ! pMesh )
2024-02-24 02:15:09 +01:00
pMesh = GetNavMeshForHull ( navmesh_debug_type . GetInt ( ) ) ;
2022-10-24 00:52:32 +02:00
if ( ! pMesh )
2022-09-30 01:16:26 +02:00
return ; // NavMesh for hull not loaded.
2022-10-04 23:00:33 +02:00
OverlayBox_t : : Transforms vTransforms ;
2023-09-23 14:01:53 +02:00
for ( int i = iBVTreeIndex , nt = pMesh - > getTileCount ( ) ; i < nt ; + + i )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( nTileRange > 0 & & i > nTileRange )
2022-10-01 00:25:21 +02:00
break ;
2022-07-25 16:39:07 +02:00
2022-10-24 00:52:32 +02:00
const dtMeshTile * pTile = & pMesh - > m_tiles [ i ] ;
2022-10-04 23:00:33 +02:00
if ( ! pTile - > header )
2022-07-25 16:39:07 +02:00
continue ;
2023-09-23 14:01:53 +02:00
if ( ! IsTileWithinRange ( pTile , vCullPlane , vCameraPos , flCameraRange ) )
2023-04-01 20:54:10 +02:00
continue ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
const float flCellSize = 1.0f / pTile - > header - > bvQuantFactor ;
2022-10-05 00:55:29 +02:00
2023-04-01 20:54:10 +02:00
const fltx4 xTileAABB = LoadGatherSIMD ( pTile - > header - > bmin [ 0 ] , pTile - > header - > bmin [ 1 ] , pTile - > header - > bmin [ 2 ] , 0.0f ) ;
const fltx4 xCellSize = LoadGatherSIMD ( flCellSize , flCellSize , flCellSize , 0.0f ) ;
2022-10-05 00:55:29 +02:00
2022-10-04 23:00:33 +02:00
for ( int j = 0 , nc = pTile - > header - > bvNodeCount ; j < nc ; + + j )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const dtBVNode * pNode = & pTile - > bvTree [ j ] ;
if ( pNode - > i < 0 ) // Leaf indices are positive.
2022-07-25 16:39:07 +02:00
continue ;
2023-04-01 20:54:10 +02:00
vTransforms . xmm [ 0 ] = LoadGatherSIMD ( 1.0f , 0.0f , 0.0f , 0.0f ) ;
vTransforms . xmm [ 1 ] = LoadGatherSIMD ( 0.0f , 1.0f , 0.0f , 0.0f ) ;
vTransforms . xmm [ 2 ] = LoadGatherSIMD ( 0.0f , 0.0f , 1.0f , 0.0f ) ;
2022-07-25 16:39:07 +02:00
2023-04-01 20:54:10 +02:00
// Formula: tile->header->bm##[axis]+node->bm##[axis]*cs;
const fltx4 xMins = MaddSIMD ( LoadGatherSIMD ( pNode - > bmin [ 0 ] , pNode - > bmin [ 1 ] , pNode - > bmin [ 2 ] , 0.0f ) , xCellSize , xTileAABB ) ;
const fltx4 xMaxs = MaddSIMD ( LoadGatherSIMD ( pNode - > bmax [ 0 ] , pNode - > bmax [ 1 ] , pNode - > bmax [ 2 ] , 0.0f ) , xCellSize , xTileAABB ) ;
2022-07-25 16:39:07 +02:00
2023-01-23 02:20:21 +01:00
v_RenderBox ( vTransforms . mat , * reinterpret_cast < const Vector3D * > ( & xMins ) , * reinterpret_cast < const Vector3D * > ( & xMaxs ) ,
2022-10-04 23:00:33 +02:00
Color ( 188 , 188 , 188 , 255 ) , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
}
}
//------------------------------------------------------------------------------
2022-09-30 01:16:26 +02:00
// Purpose: draw NavMesh portals
2023-09-23 14:01:53 +02:00
// Input : *pMesh -
// &vCameraPos -
// &vCullPlane -
// iPortalIndex -
// flCameraRange -
// nTileRange -
// bDepthBuffer -
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
void CAI_Utility : : DrawNavMeshPortals ( const dtNavMesh * pMesh ,
const Vector3D & vCameraPos ,
const VPlane & vCullPlane ,
const int iPortalIndex ,
const float flCameraRange ,
const int nTileRange ,
const bool bDepthBuffer ) const
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2024-02-24 02:15:09 +01:00
pMesh = GetNavMeshForHull ( navmesh_debug_type . GetInt ( ) ) ;
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2022-09-30 01:16:26 +02:00
return ; // NavMesh for hull not loaded.
2022-07-25 16:39:07 +02:00
2023-09-23 14:01:53 +02:00
for ( int i = iPortalIndex , nt = pMesh - > getTileCount ( ) ; i < nt ; + + i )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( nTileRange > 0 & & i > nTileRange )
2022-10-01 00:25:21 +02:00
break ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
const dtMeshTile * pTile = & pMesh - > m_tiles [ i ] ;
if ( ! pTile - > header )
2022-07-25 16:39:07 +02:00
continue ;
2023-09-23 14:01:53 +02:00
if ( ! IsTileWithinRange ( pTile , vCullPlane , vCameraPos , flCameraRange ) )
2023-04-01 20:54:10 +02:00
continue ;
2022-07-25 16:39:07 +02:00
// Draw portals
2022-10-04 23:00:33 +02:00
const float flPadX = 0.04f ;
const float flPadZ = pTile - > header - > walkableClimb ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
for ( int nSide = 0 ; nSide < 8 ; + + nSide )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
unsigned short m = DT_EXT_LINK | static_cast < unsigned short > ( nSide ) ;
for ( int j = 0 , np = pTile - > header - > polyCount ; j < np ; + + j )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const dtPoly * pPoly = & pTile - > polys [ j ] ;
2022-07-25 16:39:07 +02:00
// Create new links.
2022-10-04 23:00:33 +02:00
for ( int v = 0 , nv = pPoly - > vertCount ; v < nv ; + + v )
2022-07-25 16:39:07 +02:00
{
// Skip edges which do not point to the right side.
2022-10-04 23:00:33 +02:00
if ( pPoly - > neis [ v ] ! = m )
2022-07-25 16:39:07 +02:00
continue ;
// Create new links
2022-10-04 23:00:33 +02:00
const float * va = & pTile - > verts [ pPoly - > verts [ v ] * 3 ] ;
const float * vb = & pTile - > verts [ pPoly - > verts [ ( v + 1 ) % nv ] * 3 ] ;
2022-09-29 22:26:27 +02:00
/*****************
Vertex indices :
va - = 0 + - - - - - - +
vb - = 1 | |
va + = 2 | |
vb + = 3 + - - - - - - +
* * * * * * * * * * * * * * * * */
2023-04-01 20:54:10 +02:00
fltx4 xVerts = LoadGatherSIMD ( va [ 2 ] , vb [ 2 ] , va [ 2 ] , vb [ 2 ] ) ;
Vector4D * vVerts = reinterpret_cast < Vector4D * > ( & xVerts ) ;
xVerts = SubSIMD ( xVerts , LoadGatherSIMD ( flPadZ , flPadZ , 0.0f , 0.0f ) ) ;
xVerts = AddSIMD ( xVerts , LoadGatherSIMD ( 0.0f , 0.0f , flPadZ , flPadZ ) ) ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
if ( nSide = = 0 | | nSide = = 4 )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
Color col = nSide = = 0 ? Color ( 188 , 0 , 0 , 255 ) : Color ( 188 , 0 , 188 , 255 ) ;
const float x = va [ 0 ] + ( ( nSide = = 0 ) ? - flPadX : flPadX ) ;
2023-04-01 20:54:10 +02:00
fltx4 xOrigin = LoadGatherSIMD ( x , va [ 1 ] , vVerts - > x , 0 ) ;
fltx4 xDest = LoadGatherSIMD ( x , va [ 1 ] , vVerts - > z , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( x , va [ 1 ] , vVerts - > z , 0 ) ;
xDest = LoadGatherSIMD ( x , vb [ 1 ] , vVerts - > w , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( x , vb [ 1 ] , vVerts - > w , 0 ) ;
xDest = LoadGatherSIMD ( x , vb [ 1 ] , vVerts - > y , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( x , vb [ 1 ] , vVerts - > y , 0 ) ;
xDest = LoadGatherSIMD ( x , va [ 1 ] , vVerts - > x , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
2022-10-04 23:00:33 +02:00
else if ( nSide = = 2 | | nSide = = 6 )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
Color col = nSide = = 2 ? Color ( 0 , 188 , 0 , 255 ) : Color ( 188 , 188 , 0 , 255 ) ;
const float y = va [ 1 ] + ( ( nSide = = 2 ) ? - flPadX : flPadX ) ;
2023-04-01 20:54:10 +02:00
fltx4 xOrigin = LoadGatherSIMD ( va [ 0 ] , y , vVerts - > x , 0 ) ;
fltx4 xDest = LoadGatherSIMD ( va [ 0 ] , y , vVerts - > z , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( va [ 0 ] , y , vVerts - > z , 0 ) ;
xDest = LoadGatherSIMD ( vb [ 0 ] , y , vVerts - > w , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( vb [ 0 ] , y , vVerts - > w , 0 ) ;
xDest = LoadGatherSIMD ( vb [ 0 ] , y , vVerts - > y , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2023-04-01 20:54:10 +02:00
xOrigin = LoadGatherSIMD ( vb [ 0 ] , y , vVerts - > y , 0 ) ;
xDest = LoadGatherSIMD ( va [ 0 ] , y , vVerts - > x , 0 ) ;
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < Vector3D * > ( & xOrigin ) ,
* reinterpret_cast < Vector3D * > ( & xDest ) , col , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
}
}
}
}
}
//------------------------------------------------------------------------------
2022-09-30 01:16:26 +02:00
// Purpose: draw NavMesh polys
2023-09-23 14:01:53 +02:00
// Input : *pMesh -
// &vCameraPos -
// &vCullPlane -
// iPolyIndex -
// flCameraRange -
// nTileRange -
// bDepthBuffer -
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
void CAI_Utility : : DrawNavMeshPolys ( const dtNavMesh * pMesh ,
const Vector3D & vCameraPos ,
const VPlane & vCullPlane ,
const int iPolyIndex ,
const float flCameraRange ,
const int nTileRange ,
const bool bDepthBuffer ) const
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2024-02-24 02:15:09 +01:00
pMesh = GetNavMeshForHull ( navmesh_debug_type . GetInt ( ) ) ;
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2022-09-30 01:16:26 +02:00
return ; // NavMesh for hull not loaded.
2022-07-25 16:39:07 +02:00
2023-09-23 14:01:53 +02:00
for ( int i = iPolyIndex ; i < pMesh - > getTileCount ( ) ; + + i )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( nTileRange > 0 & & i > nTileRange )
2022-10-01 00:25:21 +02:00
break ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
const dtMeshTile * pTile = & pMesh - > m_tiles [ i ] ;
if ( ! pTile - > header )
2022-07-25 16:39:07 +02:00
continue ;
2023-09-23 14:01:53 +02:00
if ( ! IsTileWithinRange ( pTile , vCullPlane , vCameraPos , flCameraRange ) )
2023-04-01 20:54:10 +02:00
continue ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
for ( int j = 0 ; j < pTile - > header - > polyCount ; j + + )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const dtPoly * pPoly = & pTile - > polys [ j ] ;
2022-07-25 16:39:07 +02:00
Color col { 110 , 200 , 220 , 255 } ;
2022-10-04 23:00:33 +02:00
const unsigned int ip = ( unsigned int ) ( pPoly - pTile - > polys ) ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
if ( pPoly - > getType ( ) = = DT_POLYTYPE_OFFMESH_CONNECTION )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const dtOffMeshConnection * con = & pTile - > offMeshCons [ ip - pTile - > header - > offMeshBase ] ;
2022-09-30 01:16:26 +02:00
v_RenderLine ( Vector3D ( con - > pos [ 0 ] , con - > pos [ 1 ] , con - > pos [ 2 ] ) ,
2022-10-04 23:00:33 +02:00
Vector3D ( con - > pos [ 3 ] , con - > pos [ 4 ] , con - > pos [ 5 ] ) , Color ( 188 , 0 , 188 , 255 ) , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
else
{
2022-10-04 23:00:33 +02:00
const dtPolyDetail * pDetail = & pTile - > detailMeshes [ ip ] ;
2023-04-01 20:54:10 +02:00
fltx4 xTris [ 3 ] = { LoadZeroSIMD ( ) } ;
2022-10-04 23:00:33 +02:00
for ( int k = 0 ; k < pDetail - > triCount ; + + k )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const unsigned char * t = & pTile - > detailTris [ ( pDetail - > triBase + k ) * 4 ] ;
2022-07-25 16:39:07 +02:00
for ( int e = 0 ; e < 3 ; + + e )
{
2022-10-04 23:00:33 +02:00
if ( t [ e ] < pPoly - > vertCount )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
float * pflVerts = & pTile - > verts [ pPoly - > verts [ t [ e ] ] * 3 ] ;
2023-04-01 20:54:10 +02:00
xTris [ e ] = LoadGatherSIMD ( pflVerts [ 0 ] , pflVerts [ 1 ] , pflVerts [ 2 ] , 0.0f ) ;
2022-07-25 16:39:07 +02:00
}
else
{
2022-10-04 23:00:33 +02:00
float * pflVerts = & pTile - > detailVerts [ ( pDetail - > vertBase + t [ e ] - pPoly - > vertCount ) * 3 ] ;
2023-04-01 20:54:10 +02:00
xTris [ e ] = LoadGatherSIMD ( pflVerts [ 0 ] , pflVerts [ 1 ] , pflVerts [ 2 ] , 0.0f ) ;
2022-07-25 16:39:07 +02:00
}
}
2022-10-04 23:00:33 +02:00
v_RenderLine ( * reinterpret_cast < const Vector3D * > ( & xTris [ 0 ] ) ,
* reinterpret_cast < const Vector3D * > ( & xTris [ 1 ] ) , col , bDepthBuffer ) ;
v_RenderLine ( * reinterpret_cast < const Vector3D * > ( & xTris [ 1 ] ) ,
* reinterpret_cast < const Vector3D * > ( & xTris [ 2 ] ) , col , bDepthBuffer ) ;
v_RenderLine ( * reinterpret_cast < const Vector3D * > ( & xTris [ 2 ] ) ,
* reinterpret_cast < const Vector3D * > ( & xTris [ 0 ] ) , col , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
}
}
}
}
//------------------------------------------------------------------------------
// Purpose : draw NavMesh poly boundaries
2023-09-23 14:01:53 +02:00
// Input : *pMesh -
// &vCameraPos -
// &vCullPlane -
// iBoundaryIndex -
// flCameraRange -
// nTileRange -
// bDepthBuffer -
2022-07-25 16:39:07 +02:00
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
void CAI_Utility : : DrawNavMeshPolyBoundaries ( const dtNavMesh * pMesh ,
const Vector3D & vCameraPos ,
const VPlane & vCullPlane ,
const int iBoundaryIndex ,
const float flCameraRange ,
const int nTileRange ,
const bool bDepthBuffer ) const
2022-07-25 16:39:07 +02:00
{
static const float thr = 0.01f * 0.01f ;
Color col { 20 , 140 , 255 , 255 } ;
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2024-02-24 02:15:09 +01:00
pMesh = GetNavMeshForHull ( navmesh_debug_type . GetInt ( ) ) ;
2022-10-04 23:00:33 +02:00
if ( ! pMesh )
2022-09-30 01:16:26 +02:00
return ; // NavMesh for hull not loaded.
2022-07-25 16:39:07 +02:00
2024-02-24 02:15:09 +01:00
const bool bDrawInner = navmesh_draw_poly_bounds_inner . GetBool ( ) ;
2022-10-01 00:25:21 +02:00
2023-09-23 14:01:53 +02:00
for ( int i = iBoundaryIndex , nt = pMesh - > getTileCount ( ) ; i < nt ; + + i )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( nTileRange > 0 & & i > nTileRange )
2022-10-01 00:25:21 +02:00
break ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
const dtMeshTile * pTile = & pMesh - > m_tiles [ i ] ;
if ( ! pTile - > header )
2022-07-25 16:39:07 +02:00
continue ;
2023-09-23 14:01:53 +02:00
if ( ! IsTileWithinRange ( pTile , vCullPlane , vCameraPos , flCameraRange ) )
2023-04-01 20:54:10 +02:00
continue ;
2022-07-25 16:39:07 +02:00
2023-04-02 17:25:18 +02:00
for ( int j = 0 ; j < pTile - > header - > polyCount ; + + j )
2022-07-25 16:39:07 +02:00
{
2023-04-02 17:25:18 +02:00
const dtPoly * pPoly = & pTile - > polys [ j ] ;
2022-07-25 16:39:07 +02:00
2022-10-04 23:00:33 +02:00
if ( pPoly - > getType ( ) = = DT_POLYTYPE_OFFMESH_CONNECTION )
2022-07-25 16:39:07 +02:00
continue ;
2023-04-02 17:25:18 +02:00
const dtPolyDetail * pd = & pTile - > detailMeshes [ j ] ;
2022-07-25 16:39:07 +02:00
2023-04-02 17:25:18 +02:00
for ( int e = 0 , ne = static_cast < int > ( pPoly - > vertCount ) ; e < ne ; + + e )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
if ( bDrawInner )
2022-07-25 16:39:07 +02:00
{
2023-04-02 17:25:18 +02:00
if ( pPoly - > neis [ e ] = = 0 )
2022-07-25 16:39:07 +02:00
continue ;
2023-04-02 17:25:18 +02:00
if ( pPoly - > neis [ e ] & DT_EXT_LINK )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
bool bCon = false ;
for ( unsigned int k = pPoly - > firstLink ; k ! = DT_NULL_LINK ; k = pTile - > links [ k ] . next )
2022-07-25 16:39:07 +02:00
{
2023-04-02 17:25:18 +02:00
if ( pTile - > links [ k ] . edge = = e )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
bCon = true ;
2022-07-25 16:39:07 +02:00
break ;
}
}
2022-10-04 23:00:33 +02:00
if ( bCon )
2022-07-25 20:40:28 +02:00
col = Color ( 255 , 255 , 255 , 255 ) ;
2022-07-25 16:39:07 +02:00
else
2022-07-25 20:40:28 +02:00
col = Color ( 0 , 0 , 0 , 255 ) ;
2022-07-25 16:39:07 +02:00
}
else
2022-07-25 20:40:28 +02:00
col = Color ( 0 , 48 , 64 , 255 ) ;
2022-07-25 16:39:07 +02:00
}
else
{
2023-04-02 17:25:18 +02:00
if ( pPoly - > neis [ e ] ! = 0 )
2022-10-04 23:00:33 +02:00
continue ;
2022-07-25 16:39:07 +02:00
}
2023-04-02 17:25:18 +02:00
const float * v0 = & pTile - > verts [ pPoly - > verts [ e ] * 3 ] ;
const float * v1 = & pTile - > verts [ pPoly - > verts [ ( e + 1 ) % ne ] * 3 ] ;
2022-07-25 16:39:07 +02:00
// Draw detail mesh edges which align with the actual poly edge.
// This is really slow.
2023-04-02 17:25:18 +02:00
for ( int k = 0 , ke = pd - > triCount ; k < ke ; + + k )
2022-07-25 16:39:07 +02:00
{
2022-10-04 23:00:33 +02:00
const unsigned char * t = & pTile - > detailTris [ ( pd - > triBase + k ) * 4 ] ;
2022-07-25 16:39:07 +02:00
const float * tv [ 3 ] ;
for ( int m = 0 ; m < 3 ; + + m )
{
2022-10-04 23:00:33 +02:00
if ( t [ m ] < pPoly - > vertCount )
tv [ m ] = & pTile - > verts [ pPoly - > verts [ t [ m ] ] * 3 ] ;
2022-07-25 16:39:07 +02:00
else
2022-10-04 23:00:33 +02:00
tv [ m ] = & pTile - > detailVerts [ ( pd - > vertBase + ( t [ m ] - pPoly - > vertCount ) ) * 3 ] ;
2022-07-25 16:39:07 +02:00
}
for ( int m = 0 , n = 2 ; m < 3 ; n = m + + )
{
if ( ( dtGetDetailTriEdgeFlags ( t [ 3 ] , n ) & DT_DETAIL_EDGE_BOUNDARY ) = = 0 )
continue ;
if ( distancePtLine2d ( tv [ n ] , v0 , v1 ) < thr & &
distancePtLine2d ( tv [ m ] , v0 , v1 ) < thr )
{
2022-10-04 23:00:33 +02:00
v_RenderLine ( Vector3D ( tv [ n ] [ 0 ] , tv [ n ] [ 1 ] , tv [ n ] [ 2 ] ) , Vector3D ( tv [ m ] [ 0 ] , tv [ m ] [ 1 ] , tv [ m ] [ 2 ] ) , col , bDepthBuffer ) ;
2022-07-25 16:39:07 +02:00
}
}
}
}
}
}
}
2022-09-28 00:14:33 +02:00
//------------------------------------------------------------------------------
2022-10-11 01:20:59 +02:00
// Purpose: packs 4 node indices together
// Input : a - (set 1)
2022-09-28 00:14:33 +02:00
// b -
2022-10-11 01:20:59 +02:00
// c - (set 2)
// d -
// Output : packed node set as i64x2
2022-09-28 00:14:33 +02:00
//------------------------------------------------------------------------------
2023-09-23 16:34:37 +02:00
shortx8 CAI_Utility : : PackNodeLink ( int32_t a , int32_t b , int32_t c , int32_t d ) const
2022-09-28 00:14:33 +02:00
{
2023-09-23 16:34:37 +02:00
shortx8 xResult = _mm_set_epi32 ( a , b , c , d ) ;
2022-10-11 01:20:59 +02:00
// We shuffle a b and c d if following condition is met, this is to
// ensure we always end up with one possible combination of indices.
if ( a < b ) // Swap 'a' with 'b'.
xResult = _mm_shuffle_epi32 ( xResult , _MM_SHUFFLE ( 2 , 3 , 1 , 0 ) ) ;
if ( c < d ) // Swap 'c' with 'd'.
xResult = _mm_shuffle_epi32 ( xResult , _MM_SHUFFLE ( 3 , 2 , 0 , 1 ) ) ;
2022-09-28 00:14:33 +02:00
2022-10-11 01:20:59 +02:00
return xResult ;
2022-09-28 00:14:33 +02:00
}
2023-04-01 20:54:10 +02:00
//------------------------------------------------------------------------------
// Purpose: checks if the NavMesh tile is within the camera radius
// Input : *pTile -
// &vCamera -
// flCameraRadius -
// Output : true if within radius, false otherwise
//------------------------------------------------------------------------------
2023-09-23 14:01:53 +02:00
bool CAI_Utility : : IsTileWithinRange ( const dtMeshTile * pTile , const VPlane & vPlane , const Vector3D & vCamera , const float flCameraRadius ) const
2023-04-01 20:54:10 +02:00
{
const fltx4 xMinBound = LoadGatherSIMD ( pTile - > header - > bmin [ 0 ] , pTile - > header - > bmin [ 1 ] , vCamera . z , 0.0f ) ;
const fltx4 xMaxBound = LoadGatherSIMD ( pTile - > header - > bmax [ 0 ] , pTile - > header - > bmax [ 1 ] , vCamera . z , 0.0f ) ;
2023-09-23 14:01:53 +02:00
const Vector3D * vecMinBound = reinterpret_cast < const Vector3D * > ( & xMinBound ) ;
const Vector3D * vecMaxBound = reinterpret_cast < const Vector3D * > ( & xMaxBound ) ;
if ( flCameraRadius > 0.0f )
{
// Too far from camera, do not render.
if ( vCamera . DistTo ( * vecMinBound ) > flCameraRadius | |
2023-09-23 14:55:23 +02:00
vCamera . DistTo ( * vecMaxBound ) > flCameraRadius )
2023-09-23 14:01:53 +02:00
return false ;
}
// Behind the camera, do not render.
if ( vPlane . GetPointSide ( * vecMinBound ) ! = SIDE_FRONT | |
vPlane . GetPointSide ( * vecMaxBound ) ! = SIDE_FRONT )
2023-04-01 20:54:10 +02:00
return false ;
return true ;
}
2022-09-28 00:14:33 +02:00
//------------------------------------------------------------------------------
// Purpose: gets the nearest node index to position
2023-04-01 17:39:22 +02:00
// Input : *pAINetwork -
// *vPos -
2022-09-30 01:16:26 +02:00
// Output : node index ('NO_NODE' if no node has been found)
2022-09-28 00:14:33 +02:00
//------------------------------------------------------------------------------
2023-04-01 17:39:22 +02:00
int CAI_Utility : : GetNearestNodeToPos ( const CAI_Network * pAINetwork , const Vector3D * vPos ) const
2022-09-28 00:14:33 +02:00
{
2023-04-01 17:39:22 +02:00
int result ; // rax
2022-09-28 00:14:33 +02:00
unsigned int v3 ; // er10
__int64 v4 ; // rdx
float v5 ; // xmm3_4
unsigned int v6 ; // er8
CAI_ScriptNode * v7 ; // rax
float v8 ; // xmm4_4
float v9 ; // xmm5_4
float v10 ; // xmm6_4
float * v11 ; // rcx
float * v12 ; // rax
float v13 ; // xmm7_4
float v14 ; // xmm2_4
unsigned int v15 ; // er9
float v16 ; // xmm8_4
float v17 ; // xmm2_4
unsigned int v18 ; // er8
float v19 ; // xmm9_4
float v20 ; // xmm2_4
unsigned int v21 ; // er9
float v22 ; // xmm7_4
float v23 ; // xmm2_4
float * v24 ; // r9
float v25 ; // xmm4_4
float v26 ; // xmm2_4
unsigned int v27 ; // ecx
2022-09-30 01:16:26 +02:00
if ( pAINetwork )
2022-09-28 00:14:33 +02:00
{
2022-09-30 01:16:26 +02:00
v3 = pAINetwork - > m_iNumScriptNodes ;
2022-09-28 00:14:33 +02:00
v4 = 0 i64 ;
v5 = 640000.0 ;
2023-04-02 17:34:42 +02:00
v6 = ( unsigned int ) NO_NODE ;
2022-09-28 00:14:33 +02:00
if ( v3 > = 4 )
{
2022-09-30 01:16:26 +02:00
v7 = pAINetwork - > m_ScriptNode ;
2022-09-28 00:14:33 +02:00
v8 = vPos - > x ;
v9 = vPos - > y ;
v10 = vPos - > z ;
v11 = & v7 - > m_vOrigin . z ;
v12 = & v7 [ 1 ] . m_vOrigin . y ;
do
{
v13 = v5 ;
v14 = ( float ) ( ( float ) ( ( float ) ( * ( v11 - 1 ) - v9 ) * ( float ) ( * ( v11 - 1 ) - v9 ) ) + ( float ) ( ( float ) ( * ( v11 - 2 ) - v8 ) * ( float ) ( * ( v11 - 2 ) - v8 ) ) ) + ( float ) ( ( float ) ( * v11 - v10 ) * ( float ) ( * v11 - v10 ) ) ;
if ( v5 > v14 )
v5 = ( float ) ( ( float ) ( ( float ) ( * ( v11 - 1 ) - v9 ) * ( float ) ( * ( v11 - 1 ) - v9 ) ) + ( float ) ( ( float ) ( * ( v11 - 2 ) - v8 ) * ( float ) ( * ( v11 - 2 ) - v8 ) ) ) + ( float ) ( ( float ) ( * v11 - v10 ) * ( float ) ( * v11 - v10 ) ) ;
2023-04-01 17:39:22 +02:00
v15 = ( unsigned int ) v4 ;
2022-09-28 00:14:33 +02:00
if ( v13 < = v14 )
v15 = v6 ;
v16 = v5 ;
v17 = ( float ) ( ( float ) ( ( float ) ( * ( v12 - 1 ) - v9 ) * ( float ) ( * ( v12 - 1 ) - v9 ) ) + ( float ) ( ( float ) ( v11 [ 3 ] - v8 ) * ( float ) ( v11 [ 3 ] - v8 ) ) ) + ( float ) ( ( float ) ( * v12 - v10 ) * ( float ) ( * v12 - v10 ) ) ;
if ( v5 > v17 )
v5 = ( float ) ( ( float ) ( ( float ) ( * ( v12 - 1 ) - v9 ) * ( float ) ( * ( v12 - 1 ) - v9 ) ) + ( float ) ( ( float ) ( v11 [ 3 ] - v8 ) * ( float ) ( v11 [ 3 ] - v8 ) ) ) + ( float ) ( ( float ) ( * v12 - v10 ) * ( float ) ( * v12 - v10 ) ) ;
2023-04-01 17:39:22 +02:00
v18 = ( unsigned int ) v4 + 1 ;
2022-09-28 00:14:33 +02:00
if ( v16 < = v17 )
v18 = v15 ;
v19 = v5 ;
v20 = ( float ) ( ( float ) ( ( float ) ( v12 [ 4 ] - v9 ) * ( float ) ( v12 [ 4 ] - v9 ) ) + ( float ) ( ( float ) ( v11 [ 8 ] - v8 ) * ( float ) ( v11 [ 8 ] - v8 ) ) ) + ( float ) ( ( float ) ( v12 [ 5 ] - v10 ) * ( float ) ( v12 [ 5 ] - v10 ) ) ;
if ( v5 > v20 )
v5 = ( float ) ( ( float ) ( ( float ) ( v12 [ 4 ] - v9 ) * ( float ) ( v12 [ 4 ] - v9 ) ) + ( float ) ( ( float ) ( v11 [ 8 ] - v8 ) * ( float ) ( v11 [ 8 ] - v8 ) ) ) + ( float ) ( ( float ) ( v12 [ 5 ] - v10 ) * ( float ) ( v12 [ 5 ] - v10 ) ) ;
2023-04-01 17:39:22 +02:00
v21 = ( unsigned int ) v4 + 2 ;
2022-09-28 00:14:33 +02:00
if ( v19 < = v20 )
v21 = v18 ;
v22 = v5 ;
v23 = ( float ) ( ( float ) ( ( float ) ( v12 [ 9 ] - v9 ) * ( float ) ( v12 [ 9 ] - v9 ) ) + ( float ) ( ( float ) ( v11 [ 13 ] - v8 ) * ( float ) ( v11 [ 13 ] - v8 ) ) ) + ( float ) ( ( float ) ( v12 [ 10 ] - v10 ) * ( float ) ( v12 [ 10 ] - v10 ) ) ;
if ( v5 > v23 )
v5 = ( float ) ( ( float ) ( ( float ) ( v12 [ 9 ] - v9 ) * ( float ) ( v12 [ 9 ] - v9 ) ) + ( float ) ( ( float ) ( v11 [ 13 ] - v8 ) * ( float ) ( v11 [ 13 ] - v8 ) ) ) + ( float ) ( ( float ) ( v12 [ 10 ] - v10 ) * ( float ) ( v12 [ 10 ] - v10 ) ) ;
2023-04-01 17:39:22 +02:00
v6 = ( unsigned int ) v4 + 3 ;
2022-09-28 00:14:33 +02:00
if ( v22 < = v23 )
v6 = v21 ;
v11 + = 20 ;
v12 + = 20 ;
v4 = ( unsigned int ) ( v4 + 4 ) ;
2023-04-01 17:39:22 +02:00
} while ( ( unsigned int ) v4 < v3 - 3 ) ;
2022-09-28 00:14:33 +02:00
}
if ( ( unsigned int ) v4 < v3 )
{
2022-09-30 01:16:26 +02:00
v24 = & pAINetwork - > m_ScriptNode - > m_vOrigin . x + 5 * v4 ;
2022-09-28 00:14:33 +02:00
do
{
v25 = v5 ;
v26 = ( float ) ( ( float ) ( ( float ) ( v24 [ 1 ] - vPos - > y ) * ( float ) ( v24 [ 1 ] - vPos - > y ) ) + ( float ) ( ( float ) ( * v24 - vPos - > x ) * ( float ) ( * v24 - vPos - > x ) ) )
+ ( float ) ( ( float ) ( v24 [ 2 ] - vPos - > z ) * ( float ) ( v24 [ 2 ] - vPos - > z ) ) ;
if ( v5 > v26 )
v5 = ( float ) ( ( float ) ( ( float ) ( v24 [ 1 ] - vPos - > y ) * ( float ) ( v24 [ 1 ] - vPos - > y ) ) + ( float ) ( ( float ) ( * v24 - vPos - > x ) * ( float ) ( * v24 - vPos - > x ) ) )
+ ( float ) ( ( float ) ( v24 [ 2 ] - vPos - > z ) * ( float ) ( v24 [ 2 ] - vPos - > z ) ) ;
2023-04-01 17:39:22 +02:00
v27 = ( unsigned int ) v4 ;
2022-09-28 00:14:33 +02:00
if ( v25 < = v26 )
v27 = v6 ;
v24 + = 5 ;
2023-04-01 17:39:22 +02:00
LODWORD ( v4 ) = ( unsigned int ) v4 + 1 ;
2022-09-28 00:14:33 +02:00
v6 = v27 ;
2023-04-01 17:39:22 +02:00
} while ( ( unsigned int ) v4 < v3 ) ;
2022-09-28 00:14:33 +02:00
}
result = v6 ;
}
else
{
2023-04-01 17:39:22 +02:00
result = NULL ;
2022-09-28 00:14:33 +02:00
}
return result ;
}
2022-09-30 01:16:26 +02:00
CAI_Utility * g_pAIUtility = new ( CAI_Utility ) ;