Пример #1
0
void AI_DeleteSelfFromGroup( gentity_t *self ) {
	int i;

	//FIXME: if killed, keep track of how many in group killed?  To affect morale?
	for ( i = 0; i < self->NPC->group->numGroup; i++ ) {
		if ( self->NPC->group->member[i].number == self->s.number ) {
			AI_DeleteGroupMember( self->NPC->group, i );
			return;
		}
	}
}
Пример #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);
}