Example #1
0
qboolean AI_TryJoinPreviousGroup( gentity_t *self ) {//go through other groups made this frame and see if any of those have the same enemy as me... if so, add me in!
	int	i;
	for ( i = 0; i < MAX_FRAME_GROUPS; i++ ) {
		if ( level.groups[i].numGroup
			&& level.groups[i].numGroup < (MAX_GROUP_MEMBERS - 1)
			//&& level.groups[i].enemy != NULL
			&& level.groups[i].enemy == self->enemy ) {//has members, not full and has my enemy
			if ( AI_ValidateGroupMember( &level.groups[i], self ) ) {//I am a valid member for this group
				AI_InsertGroupMember( &level.groups[i], self );
				return qtrue;
			}
		}
	}
	return qfalse;
}
Example #2
0
qboolean AI_RefreshGroup( AIGroupInfo_t *group )
{
	gentity_t	*member;
	int			i;//, j;

	//see if we should merge with another group
	for ( i = 0; i < MAX_FRAME_GROUPS; i++ ) 
	{
		if ( &level.groups[i] == group )
		{
			break;
		}
		else
		{
			if ( level.groups[i].enemy == group->enemy )
			{//2 groups with same enemy
				if ( level.groups[i].numGroup+group->numGroup < (MAX_GROUP_MEMBERS - 1) )
				{//combining the members would fit in one group
					qboolean deleteWhenDone = qtrue;
					//combine the members of mine into theirs
					for ( int j = 0; j < group->numGroup; j++ )
					{
						member = &g_entities[group->member[j].number];
						if ( level.groups[i].enemy == NULL )
						{//special case for groups without enemies, must be in range
							if ( !AI_ValidateNoEnemyGroupMember( &level.groups[i], member ) )
							{
								deleteWhenDone = qfalse;
								continue;
							}
						}
						//remove this member from this group
						AI_DeleteGroupMember( group, j );
						//keep marker at same place since we deleted this guy and shifted everyone up one
						j--;
						//add them to the earlier group
						AI_InsertGroupMember( &level.groups[i], member );
					}
					//return and delete this group
					if ( deleteWhenDone )
					{
						return qfalse;
					}
				}
			}
		}
	}
	//clear numStates
	for ( i = 0; i < NUM_SQUAD_STATES; i++ )
	{
		group->numState[i] = 0;
	}

	//go through group and validate each membership
	group->commander = NULL;
	for ( i = 0; i < group->numGroup; i++ )
	{
		/*
		//this checks for duplicate copies of one member in a group
		for ( j = 0; j < group->numGroup; j++ )
		{
			if ( i != j )
			{
				if ( group->member[i].number == group->member[j].number )
				{
					break;
				}
			}
		}
		if ( j < group->numGroup )
		{//found a dupe!
			gi.Printf( S_COLOR_RED"ERROR: member %s(%d) a duplicate group member!!!\n", g_entities[group->member[i].number].targetname, group->member[i].number );
			AI_DeleteGroupMember( group, i );
			i--;
			continue;
		}
		*/
		member = &g_entities[group->member[i].number];

		//Must be alive
		if ( member->health <= 0 )
		{
			AI_DeleteGroupMember( group, i );
			//keep marker at same place since we deleted this guy and shifted everyone up one
			i--;
		}
		else if ( group->memberValidateTime < level.time && !AI_ValidateGroupMember( group, member ) )
		{
			//remove this one from the group
			AI_DeleteGroupMember( group, i );
			//keep marker at same place since we deleted this guy and shifted everyone up one
			i--;
		}
		else
		{//membership is valid
			//keep track of squadStates
			group->numState[member->NPC->squadState]++;
			if ( !group->commander || member->NPC->rank > group->commander->NPC->rank )
			{//keep track of highest rank
				group->commander = member;
			}
		}
	}
	if ( group->memberValidateTime < level.time )
	{
		group->memberValidateTime = level.time + Q_irand( 500, 2500 );
	}
	//Now add any new guys as long as we're not full
	/*
	for ( i = 0, member = &g_entities[0]; i < globals.num_entities && group->numGroup < (MAX_GROUP_MEMBERS - 1); i++, member++)
	{
		if ( !AI_ValidateGroupMember( group, member ) )
		{//FIXME: keep track of those who aren't angry yet and see if we should wake them after we assemble the core group
			continue;
		}
		if ( member->NPC->group == group )
		{//DOH, already in our group
			continue;
		}

		//store it
		AI_InsertGroupMember( group, member );
	}
	*/

	//calc the morale of this group
	group->morale = group->moraleAdjust;
	for ( i = 0; i < group->numGroup; i++ )
	{
		member = &g_entities[group->member[i].number];
		if ( member->NPC->rank < RANK_ENSIGN )
		{//grunts
			group->morale++;
		}
		else
		{
			group->morale += member->NPC->rank;
		}
		if ( group->commander && debugNPCAI->integer )
		{
			G_DebugLine( group->commander->currentOrigin, member->currentOrigin, FRAMETIME, 0x00ff00ff, qtrue );
		}
	}
	if ( group->enemy )
	{//modify morale based on enemy health and weapon
		if ( group->enemy->health < 10 )
		{
			group->morale += 10;
		}
		else if ( group->enemy->health < 25 )
		{
			group->morale += 5;
		}
		else if ( group->enemy->health < 50 )
		{
			group->morale += 2;
		}
		switch( group->enemy->s.weapon )
		{
		case WP_SABER:
			group->morale -= 5;
			break;
		case WP_BRYAR_PISTOL:
		case WP_BLASTER_PISTOL:
			group->morale += 3;
			break;
		case WP_DISRUPTOR:
			group->morale += 2;
			break;
		case WP_REPEATER:
			group->morale -= 1;
			break;
		case WP_FLECHETTE:
			group->morale -= 2;
			break;
		case WP_ROCKET_LAUNCHER:
			group->morale -= 10;
			break;
		case WP_CONCUSSION:
			group->morale -= 12;
			break;
		case WP_THERMAL:
			group->morale -= 5;
			break;
		case WP_TRIP_MINE:
			group->morale -= 3;
			break;
		case WP_DET_PACK:
			group->morale -= 10;
			break;
		case WP_MELEE:			// Any ol' melee attack
			group->morale += 20;
			break;
		case WP_STUN_BATON:
			group->morale += 10;
			break;
		case WP_EMPLACED_GUN:
			group->morale -= 8;
			break;
		case WP_ATST_MAIN:
			group->morale -= 8;
			break;
		case WP_ATST_SIDE:
			group->morale -= 20;
			break;
		}
	}
	if ( group->moraleDebounce < level.time )
	{//slowly degrade whatever moraleAdjusters we may have
		if ( group->moraleAdjust > 0 )
		{
			group->moraleAdjust--;
		}
		else if ( group->moraleAdjust < 0 )
		{
			group->moraleAdjust++;
		}
		group->moraleDebounce = level.time + 1000;//FIXME: define?
	}
	//mark this group as not having been run this frame
	group->processed = qfalse;

	return (group->numGroup>0);
}
Example #3
0
//#define MAX_WAITERS	128
void AI_GetGroup( gentity_t *self )
{
	int	i;
	gentity_t	*member;//, *waiter;
	//int	waiters[MAX_WAITERS];

	if ( !self || !self->NPC )
	{
		return;
	}

	if ( d_noGroupAI->integer )
	{
		self->NPC->group = NULL;
		return;
	}

	if ( !self->client )
	{
		self->NPC->group = NULL;
		return;
	}

	if ( self->NPC->scriptFlags&SCF_NO_GROUPS )
	{
		self->NPC->group = NULL;
		return;
	}

	if ( self->enemy && (!self->enemy->client || (level.time - self->NPC->enemyLastSeenTime > 7000 )))
	{
		self->NPC->group = NULL;
		return;
	}

	if ( !AI_GetNextEmptyGroup( self ) )
	{//either no more groups left or we're already in a group built earlier
		return;
	}

	//create a new one
	memset( self->NPC->group, 0, sizeof( AIGroupInfo_t ) );

	self->NPC->group->enemy = self->enemy;
	self->NPC->group->team = self->client->playerTeam;
	self->NPC->group->processed = qfalse;
	self->NPC->group->commander = self;
	self->NPC->group->memberValidateTime = level.time + 2000;
	self->NPC->group->activeMemberNum = 0;

	if ( self->NPC->group->enemy )
	{
		self->NPC->group->lastSeenEnemyTime = level.time;
		self->NPC->group->lastClearShotTime = level.time;
		VectorCopy( self->NPC->group->enemy->currentOrigin, self->NPC->group->enemyLastSeenPos );
	}

//	for ( i = 0, member = &g_entities[0]; i < globals.num_entities ; i++, member++)
	for ( i = 0; i < globals.num_entities ; i++)
	{
		if(!PInUse(i))
			continue;
		member = &g_entities[i];

		if ( !AI_ValidateGroupMember( self->NPC->group, member ) )
		{//FIXME: keep track of those who aren't angry yet and see if we should wake them after we assemble the core group
			continue;
		}
		
		//store it
		AI_InsertGroupMember( self->NPC->group, member );

		if ( self->NPC->group->numGroup >= (MAX_GROUP_MEMBERS - 1) )
		{//full
			break;
		}
	}

	/*
	//now go through waiters and see if any should join the group
	//NOTE:  Some should hang back and probably not attack, so we can ambush
	//NOTE: only do this if calling for reinforcements?
	for ( i = 0; i < numWaiters; i++ )
	{
		waiter = &g_entities[waiters[i]];
	
		for ( j = 0; j < self->NPC->group->numGroup; j++ )
		{
			member = &g_entities[self->NPC->group->member[j];

			if ( gi.inPVS( waiter->currentOrigin, member->currentOrigin ) )
			{//this waiter is within PVS of a current member
			}
		}
	}
	*/

	if ( self->NPC->group->numGroup <= 0 )
	{//none in group
		self->NPC->group = NULL;
		return;
	}

	AI_SortGroupByPathCostToEnemy( self->NPC->group );
	AI_SetClosestBuddy( self->NPC->group );
}