2015-06-04 11:52:48 +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>
2015-06-04 11:52:48 +03:00
ConVar yb_wptsubfolder ( " yb_wptsubfolder " , " " , VT_NOSERVER ) ;
2014-07-30 14:17:46 +04:00
2015-06-04 11:52:48 +03:00
ConVar yb_waypoint_autodl_host ( " yb_waypoint_autodl_host " , " yapb.jeefo.net " , VT_NOSERVER ) ;
ConVar yb_waypoint_autodl_enable ( " yb_waypoint_autodl_enable " , " 1 " , VT_NOSERVER ) ;
2014-07-30 14:17:46 +04:00
void Waypoint : : Init ( void )
{
// this function initialize the waypoint structures..
// have any waypoint path nodes been allocated yet?
if ( m_waypointPaths )
{
for ( int i = 0 ; i < g_numWaypoints & & m_paths [ i ] ! = NULL ; i + + )
{
delete m_paths [ i ] ;
m_paths [ i ] = NULL ;
}
}
g_numWaypoints = 0 ;
m_lastWaypoint = nullvec ;
}
void Waypoint : : AddPath ( short int addIndex , short int pathIndex , float distance )
{
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 ) ) ;
}
}
int Waypoint : : FindFarest ( Vector origin , float maxDistance )
{
// 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 ;
}
int Waypoint : : FindNearest ( Vector origin , float minDistance , int flags )
{
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
2015-06-06 14:19:19 +03:00
float distance = ( m_paths [ i ] - > origin - origin ) . GetLength ( ) ;
2014-07-30 14:17:46 +04:00
if ( distance < minDistance )
{
index = i ;
minDistance = distance ;
}
}
return index ;
}
void Waypoint : : FindInRadius ( Vector origin , float radius , int * holdTab , int * count )
{
// returns all waypoints within radius from position
int maxCount = * count ;
* count = 0 ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( ( m_paths [ i ] - > origin - origin ) . GetLength ( ) < radius )
{
* holdTab + + = i ;
* count + = 1 ;
if ( * count > = maxCount )
break ;
}
}
* count - = 1 ;
}
void Waypoint : : FindInRadius ( Array < int > & queueID , float radius , Vector origin )
{
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( ( m_paths [ i ] - > origin - origin ) . GetLength ( ) < = radius )
queueID . Push ( i ) ;
}
}
void Waypoint : : Add ( int flags , const Vector & waypointOrigin )
{
2015-06-04 11:52:48 +03:00
if ( IsEntityNull ( g_hostEntity ) )
2014-07-30 14:17:46 +04:00
return ;
int index = - 1 , i ;
float distance ;
Vector forward = nullvec ;
Path * path = NULL ;
bool placeNew = true ;
Vector newOrigin = waypointOrigin ;
if ( waypointOrigin = = nullvec )
newOrigin = g_hostEntity - > v . origin ;
if ( g_botManager - > GetBotsNum ( ) > 0 )
g_botManager - > RemoveAll ( ) ;
g_waypointsChanged = true ;
switch ( flags )
{
case 6 :
index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( index ! = - 1 )
{
path = m_paths [ index ] ;
if ( ! ( path - > flags & FLAG_CAMP ) )
{
CenterPrint ( " This is not Camping Waypoint " ) ;
return ;
}
MakeVectors ( g_hostEntity - > v . v_angle ) ;
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640 ;
path - > campEndX = forward . x ;
path - > campEndY = forward . y ;
// play "done" sound...
PlaySound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
}
return ;
case 9 :
index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( index ! = - 1 )
{
distance = ( m_paths [ index ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
if ( distance < 50 )
{
placeNew = false ;
path = m_paths [ index ] ;
if ( flags = = 9 )
path - > origin = ( path - > origin + m_learnPosition ) / 2 ;
}
}
else
newOrigin = m_learnPosition ;
break ;
case 10 :
index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( index ! = - 1 & & m_paths [ index ] ! = NULL )
{
distance = ( m_paths [ index ] - > origin - g_hostEntity - > v . origin ) . GetLength ( ) ;
if ( distance < 50 )
{
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 )
path - > origin = ( path - > origin + g_hostEntity - > v . origin ) / 2 ;
}
}
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 ;
path - > campEndX = 0 ;
path - > campEndY = 0 ;
path - > campStartX = 0 ;
path - > campStartY = 0 ;
for ( i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
path - > index [ i ] = - 1 ;
path - > distances [ i ] = 0 ;
path - > connectionFlags [ i ] = 0 ;
path - > connectionVelocity [ i ] = nullvec ;
}
// 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 ) ;
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640 ;
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 ) ;
forward = g_hostEntity - > v . origin + g_hostEntity - > v . view_ofs + g_pGlobals - > v_forward * 640 ;
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 )
{
float minDistance = 9999.0 ;
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
TraceLine ( newOrigin , m_paths [ i ] - > origin , true , g_hostEntity , & tr ) ;
if ( tr . flFraction = = 1.0 & & fabs ( newOrigin . x - m_paths [ i ] - > origin . x ) < 64 & & fabs ( newOrigin . y - m_paths [ i ] - > origin . y ) < 64 & & fabs ( newOrigin . z - m_paths [ i ] - > origin . z ) < g_autoPathDistance )
{
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 ) ;
}
}
}
PlaySound ( g_hostEntity , " weapons/xbow_hit1.wav " ) ;
CalculateWayzone ( index ) ; // calculate the wayzone of this waypoint
}
void Waypoint : : Delete ( void )
{
g_waypointsChanged = true ;
if ( g_numWaypoints < 1 )
return ;
if ( g_botManager - > GetBotsNum ( ) > 0 )
g_botManager - > RemoveAll ( ) ;
int index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( index = = - 1 )
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 ;
path - > connectionVelocity [ j ] = nullvec ;
}
}
}
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 ;
// Rotate Path Array down
for ( i = index ; i < g_numWaypoints - 1 ; i + + )
m_paths [ i ] = m_paths [ i + 1 ] ;
g_numWaypoints - - ;
m_waypointDisplayTime [ index ] = 0 ;
PlaySound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
}
void Waypoint : : ToggleFlags ( int toggleFlag )
{
// this function allow manually changing flags
int index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
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...
PlaySound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
}
}
void Waypoint : : SetRadius ( int radius )
{
// this function allow manually setting the zone radius
int index = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( index ! = - 1 )
{
m_paths [ index ] - > radius = static_cast < float > ( radius ) ;
// play "done" sound...
PlaySound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
}
}
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 ;
float viewCone [ 3 ] = { 0.0 , 0.0 , 0.0 } ;
// find the waypoint the user is pointing at
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
if ( ( m_paths [ i ] - > origin - g_hostEntity - > v . origin ) . GetLengthSquared ( ) > 250000 )
continue ;
// get the current view cone
viewCone [ 0 ] = GetShootingConeDeviation ( g_hostEntity , & m_paths [ i ] - > origin ) ;
2015-06-04 11:52:48 +03:00
Vector bound = m_paths [ i ] - > origin - Vector ( 0 , 0 , ( m_paths [ i ] - > flags & FLAG_CROUCH ) ? 8 : 15 ) ;
2014-07-30 14:17:46 +04:00
// get the current view cone
viewCone [ 1 ] = GetShootingConeDeviation ( g_hostEntity , & bound ) ;
2015-06-04 11:52:48 +03:00
bound = m_paths [ i ] - > origin + Vector ( 0 , 0 , ( m_paths [ i ] - > flags & FLAG_CROUCH ) ? 8 : 15 ) ;
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
if ( viewCone [ 0 ] < 0.998 & & viewCone [ 1 ] < 0.997 & & viewCone [ 2 ] < 0.997 )
continue ;
pointedIndex = i ;
}
return pointedIndex ;
}
void Waypoint : : CreatePath ( char dir )
{
// this function allow player to manually create a path from one waypoint to another
int nodeFrom = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( nodeFrom = = - 1 )
{
CenterPrint ( " Unable to find nearest waypoint in 50 units " ) ;
return ;
}
int nodeTo = m_facingAtIndex ;
if ( nodeTo < 0 | | nodeTo > = g_numWaypoints )
{
if ( m_cacheWaypointIndex > = 0 & & m_cacheWaypointIndex < g_numWaypoints )
nodeTo = m_cacheWaypointIndex ;
else
{
CenterPrint ( " Unable to find destination waypoint " ) ;
return ;
}
}
if ( nodeTo = = nodeFrom )
{
CenterPrint ( " Unable to connect waypoint with itself " ) ;
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 ) ;
}
PlaySound ( g_hostEntity , " common/wpn_hudon.wav " ) ;
g_waypointsChanged = true ;
}
void Waypoint : : DeletePath ( void )
{
// this function allow player to manually remove a path from one waypoint to another
int nodeFrom = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
int index = 0 ;
if ( nodeFrom = = - 1 )
{
CenterPrint ( " Unable to find nearest waypoint in 50 units " ) ;
return ;
}
int nodeTo = m_facingAtIndex ;
if ( nodeTo < 0 | | nodeTo > = g_numWaypoints )
{
if ( m_cacheWaypointIndex > = 0 & & m_cacheWaypointIndex < g_numWaypoints )
nodeTo = m_cacheWaypointIndex ;
else
{
CenterPrint ( " Unable to find destination waypoint " ) ;
return ;
}
}
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 ] - > connectionFlags [ index ] = 0 ;
m_paths [ nodeFrom ] - > connectionVelocity [ index ] = nullvec ;
m_paths [ nodeFrom ] - > distances [ index ] = 0 ;
PlaySound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
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 ] - > connectionFlags [ index ] = 0 ;
m_paths [ nodeFrom ] - > connectionVelocity [ index ] = nullvec ;
m_paths [ nodeFrom ] - > distances [ index ] = 0 ;
PlaySound ( g_hostEntity , " weapons/mine_activate.wav " ) ;
return ;
}
}
CenterPrint ( " There is already no path on this waypoint " ) ;
}
void Waypoint : : CacheWaypoint ( void )
{
int node = FindNearest ( g_hostEntity - > v . origin , 50.0 ) ;
if ( node = = - 1 )
{
m_cacheWaypointIndex = - 1 ;
CenterPrint ( " Cached waypoint cleared (nearby point not found in 50 units range) " ) ;
return ;
}
m_cacheWaypointIndex = node ;
CenterPrint ( " Waypoint #%d has been put into memory " , m_cacheWaypointIndex ) ;
}
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 )
{
path - > radius = 0 ;
return ;
}
for ( int i = 0 ; i < MAX_PATH_INDEX ; i + + )
{
if ( path - > index [ i ] ! = - 1 & & ( m_paths [ path - > index [ i ] ] - > flags & FLAG_LADDER ) )
{
path - > radius = 0 ;
return ;
}
}
for ( int scanDistance = 16 ; scanDistance < 128 ; scanDistance + = 16 )
{
start = path - > origin ;
MakeVectors ( nullvec ) ;
direction = g_pGlobals - > v_forward * scanDistance ;
direction = direction . ToAngles ( ) ;
path - > radius = scanDistance ;
for ( float circleRadius = 0.0 ; circleRadius < 180.0 ; circleRadius + = 5 )
{
MakeVectors ( direction ) ;
Vector radiusStart = start - g_pGlobals - > v_forward * scanDistance ;
Vector radiusEnd = start + g_pGlobals - > v_forward * scanDistance ;
TraceHull ( radiusStart , radiusEnd , true , head_hull , NULL , & tr ) ;
if ( tr . flFraction < 1.0 )
{
TraceLine ( radiusStart , radiusEnd , true , NULL , & tr ) ;
if ( FClassnameIs ( tr . pHit , " func_door " ) | | FClassnameIs ( tr . pHit , " func_door_rotating " ) )
{
path - > radius = 0 ;
wayBlocked = true ;
break ;
}
wayBlocked = true ;
path - > radius - = 16 ;
break ;
}
Vector dropStart = start + ( g_pGlobals - > v_forward * scanDistance ) ;
Vector dropEnd = dropStart - Vector ( 0 , 0 , scanDistance + 60 ) ;
TraceHull ( dropStart , dropEnd , true , head_hull , NULL , & tr ) ;
if ( tr . flFraction > = 1.0 )
{
wayBlocked = true ;
path - > radius - = 16 ;
break ;
}
dropStart = start - ( g_pGlobals - > v_forward * scanDistance ) ;
dropEnd = dropStart - Vector ( 0 , 0 , scanDistance + 60 ) ;
TraceHull ( dropStart , dropEnd , true , head_hull , NULL , & tr ) ;
if ( tr . flFraction > = 1.0 )
{
wayBlocked = true ;
path - > radius - = 16 ;
break ;
}
radiusEnd . z + = 34 ;
TraceHull ( radiusStart , radiusEnd , true , head_hull , NULL , & tr ) ;
if ( tr . flFraction < 1.0 )
{
wayBlocked = true ;
path - > radius - = 16 ;
break ;
}
direction . y = AngleNormalize ( direction . y + circleRadius ) ;
}
if ( wayBlocked )
break ;
}
path - > radius - = 16 ;
if ( path - > radius < 0 )
path - > radius = 0 ;
}
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 ;
}
}
int result = Compressor : : Compress ( FormatBuffer ( " %sdata/%s.exp " , GetWaypointDir ( ) , GetMapName ( ) ) , ( unsigned char * ) & header , sizeof ( ExtensionHeader ) , ( unsigned char * ) experienceSave , g_numWaypoints * g_numWaypoints * sizeof ( ExperienceSave ) ) ;
delete [ ] experienceSave ;
if ( result = = - 1 )
{
AddLogEntry ( true , LL_ERROR , " Couldn't save experience data " ) ;
return ;
}
}
void Waypoint : : InitExperienceTab ( void )
{
ExtensionHeader header ;
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 ;
}
}
File fp ( FormatBuffer ( " %sdata/%s.exp " , GetWaypointDir ( ) , GetMapName ( ) ) , " rb " ) ;
// if file exists, read the experience data from it
if ( fp . IsValid ( ) )
{
fp . Read ( & header , sizeof ( ExtensionHeader ) ) ;
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 ] ;
Compressor : : Uncompress ( FormatBuffer ( " %sdata/%s.exp " , GetWaypointDir ( ) , GetMapName ( ) ) , sizeof ( ExtensionHeader ) , ( unsigned char * ) experienceLoad , g_numWaypoints * g_numWaypoints * sizeof ( ExperienceSave ) ) ;
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
AddLogEntry ( true , LL_ERROR , " Experience data damaged (wrong version, or not for this map) " ) ;
}
}
}
void Waypoint : : SaveVisibilityTab ( void )
{
if ( g_numWaypoints = = 0 )
return ;
if ( m_visLUT = = NULL )
AddLogEntry ( true , LL_FATAL , " Can't save visiblity tab. Bad data. " ) ;
ExtensionHeader header ;
// parse header
memset ( header . header , 0 , sizeof ( header . header ) ) ;
strcpy ( header . header , FH_VISTABLE ) ;
header . fileVersion = FV_VISTABLE ;
header . pointNumber = g_numWaypoints ;
File fp ( FormatBuffer ( " %sdata/%s.vis " , GetWaypointDir ( ) , GetMapName ( ) ) , " wb " ) ;
if ( ! fp . IsValid ( ) )
{
AddLogEntry ( true , LL_ERROR , " Failed to open visiblity table for writing " ) ;
return ;
}
fp . Close ( ) ;
Compressor : : Compress ( FormatBuffer ( " %sdata/%s.vis " , GetWaypointDir ( ) , GetMapName ( ) ) , ( unsigned char * ) & header , sizeof ( ExtensionHeader ) , ( unsigned char * ) m_visLUT , MAX_WAYPOINTS * ( MAX_WAYPOINTS / 4 ) * sizeof ( byte ) ) ;
}
void Waypoint : : InitVisibilityTab ( void )
{
if ( g_numWaypoints = = 0 )
return ;
ExtensionHeader header ;
File fp ( FormatBuffer ( " %sdata/%s.vis " , GetWaypointDir ( ) , GetMapName ( ) ) , " rb " ) ;
m_redoneVisibility = false ;
if ( ! fp . IsValid ( ) )
{
m_visibilityIndex = 0 ;
m_redoneVisibility = true ;
AddLogEntry ( true , LL_DEFAULT , " Vistable, not exists, vistable will be rebuilded " ) ;
return ;
}
// read the header of the file
fp . Read ( & header , sizeof ( ExtensionHeader ) ) ;
if ( strncmp ( header . header , FH_VISTABLE , strlen ( FH_VISTABLE ) ) ! = 0 | | header . fileVersion ! = FV_VISTABLE | | header . pointNumber ! = g_numWaypoints )
{
m_visibilityIndex = 0 ;
m_redoneVisibility = true ;
AddLogEntry ( true , LL_WARNING , " Vistable damaged (wrong version, or not for this map), vistable will be rebuilded. " ) ;
fp . Close ( ) ;
return ;
}
int result = Compressor : : Uncompress ( FormatBuffer ( " %sdata/%s.vis " , GetWaypointDir ( ) , GetMapName ( ) ) , sizeof ( ExtensionHeader ) , ( unsigned char * ) m_visLUT , MAX_WAYPOINTS * ( MAX_WAYPOINTS / 4 ) * sizeof ( byte ) ) ;
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 )
{
WaypointHeader header ;
File fp ( CheckSubfolderFile ( ) , " rb " ) ;
if ( fp . IsValid ( ) )
{
fp . Read ( & header , sizeof ( header ) ) ;
if ( strncmp ( header . header , FH_WAYPOINT , strlen ( FH_WAYPOINT ) ) = = 0 )
{
if ( header . fileVersion ! = FV_WAYPOINT )
{
sprintf ( m_infoBuffer , " %s.pwf - incorrect waypoint file version (expected '%i' found '%i') " , GetMapName ( ) , FV_WAYPOINT , static_cast < int > ( header . fileVersion ) ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
else if ( stricmp ( header . mapName , GetMapName ( ) ) )
{
sprintf ( m_infoBuffer , " %s.pwf - hacked waypoint file, file name doesn't match waypoint header information (mapname: '%s', header: '%s') " , GetMapName ( ) , GetMapName ( ) , header . mapName ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
else
{
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 )
{
sprintf ( m_infoBuffer , " %s.pwf - truncated waypoint file (count: %d, need: %d) " , GetMapName ( ) , i , g_numWaypoints ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
2014-07-30 14:17:46 +04:00
}
m_waypointPaths = true ;
}
}
else
{
sprintf ( m_infoBuffer , " %s.pwf is not a yapb waypoint file (header found '%s' needed '%s' " , GetMapName ( ) , header . header , FH_WAYPOINT ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
fp . Close ( ) ;
return false ;
}
fp . Close ( ) ;
}
else
{
if ( yb_waypoint_autodl_enable . GetBool ( ) )
{
AddLogEntry ( true , LL_DEFAULT , " %s.pwf does not exist, trying to download from waypoint database " , GetMapName ( ) ) ;
WaypointDownloader dl ;
WaypointDownloadError status = dl . DoDownload ( ) ;
if ( status = = WDE_SOCKET_ERROR )
{
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Socket error. " , GetMapName ( ) ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
yb_waypoint_autodl_enable . SetInt ( 0 ) ;
return false ;
}
else if ( status = = WDE_CONNECT_ERROR )
{
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Connection problems. " , GetMapName ( ) ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
yb_waypoint_autodl_enable . SetInt ( 0 ) ;
return false ;
}
else if ( status = = WDE_NOTFOUND_ERROR )
{
sprintf ( m_infoBuffer , " %s.pwf does not exist. Can't autodownload. Waypoint not available. " , GetMapName ( ) ) ;
AddLogEntry ( true , LL_ERROR , m_infoBuffer ) ;
return false ;
}
else
{
AddLogEntry ( true , LL_DEFAULT , " %s.pwf was downloaded from waypoint database. Trying to load... " , GetMapName ( ) ) ;
return Load ( ) ;
}
}
sprintf ( m_infoBuffer , " %s.pwf does not exist " , GetMapName ( ) ) ;
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
m_pathDisplayTime = 0.0 ;
m_arrowDisplayTime = 0.0 ;
InitVisibilityTab ( ) ;
InitExperienceTab ( ) ;
g_botManager - > InitQuota ( ) ;
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 ) ;
strcpy ( header . author , STRING ( g_hostEntity - > v . netname ) ) ;
strncpy ( header . mapName , GetMapName ( ) , 31 ) ;
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
AddLogEntry ( true , LL_ERROR , " Error writing '%s.pwf' waypoint file " , GetMapName ( ) ) ;
}
String Waypoint : : CheckSubfolderFile ( void )
{
String returnFile = " " ;
if ( ! IsNullString ( yb_wptsubfolder . GetString ( ) ) )
returnFile + = ( String ( yb_wptsubfolder . GetString ( ) ) + " / " ) ;
returnFile = FormatBuffer ( " %s%s%s.pwf " , GetWaypointDir ( ) , returnFile . GetBuffer ( ) , GetMapName ( ) ) ;
if ( TryFileOpen ( returnFile ) )
return returnFile ;
return FormatBuffer ( " %s%s.pwf " , GetWaypointDir ( ) , GetMapName ( ) ) ;
}
float Waypoint : : GetTravelTime ( float maxSpeed , Vector src , Vector origin )
{
// 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 ( ) ;
// check is destination is close to us enoguh
2015-06-07 23:06:23 +03:00
if ( distance > = 150.0f )
2014-07-30 14:17:46 +04:00
return false ;
TraceResult tr ;
TraceLine ( src , dest , true , bot - > GetEntity ( ) , & tr ) ;
// if waypoint is visible from current position (even behind head)...
if ( tr . flFraction > = 1.0 )
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
if ( ( ( dest . z > src . z + 62.0 | | dest . z < src . z - 100.0f ) & & ( ! ( m_paths [ index ] - > flags & FLAG_LADDER ) ) ) | | distance2D > = 120.0f )
return false ; // unable to reach this one
return true ;
}
2014-07-30 14:17:46 +04:00
return false ;
}
bool Waypoint : : IsNodeReachable ( Vector src , Vector destination )
{
TraceResult tr ;
float height , lastHeight ;
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
TraceHull ( src , destination , ignore_monsters , head_hull , g_hostEntity , & tr ) ;
2015-06-04 11:52:48 +03:00
if ( ! IsEntityNull ( 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"...
TraceLine ( src , destination , ignore_monsters , g_hostEntity , & tr ) ;
// if waypoint is visible from current position (even behind head)...
if ( tr . flFraction > = 1.0 | | strncmp ( " func_door " , STRING ( tr . pHit - > v . classname ) , 9 ) = = 0 )
{
// if it's a door check if nothing blocks behind
if ( strncmp ( " func_door " , STRING ( tr . pHit - > v . classname ) , 9 ) = = 0 )
{
TraceLine ( tr . vecEndPos , destination , ignore_monsters , tr . pHit , & tr ) ;
if ( tr . flFraction < 1.0 )
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)
if ( destination . z > src . z + 45.0 )
{
Vector sourceNew = destination ;
Vector destinationNew = destination ;
destinationNew . z = destinationNew . z - 50 ; // straight down 50 units
TraceLine ( sourceNew , destinationNew , ignore_monsters , g_hostEntity , & tr ) ;
// check if we didn't hit anything, if not then it's in mid-air
if ( tr . flFraction > = 1.0 )
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 ;
down . z = down . z - 1000.0 ; // straight down 1000 units
TraceLine ( check , down , ignore_monsters , g_hostEntity , & tr ) ;
lastHeight = tr . flFraction * 1000.0 ; // height from ground
distance = ( destination - check ) . GetLength ( ) ; // distance from goal
while ( distance > 10.0 )
{
// move 10 units closer to the goal...
check = check + ( direction * 10.0 ) ;
down = check ;
down . z = down . z - 1000.0 ; // straight down 1000 units
TraceLine ( check , down , ignore_monsters , g_hostEntity , & tr ) ;
height = tr . flFraction * 1000.0 ; // height from ground
// is the current height greater than the step height?
if ( height < lastHeight - 18.0 )
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 )
{
if ( m_redoneVisibility = = false )
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 )
{
sourceDuck . z + = 12.0 ;
sourceStand . z + = 18.0 + 28.0 ;
}
else
{
sourceDuck . z + = - 18.0 + 12.0 ;
sourceStand . z + = 28.0 ;
}
uint16 standCount = 0 , crouchCount = 0 ;
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
// first check ducked visibility
Vector dest = m_paths [ i ] - > origin ;
TraceLine ( sourceDuck , dest , true , NULL , & tr ) ;
// check if line of sight to object is not blocked (i.e. visible)
if ( ( tr . flFraction ! = 1.0 ) | | tr . fStartSolid )
res = 1 ;
else
res = 0 ;
res < < = 1 ;
TraceLine ( sourceStand , dest , true , NULL , & tr ) ;
// check if line of sight to object is not blocked (i.e. visible)
if ( ( tr . flFraction ! = 1.0 ) | | tr . fStartSolid )
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 ) ;
}
char * Waypoint : : GetWaypointInfo ( int id )
{
// 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 ;
}
static char messageBuffer [ 1024 ] ;
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.
2015-06-04 11:52:48 +03:00
if ( IsEntityNull ( g_hostEntity ) )
2014-07-30 14:17:46 +04:00
return ; // this function is only valid on listenserver, and in waypoint enabled mode.
float nearestDistance = FLT_MAX ;
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 ) ;
m_timeJumpStarted = GetWorldTime ( ) ;
m_endJumpPoint = true ;
}
else
{
m_learnVelocity = g_hostEntity - > v . velocity ;
m_learnPosition = g_hostEntity - > v . origin ;
}
}
else if ( ( ( g_hostEntity - > v . flags & FL_ONGROUND ) | | g_hostEntity - > v . movetype = = MOVETYPE_FLY ) & & m_timeJumpStarted + 0.1 < GetWorldTime ( ) & & m_endJumpPoint )
{
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 ( ) ;
if ( distance > 16384 )
{
// 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...
if ( nearestDistance > = 16384 )
Add ( 0 ) ; // place a waypoint here
}
}
m_facingAtIndex = GetFacingIndex ( ) ;
// reset the minimal distance changed before
nearestDistance = FLT_MAX ;
// now iterate through all waypoints in a map, and draw required ones
for ( int i = 0 ; i < g_numWaypoints ; i + + )
{
float distance = ( m_paths [ i ] - > origin - g_hostEntity - > v . origin ) . GetLengthSquared ( ) ;
// check if waypoint is whitin a distance, and is visible
if ( distance < 500 * 500 & & ( ( : : IsVisible ( m_paths [ i ] - > origin , g_hostEntity ) & & IsInViewCone ( m_paths [ i ] - > origin , g_hostEntity ) ) | | ! IsAlive ( g_hostEntity ) | | distance < 2500 ) )
{
// check the distance
if ( distance < nearestDistance )
{
nearestIndex = i ;
nearestDistance = distance ;
}
if ( m_waypointDisplayTime [ i ] + 1.0 < GetWorldTime ( ) )
{
float nodeHeight = 0.0 ;
// check the node height
if ( m_paths [ i ] - > flags & FLAG_CROUCH )
nodeHeight = 36.0 ;
else
nodeHeight = 72.0 ;
float nodeHalfHeight = nodeHeight * 0.5 ;
// all waypoints are by default are green
Vector nodeColor = nullvec ;
// 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 )
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 ) ;
else // draw node with flags
{
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
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
}
m_waypointDisplayTime [ i ] = GetWorldTime ( ) ;
}
}
}
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
if ( m_arrowDisplayTime + 0.5 < GetWorldTime ( ) )
{
// finding waypoint - pink arrow
if ( m_findWPIndex ! = - 1 )
DrawArrow ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_findWPIndex ] - > origin , 10 , 0 , 128 , 0 , 128 , 200 , 0 , 5 ) ;
// cached waypoint - yellow arrow
if ( m_cacheWaypointIndex ! = - 1 )
DrawArrow ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_cacheWaypointIndex ] - > origin , 10 , 0 , 255 , 255 , 0 , 200 , 0 , 5 ) ;
// waypoint user facing at - white arrow
if ( m_facingAtIndex ! = - 1 )
DrawArrow ( g_hostEntity , g_hostEntity - > v . origin , m_paths [ m_facingAtIndex ] - > origin , 10 , 0 , 255 , 255 , 255 , 200 , 0 , 5 ) ;
m_arrowDisplayTime = GetWorldTime ( ) ;
}
}
// create path pointer for faster access
Path * path = m_paths [ nearestIndex ] ;
// draw a paths, camplines and danger directions for nearest waypoint
if ( nearestDistance < 4096 & & m_pathDisplayTime < = GetWorldTime ( ) )
{
m_pathDisplayTime = GetWorldTime ( ) + 1.0 ;
// draw the camplines
if ( path - > flags & FLAG_CAMP )
{
2015-06-04 11:52:48 +03:00
Vector campSourceOrigin = path - > origin + Vector ( 0 , 0 , 36 ) ;
2014-07-30 14:17:46 +04:00
// check if it's a source
if ( path - > flags & FLAG_CROUCH )
campSourceOrigin = path - > origin + Vector ( 0 , 0 , 18 ) ;
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
DrawLine ( g_hostEntity , campSourceOrigin , campStartOrigin , 10 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , campSourceOrigin , campEndOrigin , 10 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
}
// 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 )
DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 255 , 0 , 128 , 200 , 0 , 10 ) ;
else if ( IsConnected ( path - > index [ i ] , nearestIndex ) ) // twoway connection
DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 255 , 255 , 0 , 200 , 0 , 10 ) ;
else // oneway connection
DrawLine ( g_hostEntity , path - > origin , m_paths [ path - > index [ i ] ] - > origin , 5 , 0 , 250 , 250 , 250 , 200 , 0 , 10 ) ;
}
// 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 ) )
DrawLine ( g_hostEntity , path - > origin , m_paths [ i ] - > origin , 5 , 0 , 0 , 192 , 96 , 200 , 0 , 10 ) ;
}
// draw the radius circle
Vector origin = ( path - > flags & FLAG_CROUCH ) ? path - > origin : path - > origin - Vector ( 0 , 0 , 18 ) ;
// if radius is nonzero, draw a full circle
if ( path - > radius > 0.0 )
{
float squareRoot = sqrtf ( ( path - > radius * path - > radius ) * 0.5 ) ;
DrawLine ( g_hostEntity , origin + Vector ( path - > radius , 0 , 0 ) , origin + Vector ( squareRoot , - squareRoot , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( squareRoot , - squareRoot , 0 ) , origin + Vector ( 0 , - path - > radius , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( 0 , - path - > radius , 0 ) , origin + Vector ( - squareRoot , - squareRoot , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , - squareRoot , 0 ) , origin + Vector ( - path - > radius , 0 , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( - path - > radius , 0 , 0 ) , origin + Vector ( - squareRoot , squareRoot , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , squareRoot , 0 ) , origin + Vector ( 0 , path - > radius , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( 0 , path - > radius , 0 ) , origin + Vector ( squareRoot , squareRoot , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( squareRoot , squareRoot , 0 ) , origin + Vector ( path - > radius , 0 , 0 ) , 5 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ;
}
else
{
float squareRoot = sqrtf ( 32.0 ) ;
DrawLine ( g_hostEntity , origin + Vector ( squareRoot , - squareRoot , 0 ) , origin + Vector ( - squareRoot , squareRoot , 0 ) , 5 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
DrawLine ( g_hostEntity , origin + Vector ( - squareRoot , - squareRoot , 0 ) , origin + Vector ( squareRoot , squareRoot , 0 ) , 5 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ;
}
// draw the danger directions
if ( ! g_waypointsChanged )
{
if ( ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team0DangerIndex ! = - 1 & & GetTeam ( g_hostEntity ) = = TEAM_TF )
DrawArrow ( g_hostEntity , path - > origin , m_paths [ ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team0DangerIndex ] - > origin , 15 , 0 , 255 , 0 , 0 , 200 , 0 , 10 ) ; // draw a red arrow to this index's danger point
if ( ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team1DangerIndex ! = - 1 & & GetTeam ( g_hostEntity ) = = TEAM_CF )
DrawArrow ( g_hostEntity , path - > origin , m_paths [ ( g_experienceData + ( nearestIndex * g_numWaypoints ) + nearestIndex ) - > team1DangerIndex ] - > origin , 15 , 0 , 0 , 0 , 255 , 200 , 0 , 10 ) ; // draw a blue arrow to this index's danger point
}
// 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 connections ;
int i , j ;
for ( i = 0 ; i < g_numWaypoints ; i + + )
{
connections = 0 ;
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 ) ;
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
g_waypointOn = true ;
g_editNoclip = true ;
return false ;
}
}
}
}
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 ) ;
( * g_engfuncs . pfnSetOrigin ) ( g_hostEntity , m_paths [ i ] - > origin ) ;
g_waypointOn = true ;
g_editNoclip = true ;
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-04 11:52:48 +03:00
IterateArray ( 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
PathNode * pNewNode = new PathNode ;
pNewNode - > next = stack ;
2015-06-04 11:52:48 +03:00
pNewNode - > index = outgoingPaths [ current - > index ] [ p ] ;
2014-07-30 14:17:46 +04:00
stack = pNewNode ;
}
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 ) ;
2015-06-04 11:52:48 +03:00
SET_ORIGIN ( g_hostEntity , m_paths [ i ] - > origin ) ;
2014-07-30 14:17:46 +04:00
g_waypointOn = true ;
g_editNoclip = true ;
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 )
{
File fp ( FormatBuffer ( " %sdata/%s.pmt " , GetWaypointDir ( ) , GetMapName ( ) ) , " wb " ) ;
// 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 )
{
File fp ( FormatBuffer ( " %sdata/%s.pmt " , GetWaypointDir ( ) , GetMapName ( ) ) , " rb " ) ;
// file doesn't exists return false
if ( ! fp . IsValid ( ) )
return false ;
int num = 0 ;
// read number of waypoints
fp . Read ( & num , sizeof ( int ) ) ;
if ( num ! = g_numWaypoints )
{
AddLogEntry ( true , LL_DEFAULT , " Wrong number of points (pmt:%d/cur:%d). Matrix will be rebuilded " , num , g_numWaypoints ) ;
fp . Close ( ) ;
return false ;
}
// read path & distance matrixes
fp . Read ( m_pathMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) ;
fp . Read ( m_distMatrix , sizeof ( int ) , g_numWaypoints * g_numWaypoints ) ;
// and close the file
fp . Close ( ) ;
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 ;
if ( ! IsGoalVisited ( index ) | | ! ( m_paths [ index ] - > flags & FLAG_GOAL ) )
{
#if 0
int bombPoint = FindNearest ( GetBombPosition ( ) ) ;
Array < int > markAsVisited ;
FindInRadius ( markAsVisited , 356.0 , GetPath ( index ) - > origin ) ;
IterateArray ( markAsVisited , i )
{
// skip still valid bomb point
if ( markAsVisited [ i ] = = bombPoint )
continue ;
m_visitedGoals . Push ( markAsVisited [ i ] ) ;
}
# endif
m_visitedGoals . Push ( index ) ;
}
}
bool Waypoint : : IsGoalVisited ( int index )
{
IterateArray ( m_visitedGoals , i )
{
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
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( 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 ;
Vector diff = ( ( ladderLeft - ladderRight ) ^ Vector ( 0 , 0 , 0 ) ) . Normalize ( ) * 15.0 ;
front = back = GetEntityOrigin ( ent ) ;
front = front + diff ; // front
back = back - diff ; // back
up = down = front ;
down . z = ent - > v . absmax . z ;
TraceHull ( down , up , true , point_hull , NULL , & tr ) ;
if ( POINT_CONTENTS ( up ) = = CONTENTS_SOLID | | tr . flFraction ! = 1.0 )
{
up = down = back ;
down . z = ent - > v . absmax . z ;
}
TraceHull ( down , up - Vector ( 0 , 0 , 1000 ) , true , point_hull , NULL , & tr ) ;
up = tr . vecEndPos ;
Vector pointOrigin = up + Vector ( 0 , 0 , 39 ) ;
m_isOnLadder = true ;
do
{
if ( FindNearest ( pointOrigin , 50.0 ) = = - 1 )
Add ( 3 , pointOrigin ) ;
pointOrigin . z + = 160 ;
} while ( pointOrigin . z < down . z - 40 ) ;
pointOrigin = down + Vector ( 0 , 0 , 38 ) ;
if ( FindNearest ( pointOrigin , 50.0 ) = = - 1 )
Add ( 3 , pointOrigin ) ;
m_isOnLadder = false ;
}
// then terrortist spawnpoints
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_player_deathmatch " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 0 , origin ) ;
}
// then add ct spawnpoints
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_player_start " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 0 , origin ) ;
}
// then vip spawnpoint
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_vip_start " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 0 , origin ) ;
}
// hostage rescue zone
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_hostage_rescue " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 4 , origin ) ;
}
// hostage rescue zone (same as above)
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_hostage_rescue " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 4 , origin ) ;
}
// bombspot zone
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_bomb_target " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// bombspot zone (same as above)
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " info_bomb_target " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// hostage entities
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " hostage_entity " ) ) )
2014-07-30 14:17:46 +04:00
{
// if already saved || moving skip it
if ( ( ent - > v . effects & EF_NODRAW ) & & ( ent - > v . speed > 0 ) )
continue ;
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// vip rescue (safety) zone
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_vip_safetyzone " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// terrorist escape zone
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " func_escapezone " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
Add ( 100 , origin ) ;
}
// weapons on the map ?
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( ent = FIND_ENTITY_BY_CLASSNAME ( ent , " armoury_entity " ) ) )
2014-07-30 14:17:46 +04:00
{
Vector origin = GetEntityOrigin ( ent ) ;
if ( FindNearest ( origin , 50 ) = = - 1 )
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 ] ;
// if we're delete waypoint, delete all corresponding to it files
deleteList [ 0 ] = FormatBuffer ( " %s%s.pwf " , GetWaypointDir ( ) , GetMapName ( ) ) ; // waypoint itself
deleteList [ 1 ] = FormatBuffer ( " %sdata/%s.exp " , GetWaypointDir ( ) , GetMapName ( ) ) ; // corresponding to waypoint experience
deleteList [ 3 ] = FormatBuffer ( " %sdata/%s.vis " , GetWaypointDir ( ) , GetMapName ( ) ) ; // corresponding to waypoint vistable
deleteList [ 3 ] = FormatBuffer ( " %sdata/%s.pmt " , GetWaypointDir ( ) , GetMapName ( ) ) ; // corresponding to waypoint path matrix
deleteList [ 4 ] = FormatBuffer ( " %sdata/%s.xml " , GetWaypointDir ( ) , GetMapName ( ) ) ; // corresponding to waypoint xml database
for ( int i = 0 ; i < 4 ; i + + )
{
if ( TryFileOpen ( const_cast < char * > ( deleteList [ i ] . GetBuffer ( ) ) ) )
{
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
}
void Waypoint : : SetBombPosition ( bool shouldReset )
{
// this function stores the bomb position as a vector
if ( shouldReset )
{
m_foundBombOrigin = nullvec ;
g_bombPlanted = false ;
return ;
}
edict_t * ent = NULL ;
2015-06-04 11:52:48 +03:00
while ( ! IsEntityNull ( 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 )
{
m_foundBombOrigin = GetEntityOrigin ( ent ) ;
break ;
}
}
}
void Waypoint : : SetLearnJumpWaypoint ( void )
{
m_learnJumpWaypoint = true ;
}
void Waypoint : : SetFindIndex ( int index )
{
m_findWPIndex = index ;
if ( m_findWPIndex < g_numWaypoints )
ServerPrint ( " Showing Direction to Waypoint #%d " , m_findWPIndex ) ;
else
m_findWPIndex = - 1 ;
}
int Waypoint : : AddGoalScore ( int index , int other [ 4 ] )
{
Array < int > left ;
if ( m_goalsScore [ index ] < 1024.0 )
left . Push ( index ) ;
for ( int i = 0 ; i < 3 ; i + + )
{
if ( m_goalsScore [ other [ i ] ] < 1024.0 )
left . Push ( other [ i ] ) ;
}
if ( left . IsEmpty ( ) )
index = other [ g_randGen . Long ( 0 , 3 ) ] ;
else
index = left . GetRandomElement ( ) ;
if ( m_paths [ index ] - > flags & FLAG_GOAL )
m_goalsScore [ index ] + = 384.0 ;
else if ( m_paths [ index ] - > flags & ( FLAG_CF_ONLY | FLAG_TF_ONLY ) )
m_goalsScore [ index ] + = 768.0 ;
else if ( m_paths [ index ] - > flags & FLAG_CAMP )
m_goalsScore [ index ] + = 1024.0 ;
return index ;
}
void Waypoint : : ClearGoalScore ( void )
{
// iterate though all waypoints
for ( int i = 0 ; i < MAX_WAYPOINTS ; i + + )
m_goalsScore [ i ] = 0.0 ;
}
Waypoint : : Waypoint ( void )
{
m_waypointPaths = false ;
m_endJumpPoint = false ;
m_redoneVisibility = false ;
m_learnJumpWaypoint = false ;
m_timeJumpStarted = 0.0 ;
m_learnVelocity = nullvec ;
m_learnPosition = nullvec ;
m_lastJumpWaypoint = - 1 ;
m_cacheWaypointIndex = - 1 ;
m_findWPIndex = - 1 ;
m_visibilityIndex = 0 ;
m_lastWaypoint = nullvec ;
m_isOnLadder = false ;
m_pathDisplayTime = 0.0 ;
m_arrowDisplayTime = 0.0 ;
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 )
{
delete [ ] m_distMatrix ;
delete [ ] m_pathMatrix ;
m_distMatrix = NULL ;
m_pathMatrix = NULL ;
}
void WaypointDownloader : : FreeSocket ( int sock )
{
# if defined (PLATFORM_WIN32)
if ( sock ! = - 1 )
closesocket ( sock ) ;
WSACleanup ( ) ;
# else
if ( sock ! = - 1 )
close ( sock ) ;
# endif
}
WaypointDownloadError WaypointDownloader : : DoDownload ( void )
{
# if defined (PLATFORM_WIN32)
WORD requestedVersion = MAKEWORD ( 1 , 1 ) ;
WSADATA wsaData ;
WSAStartup ( requestedVersion , & wsaData ) ;
# 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 )
{
FreeSocket ( socketHandle ) ;
return WDE_SOCKET_ERROR ;
}
sockaddr_in dest ;
# if defined (PLATFORM_WIN32)
unsigned long mode = 0 ;
ioctlsocket ( socketHandle , FIONBIO , & mode ) ;
# else
int flags = fcntl ( socketHandle , F_GETFL , 0 ) | O_NONBLOCK ;
fcntl ( socketHandle , F_SETFL , flags ) ;
# endif
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 ;
2014-09-17 20:36:42 +04:00
setsockopt ( socketHandle , SOL_SOCKET , SO_RCVTIMEO , ( char * ) & timeout , sizeof ( timeout ) ) ;
setsockopt ( socketHandle , SOL_SOCKET , SO_SNDTIMEO , ( char * ) & timeout , sizeof ( timeout ) ) ;
2014-07-30 14:17:46 +04:00
memset ( & dest , 0 , sizeof ( dest ) ) ;
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 )
{
FreeSocket ( socketHandle ) ;
return WDE_CONNECT_ERROR ;
}
String request ;
2014-09-17 20:36:42 +04: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 " , 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
{
FreeSocket ( socketHandle ) ;
return WDE_SOCKET_ERROR ;
}
File fp ( g_waypoint - > CheckSubfolderFile ( ) , " wb " ) ;
if ( ! fp . IsValid ( ) )
{
FreeSocket ( socketHandle ) ;
return WDE_SOCKET_ERROR ;
}
2014-09-17 20:36:42 +04:00
char buffer [ 1024 ] ;
2014-07-30 14:17:46 +04:00
bool finished = false ;
int recvPosition = 0 ;
int symbolsInLine = 0 ;
// scan for the end of the header
2014-09-17 20:36:42 +04:00
while ( ! finished & & recvPosition < sizeof ( buffer ) )
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 ;
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
2014-07-30 14:17:46 +04:00
if ( strstr ( buffer , " HTTP/1.0 404 " ) ! = NULL )
{
FreeSocket ( socketHandle ) ;
return WDE_NOTFOUND_ERROR ;
}
memset ( buffer , 0 , sizeof ( buffer ) ) ;
int size = 0 ;
while ( ( size = recv ( socketHandle , buffer , sizeof ( buffer ) - 1 , 0 ) ) > 0 )
2014-09-17 20:36:42 +04:00
fp . Write ( buffer , size ) ;
2014-07-30 14:17:46 +04:00
fp . Close ( ) ;
FreeSocket ( socketHandle ) ;
return WDE_NOERROR ;
}