I dont skip waypoints neither ... but you know, the practical things of joebot xp are still very beta ...
Code:
void CBVNP_HLDM_MovePath::evaluate(list<CGoal> *pGoals,CPerceipt* p){
float fLastDist;
switch(m_iState){
case 0:{ // waypoint based moving
if(!m_CurrWay.m_iCount){
// no way to move along
m_iCurrWP = -1;
// let's camp for a second - hackhack
m_pBot->m_pCamp->campO(1);
return;
}
if(m_iCurrWP >-1){ // it's a valid waypoint
fLastDist = (g_Map.m_Waypoints[m_iCurrWP].m_VOrigin - m_pBot->m_pPlayer->getOrigin()).length();
}
else{ // no waypoint to run to set yet ?
if(!m_CurrWay.m_iCount){
reset();
}
else{
m_fLastDist = 10000;
initPath();
m_bSetTarget = true;
execute(0);
}
return;
}
if(m_fLastDist < fLastDist){ // we are moving away from current waypoint we aim to
if(fLastDist > 75.f){
m_bSetTarget = true;
execute(0);
//m_pAction->runTo(g_Map.m_Waypoints[m_iCurrWP].m_VOrigin);
}
else{
if((m_iCurrWP = m_CurrWay.getNext()) != -1){
// so we have a subsequent waypoint to go to
m_fLastVisitedWP = g_pGame->getTime();
m_bSetTarget = true;
execute(0);
//m_pAction->lookTo(g_Map.m_Waypoints.m_Waypoints[iRun2].m_VOrigin);
#ifdef DEBUGMESSAGES
//if(listenserver_edict)UTIL_DrawBeam(listenserver_edict,g_Map.m_Waypoints.m_Waypoints[m_iCurrWP].m_VOrigin,m_pPlayer->getOrigin(),10,10,255,255,255,255,20);
//if(listenserver_edict)UTIL_DrawBeam(listenserver_edict,listenserver_edict->v.origin,m_pPlayer->getOrigin(),10,10,255,255,255,255,20);
#endif
fLastDist = 10000;
}
else{
// we are at the end of the path
if(m_bMove2Origin){
m_iState = 1; // go to direct moving state
m_bSetTarget = true;
m_fLastVisitedWP = g_pGame->getTime();
}
else{
if(m_pDReached){ // call callback function
m_pDReached->onReachedDestination(m_pBot->m_pPlayer);
}
reset();
}
}
}
}
/*else{
if(m_pBot->m_pPlayer->getVelocity().length() > 100){
Vector VAim;
switch(m_iState){
case 0:{
VAim = g_Map.m_Waypoints[m_iCurrWP].m_VOrigin;
}break;
case 1:{
VAim = m_VGoal;
}break;
}
Vector Cross = CrossProduct(m_pBot->m_pPlayer->getVelocity(),VAim-m_pBot->m_pPlayer->getOrigin());
float fError = Cross.length() / m_pBot->m_pPlayer->getVelocity().length();
char szTemp[20];
sprintf(szTemp,"%f",fError);
m_pBot->fakeClientCommand("say",szTemp);
}
}*/
if(fabs(m_fLastExecution - g_pGame->getTime()) > .5f){
m_bSetTarget = true;
execute(0);
}
m_fLastDist = fLastDist;
}
break;
case 1:{
fLastDist = (m_VGoal - m_pBot->m_pPlayer->getOrigin()).length();
if(m_fLastDist < fLastDist){
if(fLastDist > 75){
m_bSetTarget = true;
}
else{
// reached location
if(m_pDReached){ // call callback function
m_pDReached->onReachedDestination(m_pBot->m_pPlayer);
}
reset();
}
}
execute(0);
m_fLastDist = fLastDist;
}
break;
}
return;
}
void CBVNP_HLDM_MovePath::execute(CGoal *pGoal){
//if(listenserver_edict)UTIL_DrawBeam(listenserver_edict,Vector(0,0,0),m_pBot->m_pPlayer->getOrigin(),10,10,0,0,255,255,20);
if(m_bSetTarget ||
m_iState || // set move direction each think frame when moving without waypoints.
m_fLastExecution != m_pBot->m_fCalledBV){ // last time this move behaviour wasnt called, so set the move target again
switch(m_iState){
case 0:{
if(m_iCurrWP != -1){
m_pBot->m_pAction->runTo(g_Map.m_Waypoints[m_iCurrWP].m_VOrigin);
m_bSetTarget = false;
#ifdef DEBUGMESSAGES
//if(listenserver_edict)UTIL_DrawBeam(listenserver_edict,g_Map.m_Waypoints.m_Waypoints[m_iCurrWP].m_VOrigin,m_pBot->m_pPlayer->getOrigin(),10,10,255,255,255,255,20);
#endif
}
else{
reset();
}
}break;
case 1:{
m_pBot->m_pAction->runTo(m_VGoal);
}break;
}
}
m_fLastExecution = g_pGame->getTime();
}
void CBVNP_HLDM_MovePath::getResult(AStarBase *p,CCallback_onReachedDestination *pDReached){
if(p){
p->getResult(m_CurrWay);
m_iTargetWP = p->getDestination();
}
else
m_iTargetWP = -1;
m_iState = 0;
m_iCurrWP = -1;
m_pDReached = pDReached;
// check if we should run there without taking the waypoints
if((m_VGoal-m_pBot->m_pPlayer->getOrigin()).length() < 250.f
&&m_bMove2Origin){
m_iState = 1;
}
else{
if(!m_CurrWay.m_iCount
&& !m_bMove2Origin){
m_pBot->m_LGoals.finishedMove();
}
}
}
void CBVNP_HLDM_MovePath::initPath(void){
// simplest method would be
// m_iCurrWP = m_CurrWay[0];
// but we wanna check which would be the best first waypoint
if(m_CurrWay.m_iCount <= 2){
m_iCurrWP = m_CurrWay.m_piIndices[0];
}
else{
Vector V1,
V2,
VNow = m_pBot->m_pPlayer->getOrigin() + m_pBot->m_pPlayer->getVelocity() * .3f;
float fLength0,fLength1;
V1 = g_Map.m_Waypoints[m_CurrWay.m_piIndices[0]].m_VOrigin - VNow;
fLength0 = V1.length();
V2 = g_Map.m_Waypoints[m_CurrWay.m_piIndices[1]].m_VOrigin - g_Map.m_Waypoints[m_CurrWay.m_piIndices[0]].m_VOrigin;
fLength1 = (g_Map.m_Waypoints[m_CurrWay.m_piIndices[1]].m_VOrigin - VNow).length();
if(fLength1 < fLength0 // check if second waypoint is already nearer
||DotProduct(V1,V2) < .0f){ // check if we would have to go back
m_iCurrWP = m_CurrWay.m_piIndices[1];
}
else{
m_iCurrWP = m_CurrWay.m_piIndices[0];
}
}
// check direct move to
if(m_bMove2Origin
&& m_CurrWay.m_iCount >= 2){
Vector VN,
VNN;
while(m_CurrWay.m_iCount >= 2){
VN = (g_Map.m_Waypoints[m_CurrWay.m_piIndices[m_CurrWay.m_iCount - 1]].m_VOrigin - m_VGoal).normalize();
VNN = (g_Map.m_Waypoints[m_CurrWay.m_piIndices[m_CurrWay.m_iCount - 1]].m_VOrigin - g_Map.m_Waypoints[m_CurrWay.m_piIndices[m_CurrWay.m_iCount - 2]].m_VOrigin).normalize();
if(DotProduct(VNN,VN) < 0.f){
m_CurrWay.m_iCount --;
}
break;
}
}
}
void CBVNP_HLDM_MovePath::reset(void){
m_CurrWay.reset();
m_iState = 0; // we wanna run go waypoints initially
m_bMove2Origin = false;
m_iCurrWP = -1;
m_fLastDist = 10000;
m_fLastVisitedWP = g_pGame->getTime();
m_bSetTarget = false;
m_pDReached = 0;
m_pBot->m_LGoals.finishedMove();
}
huh, that's not just little code neither
and for avoid getting stuck it's until now just this, but there are already structures to handle connections which are often not usable, so the pathfinder can take this into account.
Code:
void CBVNP_HLDM_AvoidStuckWP::evaluate(list<CGoal> *pGoals,CPerceipt* p){
if( (!m_pBot->m_pMovePath->m_CurrWay.m_iCount && m_pBot->m_pMovePath->m_iState == 0) )
return;
if(m_pBot->m_pMovePath->m_fLastVisitedWP+5 > g_pGame->getTime())
return;
int iPriority = (g_pGame->getTime() - m_pBot->m_pMovePath->m_fLastVisitedWP)*4 + 50;
pGoals->push_front(CGoal(iPriority,CGoal::GT_MOVE,this,0));
return;
}
void CBVNP_HLDM_AvoidStuckWP::execute(CGoal *pGoal){
m_fLastExecution = g_pGame->getTime();
m_pBot->m_pMovePath->reset();
}