2016-03-05 21:04:46 +03:00
//
2014-09-09 18:29:42 +04:00
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
// Copyright (c) YaPB Development Team.
2014-07-30 14:17:46 +04:00
//
2014-09-09 18:29:42 +04:00
// This software is licensed under the BSD-style license.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// http://yapb.jeefo.net/license
2014-07-30 14:17:46 +04:00
//
# include <core.h>
2016-01-04 15:28:38 +03:00
ConVar yb_wptsubfolder ( " yb_wptsubfolder " , " " ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 15:28:38 +03:00
ConVar yb_waypoint_autodl_host ( " yb_waypoint_autodl_host " , " yapb.jeefo.net " ) ;
ConVar yb_waypoint_autodl_enable ( " yb_waypoint_autodl_enable " , " 1 " ) ;
2014-07-30 14:17:46 +04:00
void Waypoint : : Init ( void )
{
// this function initialize the waypoint structures..
2015-08-15 18:09:15 +03:00
m_learnVelocity . Zero ( ) ;
m_learnPosition . Zero ( ) ;
m_lastWaypoint . Zero ( ) ;
2015-06-24 15:38:48 +03:00
2014-07-30 14:17:46 +04:00
// have any waypoint path nodes been allocated yet?
if ( m_waypointPaths )
2016-03-12 14:35:44 +03:00
CleanupPathMemory ( ) ;
g_numWaypoints = 0 ;
}
void Waypoint : : CleanupPathMemory ( void )
{
for ( int i = 0 ; i < g_numWaypoints & & m_paths [ i ] ! = NULL ; i + + )
2014-07-30 14:17:46 +04:00
{
2016-03-12 14:35:44 +03:00
delete m_paths [ i ] ;
m_paths [ i ] = NULL ;
2014-07-30 14:17:46 +04:00
}
}
2016-03-12 14:35:44 +03:00
void Waypoint : : AddPath ( int addIndex , int pathIndex , float distance )
2014-07-30 14:17:46 +04:00
{
if ( addIndex < 0 | | addIndex > = g_numWaypoints | | pathIndex < 0 | | pathIndex > = g_numWaypoints | | addIndex = = pathIndex )
return ;
Path * path = m_paths [ addIndex ] ;
// don't allow paths get connected twice
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > index [ i ] = = pathIndex )
{
AddLogEntry ( true , LL_WARNING , " Denied path creation from %d to %d (path already exists) " , addIndex , pathIndex ) ;
return ;
}
}
// check for free space in the connection indices
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > index [ i ] = = - 1 )
{
path - > index [ i ] = pathIndex ;
path - > distances [ i ] = abs ( static_cast < int > ( distance ) ) ;
AddLogEntry ( true , LL_DEFAULT , " Path added from %d to %d " , addIndex , pathIndex ) ;
return ;
}
}
// there wasn't any free space. try exchanging it with a long-distance path
int maxDistance = - 9999 ;
int slotID = - 1 ;
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > distances [ i ] > maxDistance )
{
maxDistance = path - > distances [ i ] ;
slotID = i ;
}
}
if ( slotID ! = - 1 )
{
AddLogEntry ( true , LL_DEFAULT , " Path added from %d to %d " , addIndex , pathIndex ) ;
path - > index [ slotID ] = pathIndex ;
path - > distances [ slotID ] = abs ( static_cast < int > ( distance ) ) ;
}
}
2015-06-10 23:41:55 +03:00
int Waypoint : : FindFarest ( const Vector & origin , float maxDistance )
2014-07-30 14:17:46 +04:00
{
// find the farest waypoint to that Origin, and return the index to this waypoint
int index = - 1 ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
float distance = ( m_paths [ i ] - > origin - origin ) . GetLength ( ) ;
if ( distance > maxDistance )
{
index = i ;
maxDistance = distance ;
}
}
return index ;
}
2015-06-10 23:41:55 +03:00
int Waypoint : : FindNearest ( const Vector & origin , float minDistance , int flags )
2014-07-30 14:17:46 +04:00
{
2015-06-04 11:52:48 +03:00
// find the nearest waypoint to that origin and return the index
2014-07-30 14:17:46 +04:00
int index = - 1 ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( flags ! = - 1 & & ! ( m_paths [ i ] - > flags & flags ) )
continue ; // if flag not -1 and waypoint has no this flag, skip waypoint
2016-01-04 18:26:06 +03:00
float distance = ( m_paths [ i ] - > origin - origin ) . GetLength ( ) ;
2015-06-06 14:19:19 +03:00
2016-01-04 18:26:06 +03:00
if ( distance < minDistance )
2014-07-30 14:17:46 +04:00
{
index = i ;
minDistance = distance ;
}
}
return index ;
}
2015-08-02 20:31:14 +03:00
void Waypoint : : FindInRadius ( Array < int > & radiusHolder , float radius , const Vector & origin , int maxCount )
2014-07-30 14:17:46 +04:00
{
// returns all waypoints within radius from position
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
2015-08-02 20:31:14 +03:00
if ( maxCount ! = - 1 & & radiusHolder . GetElementNumber ( ) > maxCount )
break ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( ( m_paths [ i ] - > origin - origin ) . GetLength ( ) < radius )
2015-07-11 19:54:46 +03:00
radiusHolder . Push ( i ) ;
2014-07-30 14:17:46 +04:00
}
}
2016-01-04 18:26:06 +03:00
2014-07-30 14:17:46 +04:00
void Waypoint : : Add ( int flags , const Vector & waypointOrigin )
{
2016-03-05 23:08:07 +03:00
if ( engine . IsNullEntity ( g_hostEntity ) )
2014-07-30 14:17:46 +04:00
return ;
int index = - 1 , i ;
float distance ;
2015-08-15 18:09:15 +03:00
Vector forward ;
2014-07-30 14:17:46 +04:00
Path * path = NULL ;
bool placeNew = true ;
Vector newOrigin = waypointOrigin ;
2015-08-15 18:09:15 +03:00
if ( waypointOrigin . IsZero ( ) )
2014-07-30 14:17:46 +04:00
newOrigin = g_hostEntity - > v . origin ;
2015-07-24 15:10:51 +03:00
if ( bots . GetBotsNum ( ) > 0 )
bots . RemoveAll ( ) ;
2014-07-30 14:17:46 +04:00
g_waypointsChanged = true ;
switch ( flags )
{
case 6 :
2015-08-15 18:09:15 +03:00
index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( index ! = - 1 )
{
path = m_paths [ index ] ;
if ( ! ( path - > flags & FLAG_CAMP ) )
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " This is not Camping Waypoint " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
MakeVectors ( g_hostEntity - > v . v_angle ) ;
2015-08-15 18:09:15 +03:00
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640.0f ;
2014-07-30 14:17:46 +04:00
path - > campEndX = forward . x ;
path - > campEndY = forward . y ;
// play "done" sound...
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
2014-07-30 14:17:46 +04:00
}
return ;
case 9 :
2015-08-15 18:09:15 +03:00
index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( index ! = - 1 )
{
distance = ( m_paths [ index ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
2015-08-15 18:09:15 +03:00
if ( distance < 50.0f )
2014-07-30 14:17:46 +04:00
{
placeNew = false ;
path = m_paths [ index ] ;
if ( flags = = 9 )
2015-08-15 18:09:15 +03:00
path - > origin = ( path - > origin + m_learnPosition ) * 0.5f ;
2014-07-30 14:17:46 +04:00
}
}
else
newOrigin = m_learnPosition ;
break ;
case 10 :
2015-08-15 18:09:15 +03:00
index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( index ! = - 1 & & m_paths [ index ] ! = NULL )
{
distance = ( m_paths [ index ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
2015-08-15 18:09:15 +03:00
if ( distance < 50.0f )
2014-07-30 14:17:46 +04:00
{
placeNew = false ;
path = m_paths [ index ] ;
2015-06-04 11:52:48 +03:00
flags = 0 ;
2014-07-30 14:17:46 +04:00
for ( i = 0 ; i < MAX_PATH_INDEX ; i + + )
flags + = path - > connectionFlags [ i ] ;
if ( flags = = 0 )
2015-08-15 18:09:15 +03:00
path - > origin = ( path - > origin + g_hostEntity - > v . origin ) * 0.5f ;
2014-07-30 14:17:46 +04:00
}
}
break ;
}
if ( placeNew )
{
if ( g_numWaypoints > = MAX_WAYPOINTS )
return ;
index = g_numWaypoints ;
m_paths [ index ] = new Path ;
if ( m_paths [ index ] = = NULL )
TerminateOnMalloc ( ) ;
path = m_paths [ index ] ;
// increment total number of waypoints
g_numWaypoints + + ;
path - > pathNumber = index ;
path - > flags = 0 ;
// store the origin (location) of this waypoint
path - > origin = newOrigin ;
2015-08-15 18:09:15 +03:00
path - > campEndX = 0.0f ;
path - > campEndY = 0.0f ;
path - > campStartX = 0.0f ;
path - > campStartY = 0.0f ;
2014-07-30 14:17:46 +04:00
for ( i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
path - > index [ i ] = - 1 ;
path - > distances [ i ] = 0 ;
path - > connectionFlags [ i ] = 0 ;
2015-08-15 18:09:15 +03:00
path - > connectionVelocity [ i ] . Zero ( ) ;
2014-07-30 14:17:46 +04:00
}
// store the last used waypoint for the auto waypoint code...
m_lastWaypoint = g_hostEntity - > v . origin ;
}
// set the time that this waypoint was originally displayed...
m_waypointDisplayTime [ index ] = 0 ;
if ( flags = = 9 )
m_lastJumpWaypoint = index ;
else if ( flags = = 10 )
{
distance = ( m_paths [ m_lastJumpWaypoint ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
AddPath ( m_lastJumpWaypoint , index , distance ) ;
for ( i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( m_paths [ m_lastJumpWaypoint ] - > index [ i ] = = index )
{
m_paths [ m_lastJumpWaypoint ] - > connectionFlags [ i ] | = PATHFLAG_JUMP ;
m_paths [ m_lastJumpWaypoint ] - > connectionVelocity [ i ] = m_learnVelocity ;
break ;
}
}
CalculateWayzone ( index ) ;
return ;
}
if ( g_hostEntity - > v . flags & FL_DUCKING )
path - > flags | = FLAG_CROUCH ; // set a crouch waypoint
if ( g_hostEntity - > v . movetype = = MOVETYPE_FLY )
{
path - > flags | = FLAG_LADDER ;
MakeVectors ( g_hostEntity - > v . v_angle ) ;
2015-08-15 18:09:15 +03:00
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640.0f ;
2014-07-30 14:17:46 +04:00
path - > campStartY = forward . y ;
}
else if ( m_isOnLadder )
path - > flags | = FLAG_LADDER ;
switch ( flags )
{
case 1 :
path - > flags | = FLAG_CROSSING ;
path - > flags | = FLAG_TF_ONLY ;
break ;
case 2 :
path - > flags | = FLAG_CROSSING ;
path - > flags | = FLAG_CF_ONLY ;
break ;
case 3 :
path - > flags | = FLAG_NOHOSTAGE ;
break ;
case 4 :
path - > flags | = FLAG_RESCUE ;
break ;
case 5 :
path - > flags | = FLAG_CROSSING ;
path - > flags | = FLAG_CAMP ;
MakeVectors ( g_hostEntity - > v . v_angle ) ;
2015-08-15 18:09:15 +03:00
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640.0f ;
2014-07-30 14:17:46 +04:00
path - > campStartX = forward . x ;
path - > campStartY = forward . y ;
break ;
case 100 :
path - > flags | = FLAG_GOAL ;
break ;
}
// Ladder waypoints need careful connections
if ( path - > flags & FLAG_LADDER )
{
2015-08-15 18:09:15 +03:00
float minDistance = 9999.0f ;
2014-07-30 14:17:46 +04:00
int destIndex = - 1 ;
TraceResult tr ;
// calculate all the paths to this new waypoint
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
if ( i = = index )
continue ; // skip the waypoint that was just added
// Other ladder waypoints should connect to this
if ( m_paths [ i ] - > flags & FLAG_LADDER )
{
// check if the waypoint is reachable from the new one
2016-03-01 13:37:10 +03:00
engine . TestLine ( newOrigin , m_paths [ i ] - > origin , TRACE_IGNORE_MONSTERS , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction = = 1.0f & & fabs ( newOrigin . x - m_paths [ i ] - > origin . x ) < 64.0f & & fabs ( newOrigin . y - m_paths [ i ] - > origin . y ) < 64.0f & & fabs ( newOrigin . z - m_paths [ i ] - > origin . z ) < g_autoPathDistance )
2014-07-30 14:17:46 +04:00
{
distance = ( m_paths [ i ] - > origin - newOrigin ) . GetLength ( ) ;
AddPath ( index , i , distance ) ;
AddPath ( i , index , distance ) ;
}
}
else
{
// check if the waypoint is reachable from the new one
if ( IsNodeReachable ( newOrigin , m_paths [ i ] - > origin ) | | IsNodeReachable ( m_paths [ i ] - > origin , newOrigin ) )
{
distance = ( m_paths [ i ] - > origin - newOrigin ) . GetLength ( ) ;
if ( distance < minDistance )
{
destIndex = i ;
minDistance = distance ;
}
}
}
}
if ( destIndex > - 1 & & destIndex < g_numWaypoints )
{
// check if the waypoint is reachable from the new one (one-way)
if ( IsNodeReachable ( newOrigin , m_paths [ destIndex ] - > origin ) )
{
distance = ( m_paths [ destIndex ] - > origin - newOrigin ) . GetLength ( ) ;
AddPath ( index , destIndex , distance ) ;
}
// check if the new one is reachable from the waypoint (other way)
if ( IsNodeReachable ( m_paths [ destIndex ] - > origin , newOrigin ) )
{
distance = ( m_paths [ destIndex ] - > origin - newOrigin ) . GetLength ( ) ;
AddPath ( destIndex , index , distance ) ;
}
}
}
else
{
// calculate all the paths to this new waypoint
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
if ( i = = index )
continue ; // skip the waypoint that was just added
// check if the waypoint is reachable from the new one (one-way)
if ( IsNodeReachable ( newOrigin , m_paths [ i ] - > origin ) )
{
distance = ( m_paths [ i ] - > origin - newOrigin ) . GetLength ( ) ;
AddPath ( index , i , distance ) ;
}
// check if the new one is reachable from the waypoint (other way)
if ( IsNodeReachable ( m_paths [ i ] - > origin , newOrigin ) )
{
distance = ( m_paths [ i ] - > origin - newOrigin ) . GetLength ( ) ;
AddPath ( i , index , distance ) ;
}
}
}
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " weapons/xbow_hit1.wav " ) ;
2014-07-30 14:17:46 +04:00
CalculateWayzone ( index ) ; // calculate the wayzone of this waypoint
}
void Waypoint : : Delete ( void )
{
g_waypointsChanged = true ;
if ( g_numWaypoints < 1 )
return ;
2015-07-24 15:10:51 +03:00
if ( bots . GetBotsNum ( ) > 0 )
bots . RemoveAll ( ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
int index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
2016-02-29 23:50:16 +03:00
if ( index < 0 )
2014-07-30 14:17:46 +04:00
return ;
Path * path = NULL ;
InternalAssert ( m_paths [ index ] ! = NULL ) ;
int i , j ;
for ( i = 0 ; i < g_numWaypoints ; i + + ) // delete all references to Node
{
path = m_paths [ i ] ;
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
if ( path - > index [ j ] = = index )
{
path - > index [ j ] = - 1 ; // unassign this path
path - > connectionFlags [ j ] = 0 ;
path - > distances [ j ] = 0 ;
2015-08-15 18:09:15 +03:00
path - > connectionVelocity [ j ] . Zero ( ) ;
2014-07-30 14:17:46 +04:00
}
}
}
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
path = m_paths [ i ] ;
if ( path - > pathNumber > index ) // if pathnumber bigger than deleted node...
path - > pathNumber - - ;
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
if ( path - > index [ j ] > index )
path - > index [ j ] - - ;
}
}
// free deleted node
delete m_paths [ index ] ;
m_paths [ index ] = NULL ;
2015-06-28 19:43:31 +03:00
// rotate path array down
2014-07-30 14:17:46 +04:00
for ( i = index ; i < g_numWaypoints - 1 ; i + + )
m_paths [ i ] = m_paths [ i + 1 ] ;
g_numWaypoints - - ;
m_waypointDisplayTime [ index ] = 0 ;
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
2014-07-30 14:17:46 +04:00
}
void Waypoint : : ToggleFlags ( int toggleFlag )
{
// this function allow manually changing flags
2015-08-15 18:09:15 +03:00
int index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( index ! = - 1 )
{
if ( m_paths [ index ] - > flags & toggleFlag )
m_paths [ index ] - > flags & = ~ toggleFlag ;
else if ( ! ( m_paths [ index ] - > flags & toggleFlag ) )
{
if ( toggleFlag = = FLAG_SNIPER & & ! ( m_paths [ index ] - > flags & FLAG_CAMP ) )
{
AddLogEntry ( true , LL_ERROR , " Cannot assign sniper flag to waypoint #%d. This is not camp waypoint " , index ) ;
return ;
}
m_paths [ index ] - > flags | = toggleFlag ;
}
// play "done" sound...
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
2014-07-30 14:17:46 +04:00
}
}
void Waypoint : : SetRadius ( int radius )
{
// this function allow manually setting the zone radius
2015-08-15 18:09:15 +03:00
int index = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( index ! = - 1 )
{
m_paths [ index ] - > radius = static_cast < float > ( radius ) ;
// play "done" sound...
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
2014-07-30 14:17:46 +04:00
}
}
bool Waypoint : : IsConnected ( int pointA , int pointB )
{
// this function checks if waypoint A has a connection to waypoint B
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( m_paths [ pointA ] - > index [ i ] = = pointB )
return true ;
}
return false ;
}
int Waypoint : : GetFacingIndex ( void )
{
// this function finds waypoint the user is pointing at.
int pointedIndex = - 1 ;
2015-08-15 18:09:15 +03:00
float viewCone [ 3 ] = { 0.0f , 0.0f , 0.0f } ;
2014-07-30 14:17:46 +04:00
// find the waypoint the user is pointing at
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
2015-08-15 18:09:15 +03:00
if ( ( m_paths [ i ] - > origin - g_hostEntity - > v . origin ) . GetLengthSquared ( ) > 250000.0f )
2014-07-30 14:17:46 +04:00
continue ;
// get the current view cone
viewCone [ 0 ] = GetShootingConeDeviation ( g_hostEntity , & m_paths [ i ] - > origin ) ;
2015-08-15 18:09:15 +03:00
Vector bound = m_paths [ i ] - > origin - Vector ( 0.0f , 0.0f , ( m_paths [ i ] - > flags & FLAG_CROUCH ) ? 8.0f : 15.0f ) ;
2014-07-30 14:17:46 +04:00
// get the current view cone
viewCone [ 1 ] = GetShootingConeDeviation ( g_hostEntity , & bound ) ;
2015-08-15 18:09:15 +03:00
bound = m_paths [ i ] - > origin + Vector ( 0.0f , 0.0f , ( m_paths [ i ] - > flags & FLAG_CROUCH ) ? 8.0f : 15.0f ) ;
2014-07-30 14:17:46 +04:00
// get the current view cone
viewCone [ 2 ] = GetShootingConeDeviation ( g_hostEntity , & bound ) ;
// check if we can see it
2015-08-15 18:09:15 +03:00
if ( viewCone [ 0 ] < 0.998f & & viewCone [ 1 ] < 0.997f & & viewCone [ 2 ] < 0.997f )
2014-07-30 14:17:46 +04:00
continue ;
pointedIndex = i ;
}
return pointedIndex ;
}
void Waypoint : : CreatePath ( char dir )
{
// this function allow player to manually create a path from one waypoint to another
2015-08-15 18:09:15 +03:00
int nodeFrom = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( nodeFrom = = - 1 )
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Unable to find nearest waypoint in 50 units " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
int nodeTo = m_facingAtIndex ;
if ( nodeTo < 0 | | nodeTo > = g_numWaypoints )
{
if ( m_cacheWaypointIndex > = 0 & & m_cacheWaypointIndex < g_numWaypoints )
nodeTo = m_cacheWaypointIndex ;
else
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Unable to find destination waypoint " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
}
if ( nodeTo = = nodeFrom )
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Unable to connect waypoint with itself " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
float distance = ( m_paths [ nodeTo ] - > origin - m_paths [ nodeFrom ] - > origin ) . GetLength ( ) ;
if ( dir = = CONNECTION_OUTGOING )
AddPath ( nodeFrom , nodeTo , distance ) ;
else if ( dir = = CONNECTION_INCOMING )
AddPath ( nodeTo , nodeFrom , distance ) ;
else
{
AddPath ( nodeFrom , nodeTo , distance ) ;
AddPath ( nodeTo , nodeFrom , distance ) ;
}
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
2014-07-30 14:17:46 +04:00
g_waypointsChanged = true ;
}
void Waypoint : : DeletePath ( void )
{
// this function allow player to manually remove a path from one waypoint to another
2015-08-15 18:09:15 +03:00
int nodeFrom = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
int index = 0 ;
if ( nodeFrom = = - 1 )
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Unable to find nearest waypoint in 50 units " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
int nodeTo = m_facingAtIndex ;
if ( nodeTo < 0 | | nodeTo > = g_numWaypoints )
{
if ( m_cacheWaypointIndex > = 0 & & m_cacheWaypointIndex < g_numWaypoints )
nodeTo = m_cacheWaypointIndex ;
else
{
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Unable to find destination waypoint " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
}
for ( index = 0 ; index < MAX_PATH_INDEX ; index + + )
{
if ( m_paths [ nodeFrom ] - > index [ index ] = = nodeTo )
{
g_waypointsChanged = true ;
2015-08-15 18:09:15 +03:00
m_paths [ nodeFrom ] - > index [ index ] = - 1 ; // unassigns this path
2014-07-30 14:17:46 +04:00
m_paths [ nodeFrom ] - > distances [ index ] = 0 ;
2015-08-15 18:09:15 +03:00
m_paths [ nodeFrom ] - > connectionFlags [ index ] = 0 ;
m_paths [ nodeFrom ] - > connectionVelocity [ index ] . Zero ( ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
}
// not found this way ? check for incoming connections then
index = nodeFrom ;
nodeFrom = nodeTo ;
nodeTo = index ;
for ( index = 0 ; index < MAX_PATH_INDEX ; index + + )
{
if ( m_paths [ nodeFrom ] - > index [ index ] = = nodeTo )
{
g_waypointsChanged = true ;
m_paths [ nodeFrom ] - > index [ index ] = - 1 ; // unassign this path
m_paths [ nodeFrom ] - > distances [ index ] = 0 ;
2015-08-15 18:09:15 +03:00
m_paths [ nodeFrom ] - > connectionFlags [ index ] = 0 ;
m_paths [ nodeFrom ] - > connectionVelocity [ index ] . Zero ( ) ;
2016-03-01 13:37:10 +03:00
engine . EmitSound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
}
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " There is already no path on this waypoint " ) ;
2014-07-30 14:17:46 +04:00
}
void Waypoint : : CacheWaypoint ( void )
{
2015-08-15 18:09:15 +03:00
int node = FindNearest ( g_hostEntity - > v . origin , 50.0f ) ;
2014-07-30 14:17:46 +04:00
if ( node = = - 1 )
{
m_cacheWaypointIndex = - 1 ;
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Cached waypoint cleared (nearby point not found in 50 units range) " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
m_cacheWaypointIndex = node ;
2016-03-01 13:37:10 +03:00
engine . CenterPrintf ( " Waypoint #%d has been put into memory " , m_cacheWaypointIndex ) ;
2014-07-30 14:17:46 +04:00
}
void Waypoint : : CalculateWayzone ( int index )
{
// calculate "wayzones" for the nearest waypoint to pentedict (meaning a dynamic distance area to vary waypoint origin)
Path * path = m_paths [ index ] ;
Vector start , direction ;
TraceResult tr ;
bool wayBlocked = false ;
if ( ( path - > flags & ( FLAG_LADDER | FLAG_GOAL | FLAG_CAMP | FLAG_RESCUE | FLAG_CROUCH ) ) | | m_learnJumpWaypoint )
{
2015-08-15 18:09:15 +03:00
path - > radius = 0.0f ;
2014-07-30 14:17:46 +04:00
return ;
}
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > index [ i ] ! = - 1 & & ( m_paths [ path - > index [ i ] ] - > flags & FLAG_LADDER ) )
{
2015-08-15 18:09:15 +03:00
path - > radius = 0.0f ;
2014-07-30 14:17:46 +04:00
return ;
}
}
for ( int scanDistance = 16 ; scanDistance < 128 ; scanDistance + = 16 )
{
start = path - > origin ;
2015-08-15 18:09:15 +03:00
MakeVectors ( Vector : : GetZero ( ) ) ;
2014-07-30 14:17:46 +04:00
direction = g_pGlobals - > v_forward * scanDistance ;
direction = direction . ToAngles ( ) ;
path - > radius = scanDistance ;
2015-08-15 18:09:15 +03:00
for ( float circleRadius = 0.0f ; circleRadius < 180.0f ; circleRadius + = 5.0f )
2014-07-30 14:17:46 +04:00
{
MakeVectors ( direction ) ;
Vector radiusStart = start - g_pGlobals - > v_forward * scanDistance ;
Vector radiusEnd = start + g_pGlobals - > v_forward * scanDistance ;
2016-03-01 13:37:10 +03:00
engine . TestHull ( radiusStart , radiusEnd , TRACE_IGNORE_MONSTERS , head_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction < 1.0f )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
engine . TestLine ( radiusStart , radiusEnd , TRACE_IGNORE_MONSTERS , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
if ( FClassnameIs ( tr . pHit , " func_door " ) | | FClassnameIs ( tr . pHit , " func_door_rotating " ) )
{
2015-08-15 18:09:15 +03:00
path - > radius = 0.0f ;
2014-07-30 14:17:46 +04:00
wayBlocked = true ;
break ;
}
wayBlocked = true ;
2015-08-15 18:09:15 +03:00
path - > radius - = 16.0f ;
2014-07-30 14:17:46 +04:00
break ;
}
2015-08-15 18:09:15 +03:00
Vector dropStart = start + g_pGlobals - > v_forward * scanDistance ;
Vector dropEnd = dropStart - Vector ( 0.0f , 0.0f , scanDistance + 60.0f ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . TestHull ( dropStart , dropEnd , TRACE_IGNORE_MONSTERS , head_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction > = 1.0f )
2014-07-30 14:17:46 +04:00
{
wayBlocked = true ;
2015-08-15 18:09:15 +03:00
path - > radius - = 16.0f ;
2014-07-30 14:17:46 +04:00
break ;
}
2015-08-15 18:09:15 +03:00
dropStart = start - g_pGlobals - > v_forward * scanDistance ;
dropEnd = dropStart - Vector ( 0.0f , 0.0f , scanDistance + 60.0f ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . TestHull ( dropStart , dropEnd , TRACE_IGNORE_MONSTERS , head_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction > = 1.0f )
2014-07-30 14:17:46 +04:00
{
wayBlocked = true ;
2015-08-15 18:09:15 +03:00
path - > radius - = 16.0f ;
2014-07-30 14:17:46 +04:00
break ;
}
2015-08-15 18:09:15 +03:00
radiusEnd . z + = 34.0f ;
2016-03-01 13:37:10 +03:00
engine . TestHull ( radiusStart , radiusEnd , TRACE_IGNORE_MONSTERS , head_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction < 1.0f )
2014-07-30 14:17:46 +04:00
{
wayBlocked = true ;
2015-08-15 18:09:15 +03:00
path - > radius - = 16.0f ;
2014-07-30 14:17:46 +04:00
break ;
}
direction . y = AngleNormalize ( direction . y + circleRadius ) ;
}
if ( wayBlocked )
break ;
}
2015-08-15 18:09:15 +03:00
path - > radius - = 16.0f ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( path - > radius < 0.0f )
path - > radius = 0.0f ;
2014-07-30 14:17:46 +04:00
}
void Waypoint : : SaveExperienceTab ( void )
{
ExtensionHeader header ;
if ( ( g_numWaypoints < = 0 ) | | g_waypointsChanged )
return ;
memset ( header . header , 0 , sizeof ( header . header ) ) ;
strcpy ( header . header , FH_EXPERIENCE ) ;
header . fileVersion = FV_EXPERIENCE ;
header . pointNumber = g_numWaypoints ;
ExperienceSave * experienceSave = new ExperienceSave [ g_numWaypoints * g_numWaypoints ] ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
for ( int j = 0 ; j < g_numWaypoints ; j + + )
{
( experienceSave + ( i * g_numWaypoints ) + j ) - > team0Damage = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage > > 3 ;
( experienceSave + ( i * g_numWaypoints ) + j ) - > team1Damage = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage > > 3 ;
( experienceSave + ( i * g_numWaypoints ) + j ) - > team0Value = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Value / 8 ;
( experienceSave + ( i * g_numWaypoints ) + j ) - > team1Value = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Value / 8 ;
}
}
2016-03-01 22:52:17 +03:00
int result = Compressor : : Compress ( FormatBuffer ( " %slearned/%s.exp " , GetDataDir ( ) , engine . GetMapName ( ) ) , ( unsigned char * ) & header , sizeof ( ExtensionHeader ) , ( unsigned char * ) experienceSave , g_numWaypoints * g_numWaypoints * sizeof ( ExperienceSave ) ) ;
2014-07-30 14:17:46 +04:00
delete [ ] experienceSave ;
if ( result = = - 1 )
{
AddLogEntry ( true , LL_ERROR , " Couldn't save experience data " ) ;
return ;
}
}
void Waypoint : : InitExperienceTab ( void )
{
int i , j ;
delete [ ] g_experienceData ;
g_experienceData = NULL ;
if ( g_numWaypoints < 1 )
return ;
g_experienceData = new Experience [ g_numWaypoints * g_numWaypoints ] ;
2014-08-05 21:04:43 +04:00
g_highestDamageCT = 1 ;
g_highestDamageT = 1 ;
2014-07-30 14:17:46 +04:00
// initialize table by hand to correct values, and NOT zero it out
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < g_numWaypoints ; j + + )
{
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0DangerIndex = - 1 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1DangerIndex = - 1 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage = 0 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage = 0 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Value = 0 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Value = 0 ;
}
}
2016-03-01 22:52:17 +03:00
File fp ( FormatBuffer ( " %slearned/%s.exp " , GetDataDir ( ) , engine . GetMapName ( ) ) , " rb " ) ;
2014-07-30 14:17:46 +04:00
// if file exists, read the experience data from it
if ( fp . IsValid ( ) )
{
2015-06-29 20:51:25 +03:00
ExtensionHeader header ;
memset ( & header , 0 , sizeof ( header ) ) ;
2015-06-29 22:06:55 +03:00
if ( fp . Read ( & header , sizeof ( header ) ) = = 0 )
2015-06-29 20:51:25 +03:00
{
AddLogEntry ( true , LL_ERROR , " Experience data damaged (unable to read header) " ) ;
fp . Close ( ) ;
return ;
}
2014-07-30 14:17:46 +04:00
fp . Close ( ) ;
if ( strncmp ( header . header , FH_EXPERIENCE , strlen ( FH_EXPERIENCE ) ) = = 0 )
{
if ( header . fileVersion = = FV_EXPERIENCE & & header . pointNumber = = g_numWaypoints )
{
ExperienceSave * experienceLoad = new ExperienceSave [ g_numWaypoints * g_numWaypoints ] ;
2016-03-01 22:52:17 +03:00
Compressor : : Uncompress ( FormatBuffer ( " %slearned/%s.exp " , GetDataDir ( ) , engine . GetMapName ( ) ) , sizeof ( ExtensionHeader ) , ( unsigned char * ) experienceLoad , g_numWaypoints * g_numWaypoints * sizeof ( ExperienceSave ) ) ;
2014-07-30 14:17:46 +04:00
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < g_numWaypoints ; j + + )
{
if ( i = = j )
{
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage = ( unsigned short ) ( ( experienceLoad + ( i * g_numWaypoints ) + j ) - > team0Damage ) ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage = ( unsigned short ) ( ( experienceLoad + ( i * g_numWaypoints ) + j ) - > team1Damage ) ;
2014-08-05 21:04:43 +04:00
if ( ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage > g_highestDamageT )
g_highestDamageT = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage ;
if ( ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage > g_highestDamageCT )
g_highestDamageCT = ( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage ;
2014-07-30 14:17:46 +04:00
}
else
{
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Damage = ( unsigned short ) ( ( experienceLoad + ( i * g_numWaypoints ) + j ) - > team0Damage ) < < 3 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Damage = ( unsigned short ) ( ( experienceLoad + ( i * g_numWaypoints ) + j ) - > team1Damage ) < < 3 ;
}
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team0Value = ( signed short ) ( ( experienceLoad + i * ( g_numWaypoints ) + j ) - > team0Value ) * 8 ;
( g_experienceData + ( i * g_numWaypoints ) + j ) - > team1Value = ( signed short ) ( ( experienceLoad + i * ( g_numWaypoints ) + j ) - > team1Value ) * 8 ;
}
}
delete [ ] experienceLoad ;
}
else
2015-07-20 21:26:20 +03:00
AddLogEntry ( true , LL_WARNING , " Experience data damaged (wrong version, or not for this map) " ) ;
2014-07-30 14:17:46 +04:00
}
}
}
void Waypoint : : SaveVisibilityTab ( void )
{
if ( g_numWaypoints = = 0 )
return ;
ExtensionHeader header ;
2015-06-29 20:51:25 +03:00
memset ( & header , 0 , sizeof ( ExtensionHeader ) ) ;
2014-07-30 14:17:46 +04:00
// parse header
memset ( header . header , 0 , sizeof ( header . header ) ) ;
strcpy ( header . header , FH_VISTABLE ) ;
header . fileVersion = FV_VISTABLE ;
header . pointNumber = g_numWaypoints ;
2016-03-01 22:52:17 +03:00
File fp ( FormatBuffer ( " %slearned/%s.vis " , GetDataDir ( ) , engine . GetMapName ( ) ) , " wb " ) ;
2014-07-30 14:17:46 +04:00
if ( ! fp . IsValid ( ) )
{
2015-06-26 00:07:06 +03:00
AddLogEntry ( true , LL_ERROR , " Failed to open visibility table for writing " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
fp . Close ( ) ;
2016-03-12 14:35:44 +03:00
Compressor : : Compress ( FormatBuffer ( " %slearned/%s.vis " , GetDataDir ( ) , engine . GetMapName ( ) ) , ( unsigned char * ) & header , sizeof ( ExtensionHeader ) , ( unsigned char * ) m_visLUT , MAX_WAYPOINTS * ( MAX_WAYPOINTS / 4 ) * sizeof ( unsigned char ) ) ;
2014-07-30 14:17:46 +04:00
}
void Waypoint : : InitVisibilityTab ( void )
{
if ( g_numWaypoints = = 0 )
return ;
ExtensionHeader header ;
2016-03-01 22:52:17 +03:00
File fp ( FormatBuffer ( " %slearned/%s.vis " , GetDataDir ( ) , engine . GetMapName ( ) ) , " rb " ) ;
2014-07-30 14:17:46 +04:00
m_redoneVisibility = false ;
if ( ! fp . IsValid ( ) )
{
m_visibilityIndex = 0 ;
m_redoneVisibility = true ;
2015-12-26 01:31:46 +03:00
AddLogEntry ( true , LL_DEFAULT , " Vistable doesn't, vistable will be rebuilded " ) ;
2014-07-30 14:17:46 +04:00
return ;
}
// read the header of the file
2015-06-29 22:06:55 +03:00
if ( fp . Read ( & header , sizeof ( header ) ) = = 0 )
2015-06-29 20:51:25 +03:00
{
AddLogEntry ( true , LL_ERROR , " Vistable damaged (unable to read header) " ) ;
fp . Close ( ) ;
return ;
}
2014-07-30 14:17:46 +04:00
if ( strncmp ( header . header , FH_VISTABLE , strlen ( FH_VISTABLE ) ) ! = 0 | | header . fileVersion ! = FV_VISTABLE | | header . pointNumber ! = g_numWaypoints )
{
m_visibilityIndex = 0 ;
m_redoneVisibility = true ;
2015-07-20 21:26:20 +03:00
AddLogEntry ( true , LL_WARNING , " Visibility table damaged (wrong version, or not for this map), vistable will be rebuilded. " ) ;
2014-07-30 14:17:46 +04:00
fp . Close ( ) ;
return ;
}
2016-03-12 14:35:44 +03:00
int result = Compressor : : Uncompress ( FormatBuffer ( " %slearned/%s.vis " , GetDataDir ( ) , engine . GetMapName ( ) ) , sizeof ( ExtensionHeader ) , ( unsigned char * ) m_visLUT , MAX_WAYPOINTS * ( MAX_WAYPOINTS / 4 ) * sizeof ( unsigned char ) ) ;
2014-07-30 14:17:46 +04:00
if ( result = = - 1 )
{
m_visibilityIndex = 0 ;
m_redoneVisibility = true ;
AddLogEntry ( true , LL_ERROR , " Failed to decode vistable, vistable will be rebuilded. " ) ;
fp . Close ( ) ;
return ;
}
fp . Close ( ) ;
}
void Waypoint : : InitTypes ( void )
{
m_terrorPoints . RemoveAll ( ) ;
m_ctPoints . RemoveAll ( ) ;
m_goalPoints . RemoveAll ( ) ;
m_campPoints . RemoveAll ( ) ;
m_rescuePoints . RemoveAll ( ) ;
m_sniperPoints . RemoveAll ( ) ;
m_visitedGoals . RemoveAll ( ) ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( m_paths [ i ] - > flags & FLAG_TF_ONLY )
m_terrorPoints . Push ( i ) ;
else if ( m_paths [ i ] - > flags & FLAG_CF_ONLY )
m_ctPoints . Push ( i ) ;
else if ( m_paths [ i ] - > flags & FLAG_GOAL )
m_goalPoints . Push ( i ) ;
else if ( m_paths [ i ] - > flags & FLAG_CAMP )
m_campPoints . Push ( i ) ;
else if ( m_paths [ i ] - > flags & FLAG_SNIPER )
m_sniperPoints . Push ( i ) ;
else if ( m_paths [ i ] - > flags & FLAG_RESCUE )
m_rescuePoints . Push ( i ) ;
}
}
bool Waypoint : : Load ( void )
{
2016-03-10 00:37:33 +03:00
File fp ( CheckSubfolderFile ( ) , " rb " ) ;
2014-07-30 14:17:46 +04:00
2015-06-29 20:51:25 +03:00
WaypointHeader header ;
2015-06-29 22:06:55 +03:00
memset ( & header , 0 , sizeof ( header ) ) ;
2015-06-29 20:51:25 +03:00
2016-03-01 13:37:10 +03:00
// save for faster access
const char * map = engine . GetMapName ( ) ;
2014-07-30 14:17:46 +04:00
if ( fp . IsValid ( ) )
{
2015-06-29 22:06:55 +03:00
if ( fp . Read ( & header , sizeof ( header ) ) = = 0 )
2015-06-29 21:49:52 +03:00
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf - damaged waypoint file (unable to read header) " , map ) ;
2015-06-29 21:49:52 +03:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
if ( strncmp ( header . header , FH_WAYPOINT , strlen ( FH_WAYPOINT ) ) = = 0 )
{
if ( header . fileVersion ! = FV_WAYPOINT )
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf - incorrect waypoint file version (expected '%d' found '%ld') " , map , FV_WAYPOINT , header . fileVersion ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2016-03-01 13:37:10 +03:00
else if ( stricmp ( header . mapName , map ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf - hacked waypoint file, file name doesn't match waypoint header information (mapname: '%s', header: '%s') " , map , map , header . mapName ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
else
{
2015-06-29 21:49:52 +03:00
if ( header . pointNumber = = 0 | | header . pointNumber > MAX_WAYPOINTS )
2015-06-29 20:51:25 +03:00
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf - waypoint file contains illegal number of waypoints (mapname: '%s', header: '%s') " , map , map , header . mapName ) ;
2015-06-29 20:51:25 +03:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
Init ( ) ;
g_numWaypoints = header . pointNumber ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
m_paths [ i ] = new Path ;
if ( m_paths [ i ] = = NULL )
TerminateOnMalloc ( ) ;
2014-09-17 20:36:42 +04:00
if ( fp . Read ( m_paths [ i ] , sizeof ( Path ) ) = = 0 )
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf - truncated waypoint file (count: %d, need: %d) " , map , i , g_numWaypoints ) ;
2014-09-17 20:36:42 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2016-03-10 00:37:33 +03:00
// more checks of waypoint quality
if ( m_paths [ i ] - > pathNumber < 0 | | m_paths [ i ] - > pathNumber > g_numWaypoints )
{
sprintf ( m_infoBuffer , " %s.pwf - bad waypoint file (path #%d index is out of bounds) " , map , i ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
}
m_waypointPaths = true ;
}
}
else
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf is not a yapb waypoint file (header found '%s' needed '%s' " , map , header . header , FH_WAYPOINT ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
fp . Close ( ) ;
}
else
{
if ( yb_waypoint_autodl_enable . GetBool ( ) )
{
2016-03-01 13:37:10 +03:00
AddLogEntry ( true , LL_DEFAULT , " %s.pwf does not exist, trying to download from waypoint database " , map ) ;
2016-03-01 22:52:17 +03:00
WaypointDownloadError status = RequestWaypoint ( ) ;
2014-07-30 14:17:46 +04:00
if ( status = = WDE_SOCKET_ERROR )
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Socket error. " , map ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
yb_waypoint_autodl_enable . SetInt ( 0 ) ;
return false ;
}
else if ( status = = WDE_CONNECT_ERROR )
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Connection problems. " , map ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
yb_waypoint_autodl_enable . SetInt ( 0 ) ;
return false ;
}
else if ( status = = WDE_NOTFOUND_ERROR )
{
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Waypoint not available. " , map ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
return false ;
}
else
{
2016-03-01 13:37:10 +03:00
AddLogEntry ( true , LL_DEFAULT , " %s.pwf was downloaded from waypoint database. Trying to load... " , map ) ;
2014-07-30 14:17:46 +04:00
return Load ( ) ;
}
}
2016-03-01 13:37:10 +03:00
sprintf ( m_infoBuffer , " %s.pwf does not exist " , map ) ;
2014-07-30 14:17:46 +04:00
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
return false ;
}
if ( strncmp ( header . author , " official " , 7 ) = = 0 )
sprintf ( m_infoBuffer , " Using Official Waypoint File " ) ;
else
sprintf ( m_infoBuffer , " Using waypoint file by: %s " , header . author ) ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
m_waypointDisplayTime [ i ] = 0.0 ;
InitPathMatrix ( ) ;
InitTypes ( ) ;
g_waypointsChanged = false ;
2014-08-05 21:04:43 +04:00
g_highestKills = 1 ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
m_pathDisplayTime = 0.0f ;
m_arrowDisplayTime = 0.0f ;
2014-07-30 14:17:46 +04:00
InitVisibilityTab ( ) ;
InitExperienceTab ( ) ;
2015-07-24 15:10:51 +03:00
bots . InitQuota ( ) ;
2014-07-30 14:17:46 +04:00
extern ConVar yb_debug_goal ;
yb_debug_goal . SetInt ( - 1 ) ;
return true ;
}
void Waypoint : : Save ( void )
{
WaypointHeader header ;
memset ( header . mapName , 0 , sizeof ( header . mapName ) ) ;
memset ( header . author , 0 , sizeof ( header . author ) ) ;
memset ( header . header , 0 , sizeof ( header . header ) ) ;
strcpy ( header . header , FH_WAYPOINT ) ;
2015-06-29 21:49:52 +03:00
strncpy ( header . author , STRING ( g_hostEntity - > v . netname ) , SIZEOF_CHAR ( header . author ) ) ;
2016-03-01 13:37:10 +03:00
strncpy ( header . mapName , engine . GetMapName ( ) , SIZEOF_CHAR ( header . mapName ) ) ;
2014-07-30 14:17:46 +04:00
header . mapName [ 31 ] = 0 ;
header . fileVersion = FV_WAYPOINT ;
header . pointNumber = g_numWaypoints ;
File fp ( CheckSubfolderFile ( ) , " wb " ) ;
// file was opened
if ( fp . IsValid ( ) )
{
// write the waypoint header to the file...
fp . Write ( & header , sizeof ( header ) , 1 ) ;
// save the waypoint paths...
for ( int i = 0 ; i < g_numWaypoints ; i + + )
fp . Write ( m_paths [ i ] , sizeof ( Path ) ) ;
fp . Close ( ) ;
}
else
2016-03-01 13:37:10 +03:00
AddLogEntry ( true , LL_ERROR , " Error writing '%s.pwf' waypoint file " , engine . GetMapName ( ) ) ;
2014-07-30 14:17:46 +04:00
}
String Waypoint : : CheckSubfolderFile ( void )
{
String returnFile = " " ;
if ( ! IsNullString ( yb_wptsubfolder . GetString ( ) ) )
returnFile + = ( String ( yb_wptsubfolder . GetString ( ) ) + " / " ) ;
2016-03-01 22:52:17 +03:00
returnFile = FormatBuffer ( " %s%s%s.pwf " , GetDataDir ( ) , returnFile . GetBuffer ( ) , engine . GetMapName ( ) ) ;
2014-07-30 14:17:46 +04:00
2015-07-11 19:54:46 +03:00
if ( File : : Accessible ( returnFile ) )
2014-07-30 14:17:46 +04:00
return returnFile ;
2016-03-01 22:52:17 +03:00
return FormatBuffer ( " %s%s.pwf " , GetDataDir ( ) , engine . GetMapName ( ) ) ;
2014-07-30 14:17:46 +04:00
}
2015-06-10 23:41:55 +03:00
float Waypoint : : GetTravelTime ( float maxSpeed , const Vector & src , const Vector & origin )
2014-07-30 14:17:46 +04:00
{
// this function returns 2D traveltime to a position
return ( origin - src ) . GetLength2D ( ) / maxSpeed ;
}
bool Waypoint : : Reachable ( Bot * bot , int index )
{
// this function return wether bot able to reach index waypoint or not, depending on several factors.
2014-08-05 21:04:43 +04:00
if ( bot = = NULL | | index < 0 | | index > = g_numWaypoints )
2014-07-30 14:17:46 +04:00
return false ;
Vector src = bot - > pev - > origin ;
2015-06-07 19:43:16 +03:00
Vector dest = m_paths [ index ] - > origin ;
2014-07-30 14:17:46 +04:00
float distance = ( dest - src ) . GetLength ( ) ;
2016-02-29 23:50:16 +03:00
// check is destination is close to us enough
2015-06-07 23:06:23 +03:00
if ( distance > = 150.0f )
2014-07-30 14:17:46 +04:00
return false ;
TraceResult tr ;
2016-03-01 13:37:10 +03:00
engine . TestLine ( src , dest , TRACE_IGNORE_MONSTERS , bot - > GetEntity ( ) , & tr ) ;
2014-07-30 14:17:46 +04:00
// if waypoint is visible from current position (even behind head)...
2016-01-04 18:26:06 +03:00
if ( tr . flFraction > = 1.0f )
2015-06-07 23:06:23 +03:00
{
if ( bot - > pev - > waterlevel = = 2 | | bot - > pev - > waterlevel = = 3 )
return true ;
float distance2D = ( dest - src ) . GetLength2D ( ) ;
2014-07-30 14:17:46 +04:00
2015-06-07 23:06:23 +03:00
// is destination waypoint higher that source (62 is max jump height), or destination waypoint higher that source
2015-08-15 18:09:15 +03:00
if ( ( ( dest . z > src . z + 62.0f | | dest . z < src . z - 100.0f ) & & ( ! ( m_paths [ index ] - > flags & FLAG_LADDER ) ) ) | | distance2D > = 120.0f )
2015-06-07 23:06:23 +03:00
return false ; // unable to reach this one
return true ;
}
2014-07-30 14:17:46 +04:00
return false ;
}
2015-06-10 23:41:55 +03:00
bool Waypoint : : IsNodeReachable ( const Vector & src , const Vector & destination )
2014-07-30 14:17:46 +04:00
{
TraceResult tr ;
float distance = ( destination - src ) . GetLength ( ) ;
// is the destination not close enough?
if ( distance > g_autoPathDistance )
return false ;
// check if we go through a func_illusionary, in which case return false
2016-03-01 13:37:10 +03:00
engine . TestHull ( src , destination , TRACE_IGNORE_MONSTERS , head_hull , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-03-05 23:08:07 +03:00
if ( ! engine . IsNullEntity ( tr . pHit ) & & strcmp ( " func_illusionary " , STRING ( tr . pHit - > v . classname ) ) = = 0 )
2014-07-30 14:17:46 +04:00
return false ; // don't add pathwaypoints through func_illusionaries
// check if this waypoint is "visible"...
2016-03-01 13:37:10 +03:00
engine . TestLine ( src , destination , TRACE_IGNORE_MONSTERS , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
// if waypoint is visible from current position (even behind head)...
2016-01-04 18:26:06 +03:00
if ( tr . flFraction > = 1.0f | | strncmp ( " func_door " , STRING ( tr . pHit - > v . classname ) , 9 ) = = 0 )
2014-07-30 14:17:46 +04:00
{
// if it's a door check if nothing blocks behind
if ( strncmp ( " func_door " , STRING ( tr . pHit - > v . classname ) , 9 ) = = 0 )
{
2016-03-01 13:37:10 +03:00
engine . TestLine ( tr . vecEndPos , destination , TRACE_IGNORE_MONSTERS , tr . pHit , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( tr . flFraction < 1.0f )
2014-07-30 14:17:46 +04:00
return false ;
}
// check for special case of both waypoints being in water...
if ( POINT_CONTENTS ( src ) = = CONTENTS_WATER & & POINT_CONTENTS ( destination ) = = CONTENTS_WATER )
return true ; // then they're reachable each other
// is dest waypoint higher than src? (45 is max jump height)
2015-08-15 18:09:15 +03:00
if ( destination . z > src . z + 45.0f )
2014-07-30 14:17:46 +04:00
{
Vector sourceNew = destination ;
Vector destinationNew = destination ;
2015-08-15 18:09:15 +03:00
destinationNew . z = destinationNew . z - 50.0f ; // straight down 50 units
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . TestLine ( sourceNew , destinationNew , TRACE_IGNORE_MONSTERS , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
// check if we didn't hit anything, if not then it's in mid-air
2016-01-04 18:26:06 +03:00
if ( tr . flFraction > = 1.0 )
2014-07-30 14:17:46 +04:00
return false ; // can't reach this one
}
// check if distance to ground drops more than step height at points between source and destination...
Vector direction = ( destination - src ) . Normalize ( ) ; // 1 unit long
Vector check = src , down = src ;
2015-08-15 18:09:15 +03:00
down . z = down . z - 1000.0f ; // straight down 1000 units
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . TestLine ( check , down , TRACE_IGNORE_MONSTERS , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
float lastHeight = tr . flFraction * 1000.0f ; // height from ground
2014-07-30 14:17:46 +04:00
distance = ( destination - check ) . GetLength ( ) ; // distance from goal
2015-08-15 18:09:15 +03:00
while ( distance > 10.0f )
2014-07-30 14:17:46 +04:00
{
// move 10 units closer to the goal...
2015-08-15 18:09:15 +03:00
check = check + ( direction * 10.0f ) ;
2014-07-30 14:17:46 +04:00
down = check ;
2015-08-15 18:09:15 +03:00
down . z = down . z - 1000.0f ; // straight down 1000 units
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . TestLine ( check , down , TRACE_IGNORE_MONSTERS , g_hostEntity , & tr ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
float height = tr . flFraction * 1000.0f ; // height from ground
2014-07-30 14:17:46 +04:00
// is the current height greater than the step height?
2015-08-15 18:09:15 +03:00
if ( height < lastHeight - 18.0f )
2014-07-30 14:17:46 +04:00
return false ; // can't get there without jumping...
lastHeight = height ;
distance = ( destination - check ) . GetLength ( ) ; // distance from goal
}
return true ;
}
return false ;
}
void Waypoint : : InitializeVisibility ( void )
{
2016-01-04 18:26:06 +03:00
if ( ! m_redoneVisibility )
2014-07-30 14:17:46 +04:00
return ;
TraceResult tr ;
byte res , shift ;
for ( m_visibilityIndex = 0 ; m_visibilityIndex < g_numWaypoints ; m_visibilityIndex + + )
{
Vector sourceDuck = m_paths [ m_visibilityIndex ] - > origin ;
Vector sourceStand = m_paths [ m_visibilityIndex ] - > origin ;
if ( m_paths [ m_visibilityIndex ] - > flags & FLAG_CROUCH )
{
2015-08-15 18:09:15 +03:00
sourceDuck . z + = 12.0f ;
sourceStand . z + = 18.0f + 28.0f ;
2014-07-30 14:17:46 +04:00
}
else
{
2015-08-15 18:09:15 +03:00
sourceDuck . z + = - 18.0f + 12.0f ;
sourceStand . z + = 28.0f ;
2014-07-30 14:17:46 +04:00
}
uint16 standCount = 0 , crouchCount = 0 ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
// first check ducked visibility
Vector dest = m_paths [ i ] - > origin ;
2016-03-01 13:37:10 +03:00
engine . TestLine ( sourceDuck , dest , TRACE_IGNORE_MONSTERS , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
// check if line of sight to object is not blocked (i.e. visible)
2016-01-04 18:26:06 +03:00
if ( tr . flFraction ! = 1.0f | | tr . fStartSolid )
2014-07-30 14:17:46 +04:00
res = 1 ;
else
res = 0 ;
res < < = 1 ;
2016-03-01 13:37:10 +03:00
engine . TestLine ( sourceStand , dest , TRACE_IGNORE_MONSTERS , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
// check if line of sight to object is not blocked (i.e. visible)
2016-01-04 18:26:06 +03:00
if ( tr . flFraction ! = 1.0f | | tr . fStartSolid )
2014-07-30 14:17:46 +04:00
res | = 1 ;
shift = ( i % 4 ) < < 1 ;
m_visLUT [ m_visibilityIndex ] [ i > > 2 ] & = ~ ( 3 < < shift ) ;
m_visLUT [ m_visibilityIndex ] [ i > > 2 ] | = res < < shift ;
if ( ! ( res & 2 ) )
crouchCount + + ;
if ( ! ( res & 1 ) )
standCount + + ;
}
m_paths [ m_visibilityIndex ] - > vis . crouch = crouchCount ;
m_paths [ m_visibilityIndex ] - > vis . stand = standCount ;
}
m_redoneVisibility = false ;
}
bool Waypoint : : IsVisible ( int srcIndex , int destIndex )
{
unsigned char res = m_visLUT [ srcIndex ] [ destIndex > > 2 ] ;
res > > = ( destIndex % 4 ) < < 1 ;
return ! ( ( res & 3 ) = = 3 ) ;
}
bool Waypoint : : IsDuckVisible ( int srcIndex , int destIndex )
{
unsigned char res = m_visLUT [ srcIndex ] [ destIndex > > 2 ] ;
res > > = ( destIndex % 4 ) < < 1 ;
return ! ( ( res & 2 ) = = 2 ) ;
}
bool Waypoint : : IsStandVisible ( int srcIndex , int destIndex )
{
unsigned char res = m_visLUT [ srcIndex ] [ destIndex > > 2 ] ;
res > > = ( destIndex % 4 ) < < 1 ;
return ! ( ( res & 1 ) = = 1 ) ;
}
2015-06-28 19:43:31 +03:00
const char * Waypoint : : GetWaypointInfo ( int id )
2014-07-30 14:17:46 +04:00
{
// this function returns path information for waypoint pointed by id.
2015-06-07 19:43:16 +03:00
Path * path = m_paths [ id ] ;
2014-07-30 14:17:46 +04:00
// if this path is null, return
if ( path = = NULL )
return " \0 " ;
bool jumpPoint = false ;
// iterate through connections and find, if it's a jump path
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
// check if we got a valid connection
if ( path - > index [ i ] ! = - 1 & & ( path - > connectionFlags [ i ] & PATHFLAG_JUMP ) )
jumpPoint = true ;
}
2016-03-12 14:35:44 +03:00
static char messageBuffer [ MAX_PRINT_BUFFER ] ;
2015-06-04 11:52:48 +03:00
sprintf ( messageBuffer , " %s%s%s%s%s%s%s%s%s%s%s%s%s%s " , ( path - > flags = = 0 & & ! jumpPoint ) ? " (none) " : " " , ( path - > flags & FLAG_LIFT ) ? " LIFT " : " " , ( path - > flags & FLAG_CROUCH ) ? " CROUCH " : " " , ( path - > flags & FLAG_CROSSING ) ? " CROSSING " : " " , ( path - > flags & FLAG_CAMP ) ? " CAMP " : " " , ( path - > flags & FLAG_TF_ONLY ) ? " TERRORIST " : " " , ( path - > flags & FLAG_CF_ONLY ) ? " CT " : " " , ( path - > flags & FLAG_SNIPER ) ? " SNIPER " : " " , ( path - > flags & FLAG_GOAL ) ? " GOAL " : " " , ( path - > flags & FLAG_LADDER ) ? " LADDER " : " " , ( path - > flags & FLAG_RESCUE ) ? " RESCUE " : " " , ( path - > flags & FLAG_DOUBLEJUMP ) ? " JUMPHELP " : " " , ( path - > flags & FLAG_NOHOSTAGE ) ? " NOHOSTAGE " : " " , jumpPoint ? " JUMP " : " " ) ;
2014-07-30 14:17:46 +04:00
// return the message buffer
return messageBuffer ;
}
void Waypoint : : Think ( void )
{
// this function executes frame of waypoint operation code.
2016-03-05 23:08:07 +03:00
if ( engine . IsNullEntity ( g_hostEntity ) )
2014-07-30 14:17:46 +04:00
return ; // this function is only valid on listenserver, and in waypoint enabled mode.
2015-07-12 17:18:20 +03:00
float nearestDistance = 99999.0f ;
2014-07-30 14:17:46 +04:00
int nearestIndex = - 1 ;
// check if it's time to add jump waypoint
if ( m_learnJumpWaypoint )
{
if ( ! m_endJumpPoint )
{
if ( g_hostEntity - > v . button & IN_JUMP )
{
Add ( 9 ) ;
2016-03-01 13:37:10 +03:00
m_timeJumpStarted = engine . Time ( ) ;
2014-07-30 14:17:46 +04:00
m_endJumpPoint = true ;
}
else
{
m_learnVelocity = g_hostEntity - > v . velocity ;
m_learnPosition = g_hostEntity - > v . origin ;
}
}
2016-03-01 13:37:10 +03:00
else if ( ( ( g_hostEntity - > v . flags & FL_ONGROUND ) | | g_hostEntity - > v . movetype = = MOVETYPE_FLY ) & & m_timeJumpStarted + 0.1 < engine . Time ( ) & & m_endJumpPoint )
2014-07-30 14:17:46 +04:00
{
Add ( 10 ) ;
m_learnJumpWaypoint = false ;
m_endJumpPoint = false ;
}
}
// check if it's a autowaypoint mode enabled
if ( g_autoWaypoint & & ( g_hostEntity - > v . flags & ( FL_ONGROUND | FL_PARTIALGROUND ) ) )
{
// find the distance from the last used waypoint
float distance = ( m_lastWaypoint - g_hostEntity - > v . origin ) . GetLengthSquared ( ) ;
2015-08-15 18:09:15 +03:00
if ( distance > 16384.0f )
2014-07-30 14:17:46 +04:00
{
// check that no other reachable waypoints are nearby...
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( IsNodeReachable ( g_hostEntity - > v . origin , m_paths [ i ] - > origin ) )
{
distance = ( m_paths [ i ] - > origin - g_hostEntity - > v . origin ) . GetLengthSquared ( ) ;
if ( distance < nearestDistance )
nearestDistance = distance ;
}
}
// make sure nearest waypoint is far enough away...
2015-08-15 18:09:15 +03:00
if ( nearestDistance > = 16384.0f )
2014-07-30 14:17:46 +04:00
Add ( 0 ) ; // place a waypoint here
}
}
m_facingAtIndex = GetFacingIndex ( ) ;
// reset the minimal distance changed before
2016-01-05 20:29:34 +03:00
nearestDistance = 999999.0f ;
2014-07-30 14:17:46 +04:00
// now iterate through all waypoints in a map, and draw required ones
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
2016-01-05 20:29:34 +03:00
float distance = ( m_paths [ i ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
2014-07-30 14:17:46 +04:00
// check if waypoint is whitin a distance, and is visible
2016-01-27 21:40:47 +03:00
if ( distance < 512.0f & & ( ( : : IsVisible ( m_paths [ i ] - > origin , g_hostEntity ) & & IsInViewCone ( m_paths [ i ] - > origin , g_hostEntity ) ) | | ! IsAlive ( g_hostEntity ) | | distance < 128.0f ) )
2014-07-30 14:17:46 +04:00
{
// check the distance
if ( distance < nearestDistance )
{
nearestIndex = i ;
nearestDistance = distance ;
}
2016-03-01 13:37:10 +03:00
if ( m_waypointDisplayTime [ i ] + 0.8f < engine . Time ( ) )
2014-07-30 14:17:46 +04:00
{
2015-08-15 18:09:15 +03:00
float nodeHeight = 0.0f ;
2014-07-30 14:17:46 +04:00
// check the node height
if ( m_paths [ i ] - > flags & FLAG_CROUCH )
2015-08-15 18:09:15 +03:00
nodeHeight = 36.0f ;
2014-07-30 14:17:46 +04:00
else
2015-08-15 18:09:15 +03:00
nodeHeight = 72.0f ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
float nodeHalfHeight = nodeHeight * 0.5f ;
2014-07-30 14:17:46 +04:00
// all waypoints are by default are green
2015-08-15 18:09:15 +03:00
Vector nodeColor ;
2014-07-30 14:17:46 +04:00
// colorize all other waypoints
if ( m_paths [ i ] - > flags & FLAG_CAMP )
nodeColor = Vector ( 0 , 255 , 255 ) ;
else if ( m_paths [ i ] - > flags & FLAG_GOAL )
nodeColor = Vector ( 128 , 0 , 255 ) ;
else if ( m_paths [ i ] - > flags & FLAG_LADDER )
nodeColor = Vector ( 128 , 64 , 0 ) ;
else if ( m_paths [ i ] - > flags & FLAG_RESCUE )
nodeColor = Vector ( 255 , 255 , 255 ) ;
else
nodeColor = Vector ( 0 , 255 , 0 ) ;
// colorize additional flags
Vector nodeFlagColor = Vector ( - 1 , - 1 , - 1 ) ;
// check the colors
if ( m_paths [ i ] - > flags & FLAG_SNIPER )
nodeFlagColor = Vector ( 130 , 87 , 0 ) ;
else if ( m_paths [ i ] - > flags & FLAG_NOHOSTAGE )
nodeFlagColor = Vector ( 255 , 255 , 255 ) ;
else if ( m_paths [ i ] - > flags & FLAG_TF_ONLY )
nodeFlagColor = Vector ( 255 , 0 , 0 ) ;
else if ( m_paths [ i ] - > flags & FLAG_CF_ONLY )
nodeFlagColor = Vector ( 0 , 0 , 255 ) ;
// draw node without additional flags
if ( nodeFlagColor . x = = - 1 )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , m_paths [ i ] - > origin - Vector ( 0 , 0 , nodeHalfHeight ) , m_paths [ i ] - > origin + Vector ( 0 , 0 , nodeHalfHeight ) , 15 , 0 , static_cast < int > ( nodeColor . x ) , static_cast < int > ( nodeColor . y ) , static_cast < int > ( nodeColor . z ) , 250 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
else // draw node with flags
{
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , m_paths [ i ] - > origin - Vector ( 0 , 0 , nodeHalfHeight ) , m_paths [ i ] - > origin - Vector ( 0 , 0 , nodeHalfHeight - nodeHeight * 0.75 ) , 14 , 0 , static_cast < int > ( nodeColor . x ) , static_cast < int > ( nodeColor . y ) , static_cast < int > ( nodeColor . z ) , 250 , 0 , 10 ) ; // draw basic path
engine . DrawLine ( g_hostEntity , m_paths [ i ] - > origin - Vector ( 0 , 0 , nodeHalfHeight - nodeHeight * 0.75 ) , m_paths [ i ] - > origin + Vector ( 0 , 0 , nodeHalfHeight ) , 14 , 0 , static_cast < int > ( nodeFlagColor . x ) , static_cast < int > ( nodeFlagColor . y ) , static_cast < int > ( nodeFlagColor . z ) , 250 , 0 , 10 ) ; // draw additional path
2014-07-30 14:17:46 +04:00
}
2016-03-01 13:37:10 +03:00
m_waypointDisplayTime [ i ] = engine . Time ( ) ;
2014-07-30 14:17:46 +04:00
}
}
}
if ( nearestIndex = = - 1 )
return ;
// draw arrow to a some importaint waypoints
if ( ( m_findWPIndex ! = - 1 & & m_findWPIndex < g_numWaypoints ) | | ( m_cacheWaypointIndex ! = - 1 & & m_cacheWaypointIndex < g_numWaypoints ) | | ( m_facingAtIndex ! = - 1 & & m_facingAtIndex < g_numWaypoints ) )
{
// check for drawing code
2016-03-01 13:37:10 +03:00
if ( m_arrowDisplayTime + 0.5f < engine . Time ( ) )
2014-07-30 14:17:46 +04:00
{
// finding waypoint - pink arrow
if ( m_findWPIndex ! = - 1 )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_findWPIndex ] - > origin , 10 , 0 , 128 , 0 , 128 , 200 , 0 , 5 , DRAW_ARROW ) ;
2014-07-30 14:17:46 +04:00
// cached waypoint - yellow arrow
if ( m_cacheWaypointIndex ! = - 1 )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_cacheWaypointIndex ] - > origin , 10 , 0 , 255 , 255 , 0 , 200 , 0 , 5 , DRAW_ARROW ) ;
2014-07-30 14:17:46 +04:00
// waypoint user facing at - white arrow
if ( m_facingAtIndex ! = - 1 )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_facingAtIndex ] - > origin , 10 , 0 , 255 , 255 , 255 , 200 , 0 , 5 , DRAW_ARROW ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
m_arrowDisplayTime = engine . Time ( ) ;
2014-07-30 14:17:46 +04:00
}
}
// create path pointer for faster access
Path * path = m_paths [ nearestIndex ] ;
// draw a paths, camplines and danger directions for nearest waypoint
2016-03-01 13:37:10 +03:00
if ( nearestDistance < = 56.0f & & m_pathDisplayTime < = engine . Time ( ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
m_pathDisplayTime = engine . Time ( ) + 1.0f ;
2014-07-30 14:17:46 +04:00
// draw the camplines
if ( path - > flags & FLAG_CAMP )
{
2015-08-15 18:09:15 +03:00
Vector campSourceOrigin = path - > origin + Vector ( 0.0f , 0.0f , 36.0f ) ;
2014-07-30 14:17:46 +04:00
// check if it's a source
if ( path - > flags & FLAG_CROUCH )
2015-08-15 18:09:15 +03:00
campSourceOrigin = path - > origin + Vector ( 0.0f , 0.0f , 18.0f ) ;
2014-07-30 14:17:46 +04:00
Vector campStartOrigin = Vector ( path - > campStartX , path - > campStartY , campSourceOrigin . z ) ; // camp start
Vector campEndOrigin = Vector ( path - > campEndX , path - > campEndY , campSourceOrigin . z ) ; // camp end
// draw it now
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , campSourceOrigin , campStartOrigin , 10 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , campSourceOrigin , campEndOrigin , 10 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
}
// draw the connections
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > index [ i ] = = - 1 )
continue ;
// jump connection
if ( path - > connectionFlags [ i ] & PATHFLAG_JUMP )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 255 , 0 , 128 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
else if ( IsConnected ( path - > index [ i ] , nearestIndex ) ) // twoway connection
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 255 , 255 , 0 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
else // oneway connection
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 250 , 250 , 250 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
}
// now look for oneway incoming connections
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( IsConnected ( m_paths [ i ] - > pathNumber , path - > pathNumber ) & & ! IsConnected ( path - > pathNumber , m_paths [ i ] - > pathNumber ) )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ i ] - > origin , 5 , 0 , 0 , 192 , 96 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
}
// draw the radius circle
2015-08-15 18:09:15 +03:00
Vector origin = ( path - > flags & FLAG_CROUCH ) ? path - > origin : path - > origin - Vector ( 0.0f , 0.0f , 18.0f ) ;
2014-07-30 14:17:46 +04:00
// if radius is nonzero, draw a full circle
2015-08-15 18:09:15 +03:00
if ( path - > radius > 0.0f )
2014-07-30 14:17:46 +04:00
{
2015-08-15 18:09:15 +03:00
float squareRoot = sqrtf ( path - > radius * path - > radius * 0.5f ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , origin + Vector ( path - > radius , 0.0f , 0.0f ) , origin + Vector ( squareRoot , - squareRoot , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , origin + Vector ( squareRoot , - squareRoot , 0.0f ) , origin + Vector ( 0.0f , - path - > radius , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , origin + Vector ( 0.0f , - path - > radius , 0.0f ) , origin + Vector ( - squareRoot , - squareRoot , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , - squareRoot , 0.0f ) , origin + Vector ( - path - > radius , 0.0f , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , origin + Vector ( - path - > radius , 0.0f , 0.0f ) , origin + Vector ( - squareRoot , squareRoot , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , squareRoot , 0.0f ) , origin + Vector ( 0.0f , path - > radius , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , origin + Vector ( 0.0f , path - > radius , 0.0f ) , origin + Vector ( squareRoot , squareRoot , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , origin + Vector ( squareRoot , squareRoot , 0.0f ) , origin + Vector ( path - > radius , 0.0f , 0.0f ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
}
else
{
2015-08-15 18:09:15 +03:00
float squareRoot = sqrtf ( 32.0f ) ;
2014-07-30 14:17:46 +04:00
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , origin + Vector ( squareRoot , - squareRoot , 0.0f ) , origin + Vector ( - squareRoot , squareRoot , 0.0f ) , 5 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
engine . DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , - squareRoot , 0.0f ) , origin + Vector ( squareRoot , squareRoot , 0.0f ) , 5 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
2014-07-30 14:17:46 +04:00
}
// draw the danger directions
if ( ! g_waypointsChanged )
{
2016-03-05 23:08:07 +03:00
if ( ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team0DangerIndex ! = - 1 & & engine . GetTeam ( g_hostEntity ) = = TERRORIST )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team0DangerIndex ] - > origin , 15 , 0 , 255 , 0 , 0 , 200 , 0 , 10 , DRAW_ARROW ) ; // draw a red arrow to this index's danger point
2014-07-30 14:17:46 +04:00
2016-03-05 23:08:07 +03:00
if ( ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team1DangerIndex ! = - 1 & & engine . GetTeam ( g_hostEntity ) = = CT )
2016-03-01 13:37:10 +03:00
engine . DrawLine ( g_hostEntity , path - > origin , m_paths [ ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team1DangerIndex ] - > origin , 15 , 0 , 0 , 0 , 255 , 200 , 0 , 10 , DRAW_ARROW ) ; // draw a blue arrow to this index's danger point
2014-07-30 14:17:46 +04:00
}
// display some information
char tempMessage [ 4096 ] ;
// show the information about that point
int length = sprintf ( tempMessage , " \n \n \n \n Waypoint Information: \n \n "
" Waypoint %d of %d, Radius: %.1f \n "
" Flags: %s \n \n " , nearestIndex , g_numWaypoints , path - > radius , GetWaypointInfo ( nearestIndex ) ) ;
// if waypoint is not changed display experience also
if ( ! g_waypointsChanged )
{
int dangerIndexCT = ( g_experienceData + nearestIndex * g_numWaypoints + nearestIndex ) - > team1DangerIndex ;
int dangerIndexT = ( g_experienceData + nearestIndex * g_numWaypoints + nearestIndex ) - > team0DangerIndex ;
length + = sprintf ( & tempMessage [ length ] ,
" Experience Info: \n "
" CT: %d / %d \n "
" T: %d / %d \n " , dangerIndexCT , dangerIndexCT ! = - 1 ? ( g_experienceData + nearestIndex * g_numWaypoints + dangerIndexCT ) - > team1Damage : 0 , dangerIndexT , dangerIndexT ! = - 1 ? ( g_experienceData + nearestIndex * g_numWaypoints + dangerIndexT ) - > team0Damage : 0 ) ;
}
// check if we need to show the cached point index
if ( m_cacheWaypointIndex ! = - 1 )
{
length + = sprintf ( & tempMessage [ length ] , " \n Cached Waypoint Information: \n \n "
" Waypoint %d of %d, Radius: %.1f \n "
" Flags: %s \n " , m_cacheWaypointIndex , g_numWaypoints , m_paths [ m_cacheWaypointIndex ] - > radius , GetWaypointInfo ( m_cacheWaypointIndex ) ) ;
}
// check if we need to show the facing point index
if ( m_facingAtIndex ! = - 1 )
{
length + = sprintf ( & tempMessage [ length ] , " \n Facing Waypoint Information: \n \n "
" Waypoint %d of %d, Radius: %.1f \n "
" Flags: %s \n " , m_facingAtIndex , g_numWaypoints , m_paths [ m_facingAtIndex ] - > radius , GetWaypointInfo ( m_facingAtIndex ) ) ;
}
// draw entire message
MESSAGE_BEGIN ( MSG_ONE_UNRELIABLE , SVC_TEMPENTITY , NULL , g_hostEntity ) ;
WRITE_BYTE ( TE_TEXTMESSAGE ) ;
WRITE_BYTE ( 4 ) ; // channel
WRITE_SHORT ( FixedSigned16 ( 0 , 1 < < 13 ) ) ; // x
WRITE_SHORT ( FixedSigned16 ( 0 , 1 < < 13 ) ) ; // y
WRITE_BYTE ( 0 ) ; // effect
WRITE_BYTE ( 255 ) ; // r1
WRITE_BYTE ( 255 ) ; // g1
WRITE_BYTE ( 255 ) ; // b1
WRITE_BYTE ( 1 ) ; // a1
WRITE_BYTE ( 255 ) ; // r2
WRITE_BYTE ( 255 ) ; // g2
WRITE_BYTE ( 255 ) ; // b2
WRITE_BYTE ( 255 ) ; // a2
WRITE_SHORT ( 0 ) ; // fadeintime
WRITE_SHORT ( 0 ) ; // fadeouttime
WRITE_SHORT ( FixedUnsigned16 ( 1.1 , 1 < < 8 ) ) ; // holdtime
WRITE_STRING ( tempMessage ) ;
MESSAGE_END ( ) ;
}
}
bool Waypoint : : IsConnected ( int index )
{
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( i ! = index )
{
for ( int j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
if ( m_paths [ i ] - > index [ j ] = = index )
return true ;
}
}
}
return false ;
}
bool Waypoint : : NodesValid ( void )
{
int terrPoints = 0 ;
int ctPoints = 0 ;
int goalPoints = 0 ;
int rescuePoints = 0 ;
int i , j ;
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
2015-06-24 15:38:48 +03:00
int connections = 0 ;
2014-07-30 14:17:46 +04:00
2015-06-04 11:52:48 +03:00
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
2014-07-30 14:17:46 +04:00
{
if ( m_paths [ i ] - > index [ j ] ! = - 1 )
{
if ( m_paths [ i ] - > index [ j ] > g_numWaypoints )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d connected with invalid Waypoint #%d! " , i , m_paths [ i ] - > index [ j ] ) ;
return false ;
}
connections + + ;
break ;
}
}
if ( connections = = 0 )
{
if ( ! IsConnected ( i ) )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d isn't connected with any other Waypoint! " , i ) ;
return false ;
}
}
if ( m_paths [ i ] - > pathNumber ! = i )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d pathnumber differs from index! " , i ) ;
return false ;
}
if ( m_paths [ i ] - > flags & FLAG_CAMP )
{
if ( m_paths [ i ] - > campEndX = = 0 & & m_paths [ i ] - > campEndY = = 0 )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d Camp-Endposition not set! " , i ) ;
return false ;
}
}
else if ( m_paths [ i ] - > flags & FLAG_TF_ONLY )
terrPoints + + ;
else if ( m_paths [ i ] - > flags & FLAG_CF_ONLY )
ctPoints + + ;
else if ( m_paths [ i ] - > flags & FLAG_GOAL )
goalPoints + + ;
else if ( m_paths [ i ] - > flags & FLAG_RESCUE )
rescuePoints + + ;
for ( int k = 0 ; k < MAX_PATH_INDEX ; k + + )
{
if ( m_paths [ i ] - > index [ k ] ! = - 1 )
{
if ( m_paths [ i ] - > index [ k ] > = g_numWaypoints | | m_paths [ i ] - > index [ k ] < - 1 )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d - Pathindex %d out of Range! " , i , k ) ;
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
g_waypointOn = true ;
g_editNoclip = true ;
return false ;
}
else if ( m_paths [ i ] - > index [ k ] = = i )
{
AddLogEntry ( true , LL_WARNING , " Waypoint %d - Pathindex %d points to itself! " , i , k ) ;
2016-03-01 13:37:10 +03:00
if ( g_waypointOn & & ! engine . IsDedicatedServer ( ) )
2015-06-24 15:38:48 +03:00
{
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
2014-07-30 14:17:46 +04:00
2015-06-24 15:38:48 +03:00
g_waypointOn = true ;
g_editNoclip = true ;
}
2014-07-30 14:17:46 +04:00
return false ;
}
}
}
}
2015-06-24 15:38:48 +03:00
2014-07-30 14:17:46 +04:00
if ( g_mapType & MAP_CS )
{
if ( rescuePoints = = 0 )
{
AddLogEntry ( true , LL_WARNING , " You didn't set a Rescue Point! " ) ;
return false ;
}
}
if ( terrPoints = = 0 )
{
AddLogEntry ( true , LL_WARNING , " You didn't set any Terrorist Important Point! " ) ;
return false ;
}
else if ( ctPoints = = 0 )
{
AddLogEntry ( true , LL_WARNING , " You didn't set any CT Important Point! " ) ;
return false ;
}
else if ( goalPoints = = 0 )
{
AddLogEntry ( true , LL_WARNING , " You didn't set any Goal Point! " ) ;
return false ;
}
// perform DFS instead of floyd-warshall, this shit speedup this process in a bit
PathNode * stack = NULL ;
bool visited [ MAX_WAYPOINTS ] ;
// first check incoming connectivity, initialize the "visited" table
for ( i = 0 ; i < g_numWaypoints ; i + + )
visited [ i ] = false ;
// check from waypoint nr. 0
stack = new PathNode ;
stack - > next = NULL ;
stack - > index = 0 ;
while ( stack ! = NULL )
{
// pop a node from the stack
PathNode * current = stack ;
stack = stack - > next ;
visited [ current - > index ] = true ;
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
int index = m_paths [ current - > index ] - > index [ j ] ;
if ( visited [ index ] )
continue ; // skip this waypoint as it's already visited
if ( index > = 0 & & index < g_numWaypoints )
{
PathNode * pNewNode = new PathNode ;
pNewNode - > next = stack ;
pNewNode - > index = index ;
stack = pNewNode ;
}
}
delete current ;
}
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
if ( ! visited [ i ] )
{
AddLogEntry ( true , LL_WARNING , " Path broken from Waypoint #0 to Waypoint #%d! " , i ) ;
2016-03-01 13:37:10 +03:00
if ( g_waypointOn & & ! engine . IsDedicatedServer ( ) )
2015-06-24 15:38:48 +03:00
{
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
2014-07-30 14:17:46 +04:00
2015-06-24 15:38:48 +03:00
g_waypointOn = true ;
g_editNoclip = true ;
}
2014-07-30 14:17:46 +04:00
return false ;
}
}
// then check outgoing connectivity
Array < int > outgoingPaths [ MAX_WAYPOINTS ] ; // store incoming paths for speedup
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
if ( m_paths [ i ] - > index [ j ] > = 0 & & m_paths [ i ] - > index [ j ] < g_numWaypoints )
outgoingPaths [ m_paths [ i ] - > index [ j ] ] . Push ( i ) ;
}
}
// initialize the "visited" table
for ( i = 0 ; i < g_numWaypoints ; i + + )
visited [ i ] = false ;
// check from Waypoint nr. 0
stack = new PathNode ;
stack - > next = NULL ;
stack - > index = 0 ;
while ( stack ! = NULL )
{
// pop a node from the stack
PathNode * current = stack ;
stack = stack - > next ;
visited [ current - > index ] = true ;
2015-06-28 19:43:31 +03:00
FOR_EACH_AE ( outgoingPaths [ current - > index ] , p )
2014-07-30 14:17:46 +04:00
{
2015-06-04 11:52:48 +03:00
if ( visited [ outgoingPaths [ current - > index ] [ p ] ] )
2014-07-30 14:17:46 +04:00
continue ; // skip this waypoint as it's already visited
2015-08-03 12:36:57 +03:00
PathNode * newNode = new PathNode ;
2014-07-30 14:17:46 +04:00
2015-08-03 12:36:57 +03:00
newNode - > next = stack ;
newNode - > index = outgoingPaths [ current - > index ] [ p ] ;
stack = newNode ;
2014-07-30 14:17:46 +04:00
}
delete current ;
}
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
if ( ! visited [ i ] )
{
AddLogEntry ( true , LL_WARNING , " Path broken from Waypoint #%d to Waypoint #0! " , i ) ;
2016-03-01 13:37:10 +03:00
if ( g_waypointOn & & ! engine . IsDedicatedServer ( ) )
2015-06-24 15:38:48 +03:00
{
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
2014-07-30 14:17:46 +04:00
2015-06-24 15:38:48 +03:00
g_waypointOn = true ;
g_editNoclip = true ;
}
2014-07-30 14:17:46 +04:00
return false ;
}
}
return true ;
}
void Waypoint : : InitPathMatrix ( void )
{
int i , j , k ;
delete [ ] m_distMatrix ;
delete [ ] m_pathMatrix ;
m_distMatrix = NULL ;
m_pathMatrix = NULL ;
m_distMatrix = new int [ g_numWaypoints * g_numWaypoints ] ;
m_pathMatrix = new int [ g_numWaypoints * g_numWaypoints ] ;
if ( LoadPathMatrix ( ) )
return ; // matrix loaded from file
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < g_numWaypoints ; j + + )
{
* ( m_distMatrix + i * g_numWaypoints + j ) = 999999 ;
* ( m_pathMatrix + i * g_numWaypoints + j ) = - 1 ;
}
}
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < MAX_PATH_INDEX ; j + + )
{
if ( m_paths [ i ] - > index [ j ] > = 0 & & m_paths [ i ] - > index [ j ] < g_numWaypoints )
{
* ( m_distMatrix + ( i * g_numWaypoints ) + m_paths [ i ] - > index [ j ] ) = m_paths [ i ] - > distances [ j ] ;
* ( m_pathMatrix + ( i * g_numWaypoints ) + m_paths [ i ] - > index [ j ] ) = m_paths [ i ] - > index [ j ] ;
}
}
}
for ( i = 0 ; i < g_numWaypoints ; i + + )
* ( m_distMatrix + ( i * g_numWaypoints ) + i ) = 0 ;
for ( k = 0 ; k < g_numWaypoints ; k + + )
{
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
for ( j = 0 ; j < g_numWaypoints ; j + + )
{
if ( * ( m_distMatrix + ( i * g_numWaypoints ) + k ) + * ( m_distMatrix + ( k * g_numWaypoints ) + j ) < ( * ( m_distMatrix + ( i * g_numWaypoints ) + j ) ) )
{
* ( m_distMatrix + ( i * g_numWaypoints ) + j ) = * ( m_distMatrix + ( i * g_numWaypoints ) + k ) + * ( m_distMatrix + ( k * g_numWaypoints ) + j ) ;
* ( m_pathMatrix + ( i * g_numWaypoints ) + j ) = * ( m_pathMatrix + ( i * g_numWaypoints ) + k ) ;
}
}
}
}
// save path matrix to file for faster access
SavePathMatrix ( ) ;
}
void Waypoint : : SavePathMatrix ( void )
{
2016-03-01 22:52:17 +03:00
File fp ( FormatBuffer ( " %slearned/%s.pmt " , GetDataDir ( ) , engine . GetMapName ( ) ) , " wb " ) ;
2014-07-30 14:17:46 +04:00
// unable to open file
if ( ! fp . IsValid ( ) )
{
AddLogEntry ( false , LL_FATAL , " Failed to open file for writing " ) ;
return ;
}
// write number of waypoints
fp . Write ( & g_numWaypoints , sizeof ( int ) ) ;
// write path & distance matrix
fp . Write ( m_pathMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) ;
fp . Write ( m_distMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) ;
// and close the file
fp . Close ( ) ;
}
bool Waypoint : : LoadPathMatrix ( void )
{
2016-03-01 22:52:17 +03:00
File fp ( FormatBuffer ( " %slearned/%s.pmt " , GetDataDir ( ) , engine . GetMapName ( ) ) , " rb " ) ;
2014-07-30 14:17:46 +04:00
// file doesn't exists return false
if ( ! fp . IsValid ( ) )
return false ;
int num = 0 ;
// read number of waypoints
2015-06-29 21:49:52 +03:00
if ( fp . Read ( & num , sizeof ( int ) ) = = 0 )
{
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
if ( num ! = g_numWaypoints )
{
2015-07-20 21:26:20 +03:00
AddLogEntry ( true , LL_WARNING , " Pathmatrix damaged (wrong version, or not for this map). Pathmatrix will be rebuilt. " ) ;
2014-07-30 14:17:46 +04:00
fp . Close ( ) ;
return false ;
}
// read path & distance matrixes
2015-06-29 20:51:25 +03:00
if ( fp . Read ( m_pathMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) = = 0 )
{
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
2015-06-29 20:51:25 +03:00
if ( fp . Read ( m_distMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) = = 0 )
{
fp . Close ( ) ;
return false ;
}
fp . Close ( ) ; // and close the file
2014-07-30 14:17:46 +04:00
return true ;
}
int Waypoint : : GetPathDistance ( int srcIndex , int destIndex )
{
if ( srcIndex < 0 | | srcIndex > = g_numWaypoints | | destIndex < 0 | | destIndex > = g_numWaypoints )
return 1 ;
return * ( m_distMatrix + ( srcIndex * g_numWaypoints ) + destIndex ) ;
}
void Waypoint : : SetGoalVisited ( int index )
{
if ( index < 0 | | index > = g_numWaypoints )
return ;
2016-01-07 18:49:55 +03:00
if ( ! IsGoalVisited ( index ) & & ( m_paths [ index ] - > flags & FLAG_GOAL ) )
2014-07-30 14:17:46 +04:00
m_visitedGoals . Push ( index ) ;
2016-01-07 18:49:55 +03:00
}
void Waypoint : : ClearVisitedGoals ( void )
{
m_visitedGoals . RemoveAll ( ) ;
2014-07-30 14:17:46 +04:00
}
bool Waypoint : : IsGoalVisited ( int index )
{
2015-06-28 19:43:31 +03:00
FOR_EACH_AE ( m_visitedGoals , i )
2014-07-30 14:17:46 +04:00
{
if ( m_visitedGoals [ i ] = = index )
return true ;
}
return false ;
}
void Waypoint : : CreateBasic ( void )
{
// this function creates basic waypoint types on map
edict_t * ent = NULL ;
// first of all, if map contains ladder points, create it
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_ladder " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector ladderLeft = ent - > v . absmin ;
Vector ladderRight = ent - > v . absmax ;
ladderLeft . z = ladderRight . z ;
TraceResult tr ;
Vector up , down , front , back ;
2015-08-15 18:09:15 +03:00
Vector diff = ( ( ladderLeft - ladderRight ) ^ Vector ( 0.0f , 0.0f , 0.0f ) ) . Normalize ( ) * 15.0f ;
2016-03-01 13:37:10 +03:00
front = back = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
front = front + diff ; // front
back = back - diff ; // back
up = down = front ;
down . z = ent - > v . absmax . z ;
2016-03-01 13:37:10 +03:00
engine . TestHull ( down , up , TRACE_IGNORE_MONSTERS , point_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
2016-01-04 18:26:06 +03:00
if ( POINT_CONTENTS ( up ) = = CONTENTS_SOLID | | tr . flFraction ! = 1.0f )
2014-07-30 14:17:46 +04:00
{
up = down = back ;
down . z = ent - > v . absmax . z ;
}
2016-03-01 13:37:10 +03:00
engine . TestHull ( down , up - Vector ( 0.0f , 0.0f , 1000.0f ) , TRACE_IGNORE_MONSTERS , point_hull , NULL , & tr ) ;
2014-07-30 14:17:46 +04:00
up = tr . vecEndPos ;
2015-08-15 18:09:15 +03:00
Vector pointOrigin = up + Vector ( 0.0f , 0.0f , 39.0f ) ;
2014-07-30 14:17:46 +04:00
m_isOnLadder = true ;
do
{
2015-08-15 18:09:15 +03:00
if ( FindNearest ( pointOrigin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 3 , pointOrigin ) ;
pointOrigin . z + = 160 ;
2015-08-15 18:09:15 +03:00
} while ( pointOrigin . z < down . z - 40.0f ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
pointOrigin = down + Vector ( 0.0f , 0.0f , 38.0f ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( pointOrigin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 3 , pointOrigin ) ;
m_isOnLadder = false ;
}
// then terrortist spawnpoints
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_player_deathmatch " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 0 , origin ) ;
}
// then add ct spawnpoints
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_player_start " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 0 , origin ) ;
}
// then vip spawnpoint
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_vip_start " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 0 , origin ) ;
}
// hostage rescue zone
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_hostage_rescue " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 4 , origin ) ;
}
// hostage rescue zone (same as above)
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_hostage_rescue " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 4 , origin ) ;
}
// bombspot zone
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_bomb_target " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 100 , origin ) ;
}
// bombspot zone (same as above)
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_bomb_target " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 100 , origin ) ;
}
// hostage entities
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " hostage_entity " ) ) )
2014-07-30 14:17:46 +04:00
{
// if already saved || moving skip it
2015-08-15 18:09:15 +03:00
if ( ( ent - > v . effects & EF_NODRAW ) & & ent - > v . speed > 0.0f )
2014-07-30 14:17:46 +04:00
continue ;
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// vip rescue (safety) zone
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_vip_safetyzone " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 100 , origin ) ;
}
// terrorist escape zone
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_escapezone " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 100 , origin ) ;
}
// weapons on the map ?
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " armoury_entity " ) ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 13:37:10 +03:00
Vector origin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
2015-08-15 18:09:15 +03:00
if ( FindNearest ( origin , 50.0f ) = = - 1 )
2014-07-30 14:17:46 +04:00
Add ( 0 , origin ) ;
}
}
Path * Waypoint : : GetPath ( int id )
{
Path * path = m_paths [ id ] ;
if ( path = = NULL )
return NULL ;
return path ;
}
void Waypoint : : EraseFromHardDisk ( void )
{
// this function removes waypoint file from the hard disk
String deleteList [ 5 ] ;
2016-03-01 13:37:10 +03:00
const char * map = engine . GetMapName ( ) ;
2014-07-30 14:17:46 +04:00
// if we're delete waypoint, delete all corresponding to it files
2016-03-01 22:52:17 +03:00
deleteList [ 0 ] = FormatBuffer ( " %s%s.pwf " , GetDataDir ( ) , map ) ; // waypoint itself
deleteList [ 1 ] = FormatBuffer ( " %slearned/%s.exp " , GetDataDir ( ) , map ) ; // corresponding to waypoint experience
deleteList [ 3 ] = FormatBuffer ( " %slearned/%s.vis " , GetDataDir ( ) , map ) ; // corresponding to waypoint vistable
deleteList [ 3 ] = FormatBuffer ( " %slearned/%s.pmt " , GetDataDir ( ) , map ) ; // corresponding to waypoint path matrix
deleteList [ 4 ] = FormatBuffer ( " %slearned/%s.xml " , GetDataDir ( ) , map ) ; // corresponding to waypoint xml database
2014-07-30 14:17:46 +04:00
for ( int i = 0 ; i < 4 ; i + + )
{
2015-07-11 19:54:46 +03:00
if ( File : : Accessible ( const_cast < char * > ( deleteList [ i ] . GetBuffer ( ) ) ) )
2014-07-30 14:17:46 +04:00
{
unlink ( deleteList [ i ] . GetBuffer ( ) ) ;
AddLogEntry ( true , LL_DEFAULT , " File %s, has been deleted from the hard disk " , deleteList [ i ] . GetBuffer ( ) ) ;
}
else
AddLogEntry ( true , LL_ERROR , " Unable to open %s " , deleteList [ i ] . GetBuffer ( ) ) ;
}
Init ( ) ; // reintialize points
}
2016-03-01 22:52:17 +03:00
const char * Waypoint : : GetDataDir ( void )
{
return FormatBuffer ( " %s/addons/yapb/data/ " , engine . GetModName ( ) ) ;
}
2014-07-30 14:17:46 +04:00
void Waypoint : : SetBombPosition ( bool shouldReset )
{
// this function stores the bomb position as a vector
if ( shouldReset )
{
2015-08-15 18:09:15 +03:00
m_foundBombOrigin . Zero ( ) ;
2014-07-30 14:17:46 +04:00
g_bombPlanted = false ;
return ;
}
edict_t * ent = NULL ;
2016-03-05 23:08:07 +03:00
while ( ! engine . IsNullEntity ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " grenade " ) ) )
2014-07-30 14:17:46 +04:00
{
if ( strcmp ( STRING ( ent - > v . model ) + 9 , " c4.mdl " ) = = 0 )
{
2016-03-01 13:37:10 +03:00
m_foundBombOrigin = engine . GetAbsOrigin ( ent ) ;
2014-07-30 14:17:46 +04:00
break ;
}
}
}
void Waypoint : : SetLearnJumpWaypoint ( void )
{
m_learnJumpWaypoint = true ;
}
void Waypoint : : SetFindIndex ( int index )
{
m_findWPIndex = index ;
if ( m_findWPIndex < g_numWaypoints )
2016-03-01 13:37:10 +03:00
engine . Printf ( " Showing Direction to Waypoint #%d " , m_findWPIndex ) ;
2014-07-30 14:17:46 +04:00
else
m_findWPIndex = - 1 ;
}
Waypoint : : Waypoint ( void )
{
2016-03-12 14:35:44 +03:00
CleanupPathMemory ( ) ;
2014-07-30 14:17:46 +04:00
m_waypointPaths = false ;
m_endJumpPoint = false ;
m_redoneVisibility = false ;
m_learnJumpWaypoint = false ;
2015-08-15 18:09:15 +03:00
m_timeJumpStarted = 0.0f ;
2014-07-30 14:17:46 +04:00
m_lastJumpWaypoint = - 1 ;
m_cacheWaypointIndex = - 1 ;
m_findWPIndex = - 1 ;
2015-06-29 20:51:25 +03:00
m_facingAtIndex = - 1 ;
2014-07-30 14:17:46 +04:00
m_visibilityIndex = 0 ;
m_isOnLadder = false ;
2015-08-15 18:09:15 +03:00
m_pathDisplayTime = 0.0f ;
m_arrowDisplayTime = 0.0f ;
2014-07-30 14:17:46 +04:00
m_terrorPoints . RemoveAll ( ) ;
m_ctPoints . RemoveAll ( ) ;
m_goalPoints . RemoveAll ( ) ;
m_campPoints . RemoveAll ( ) ;
m_rescuePoints . RemoveAll ( ) ;
m_sniperPoints . RemoveAll ( ) ;
m_distMatrix = NULL ;
m_pathMatrix = NULL ;
}
Waypoint : : ~ Waypoint ( void )
{
2016-03-12 14:35:44 +03:00
CleanupPathMemory ( ) ;
2014-07-30 14:17:46 +04:00
delete [ ] m_distMatrix ;
delete [ ] m_pathMatrix ;
m_distMatrix = NULL ;
m_pathMatrix = NULL ;
}
2016-03-01 22:52:17 +03:00
void Waypoint : : CloseSocketHandle ( int sock )
2014-07-30 14:17:46 +04:00
{
# if defined (PLATFORM_WIN32)
if ( sock ! = - 1 )
closesocket ( sock ) ;
WSACleanup ( ) ;
# else
if ( sock ! = - 1 )
close ( sock ) ;
# endif
}
2016-03-01 22:52:17 +03:00
WaypointDownloadError Waypoint : : RequestWaypoint ( void )
2014-07-30 14:17:46 +04:00
{
# if defined (PLATFORM_WIN32)
2015-06-28 19:43:31 +03:00
WORD requestedVersion = MAKEWORD ( 1 , 1 ) ;
2014-07-30 14:17:46 +04:00
WSADATA wsaData ;
2015-06-28 19:43:31 +03:00
int wsa = WSAStartup ( requestedVersion , & wsaData ) ;
if ( wsa ! = 0 )
return WDE_SOCKET_ERROR ;
2014-07-30 14:17:46 +04:00
# endif
hostent * host = gethostbyname ( yb_waypoint_autodl_host . GetString ( ) ) ;
if ( host = = NULL )
return WDE_SOCKET_ERROR ;
int socketHandle = socket ( AF_INET , SOCK_STREAM , 0 ) ;
if ( socketHandle < 0 )
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2014-07-30 14:17:46 +04:00
return WDE_SOCKET_ERROR ;
}
sockaddr_in dest ;
timeval timeout ;
2014-09-17 20:36:42 +04:00
timeout . tv_sec = 5 ;
2014-07-30 14:17:46 +04:00
timeout . tv_usec = 0 ;
2015-08-03 12:36:57 +03:00
int result = setsockopt ( socketHandle , SOL_SOCKET , SO_RCVTIMEO , ( char * ) & timeout , sizeof ( timeout ) ) ;
2014-07-30 14:17:46 +04:00
2015-06-29 21:49:52 +03:00
if ( result < 0 )
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2015-06-29 21:49:52 +03:00
return WDE_SOCKET_ERROR ;
}
result = setsockopt ( socketHandle , SOL_SOCKET , SO_SNDTIMEO , ( char * ) & timeout , sizeof ( timeout ) ) ;
if ( result < 0 )
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2015-06-29 21:49:52 +03:00
return WDE_SOCKET_ERROR ;
}
2014-07-30 14:17:46 +04:00
memset ( & dest , 0 , sizeof ( dest ) ) ;
2015-06-29 21:49:52 +03:00
2014-07-30 14:17:46 +04:00
dest . sin_family = AF_INET ;
dest . sin_port = htons ( 80 ) ;
dest . sin_addr . s_addr = inet_addr ( inet_ntoa ( * ( ( struct in_addr * ) host - > h_addr ) ) ) ;
if ( connect ( socketHandle , ( struct sockaddr * ) & dest , ( int ) sizeof ( dest ) ) = = - 1 )
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2014-07-30 14:17:46 +04:00
return WDE_CONNECT_ERROR ;
}
String request ;
2016-03-01 13:37:10 +03:00
request . AssignFormat ( " GET /wpdb/%s.pwf HTTP/1.0 \r \n Accept: */* \r \n User-Agent: YaPB/%s \r \n Host: %s \r \n \r \n " , engine . GetMapName ( ) , PRODUCT_VERSION , yb_waypoint_autodl_host . GetString ( ) ) ;
2014-07-30 14:17:46 +04:00
2014-09-17 20:36:42 +04:00
if ( send ( socketHandle , request . GetBuffer ( ) , request . GetLength ( ) + 1 , 0 ) < 1 )
2014-07-30 14:17:46 +04:00
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2014-07-30 14:17:46 +04:00
return WDE_SOCKET_ERROR ;
}
2016-03-12 14:35:44 +03:00
const int ChunkSize = MAX_PRINT_BUFFER ;
2015-06-21 21:39:59 +03:00
char buffer [ ChunkSize ] = { 0 , } ;
2014-07-30 14:17:46 +04:00
bool finished = false ;
int recvPosition = 0 ;
int symbolsInLine = 0 ;
// scan for the end of the header
2015-06-21 21:39:59 +03:00
while ( ! finished & & recvPosition < ChunkSize )
2014-07-30 14:17:46 +04:00
{
2014-09-17 20:36:42 +04:00
if ( recv ( socketHandle , & buffer [ recvPosition ] , 1 , 0 ) = = 0 )
2014-07-30 14:17:46 +04:00
finished = true ;
2015-06-21 21:39:59 +03:00
// ugly, but whatever
2016-02-29 23:50:16 +03:00
if ( recvPosition > 2 & & buffer [ recvPosition - 2 ] = = ' 4 ' & & buffer [ recvPosition - 1 ] = = ' 0 ' & & buffer [ recvPosition ] = = ' 4 ' )
2015-06-21 21:39:59 +03:00
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2015-06-21 21:39:59 +03:00
return WDE_NOTFOUND_ERROR ;
}
2014-07-30 14:17:46 +04:00
switch ( buffer [ recvPosition ] )
{
case ' \r ' :
break ;
case ' \n ' :
if ( symbolsInLine = = 0 )
finished = true ;
symbolsInLine = 0 ;
break ;
default :
symbolsInLine + + ;
break ;
}
recvPosition + + ;
}
2014-09-17 20:36:42 +04:00
2015-07-24 15:10:51 +03:00
File fp ( waypoints . CheckSubfolderFile ( ) , " wb " ) ;
2015-06-21 21:39:59 +03:00
if ( ! fp . IsValid ( ) )
2014-07-30 14:17:46 +04:00
{
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2015-06-21 21:39:59 +03:00
return WDE_SOCKET_ERROR ;
2014-07-30 14:17:46 +04:00
}
2015-06-21 21:39:59 +03:00
int recvSize = 0 ;
2014-07-30 14:17:46 +04:00
2015-06-21 21:39:59 +03:00
do
{
recvSize = recv ( socketHandle , buffer , ChunkSize , 0 ) ;
2014-07-30 14:17:46 +04:00
2015-06-29 20:51:25 +03:00
if ( recvSize > 0 )
{
fp . Write ( buffer , recvSize ) ;
fp . Flush ( ) ;
}
2015-06-21 21:39:59 +03:00
} while ( recvSize ! = 0 ) ;
2014-07-30 14:17:46 +04:00
2015-06-21 21:39:59 +03:00
fp . Close ( ) ;
2016-03-01 22:52:17 +03:00
CloseSocketHandle ( socketHandle ) ;
2015-06-21 21:39:59 +03:00
2014-07-30 14:17:46 +04:00
return WDE_NOERROR ;
}