Exemplo n.º 1
0
void NAV_CheckCalcPaths( void )
{	
	if ( navCalcPathTime && navCalcPathTime < level.time )
	{//first time we've ever loaded this map...
		//clear all the failed edges
		navigator.ClearAllFailedEdges();

		//Calculate all paths
		NAV_CalculatePaths( level.mapname, giMapChecksum );
		
		navigator.CalculatePaths();

#ifndef FINAL_BUILD
		if ( fatalErrors )
		{
			gi.Printf( S_COLOR_RED"Not saving .nav file due to fatal nav errors\n" );
		}
		else 
#endif
		if ( navigator.Save( level.mapname, giMapChecksum ) == qfalse )
		{
			gi.Printf("Unable to save navigations data for map \"%s\" (checksum:%d)\n", level.mapname, giMapChecksum );
		}
		navCalcPathTime = 0;
	}
}
Exemplo n.º 2
0
int AI_ClosestGroupEntityNumToPoint( AIGroupInfo_t &group, vec3_t point )
{
	int	markerWP = WAYPOINT_NONE;
	int	cost, bestCost = Q3_INFINITE;
	int	closest = ENTITYNUM_NONE;
	
	if ( &group == NULL || group.numGroup <= 0 )
	{
		return ENTITYNUM_NONE;
	}

	markerWP = NAV_FindClosestWaypointForPoint( &g_entities[group.member[0].number], point );

	if ( markerWP == WAYPOINT_NONE )
	{
		return ENTITYNUM_NONE;
	}

	for ( int i = 0; i < group.numGroup; i++ )
	{
		cost = navigator.GetPathCost( group.member[i].waypoint, markerWP );
		if ( cost < bestCost )
		{
			bestCost = cost;
			closest = group.member[i].number;
		}
	}

	return closest;
}
Exemplo n.º 3
0
void NPC_BSSearchStart( int homeWp, bState_t bState )
{
	//FIXME: Reimplement
	NPCInfo->homeWp = homeWp;
	NPCInfo->tempBehavior = bState;
	NPCInfo->aiFlags |= NPCAI_ENROUTE_TO_HOMEWP;
	NPCInfo->investigateDebounceTime = 0;
	navigator.GetNodePosition( homeWp, NPCInfo->tempGoal->currentOrigin );
	NPCInfo->tempGoal->waypoint = homeWp;
	//gi.Printf("\nHeading for wp %d...\n", NPCInfo->homeWp);
}
Exemplo n.º 4
0
qboolean NAVNEW_TestNodeConnectionBlocked( int wp1, int wp2, gentity_t *ignoreEnt, int goalEntNum, qboolean checkWorld, qboolean checkEnts )
{//see if the direct path between 2 nodes is blocked by architecture or an ent
	vec3_t	pos1, pos2, mins, maxs;
	trace_t	trace;
	int		clipmask = MASK_NPCSOLID|CONTENTS_BOTCLIP;
	int ignoreEntNum;

	if ( !checkWorld && !checkEnts )
	{//duh, nothing to trace against
		return qfalse;
	}
	navigator.GetNodePosition( wp1, pos1 );
	navigator.GetNodePosition( wp2, pos2 );

	if ( !checkWorld )
	{
		clipmask &= ~(CONTENTS_SOLID|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP);
	}
	if ( !checkEnts )
	{
		clipmask &= ~CONTENTS_BODY;
	}
	if ( ignoreEnt )
	{
		VectorCopy( ignoreEnt->mins, mins );
		VectorCopy( ignoreEnt->maxs, maxs );
		ignoreEntNum = ignoreEnt->s.number;
	}
	else
	{
		VectorCopy( playerMins, mins );
		VectorCopy( playerMaxs, maxs );
		ignoreEntNum = ENTITYNUM_NONE;
	}
	mins[2] += STEPSIZE;
	//don't let box get inverted
	if ( mins[2] > maxs[2] )
	{
		mins[2] = maxs[2];
	}

	gi.trace( &trace, pos1, mins, maxs, pos2, ignoreEntNum, clipmask, G2_NOCOLLIDE, 0 );
	if ( trace.fraction >= 1.0f || trace.entityNum == goalEntNum )
	{//clear or hit goal
		return qfalse;
	}
	//hit something we weren't supposed to
	return qtrue;
}
Exemplo n.º 5
0
void NPC_BSSearch (void)
{
	NPC_CheckEnemy(qtrue, qfalse);
	//Look for enemies, if find one:
	if ( NPC->enemy )
	{
		if( NPCInfo->tempBehavior == BS_SEARCH )
		{//if tempbehavior, set tempbehavior to default
			NPCInfo->tempBehavior = BS_DEFAULT;
		}
		else
		{//if bState, change to run and shoot
			NPCInfo->behaviorState = BS_HUNT_AND_KILL;
			NPC_BSRunAndShoot();
		}
		return;
	}

	//FIXME: what if our goalEntity is not NULL and NOT our tempGoal - they must
	//want us to do something else?  If tempBehavior, just default, else set
	//to run and shoot...?

	//FIXME: Reimplement

	if ( !NPCInfo->investigateDebounceTime )
	{//On our way to a tempGoal
		float	minGoalReachedDistSquared = 32*32;
		vec3_t	vec;

		//Keep moving toward our tempGoal
		NPCInfo->goalEntity = NPCInfo->tempGoal;

		VectorSubtract ( NPCInfo->tempGoal->currentOrigin, NPC->currentOrigin, vec);
		if ( vec[2] < 24 )
		{
			vec[2] = 0;
		}

		if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
		{
			/*
			//FIXME: can't get the radius...
			float	wpRadSq = waypoints[NPCInfo->tempGoal->waypoint].radius * waypoints[NPCInfo->tempGoal->waypoint].radius;
			if ( minGoalReachedDistSquared > wpRadSq )
			{
				minGoalReachedDistSquared = wpRadSq;
			}
			*/

			minGoalReachedDistSquared = 32*32;//12*12;
		}

		if ( VectorLengthSquared( vec ) < minGoalReachedDistSquared )
		{
			//Close enough, just got there
			NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );

			if ( ( NPCInfo->homeWp == WAYPOINT_NONE ) || ( NPC->waypoint == WAYPOINT_NONE ) )
			{
				//Heading for or at an invalid waypoint, get out of this bState
				if( NPCInfo->tempBehavior == BS_SEARCH )
				{//if tempbehavior, set tempbehavior to default
					NPCInfo->tempBehavior = BS_DEFAULT;
				}
				else
				{//if bState, change to stand guard
					NPCInfo->behaviorState = BS_STAND_GUARD;
					NPC_BSRunAndShoot();
				}
				return;
			}

			if ( NPC->waypoint == NPCInfo->homeWp )
			{
				//Just Reached our homeWp, if this is the first time, run your lostenemyscript
				if ( NPCInfo->aiFlags & NPCAI_ENROUTE_TO_HOMEWP )
				{
					NPCInfo->aiFlags &= ~NPCAI_ENROUTE_TO_HOMEWP;
					G_ActivateBehavior( NPC, BSET_LOSTENEMY );
				}

			}

			//gi.Printf("Got there.\n");
			//gi.Printf("Looking...");
			if( !Q_irand(0, 1) )
			{
				NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_LOOKAROUND1, SETANIM_FLAG_NORMAL);
			}
			else
			{
				NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_IDLE1, SETANIM_FLAG_NORMAL);
			}
			NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000);
		}
		else
		{
			NPC_MoveToGoal( qtrue );
		}
	}
	else
	{
		//We're there
		if ( NPCInfo->investigateDebounceTime > level.time )
		{
			//Still waiting around for a bit
			//Turn angles every now and then to look around
			if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
			{
				if ( !Q_irand( 0, 30 ) )
				{
					int	numEdges = navigator.GetNodeNumEdges( NPCInfo->tempGoal->waypoint );

					if ( numEdges != WAYPOINT_NONE )
					{
						int branchNum = Q_irand( 0, numEdges - 1 );

						vec3_t	branchPos, lookDir;

						int nextWp = navigator.GetNodeEdge( NPCInfo->tempGoal->waypoint, branchNum );
						navigator.GetNodePosition( nextWp, branchPos );

						VectorSubtract( branchPos, NPCInfo->tempGoal->currentOrigin, lookDir );
						NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + Q_flrand( -45, 45 ) );
					}

					//pick an angle +-45 degrees off of the dir of a random branch
					//from NPCInfo->tempGoal->waypoint
					//int branch = Q_irand( 0, (waypoints[NPCInfo->tempGoal->waypoint].numNeighbors - 1) );
					//int	nextWp = waypoints[NPCInfo->tempGoal->waypoint].nextWaypoint[branch][NPCInfo->stats.moveType];
					//vec3_t	lookDir;

					//VectorSubtract( waypoints[nextWp].origin, NPCInfo->tempGoal->currentOrigin, lookDir );
					//Look in that direction +- 45 degrees
					//NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + Q_flrand( -45, 45 ) );
				}
			}
			//gi.Printf(".");
		}
		else
		{//Just finished waiting
			NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
			
			if ( NPC->waypoint == NPCInfo->homeWp )
			{
				int	numEdges = navigator.GetNodeNumEdges( NPCInfo->tempGoal->waypoint );

				if ( numEdges != WAYPOINT_NONE )
				{
					int branchNum = Q_irand( 0, numEdges - 1 );

					int nextWp = navigator.GetNodeEdge( NPCInfo->homeWp, branchNum );
					navigator.GetNodePosition( nextWp, NPCInfo->tempGoal->currentOrigin );
					NPCInfo->tempGoal->waypoint = nextWp;
				}

				/*
				//Pick a random branch
				int branch = Q_irand( 0, (waypoints[NPCInfo->homeWp].numNeighbors - 1) );
				int	nextWp = waypoints[NPCInfo->homeWp].nextWaypoint[branch][NPCInfo->stats.moveType];

				VectorCopy( waypoints[nextWp].origin, NPCInfo->tempGoal->currentOrigin );
				NPCInfo->tempGoal->waypoint = nextWp;
				//gi.Printf("\nHeading for wp %d...\n", waypoints[NPCInfo->homeWp].nextWaypoint[branch][NPCInfo->stats.moveType]);
				*/
			}
			else
			{//At a branch, so return home
				navigator.GetNodePosition( NPCInfo->homeWp, NPCInfo->tempGoal->currentOrigin );
				NPCInfo->tempGoal->waypoint = NPCInfo->homeWp;
				/*
				VectorCopy( waypoints[NPCInfo->homeWp].origin, NPCInfo->tempGoal->currentOrigin );
				NPCInfo->tempGoal->waypoint = NPCInfo->homeWp;
				//gi.Printf("\nHeading for wp %d...\n", NPCInfo->homeWp);
				*/
			}

			NPCInfo->investigateDebounceTime = 0;
			//Start moving toward our tempGoal
			NPCInfo->goalEntity = NPCInfo->tempGoal;
			NPC_MoveToGoal( qtrue );
		}
	}

	NPC_UpdateAngles( qtrue, qtrue );
}
Exemplo n.º 6
0
void NPC_BSFlee( void )
{//FIXME: keep checking for danger
	if ( TIMER_Done( NPC, "flee" ) && NPCInfo->tempBehavior == BS_FLEE )
	{
		NPCInfo->tempBehavior = BS_DEFAULT;
		NPCInfo->squadState = SQUAD_IDLE;
		//FIXME: should we set some timer to make him stay in this spot for a bit, 
		//so he doesn't just suddenly turn around and come back at the enemy?
		//OR, just stop running toward goal for last second or so of flee?
	}
	if ( NPC_CheckSurrender() )
	{
		return;
	}
	gentity_t *goal = NPCInfo->goalEntity;
	if ( !goal )
	{
		goal = NPCInfo->lastGoalEntity;
		if ( !goal )
		{//???!!!
			goal = NPCInfo->tempGoal;
		}
	}

	if ( goal )
	{
		qboolean reverseCourse = qtrue;

		//FIXME: if no weapon, find one and run to pick it up?

		//Let's try to find a waypoint that gets me away from this thing
		if ( NPC->waypoint == WAYPOINT_NONE )
		{
			NPC->waypoint = NAV_GetNearestNode( NPC, NPC->lastWaypoint );
		}
		if ( NPC->waypoint != WAYPOINT_NONE )
		{
			int	numEdges = navigator.GetNodeNumEdges( NPC->waypoint );

			if ( numEdges != WAYPOINT_NONE )
			{
				vec3_t	dangerDir;
				int		nextWp;

				VectorSubtract( NPCInfo->investigateGoal, NPC->currentOrigin, dangerDir );
				VectorNormalize( dangerDir );

				for ( int branchNum = 0; branchNum < numEdges; branchNum++ )
				{
					vec3_t	branchPos, runDir;

					nextWp = navigator.GetNodeEdge( NPC->waypoint, branchNum );
					navigator.GetNodePosition( nextWp, branchPos );

					VectorSubtract( branchPos, NPC->currentOrigin, runDir );
					VectorNormalize( runDir );
					if ( DotProduct( runDir, dangerDir ) > Q_flrand( 0, 0.5 ) )
					{//don't run toward danger
						continue;
					}
					//FIXME: don't want to ping-pong back and forth
					NPC_SetMoveGoal( NPC, branchPos, 0, qtrue );
					reverseCourse = qfalse;
					break;
				}
			}
		}

		qboolean	moved = NPC_MoveToGoal( qfalse );//qtrue? (do try to move straight to (away from) goal)

		if ( NPC->s.weapon == WP_NONE && (moved == qfalse || reverseCourse) )
		{//No weapon and no escape route... Just cower?  Need anim.
			NPC_Surrender();
			NPC_UpdateAngles( qtrue, qtrue );
			return;
		}
		//If our move failed, then just run straight away from our goal
		//FIXME: We really shouldn't do this.
		if ( moved == qfalse )
		{
			vec3_t	dir;
			float	dist;
			if ( reverseCourse )
			{
				VectorSubtract( NPC->currentOrigin, goal->currentOrigin, dir );
			}
			else
			{
				VectorSubtract( goal->currentOrigin, NPC->currentOrigin, dir );
			}
			NPCInfo->distToGoal	= dist = VectorNormalize( dir );
			NPCInfo->desiredYaw = vectoyaw( dir );
			NPCInfo->desiredPitch = 0;
			ucmd.forwardmove = 127;
		}
		else if ( reverseCourse )
		{
			//ucmd.forwardmove *= -1;
			//ucmd.rightmove *= -1;
			//VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );
			NPCInfo->desiredYaw *= -1;
		}
		//FIXME: can stop after a safe distance?
		ucmd.upmove = 0;
		ucmd.buttons &= ~BUTTON_WALKING;
		//FIXME: what do we do once we've gotten to our goal?
	}
	NPC_UpdateAngles( qtrue, qtrue );

	NPC_CheckGetNewWeapon();
}
Exemplo n.º 7
0
void NPC_BSWander (void)
{//FIXME: don't actually go all the way to the next waypoint, just move in fits and jerks...?
	if ( !NPCInfo->investigateDebounceTime )
	{//Starting out
		float	minGoalReachedDistSquared = 64;//32*32;
		vec3_t	vec;

		//Keep moving toward our tempGoal
		NPCInfo->goalEntity = NPCInfo->tempGoal;

		VectorSubtract ( NPCInfo->tempGoal->currentOrigin, NPC->currentOrigin, vec);

		if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
		{
			minGoalReachedDistSquared = 64;
		}

		if ( VectorLengthSquared( vec ) < minGoalReachedDistSquared )
		{
			//Close enough, just got there
			NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );

			if( !Q_irand(0, 1) )
			{
				NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_LOOKAROUND1, SETANIM_FLAG_NORMAL);
			}
			else
			{
				NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_IDLE1, SETANIM_FLAG_NORMAL);
			}
			//Just got here, so Look around for a while
			NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000);
		}
		else
		{
			//Keep moving toward goal
			NPC_MoveToGoal( qtrue );
		}
	}
	else
	{
		//We're there
		if ( NPCInfo->investigateDebounceTime > level.time )
		{
			//Still waiting around for a bit
			//Turn angles every now and then to look around
			if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
			{
				if ( !Q_irand( 0, 30 ) )
				{
					int	numEdges = navigator.GetNodeNumEdges( NPCInfo->tempGoal->waypoint );

					if ( numEdges != WAYPOINT_NONE )
					{
						int branchNum = Q_irand( 0, numEdges - 1 );

						vec3_t	branchPos, lookDir;

						int	nextWp = navigator.GetNodeEdge( NPCInfo->tempGoal->waypoint, branchNum );
						navigator.GetNodePosition( nextWp, branchPos );

						VectorSubtract( branchPos, NPCInfo->tempGoal->currentOrigin, lookDir );
						NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + Q_flrand( -45, 45 ) );
					}
				}
			}
		}
		else
		{//Just finished waiting
			NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
			
			if ( NPC->waypoint != WAYPOINT_NONE )
			{
				int	numEdges = navigator.GetNodeNumEdges( NPC->waypoint );

				if ( numEdges != WAYPOINT_NONE )
				{
					int branchNum = Q_irand( 0, numEdges - 1 );

					int nextWp = navigator.GetNodeEdge( NPC->waypoint, branchNum );
					navigator.GetNodePosition( nextWp, NPCInfo->tempGoal->currentOrigin );
					NPCInfo->tempGoal->waypoint = nextWp;
				}

				NPCInfo->investigateDebounceTime = 0;
				//Start moving toward our tempGoal
				NPCInfo->goalEntity = NPCInfo->tempGoal;
				NPC_MoveToGoal( qtrue );
			}
		}
	}

	NPC_UpdateAngles( qtrue, qtrue );
}
Exemplo n.º 8
0
void InitGame(  const char *mapname, const char *spawntarget, int checkSum, const char *entities, int levelTime, int randomSeed, int globalTime, SavedGameJustLoaded_e eSavedGameJustLoaded, qboolean qbLoadTransition )
{
	int		i;

	giMapChecksum = checkSum;
	g_eSavedGameJustLoaded = eSavedGameJustLoaded;
	g_qbLoadTransition = qbLoadTransition;

	gi.Printf ("------- Game Initialization -------\n");
	gi.Printf ("gamename: %s\n", GAMEVERSION);
	gi.Printf ("gamedate: %s\n", __DATE__);

	srand( randomSeed );

	G_InitCvars();

	G_InitMemory();

	// set some level globals
	memset( &level, 0, sizeof( level ) );
	level.time = levelTime;
	level.globalTime = globalTime;
	Q_strncpyz( level.mapname, mapname, sizeof(level.mapname) );
	if ( spawntarget != NULL && spawntarget[0] )
	{
		Q_strncpyz( level.spawntarget, spawntarget, sizeof(level.spawntarget) );
	}
	else
	{
		level.spawntarget[0] = 0;
	}


	G_InitWorldSession();

	// initialize all entities for this game
	memset( g_entities, 0, MAX_GENTITIES * sizeof(g_entities[0]) );
	globals.gentities = g_entities;
	ClearAllInUse();
	// initialize all clients for this game
	level.maxclients = 1;
	level.clients = (struct gclient_s *) G_Alloc( level.maxclients * sizeof(level.clients[0]) );

	// set client fields on player
	g_entities[0].client = level.clients;

	// always leave room for the max number of clients,
	// even if they aren't all used, so numbers inside that
	// range are NEVER anything but clients
	globals.num_entities = MAX_CLIENTS;

	//Set up NPC init data
	NPC_InitGame();
	
	TIMER_Clear();

	//
	//ICARUS INIT START

	gi.Printf("------ ICARUS Initialization ------\n");
	gi.Printf("ICARUS version : %1.2f\n", ICARUS_VERSION);

	Interface_Init( &interface_export );
	ICARUS_Init();

	gi.Printf ("-----------------------------------\n");

	//ICARUS INIT END
	//

	IT_LoadItemParms ();

	ClearRegisteredItems();

	//FIXME: if this is from a loadgame, it needs to be sure to write this out whenever you do a savegame since the edges and routes are dynamic...
	navCalculatePaths	= ( navigator.Load( mapname, checkSum ) == qfalse );

	// parse the key/value pairs and spawn gentities
	G_SpawnEntitiesFromString( entities );

	// general initialization
	G_FindTeams();

//	SaveRegisteredItems();

	gi.Printf ("-----------------------------------\n");

	//randomize the rand functions
	byte num_calls = (byte)timeGetTime();

	for(i = 0; i < (int)num_calls; i++)
	{
		rand();
	}

	if ( navCalculatePaths )
	{//not loaded - need to calc paths
		navCalcPathTime = level.time + START_TIME_NAV_CALC;//make sure all ents are in and linked
	}
	else
	{//loaded
		//FIXME: if this is from a loadgame, it needs to be sure to write this 
		//out whenever you do a savegame since the edges and routes are dynamic...
		//OR: always do a navigator.CheckBlockedEdges() on map startup after nav-load/calc-paths
		navigator.pathsCalculated = qtrue;//just to be safe?  Does this get saved out?  No... assumed
		//need to do this, because combatpoint waypoints aren't saved out...?
		CP_FindCombatPointWaypoints();
		navCalcPathTime = 0;

		if ( g_eSavedGameJustLoaded == eNO )
		{//clear all the failed edges unless we just loaded the game (which would include failed edges)
			navigator.ClearAllFailedEdges();
		}
	}

	player = &g_entities[0];

	//Init dynamic music
	level.dmState = DM_EXPLORE;
	level.dmDebounceTime = 0;
	level.dmBeatTime = 0;

	level.curAlertID = 1;//0 is default for lastAlertEvent, so...
	eventClearTime = 0;
}
Exemplo n.º 9
0
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;
	int			msec;
	int			ents_inuse=0; // someone's gonna be pissed I put this here...
#if	AI_TIMERS
	AITime = 0;
	navTime = 0;
#endif//	AI_TIMERS
	
	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;
	msec = level.time - level.previousTime;
	
	NAV_CheckCalcPaths();
	//ResetTeamCounters();
	
	AI_UpdateGroups();

	if ( d_altRoutes->integer )
	{
		navigator.CheckAllFailedEdges();
	}
	navigator.ClearCheckedNodes();

	//remember last waypoint, clear current one
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++) 
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		
		ent = &g_entities[i];
	
		if ( ent->waypoint != WAYPOINT_NONE 
			&& ent->noWaypointTime < level.time )
		{
			ent->lastWaypoint = ent->waypoint;
			ent->waypoint = WAYPOINT_NONE;
		}
		if ( d_altRoutes->integer )
		{
			navigator.CheckFailedNodes( ent );
		}
	}

	//Look to clear out old events
	ClearPlayerAlertEvents();

	//Run the frame for all entities
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++)
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		ents_inuse++;
		ent = &g_entities[i];

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				gi.unlinkentity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent )
			continue;

		G_CheckTasksCompleted(ent);

		G_Roff( ent );

		if( !ent->client )
		{
			if ( !(ent->svFlags & SVF_SELF_ANIMATING) )
			{//FIXME: make sure this is done only for models with frames?
				//Or just flag as animating?
				if ( ent->s.eFlags & EF_ANIM_ONCE )
				{
					ent->s.frame++;
				}
				else if ( !(ent->s.eFlags & EF_ANIM_ALLFAST) )
				{
					G_Animate( ent );
				}
			}
		}
		G_CheckSpecialPersistentEvents( ent );

		if ( ent->s.eType == ET_MISSILE ) 
		{
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM ) 
		{
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) 
		{
			if ( ent->model && Q_stricmp( "models/test/mikeg/tie_fighter.md3", ent->model ) == 0 )
			{
				TieFighterThink( ent );
			}
			G_RunMover( ent );
			continue;
		}

		//The player
		if ( i == 0 ) 
		{
			// decay batteries if the goggles are active
			if ( cg.zoomMode == 1 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge--;
			}
			else if ( cg.zoomMode == 3 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge -= 2;

				if ( ent->client->ps.batteryCharge < 0 )
				{
					ent->client->ps.batteryCharge = 0;
				}
			}

			G_CheckEndLevelTimers( ent );
			//Recalculate the nearest waypoint for the coming NPC updates
			NAV_FindPlayerWaypoint();

			if( ent->taskManager && !stop_icarus )
			{
				ent->taskManager->Update();
			}
			//dead
			if ( ent->health <= 0 )
			{
				if ( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
				{//on the ground
					pitch_roll_for_slope( ent, NULL );
				}
			}

			continue;	// players are ucmd driven
		}

		G_RunThink( ent );	// be aware that ent may be free after returning from here, at least one func frees them
		ClearNPCGlobals();			//	but these 2 funcs are ok
		//UpdateTeamCounters( ent );	//	   to call anyway on a freed ent.
	}

	// perform final fixups on the player
	ent = &g_entities[0];
	if ( ent->inuse ) 
	{
		ClientEndFrame( ent );
	}
	if( g_numEntities->integer )
	{
		gi.Printf( S_COLOR_WHITE"Number of Entities in use : %d\n", ents_inuse );
	}
	//DEBUG STUFF
	NAV_ShowDebugInfo();
	NPC_ShowDebugInfo();

	G_DynamicMusicUpdate();

#if	AI_TIMERS
	AITime -= navTime;
	if ( AITime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total AI time: %d\n", AITime );
	}
	else if ( AITime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total AI time: %d\n", AITime );
	}
	else if ( AITime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total AI time: %d\n", AITime );
	}
	if ( navTime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total nav time: %d\n", navTime );
	}
	else if ( navTime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total nav time: %d\n", navTime );
	}
	else if ( navTime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total nav time: %d\n", navTime );
	}
#endif//	AI_TIMERS

#ifndef FINAL_BUILD
	if ( delayedShutDown != 0 && delayedShutDown < level.time )
	{
		G_Error( "Game Errors. Scroll up the console to read them.\n" );
	}
#endif

#ifdef _DEBUG
	if(!(level.framenum&0xff))
	{
		ValidateInUseBits();
	}
#endif
}
Exemplo n.º 10
0
/*
-------------------------
NAVNEW_MoveToGoal
-------------------------
*/
int	NAVNEW_MoveToGoal( gentity_t *self, navInfo_t &info )
{
	int			bestNode = WAYPOINT_NONE;
	qboolean	foundClearPath = qfalse;
	vec3_t		origin;
	navInfo_t	tempInfo;
	qboolean	setBlockedInfo = qtrue;
	qboolean	inGoalWP;
	int			numTries = 0;

	memcpy( &tempInfo, &info, sizeof( tempInfo ) );

	//Must have a goal entity to move there
	if( self->NPC->goalEntity == NULL )
		return WAYPOINT_NONE;

	if ( self->waypoint == WAYPOINT_NONE && self->noWaypointTime > level.time )
	{//didn't have a valid one in about the past second, don't look again just yet
		return WAYPOINT_NONE;
	}
	if ( self->NPC->goalEntity->waypoint == WAYPOINT_NONE && self->NPC->goalEntity->noWaypointTime > level.time )
	{//didn't have a valid one in about the past second, don't look again just yet
		return WAYPOINT_NONE;
	}
	if ( self->noWaypointTime > level.time &&
		self->NPC->goalEntity->noWaypointTime > level.time )
	{//just use current waypoints
		bestNode = navigator.GetBestNodeAltRoute( self->waypoint, self->NPC->goalEntity->waypoint, bestNode );
	}
	//FIXME!!!!: this is making them wiggle back and forth between waypoints
	else if ( (bestNode = navigator.GetBestPathBetweenEnts( self, self->NPC->goalEntity, NF_CLEAR_PATH )) == NODE_NONE )//!NAVNEW_GetWaypoints( self, qtrue ) )
	{//one of us didn't have a valid waypoint!
		if ( self->waypoint == NODE_NONE )
		{//don't even try to find one again for a bit
			self->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
		if ( self->NPC->goalEntity->waypoint == NODE_NONE )
		{//don't even try to find one again for a bit
			self->NPC->goalEntity->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
		return WAYPOINT_NONE;
	}
	else
	{
		if ( self->NPC->goalEntity->noWaypointTime < level.time )
		{
			self->NPC->goalEntity->noWaypointTime = level.time + Q_irand( 500, 1500 );
		}
	}

	while( !foundClearPath )
	{
		/*inBestWP = */inGoalWP = qfalse;
		/*
		bestNode = navigator.GetBestNodeAltRoute( self->waypoint, self->NPC->goalEntity->waypoint, bestNode );
		*/

		if ( bestNode == WAYPOINT_NONE )
		{
			goto failed;
		}

		//see if we can get directly to the next node off bestNode en route to goal's node...
		//NOTE: shouldn't be necc. now
		/*
		int oldBestNode = bestNode;
		bestNode = NAV_TestBestNode( self, self->waypoint, bestNode, qtrue );//, self->NPC->goalEntity->waypoint );//
		//NOTE: Guaranteed to return something
		if ( bestNode != oldBestNode )
		{//we were blocked somehow
			if ( setBlockedInfo )
			{
				self->NPC->aiFlags |= NPCAI_BLOCKED;
				navigator.GetNodePosition( oldBestNode, NPCInfo->blockedDest );
			}
		}
		*/
		navigator.GetNodePosition( bestNode, origin );
		/*
		if ( !goalWPFailed )
		{//we haven't already tried to go straight to goal or goal's wp
			if ( bestNode == self->NPC->goalEntity->waypoint )
			{//our bestNode is the goal's wp
				if ( NAV_HitNavGoal( self->currentOrigin, self->mins, self->maxs, origin, navigator.GetNodeRadius( bestNode ), FlyingCreature( self ) ) )
				{//we're in the goal's wp
					inGoalWP = qtrue;
					//we're in the goalEntity's waypoint already
					//so head for the goalEntity since we know it's clear of architecture
					//FIXME: this is pretty stupid because the NPCs try to go straight
					//		towards their goal before then even try macro_nav...
					VectorCopy( self->NPC->goalEntity->currentOrigin, origin );
				}
			}
		}
		*/
		if ( !inGoalWP )
		{//not heading straight for goal
			if ( bestNode == self->waypoint )
			{//we know it's clear or architecture
				//navigator.GetNodePosition( self->waypoint, origin );
				/*
				if ( NAV_HitNavGoal( self->currentOrigin, self->mins, self->maxs, origin, navigator.GetNodeRadius( bestNode ), FlyingCreature( self ) ) )
				{//we're in the wp we're heading for already
					inBestWP = qtrue;
				}
				*/
			}
			else
			{//heading to an edge off our confirmed clear waypoint... make sure it's clear
				//it it's not, bestNode will fall back to our waypoint
				int oldBestNode = bestNode;
				bestNode = NAV_TestBestNode( self, self->waypoint, bestNode, qtrue );
				if ( bestNode == self->waypoint )
				{//we fell back to our waypoint, reset the origin
					self->NPC->aiFlags |= NPCAI_BLOCKED;
					navigator.GetNodePosition( oldBestNode, NPCInfo->blockedDest );
					navigator.GetNodePosition( bestNode, origin );
				}
			}
		}
		//Com_Printf( "goalwp = %d, mywp = %d, node = %d, origin = %s\n", self->NPC->goalEntity->waypoint, self->waypoint, bestNode, vtos(origin) );

		memcpy( &tempInfo, &info, sizeof( tempInfo ) );
		VectorSubtract( origin, self->currentOrigin, tempInfo.direction );
		VectorNormalize( tempInfo.direction );

		//NOTE: One very important thing NAVNEW_AvoidCollision does is
		//		it actually CHANGES the value of "direction" - it changes it to
		//		whatever dir you need to go in to avoid the obstacle...
		foundClearPath = NAVNEW_AvoidCollision( self, self->NPC->goalEntity, tempInfo, setBlockedInfo, 5 );

		if ( !foundClearPath )
		{//blocked by an ent
			if ( inGoalWP )
			{//we were heading straight for the goal, head for the goal's wp instead
				navigator.GetNodePosition( bestNode, origin );
				foundClearPath = NAVNEW_AvoidCollision( self, self->NPC->goalEntity, tempInfo, setBlockedInfo, 5 );
			}
		}

		if ( foundClearPath )
		{//clear!
			//If we got set to blocked, clear it
			NPC_ClearBlocked( self );
			//Take the dir
			memcpy( &info, &tempInfo, sizeof( info ) );
			if ( self->s.weapon == WP_SABER )
			{//jedi
				if ( info.direction[2] * info.distance > 64 )
				{
					self->NPC->aiFlags |= NPCAI_BLOCKED;
					VectorCopy( origin, NPCInfo->blockedDest );
					goto failed;
				}
			}
		}
		else
		{//blocked by ent!
			if ( setBlockedInfo )
			{
				self->NPC->aiFlags |= NPCAI_BLOCKED;
				navigator.GetNodePosition( bestNode, NPCInfo->blockedDest );
			}
			//Only set blocked info first time
			setBlockedInfo = qfalse;

			if ( inGoalWP )
			{//we headed for our goal and failed and our goal's WP and failed
				if ( self->waypoint == self->NPC->goalEntity->waypoint )
				{//our waypoint is our goal's waypoint, nothing we can do
					//remember that this node is blocked
					navigator.AddFailedNode( self, self->waypoint );
					goto failed;
				}
				else
				{//try going for our waypoint this time
					//goalWPFailed = qtrue;
					inGoalWP = qfalse;
				}
			}
			else if ( bestNode != self->waypoint )
			{//we headed toward our next waypoint (instead of our waypoint) and failed
				if ( d_altRoutes->integer )
				{//mark this edge failed and try our waypoint
					//NOTE: don't assume there is something blocking the direct path
					//			between my waypoint and the bestNode... I could be off
					//			that path because of collision avoidance...
					if ( d_patched->integer &&//use patch-style navigation
 						( !navigator.NodesAreNeighbors( self->waypoint, bestNode )
						|| NAVNEW_TestNodeConnectionBlocked( self->waypoint, bestNode, self, self->NPC->goalEntity->s.number, qfalse, qtrue ) ) )
					{//the direct path between these 2 nodes is blocked by an ent
						navigator.AddFailedEdge( self->s.number, self->waypoint, bestNode );
					}
					bestNode = self->waypoint;
				}
				else
				{
					//we should stop
					goto failed;
				}
			}
			else
			{//we headed for *our* waypoint and couldn't get to it
				if ( d_altRoutes->integer )
				{
					//remember that this node is blocked
					navigator.AddFailedNode( self, self->waypoint );
					//Now we should get our waypoints again
					//FIXME: cache the trace-data for subsequent calls as only the route info would have changed
					//if ( (bestNode = navigator.GetBestPathBetweenEnts( self, self->NPC->goalEntity, NF_CLEAR_PATH )) == NODE_NONE )//!NAVNEW_GetWaypoints( self, qfalse ) )
					{//one of our waypoints is WAYPOINT_NONE now
						goto failed;
					}
				}
				else
				{
					//we should stop
					goto failed;
				}
			}

			if ( ++numTries >= 10 )
			{
				goto failed;
			}
		}
	}

//finish:
	//Draw any debug info, if requested
	if ( NAVDEBUG_showEnemyPath )
	{
		vec3_t	dest, start;

		//Get the positions
		navigator.GetNodePosition( self->NPC->goalEntity->waypoint, dest );
		navigator.GetNodePosition( bestNode, start );

		//Draw the route
		CG_DrawNode( start, NODE_START );
		if ( bestNode != self->waypoint )
		{
			vec3_t	wpPos;
			navigator.GetNodePosition( self->waypoint, wpPos );
			CG_DrawNode( wpPos, NODE_NAVGOAL );
		}
		CG_DrawNode( dest, NODE_GOAL );
		CG_DrawEdge( dest, self->NPC->goalEntity->currentOrigin, EDGE_PATH );
		CG_DrawNode( self->NPC->goalEntity->currentOrigin, NODE_GOAL );
		navigator.ShowPath( bestNode, self->NPC->goalEntity->waypoint );
	}

	self->NPC->shoveCount = 0;

	//let me keep this waypoint for a while
	if ( self->noWaypointTime < level.time )
	{
		self->noWaypointTime = level.time + Q_irand( 500, 1500 );
	}
	return bestNode;

failed:
	//FIXME: What we should really do here is have a list of the goal's and our
	//		closest clearpath waypoints, ranked.  If the first set fails, try the rest
	//		until there are no alternatives.

	navigator.GetNodePosition( self->waypoint, origin );

	//do this to avoid ping-ponging?
	return WAYPOINT_NONE;
	/*
	//this was causing ping-ponging
	if ( DistanceSquared( origin, self->currentOrigin ) < 16 )//woo, magic number
	{//We're right up on our waypoint, so that won't help, return none
		//Or maybe find the nextbest here?
		return WAYPOINT_NONE;
	}
	else
	{//Try going to our waypoint
		bestNode = self->waypoint;

		VectorSubtract( origin, self->currentOrigin, info.direction );
		VectorNormalize( info.direction );
	}

	goto finish;
	*/
}
Exemplo n.º 11
0
void AI_SortGroupByPathCostToEnemy( AIGroupInfo_t *group )
{
	AIGroupMember_t bestMembers[MAX_GROUP_MEMBERS];
	int				i, j, k;
	qboolean		sort = qfalse;

	if ( group->enemy != NULL )
	{//FIXME: just use enemy->waypoint?
		group->enemyWP = NAV_FindClosestWaypointForEnt( group->enemy, WAYPOINT_NONE );
	}
	else
	{
		group->enemyWP = WAYPOINT_NONE;
	}

	for ( i = 0; i < group->numGroup; i++ )
	{
		if ( group->enemyWP == WAYPOINT_NONE )
		{//FIXME: just use member->waypoint?
			group->member[i].waypoint = WAYPOINT_NONE;
			group->member[i].pathCostToEnemy = Q3_INFINITE;
		}
		else
		{//FIXME: just use member->waypoint?
			group->member[i].waypoint = NAV_FindClosestWaypointForEnt( group->enemy, WAYPOINT_NONE );
			if ( group->member[i].waypoint != WAYPOINT_NONE )
			{
				group->member[i].pathCostToEnemy = navigator.GetPathCost( group->member[i].waypoint, group->enemyWP );
				//at least one of us has a path, so do sorting
				sort = qtrue;
			}
			else
			{
				group->member[i].pathCostToEnemy = Q3_INFINITE;
			}
		}
	}
	//Now sort
	if ( sort )
	{
		//initialize bestMembers data
		for ( j = 0; j < group->numGroup; j++ )
		{
			bestMembers[j].number = ENTITYNUM_NONE;
		}

		for ( i = 0; i < group->numGroup; i++ )
		{
			for ( j = 0; j < group->numGroup; j++ )
			{
				if ( bestMembers[j].number != ENTITYNUM_NONE )
				{//slot occupied
					if ( group->member[i].pathCostToEnemy < bestMembers[j].pathCostToEnemy )
					{//this guy has a shorter path than the one currenly in this spot, bump him and put myself in here
						for ( k = group->numGroup; k > j; k++ )
						{
							memcpy( &bestMembers[k], &bestMembers[k-1], sizeof( bestMembers[k] ) );
						}
						memcpy( &bestMembers[j], &group->member[i], sizeof( bestMembers[j] ) );
						break;
					}
				}
				else
				{//slot unoccupied, reached end of list, throw self in here
					memcpy( &bestMembers[j], &group->member[i], sizeof( bestMembers[j] ) );
					break;
				}
			}
		}

		//Okay, now bestMembers is a sorted list, just copy it into group->members
		for ( i = 0; i < group->numGroup; i++ )
		{
			memcpy( &group->member[i], &bestMembers[i], sizeof( group->member[i] ) );
		}
	}
}
Exemplo n.º 12
0
BOOL CRVTrackerZoom::OnUpdate(const CUIEvent &cEvent)
{
	// Only move during idle
	if (m_bIdleOnly && (cEvent.GetType() != UIEVENT_NONE))
		return TRUE;

	int32 zDelta = GetWheelDelta();

	if( zDelta == 0 )
		return FALSE;

	BOOL bZoomToCursor = GetApp()->GetOptions().GetControlsOptions()->IsZoomToCursor();

	//clear out the wheel delta
	SetWheelDelta( 0 );

	CNavigator *pNav = &m_pView->Nav();

	// Set the initial speed value
	float fSpeed = (m_bFast) ? 3.0f : 0.5f;

	//see if we are in a parallel viewport
	if( m_pView->IsParallelViewType() )
	{
		

		//see if we want to zoom to the cursor
		if(bZoomToCursor)
		{
			// Convert cursor position to world coordinates:
			CVector vCursor;
			CRect rect;
			m_pView->GetWindowRect( &rect );
			CPoint cursorPt = m_cCurPt;
			m_pView->GetVertexFromPoint( cursorPt, vCursor, FALSE );

			// Zoom:
			m_pView->ViewDef()->m_Magnify += ((CReal)zDelta * m_pView->ViewDef()->m_Magnify) / 300.0f;
			if( m_pView->ViewDef()->m_Magnify < 0.0001f )
				m_pView->ViewDef()->m_Magnify = 0.0001f;

			CVector vCursor2;
			m_pView->GetVertexFromPoint( cursorPt, vCursor2, FALSE );
			// This effectively makes the cursor position the focal point for the zoom.
			pNav->Pos() += vCursor - vCursor2;  
		}
		else
		{
			//we just want to zoom in
			m_pView->ViewDef()->m_Magnify += ((CReal)zDelta * m_pView->ViewDef()->m_Magnify) / 300.0f;
			if( m_pView->ViewDef()->m_Magnify < 0.0001f )
				m_pView->ViewDef()->m_Magnify = 0.0001f;
		}
		
	}
	//Walk-through, meaning that we take a ray through the screen
	else 
	{
		//we are in a perspective viewport.

		if(!bZoomToCursor)
		{
			pNav->Pos() += pNav->Forward() * (float)zDelta * fSpeed;
		}
		else
		{
			CEditRay ray = m_pView->ViewDef()->MakeRayFromScreenPoint( m_cCurPt );
			CVector forward = ray.m_Dir;
			forward.Norm();
			pNav->Pos() += forward * ((CReal)zDelta * fSpeed);
		}
	}

	m_pView->Invalidate();

	return TRUE;
}