View Single Post
Re: what's your pathwalking algorithm
Old
  (#4)
@$3.1415rin
Council Member, Author of JoeBOT
 
@$3.1415rin's Avatar
 
Status: Offline
Posts: 1,381
Join Date: Nov 2003
Location: Germany
Default Re: what's your pathwalking algorithm - 01-01-2004

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();
}


  
Reply With Quote