Пример #1
0
/*
==================
BotTestAAS
==================
*/
void BotTestAAS(vec3_t origin)
{
    int areanum;
    aas_areainfo_t info;

    if (bot_testsolid->integer)
    {
        if (!botlib_export->aas.AAS_Initialized()) return;
        areanum = BotPointAreaNum(origin);
        if (areanum) BotAI_Print(PRT_MESSAGE, "\remtpy area");
        else BotAI_Print(PRT_MESSAGE, "\r^1SOLID area");
    }
    else if (bot_testclusters->integer)
    {
        if (!botlib_export->aas.AAS_Initialized()) return;
        areanum = BotPointAreaNum(origin);
        if (!areanum)
            BotAI_Print(PRT_MESSAGE, "\r^1Solid!                              ");
        else
        {
            botlib_export->aas.AAS_AreaInfo(areanum, &info);
            BotAI_Print(PRT_MESSAGE, "\rarea %d, cluster %d       ", areanum, info.cluster);
        }
    }
}
Пример #2
0
/*
 * BotTestAAS
 */
void
BotTestAAS(Vec3 origin)
{
	int areanum;
	aas_areainfo_t info;

	trap_cvarupdate(&bot_testsolid);
	trap_cvarupdate(&bot_testclusters);
	if(bot_testsolid.integer){
		if(!trap_AAS_Initialized()) return;
		areanum = BotPointAreaNum(origin);
		if(areanum) BotAI_Print(PRT_MESSAGE, "\remtpy area");
		else BotAI_Print(PRT_MESSAGE, "\r^1SOLID area");
	}else if(bot_testclusters.integer){
		if(!trap_AAS_Initialized()) return;
		areanum = BotPointAreaNum(origin);
		if(!areanum)
			BotAI_Print(PRT_MESSAGE,
				"\r^1Solid!                              ");
		else{
			trap_AAS_AreaInfo(areanum, &info);
			BotAI_Print(PRT_MESSAGE, "\rarea %d, cluster %d       ",
				areanum,
				info.cluster);
		}
	}
}
Пример #3
0
int BotTeamCarrierVisible( bot_state_t *bs ) {
	int	i;
	float	vis;
	aas_entityinfo_t	entinfo;
	gentity_t	*ent;
	float	f, alertness;
	float	squaredist;
	vec3_t	dir;
	int	areanum;

	alertness = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_ALERTNESS, 0, 1 );

	for ( i = 0; i < maxclients && i < MAX_CLIENTS; i++ ) {
		if ( i == bs->client ) continue;
		ent = &g_entities[ i ];
		if ( !ent->inuse || !ent->target_ent ) continue;
		BotEntityInfo( ent->target_ent->s.number, &entinfo );
		if ( !entinfo.valid || !( entinfo.powerups & ( 1 << PW_BATTLESUIT ) ) ) continue;
		if ( !BotSameTeam( bs, i ) ) continue;
		VectorSubtract( entinfo.origin, bs->origin, dir );
		squaredist = VectorLengthSquared( dir );
		if ( squaredist > Square( 900.0 + alertness * 4000.0 ) ) continue;
		f = 90 + 90 - ( 90 - ( squaredist > Square( 810 ) ? Square( 810 ) : squaredist ) / ( 810 * 9 ) );
		vis = BotEntityVisible( bs->entitynum, bs->eye, bs->viewangles, f, entinfo.number );
		if ( vis <= 0 ) continue;
		areanum = BotPointAreaNum( entinfo.origin );
		if ( trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, areanum, bs->tfl ) ) {
			return entinfo.number;
		}
	}
	return -1;
}
Пример #4
0
/*
=======================================================================================================================================
BotMatch_CheckPoint
=======================================================================================================================================
*/
void BotMatch_CheckPoint(bot_state_t *bs, bot_match_t *match) {
	int areanum;
	char buf[MAX_MESSAGE_SIZE];
	vec3_t position;
	bot_waypoint_t *cp;

	if (!TeamPlayIsOn()) {
		return;
	}

	trap_BotMatchVariable(match, POSITION, buf, MAX_MESSAGE_SIZE);
	VectorClear(position);
	// BotGPSToPosition(buf, position);
	sscanf(buf, "%f %f %f", &position[0], &position[1], &position[2]);
	position[2] += 0.5;
	areanum = BotPointAreaNum(position);

	if (!areanum) {
		if (BotAddressedToBot(bs, match)) {
			BotAI_BotInitialChat(bs, "checkpoint_invalid", NULL);
			trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		}

		return;
	}

	trap_BotMatchVariable(match, NAME, buf, MAX_MESSAGE_SIZE);
	// check if there already exists a checkpoint with this name
	cp = BotFindWayPoint(bs->checkpoints, buf);

	if (cp) {
		if (cp->next) {
			cp->next->prev = cp->prev;
		}

		if (cp->prev) {
			cp->prev->next = cp->next;
		} else {bs->checkpoints = cp->next;}

		cp->inuse = qfalse;
	}
	// create a new check point
	cp = BotCreateWayPoint(buf, position, areanum);
	// add the check point to the bot's known chech points
	cp->next = bs->checkpoints;

	if (bs->checkpoints) {
		bs->checkpoints->prev = cp;
	}

	bs->checkpoints = cp;

	if (BotAddressedToBot(bs, match)) {
		Com_sprintf(buf, sizeof(buf), "%1.0f %1.0f %1.0f", cp->goal.origin[0], cp->goal.origin[1], cp->goal.origin[2]);

		BotAI_BotInitialChat(bs, "checkpoint_confirm", cp->name, buf, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
	}
}
Пример #5
0
/*
==================
BotClientTravelTimeToGoal
==================
*/
int BotClientTravelTimeToGoal(int client, bot_goal_t *goal) {
    playerState_t ps;
    int areanum;

    BotAI_GetClientState(client, &ps);
    areanum = BotPointAreaNum(ps.origin);
    if (!areanum) return 1;
    return trap_AAS_AreaTravelTimeToGoalArea(areanum, ps.origin, goal->areanum, TFL_DEFAULT);
}
Пример #6
0
/*
==================
BotVoiceChat_Camp
==================
*/
void
BotVoiceChat_Camp(bot_state_t * bs, int client, int mode)
{
  int areanum;
  aas_entityinfo_t entinfo;
  char netname[MAX_NETNAME];

  //
  bs->teamgoal.entitynum = -1;
  BotEntityInfo(client, &entinfo);
  //if info is valid (in PVS)
  if (entinfo.valid)
  {
    areanum = BotPointAreaNum(entinfo.origin);
    if (areanum)
    {				// && trap_AAS_AreaReachability(areanum)) {
      //NOTE: just assume the bot knows where the person is
      //if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, client)) {
      bs->teamgoal.entitynum = client;
      bs->teamgoal.areanum = areanum;
      VectorCopy(entinfo.origin, bs->teamgoal.origin);
      VectorSet(bs->teamgoal.mins, -8, -8, -8);
      VectorSet(bs->teamgoal.maxs, 8, 8, 8);
      //}
    }
  }
  //if the other is not visible
  if (bs->teamgoal.entitynum < 0)
  {
    BotAI_BotInitialChat(bs, "whereareyou",
			 EasyClientName(client, netname,
					sizeof(netname)), NULL);
    trap_BotEnterChat(bs->cs, client, CHAT_TELL);
    return;
  }
  //
  bs->decisionmaker = client;
  bs->ordered = qtrue;
  bs->order_time = FloatTime();
  //set the time to send a message to the team mates
  bs->teammessage_time = FloatTime() + 2 * random();
  //set the ltg type
  bs->ltgtype = LTG_CAMPORDER;
  //get the team goal time
  bs->teamgoal_time = FloatTime() + TEAM_CAMP_TIME;
  //the teammate that requested the camping
  bs->teammate = client;
  //not arrived yet
  bs->arrive_time = 0;
  //
  BotSetTeamStatus(bs);
  // remember last ordered task
  BotRememberLastOrderedTask(bs);
#ifdef DEBUG
  BotPrintTeamGoal(bs);
#endif //DEBUG
}
Пример #7
0
/*
==================
BotVoiceChat_FollowMe
==================
*/
void
BotVoiceChat_FollowMe(bot_state_t * bs, int client, int mode)
{
  int areanum;
  aas_entityinfo_t entinfo;
  char netname[MAX_NETNAME];

  bs->teamgoal.entitynum = -1;
  BotEntityInfo(client, &entinfo);
  //if info is valid (in PVS)
  if (entinfo.valid)
  {
    areanum = BotPointAreaNum(entinfo.origin);
    if (areanum)
    {				// && trap_AAS_AreaReachability(areanum)) {
      bs->teamgoal.entitynum = client;
      bs->teamgoal.areanum = areanum;
      VectorCopy(entinfo.origin, bs->teamgoal.origin);
      VectorSet(bs->teamgoal.mins, -8, -8, -8);
      VectorSet(bs->teamgoal.maxs, 8, 8, 8);
    }
  }
  //if the other is not visible
  if (bs->teamgoal.entitynum < 0)
  {
    BotAI_BotInitialChat(bs, "whereareyou",
			 EasyClientName(client, netname,
					sizeof(netname)), NULL);
    trap_BotEnterChat(bs->cs, client, CHAT_TELL);
    return;
  }
  //
  bs->decisionmaker = client;
  bs->ordered = qtrue;
  bs->order_time = FloatTime();
  //the team mate
  bs->teammate = client;
  //last time the team mate was assumed visible
  bs->teammatevisible_time = FloatTime();
  //set the time to send a message to the team mates
  bs->teammessage_time = FloatTime() + 2 * random();
  //get the team goal time
  bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
  //set the ltg type
  bs->ltgtype = LTG_TEAMACCOMPANY;
  bs->formation_dist = 3.5 * 32;	//3.5 meter
  bs->arrive_time = 0;
  //
  BotSetTeamStatus(bs);
  // remember last ordered task
  BotRememberLastOrderedTask(bs);
#ifdef DEBUG
  BotPrintTeamGoal(bs);
#endif //DEBUG
}
Пример #8
0
/*
=======================================================================================================================================
BotMatch_HelpAccompany
=======================================================================================================================================
*/
void BotMatch_HelpAccompany(bot_state_t *bs, bot_match_t *match) {
	int client, other, areanum;
	char teammate[MAX_MESSAGE_SIZE], netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	bot_match_t teammatematch;
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// get the team mate name
	trap_BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
	// get the client to help
	if (trap_BotFindMatch(teammate, &teammatematch, MTCONTEXT_TEAMMATE) &&
		// if someone asks for him or herself
		 teammatematch.type == MSG_ME) {
		// get the netname
		trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		client = ClientFromName(netname);
		other = qfalse;
	} else {
		// asked for someone else
		client = FindClientByName(teammate);
		// if this is the bot self
		if (client == bs->client) {
			other = qfalse;
		} else if (!BotSameTeam(bs, client)) {
			// FIXME: say "I don't help the enemy"
			return;
		} else {
			other = qtrue;
		}
	}
	// if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whois", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whois", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// don't help or accompany yourself
	if (client == bs->client) {
		return;
	}

	bs->teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	// if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);

		if (areanum && trap_AAS_AreaReachability(areanum)) {
			bs->teamgoal.entitynum = client;
			bs->teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->teamgoal.origin);
			VectorSet(bs->teamgoal.mins, -8, -8, -8);
			VectorSet(bs->teamgoal.maxs, 8, 8, 8);
		}
	}
	// if no teamgoal yet
	if (bs->teamgoal.entitynum < 0) {
		// if near an item
		if (match->subtype & ST_NEARITEM) {
			// get the match variable
			trap_BotMatchVariable(match, ITEM, itemname, sizeof(itemname));

			if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
				// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
				// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
				return;
			}
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// the team mate
	bs->teammate = client;
	// last time the team mate was assumed visible
	bs->teammatevisible_time = trap_AAS_Time();
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the ltg type
	if (match->type == MSG_HELP) {
		bs->ltgtype = LTG_TEAMHELP;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_HELP_TIME;
		}
	} else {
		bs->ltgtype = LTG_TEAMACCOMPANY;

		if (!bs->teamgoal_time) {
			bs->teamgoal_time = trap_AAS_Time() + TEAM_ACCOMPANY_TIME;
		}

		bs->formation_dist = 3.5 * 32;     // 3.5 meter
		bs->arrive_time = 0;
	}
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Пример #9
0
/*
=======================================================================================================================================
BotMatch_LeadTheWay
=======================================================================================================================================
*/
void BotMatch_LeadTheWay(bot_state_t *bs, bot_match_t *match) {
	aas_entityinfo_t entinfo;
	char netname[MAX_MESSAGE_SIZE], teammate[MAX_MESSAGE_SIZE];
	int client, areanum, other;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}
	// if someone asks for someone else
	if (match->subtype & ST_SOMEONE) {
		// get the team mate name
		trap_BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
		client = FindClientByName(teammate);
		// if this is the bot self
		if (client == bs->client) {
			other = qfalse;
		} else if (!BotSameTeam(bs, client)) {
			// FIXME: say "I don't help the enemy"
			return;
		} else {
			other = qtrue;
		}
	} else {
		// get the netname
		trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		client = ClientFromName(netname);
		other = qfalse;
	}
	// if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}

	bs->lead_teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	// if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);

		if (areanum && trap_AAS_AreaReachability(areanum)) {
			bs->lead_teamgoal.entitynum = client;
			bs->lead_teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->lead_teamgoal.origin);
			VectorSet(bs->lead_teamgoal.mins, -8, -8, -8);
			VectorSet(bs->lead_teamgoal.maxs, 8, 8, 8);
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		if (other) {
			BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		} else {BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);}

		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}

	bs->lead_teammate = client;
	bs->lead_time = trap_AAS_Time() + TEAM_LEAD_TIME;
	bs->leadvisible_time = 0;
	bs->leadmessage_time = -(trap_AAS_Time() + 2 * random());
}
Пример #10
0
/*
============
AICast_Think

  entry point for all cast AI
============
*/
void AICast_Think( int client, float thinktime ) {
	gentity_t       *ent;
	cast_state_t    *cs;
	int i;
	int animIndex;
	animation_t     *anim;

//	if (saveGamePending || (strlen( g_missionStats.string ) > 2 )) {
//		return;
//	}

	//
	// get the cast ready for processing
	//
	cs = AICast_GetCastState( client );
	ent = &g_entities[client];
	//
	// make sure we are using the right AAS data for this entity (one's that don't get set will default to the player's AAS data)
	trap_AAS_SetCurrentWorld( cs->aasWorldIndex );
	//
	// make sure we have a valid navigation system
	//
	if ( !trap_AAS_Initialized() ) {
		return;
	}
	//
	trap_EA_ResetInput( client, NULL );
	cs->aiFlags &= ~AIFL_VIEWLOCKED;
	//cs->bs->weaponnum = ent->client->ps.weapon;
	//
	// turn off flags that are set each frame if needed
	ent->client->ps.eFlags &= ~( EF_NOSWINGANGLES | EF_MONSTER_EFFECT | EF_MONSTER_EFFECT2 | EF_MONSTER_EFFECT3 );
	// conditional flags
	if ( ent->aiCharacter == AICHAR_ZOMBIE ) {
		if ( COM_BitCheck( ent->client->ps.weapons, WP_MONSTER_ATTACK1 ) ) {
			cs->aiFlags |= AIFL_NO_FLAME_DAMAGE;
			SET_FLAMING_ZOMBIE( ent->s, 1 );
		} else {
			SET_FLAMING_ZOMBIE( ent->s, 0 );
		}
	}
	//
	// if we're dead, do special stuff only
	if ( ent->health <= 0 || cs->revivingTime || cs->rebirthTime ) {
		//
		if ( cs->revivingTime && cs->revivingTime < level.time ) {
			// start us thinking again
			ent->client->ps.pm_type = PM_NORMAL;
			cs->revivingTime = 0;
		}
		//
		if ( cs->rebirthTime && cs->rebirthTime < level.time ) {
			vec3_t mins, maxs;
			int touch[10], numTouch;
			float oldmaxZ;

			oldmaxZ = ent->r.maxs[2];

			// make sure the area is clear
			AIChar_SetBBox( ent, cs );

			VectorAdd( ent->r.currentOrigin, ent->r.mins, mins );
			VectorAdd( ent->r.currentOrigin, ent->r.maxs, maxs );
			trap_UnlinkEntity( ent );

			numTouch = trap_EntitiesInBox( mins, maxs, touch, 10 );

			if ( numTouch ) {
				for ( i = 0; i < numTouch; i++ ) {
					//if (!g_entities[touch[i]].client || g_entities[touch[i]].r.contents == CONTENTS_BODY)
					if ( g_entities[touch[i]].r.contents & MASK_PLAYERSOLID ) {
						break;
					}
				}
				if ( i == numTouch ) {
					numTouch = 0;
				}
			}

			if ( numTouch == 0 ) {    // ok to spawn

				// give them health when they start reviving, so we won't gib after
				// just a couple shots while reviving
				ent->health =
					ent->client->ps.stats[STAT_HEALTH] =
						ent->client->ps.stats[STAT_MAX_HEALTH] =
							( ( cs->attributes[STARTING_HEALTH] - 50 ) > 30 ? ( cs->attributes[STARTING_HEALTH] - 50 ) : 30 );

				ent->r.contents = CONTENTS_BODY;
				ent->clipmask = MASK_PLAYERSOLID;
				ent->takedamage = qtrue;
				ent->waterlevel = 0;
				ent->watertype = 0;
				ent->flags = 0;
				ent->die = AICast_Die;
				ent->client->ps.eFlags &= ~EF_DEAD;
				ent->s.eFlags &= ~EF_DEAD;

				cs->rebirthTime = 0;
				cs->deathTime = 0;

				// play the revive animation
				cs->revivingTime = level.time + BG_AnimScriptEvent( &ent->client->ps, ANIM_ET_REVIVE, qfalse, qtrue );;
			} else {
				// can't spawn yet, so set bbox back, and wait
				ent->r.maxs[2] = oldmaxZ;
				ent->client->ps.maxs[2] = ent->r.maxs[2];
			}
			trap_LinkEntity( ent );
		}
		// ZOMBIE should set effect flag if really dead
		if ( cs->aiCharacter == AICHAR_ZOMBIE && !ent->r.contents ) {
			ent->client->ps.eFlags |= EF_MONSTER_EFFECT2;
		}
		//
		if ( ent->health > GIB_HEALTH && cs->deathTime && cs->deathTime < ( level.time - 3000 ) ) {
/*
			// been dead for long enough, set our animation to the end frame
			switch ( ent->s.legsAnim & ~ANIM_TOGGLEBIT ) {
			case BOTH_DEATH1:
			case BOTH_DEAD1:
				anim = BOTH_DEAD1;
				break;
			case BOTH_DEATH2:
			case BOTH_DEAD2:
				anim = BOTH_DEAD2;
				break;
			case BOTH_DEATH3:
			case BOTH_DEAD3:
				anim = BOTH_DEAD3;
				break;
			default:
				G_Error( "%s has unknown death animation\n", ent->classname);
			}
			ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
			ent->client->ps.legsAnim = ( ( ent->client->ps.legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
*/
			cs->deathTime = 0;
			ent->r.svFlags &= ~SVF_BROADCAST;
		}
		//
		// no more thinking required
		return;
	}
	//
	// set some anim conditions
	if ( cs->secondDeadTime ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qtrue, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SECONDLIFE, qfalse, qfalse );
	}
	// set health value
	if ( ent->health <= 0.25 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 3, qfalse );
	} else if ( ent->health <= 0.5 * cs->attributes[STARTING_HEALTH] ) {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 2, qfalse );
	} else {
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_HEALTH_LEVEL, 1, qfalse );
	}
	//
	cs->speedScale = 1.0;           // reset each frame, set if required
	cs->actionFlags = 0;            // FIXME: move this to a Cast AI movement init function!
	//retrieve the current client state
	BotAI_GetClientState( client, &( cs->bs->cur_ps ) );
	//
	// setup movement speeds for the given state
	// walking
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALK );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[WALKING_SPEED] = anim->moveSpeed;
	}
	// crouching
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_WALKCR );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[CROUCHING_SPEED] = anim->moveSpeed;
	}
	// running
	animIndex = BG_GetAnimScriptAnimation( cs->entityNum, ent->client->ps.aiState, ANIM_MT_RUN );
	if ( animIndex >= 0 ) {
		anim = BG_GetAnimationForIndex( cs->entityNum, animIndex );
		cs->attributes[RUNNING_SPEED] = anim->moveSpeed;
	}
	// update crouch speed scale
	ent->client->ps.crouchSpeedScale = cs->attributes[CROUCHING_SPEED] / cs->attributes[RUNNING_SPEED];
	//
	// only enable headlook if we want to this frame
	ent->client->ps.eFlags &= ~EF_HEADLOOK;
	if ( cs->bs->enemy >= 0 ) {
		ent->client->ps.eFlags &= ~EF_STAND_IDLE2;  // never use alt idle if fighting
	}
	//
	// check for dead leader
	if ( cs->leaderNum >= 0 && g_entities[cs->leaderNum].health <= 0 ) {
		cs->leaderNum = -1;
	}
	//
#if 0
	// HACK for village2, if they are stuck, find a good position (there is a friendly guy placed inside a table)
	{
		trace_t tr;
		vec3_t org;
		trap_Trace( &tr, cs->bs->cur_ps.origin, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, cs->bs->cur_ps.origin, cs->entityNum, CONTENTS_SOLID );
		while ( tr.startsolid ) {
			VectorCopy( cs->bs->cur_ps.origin, org );
			org[0] += 96 * crandom();
			org[1] += 96 * crandom();
			org[2] += 16 * crandom();
			trap_Trace( &tr, org, cs->bs->cur_ps.mins, cs->bs->cur_ps.maxs, org, cs->entityNum, CONTENTS_SOLID );
			G_SetOrigin( &g_entities[cs->entityNum], org );
			VectorCopy( org, g_entities[cs->entityNum].client->ps.origin );
		}
	}
#endif
	//add the delta angles to the cast's current view angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] + SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
	//
	//increase the local time of the cast
	cs->bs->ltime += thinktime;
	//
	cs->bs->thinktime = thinktime;
	//origin of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->origin );
	//eye coordinates of the cast
	VectorCopy( cs->bs->cur_ps.origin, cs->bs->eye );
	cs->bs->eye[2] += cs->bs->cur_ps.viewheight;
	//get the area the cast is in
	cs->bs->areanum = BotPointAreaNum( cs->bs->origin );
	// clear flags each frame
	cs->bs->flags = 0;
	//
	// check enemy health
	if ( cs->bs->enemy >= 0 && g_entities[cs->bs->enemy].health <= 0 ) {
		cs->bs->enemy = -1;
	}
	//
	// if the previous movetype was temporary, set it back
	if ( cs->movestateType == MSTYPE_TEMPORARY ) {
		cs->movestate = MS_DEFAULT;
		cs->movestateType = MSTYPE_NONE;
	}
	// crouching?
	if (    ( cs->bs->attackcrouch_time > trap_AAS_Time() ) &&
			( ( cs->lastAttackCrouch > level.time - 500 ) || ( cs->thinkFuncChangeTime < level.time - 1000 ) ) ) {
		// if we are not moving, and we are firing, always stand, unless we are allowed to crouch + fire
		if ( VectorLength( cs->bs->cur_ps.velocity ) || ( cs->lastWeaponFired < level.time - 2000 ) || ( cs->aiFlags & AIFL_ATTACK_CROUCH ) ) {
			cs->lastAttackCrouch = level.time;
			trap_EA_Crouch( cs->bs->client );
		}
	}
	//
	//if (cs->bs->enemy >= 0) {
	//update the attack inventory values
	AICast_UpdateBattleInventory( cs, cs->bs->enemy );
	//}
	//
	// if we don't have ammo for the current weapon, get rid of it
	if ( !( COM_BitCheck( cs->bs->cur_ps.weapons, cs->bs->weaponnum ) ) || !AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum ) ) {
		// select a weapon
		AICast_ChooseWeapon( cs, qfalse );
		// if still no ammo, select a blank weapon
		//if (!AICast_GotEnoughAmmoForWeapon( cs, cs->bs->weaponnum )) {
		//	cs->bs->weaponnum = WP_NONE;
		//}
	}
	//
	// in query mode, we do special handling (pause scripting, check for transition to alert/combat, etc)
	if ( cs->aiState == AISTATE_QUERY ) {
		AICast_QueryThink( cs );
	} else if ( cs->pauseTime < level.time )     {
		// do the thinking
		AICast_ProcessAIFunctions( cs, thinktime );
		//
		// make sure the correct weapon is selected
		trap_EA_SelectWeapon( cs->bs->client, cs->bs->weaponnum );
		//
		// process current script if it exists
		cs->castScriptStatusCurrent = cs->castScriptStatus;
		AICast_ScriptRun( cs, qfalse );
	}
	//
	// set special movestate if necessary
	if ( cs->movestateType != MSTYPE_NONE ) {
		switch ( cs->movestate ) {
		case MS_WALK:
			cs->actionFlags |= CASTACTION_WALK;
			break;
		case MS_CROUCH:
			trap_EA_Crouch( cs->entityNum );
			break;
		default:
			break; // TTimo gcc: MS_DEFAULT MS_RUN not handled in switch
		}
	}
	//
	//subtract the delta angles
	for ( i = 0; i < 3; i++ ) {
		cs->bs->viewangles[i] = AngleMod( cs->bs->viewangles[i] - SHORT2ANGLE( cs->bs->cur_ps.delta_angles[i] ) );
	}
}
Пример #11
0
/*
================
AICast_EvaluatePmove

  Avoidance after the event (leaders instruct AI's to get out the way, AI's instruct other non-moving AI's to get out the way)
================
*/
void AICast_EvaluatePmove( int clientnum, pmove_t *pm ) {
	cast_state_t    *cs, *ocs;
	int i, ent;
	bot_goal_t ogoal;

	//vec3_t pos, dir;
	cs = AICast_GetCastState( clientnum );
	// make sure we are using the right AAS data for this entity (one's that don't get set will default to the player's AAS data)
	trap_AAS_SetCurrentWorld( cs->aasWorldIndex );

	// NOTE: this is only enabled for real clients, so their followers get out of their way
	//if (cs->bs)
	//	return;

	// look through the touchent's to see if we've bumped into something we should avoid, or react to
	for ( i = 0; i < pm->numtouch; i++ )
	{
		// mark the time, so they can deal with the obstruction in their own think functions
		cs->blockedTime = level.time;

		if ( pm->touchents[i] == pm->ps->groundEntityNum ) {
			continue;
		}

		// if they are an AI Cast, inform them of our disposition, and hope that they are reasonable
		// enough to assist us in our desire to move beyond our current position
		if ( pm->touchents[i] < aicast_maxclients ) {
			if ( !AICast_EntityVisible( cs, pm->touchents[i], qtrue ) ) {
				continue;
			}

			// if we are inspecting the body, abort if we touch anything
			if ( cs->bs && cs->bs->enemy >= 0 && g_entities[cs->bs->enemy].health <= 0 ) {
				cs->bs->enemy = -1;
			}

			// anything we touch, should see us
			AICast_UpdateVisibility( &g_entities[pm->touchents[i]], &g_entities[cs->entityNum], qfalse, qtrue );

			ocs = AICast_GetCastState( pm->touchents[i] );
			if (    ( ocs->bs ) &&
					( !( ocs->aiFlags & AIFL_NOAVOID ) ) &&
					( ( ocs->leaderNum == cs->entityNum ) || ( VectorLength( ocs->bs->velocity ) < 5 ) ) &&
					( ocs->obstructingTime < ( level.time + 100 ) ) ) {
				// if they are moving away from us already, let them go
				if ( VectorLength( ocs->bs->cur_ps.velocity ) > 10 ) {
					vec3_t v1, v2;

					VectorSubtract( ocs->bs->origin, g_entities[clientnum].client->ps.velocity, v2 );
					VectorNormalize( v2 );
					VectorNormalize2( ocs->bs->cur_ps.velocity, v1 );

					if ( DotProduct( v1, v2 ) > 0.0 ) {
						continue;
					}
				}
				if ( ocs->leaderNum >= 0 ) {
					VectorCopy( g_entities[ocs->leaderNum].r.currentOrigin, ogoal.origin );
					ogoal.areanum = BotPointAreaNum( ogoal.origin );
					ogoal.entitynum = ocs->leaderNum;
					if ( ocs->bs && AICast_GetAvoid( ocs, &ogoal, ocs->obstructingPos, qfalse, cs->entityNum ) ) { // give them time to move somewhere else
						ocs->obstructingTime = level.time + 1000;
					}
				} else {
					if ( ocs->bs && AICast_GetAvoid( ocs, NULL, ocs->obstructingPos, qfalse, cs->entityNum ) ) { // give them time to move somewhere else
						ocs->obstructingTime = level.time + 1000;
					}
				}
			}
		} else if ( cs->bs ) {
			// if we are blocked by a brush entity, see if we can activate it
			ent = pm->touchents[i];
			if ( g_entities[ent].s.modelindex > 0 && g_entities[ent].s.eType == ET_MOVER ) {
				//find the bsp entity which should be activated in order to remove
				//the blocking entity

				if ( !g_entities[ent].isProp
					 && Q_stricmp( g_entities[ent].classname, "func_static" )
					 && Q_stricmp( g_entities[ent].classname, "func_button" )
					 && Q_stricmp( g_entities[ent].classname, "func_tram" ) ) {
					G_Activate( &g_entities[ent], &g_entities[cs->entityNum] );
				}

			}
		}
	}
}
Пример #12
0
/*
==============
BotAI
==============
*/
int BotAI( int client, float thinktime ) {
	bot_state_t *bs;
	char buf[1024], *args;
	int j;

	trap_EA_ResetInput( client, NULL );
	//
	bs = botstates[client];
	if ( !bs || !bs->inuse ) {
		BotAI_Print( PRT_FATAL, "client %d hasn't been setup\n", client );
		return BLERR_AICLIENTNOTSETUP;
	}

	//retrieve the current client state
	BotAI_GetClientState( client, &bs->cur_ps );

	//retrieve any waiting console messages
	while ( trap_BotGetServerCommand( client, buf, sizeof( buf ) ) ) {
		//have buf point to the command and args to the command arguments
		args = strchr( buf, ' ' );
		if ( !args ) {
			continue;
		}
		*args++ = '\0';

		//remove color espace sequences from the arguments
		Q_CleanStr( args );

		//botai_import.Print(PRT_MESSAGE, "ConsoleMessage: \"%s\"\n", buf);
		if ( !Q_stricmp( buf, "cp " ) ) { /*CenterPrintf*/
		} else if ( !Q_stricmp( buf, "cs" ) )                                                      { /*ConfigStringModified*/
		} else if ( !Q_stricmp( buf, "print" ) )                                                                                                                       {
			trap_BotQueueConsoleMessage( bs->cs, CMS_NORMAL, args );
		} else if ( !Q_stricmp( buf, "chat" ) ) {
			trap_BotQueueConsoleMessage( bs->cs, CMS_CHAT, args );
		} else if ( !Q_stricmp( buf, "tchat" ) ) {
			trap_BotQueueConsoleMessage( bs->cs, CMS_CHAT, args );
		} else if ( !Q_stricmp( buf, "scores" ) ) { /*FIXME: parse scores?*/
		} else if ( !Q_stricmp( buf, "clientLevelShot" ) )                                                                    { /*ignore*/
		}
	}
	//add the delta angles to the bot's current view angles
	for ( j = 0; j < 3; j++ ) {
		bs->viewangles[j] = AngleMod( bs->viewangles[j] + SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) );
	}
	//increase the local time of the bot
	bs->ltime += thinktime;
	//
	bs->thinktime = thinktime;
	//origin of the bot
	VectorCopy( bs->cur_ps.origin, bs->origin );
	//eye coordinates of the bot
	VectorCopy( bs->cur_ps.origin, bs->eye );
	bs->eye[2] += bs->cur_ps.viewheight;
	//get the area the bot is in
	bs->areanum = BotPointAreaNum( bs->origin );
	//the real AI
	BotDeathmatchAI( bs, thinktime );
	//set the weapon selection every AI frame
	trap_EA_SelectWeapon( bs->client, bs->weaponnum );
	//subtract the delta angles
	for ( j = 0; j < 3; j++ ) {
		bs->viewangles[j] = AngleMod( bs->viewangles[j] - SHORT2ANGLE( bs->cur_ps.delta_angles[j] ) );
	}
	//everything was ok
	return BLERR_NOERROR;
}
Пример #13
0
/*
 * BotAI
 */
int
BotAI(int client, float thinktime)
{
	bot_state_t *bs;
	char	buf[1024], *args;
	int	j;

	trap_EA_ResetInput(client);
	bs = botstates[client];
	if(!bs || !bs->inuse){
		BotAI_Print(PRT_FATAL, "BotAI: client %d is not setup\n", client);
		return qfalse;
	}

	/* retrieve the current client state */
	BotAI_GetClientState(client, &bs->cur_ps);

	/* retrieve any waiting server commands */
	while(trap_BotGetServerCommand(client, buf, sizeof(buf))){
		/* have buf point to the command and args to the command arguments */
		args = strchr(buf, ' ');
		if(!args) continue;
		*args++ = '\0';

		/* remove color espace sequences from the arguments */
		RemoveColorEscapeSequences(args);

		if(!Q_stricmp(buf, "cp ")){	/*CenterPrintf*/
		}else if(!Q_stricmp(buf, "cs")){/*ConfigStringModified*/
		}else if(!Q_stricmp(buf, "print")){
			/* remove first and last quote from the chat message */
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_NORMAL, args);
		}else if(!Q_stricmp(buf, "chat")){
			/* remove first and last quote from the chat message */
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}else if(!Q_stricmp(buf, "tchat")){
			/* remove first and last quote from the chat message */
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
#ifdef MISSIONPACK
		else if(!Q_stricmp(buf, "vchat"))
			BotVoiceChatCommand(bs, SAY_ALL, args);
		else if(!Q_stricmp(buf, "vtchat"))
			BotVoiceChatCommand(bs, SAY_TEAM, args);
		else if(!Q_stricmp(buf, "vtell"))
			BotVoiceChatCommand(bs, SAY_TELL, args);

#endif
		else if(!Q_stricmp(buf, "scores")){		/*FIXME: parse scores?*/
		}else if(!Q_stricmp(buf, "clientLevelShot")){	/*ignore*/
		}
	}
	/* add the delta angles to the bot's current view angles */
	for(j = 0; j < 3; j++)
		bs->viewangles[j] =
			modeuler(bs->viewangles[j] +
				SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	/* increase the local time of the bot */
	bs->ltime += thinktime;
	bs->thinktime = thinktime;
	/* origin of the bot */
	copyv3(bs->cur_ps.origin, bs->origin);
	/* eye coordinates of the bot */
	copyv3(bs->cur_ps.origin, bs->eye);
	bs->eye[2] += bs->cur_ps.viewheight;
	/* get the area the bot is in */
	bs->areanum = BotPointAreaNum(bs->origin);
	/* the real AI */
	BotDeathmatchAI(bs, thinktime);
	/* set the weapon selection every AI frame */
	trap_EA_SelectWeapon(bs->client, bs->weaponnum);
	/* subtract the delta angles */
	for(j = 0; j < 3; j++)
		bs->viewangles[j] =
			modeuler(bs->viewangles[j] -
				SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	/* everything was ok */
	return qtrue;
}
Пример #14
0
/*
==================
BotMatch_Camp
==================
*/
void BotMatch_Camp(bot_state_t *bs, bot_match_t *match) {
	int playernum, areanum;
	char netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) return;
	//if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) return;
	//
	BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	//asked for someone else
	playernum = FindPlayerByName(netname);
	//if there's no valid player with this name
	if (playernum < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		BotEnterChat(bs->cs, bs->playernum, CHAT_TEAM);
		return;
	}
	//get the match variable
	BotMatchVariable(match, KEYAREA, itemname, sizeof(itemname));
	//in CTF it could be the base
	if (match->subtype & ST_THERE) {
		//camp at the spot the bot is currently standing
		bs->teamgoal.entitynum = bs->entitynum;
		bs->teamgoal.areanum = bs->areanum;
		VectorCopy(bs->origin, bs->teamgoal.origin);
		VectorSet(bs->teamgoal.mins, -8, -8, -8);
		VectorSet(bs->teamgoal.maxs, 8, 8, 8);
	}
	else if (match->subtype & ST_HERE) {
		//if this is the bot self
		if (playernum == bs->playernum) return;
		//
		bs->teamgoal.entitynum = -1;
		BotEntityInfo(playernum, &entinfo);
		//if info is valid (in PVS)
		if (entinfo.valid) {
			areanum = BotPointAreaNum(entinfo.origin);
			if (areanum) {// && trap_AAS_AreaReachability(areanum)) {
				//NOTE: just assume the bot knows where the person is
				//if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, playernum)) {
					bs->teamgoal.entitynum = playernum;
					bs->teamgoal.areanum = areanum;
					VectorCopy(entinfo.origin, bs->teamgoal.origin);
					VectorSet(bs->teamgoal.mins, -8, -8, -8);
					VectorSet(bs->teamgoal.maxs, 8, 8, 8);
				//}
			}
		}
		//if the other is not visible
		if (bs->teamgoal.entitynum < 0) {
			BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);
			playernum = PlayerFromName(netname);
			BotEnterChat(bs->cs, playernum, CHAT_TELL);
			return;
		}
	}
	else if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
		//BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
		//playernum = PlayerFromName(netname);
		//BotEnterChat(bs->cs, playernum, CHAT_TELL);
		return;
	}
	//
	bs->decisionmaker = playernum;
	bs->ordered = qtrue;
	bs->order_time = FloatTime();
	//set the time to send a message to the team mates
	bs->teammessage_time = FloatTime() + 2 * random();
	//set the ltg type
	bs->ltgtype = LTG_CAMPORDER;
	//get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	//set the team goal time
	if (!bs->teamgoal_time) bs->teamgoal_time = FloatTime() + TEAM_CAMP_TIME;
	//not arrived yet
	bs->arrive_time = 0;
	//
	BotSetTeamStatus(bs);
	// remember last ordered task
	BotRememberLastOrderedTask(bs);
	BotPrintTeamGoal(bs);
}
Пример #15
0
/*
==================
BotMatch_HelpAccompany
==================
*/
void BotMatch_HelpAccompany(bot_state_t *bs, bot_match_t *match) {
	int playernum, other, areanum;
	char teammate[MAX_MESSAGE_SIZE];
	char netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	bot_match_t teammatematch;
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) return;
	//if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) return;
	//get the team mate name
	BotMatchVariable(match, TEAMMATE, teammate, sizeof(teammate));
	//get the player to help
	if (BotFindMatch(teammate, &teammatematch, MTCONTEXT_TEAMMATE) &&
			//if someone asks for him or herself
			teammatematch.type == MSG_ME) {
		//get the netname
		BotMatchVariable(match, NETNAME, netname, sizeof(netname));
		playernum = PlayerFromName(netname);
		other = qfalse;
	}
	else {
		//asked for someone else
		playernum = FindPlayerByName(teammate);
		//if this is the bot self
		if (playernum == bs->playernum) {
			other = qfalse;
		}
		else if (!BotSameTeam(bs, playernum)) {
			//FIXME: say "I don't help the enemy"
			return;
		}
		else {
			other = qtrue;
		}
	}
	//if the bot doesn't know who to help (FindPlayerByName returned -1)
	if (playernum < 0) {
		if (other) BotAI_BotInitialChat(bs, "whois", teammate, NULL);
		else BotAI_BotInitialChat(bs, "whois", netname, NULL);
		playernum = PlayerFromName(netname);
		BotEnterChat(bs->cs, playernum, CHAT_TELL);
		return;
	}
	//don't help or accompany yourself
	if (playernum == bs->playernum) {
		return;
	}
	//
	bs->teamgoal.entitynum = -1;
	BotEntityInfo(playernum, &entinfo);
	//if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);
		if (areanum) {// && trap_AAS_AreaReachability(areanum)) {
			bs->teamgoal.entitynum = playernum;
			bs->teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->teamgoal.origin);
			VectorSet(bs->teamgoal.mins, -8, -8, -8);
			VectorSet(bs->teamgoal.maxs, 8, 8, 8);
		}
	}
	//if no teamgoal yet
	if (bs->teamgoal.entitynum < 0) {
		//if near an item
		if (match->subtype & ST_NEARITEM) {
			//get the match variable
			BotMatchVariable(match, ITEM, itemname, sizeof(itemname));
			//
			if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
				//BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
				//BotEnterChat(bs->cs, bs->playernum, CHAT_TEAM);
				return;
			}
		}
	}
	//
	if (bs->teamgoal.entitynum < 0) {
		if (other) BotAI_BotInitialChat(bs, "whereis", teammate, NULL);
		else BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);
		playernum = PlayerFromName(netname);
		BotEnterChat(bs->cs, playernum, CHAT_TEAM);
		return;
	}
	//the team mate
	bs->teammate = playernum;
	//
	BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	//
	playernum = PlayerFromName(netname);
	//the team mate who ordered
	bs->decisionmaker = playernum;
	bs->ordered = qtrue;
	bs->order_time = FloatTime();
	//last time the team mate was assumed visible
	bs->teammatevisible_time = FloatTime();
	//set the time to send a message to the team mates
	bs->teammessage_time = FloatTime() + 2 * random();
	//get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	//set the ltg type
	if (match->type == MSG_HELP) {
		bs->ltgtype = LTG_TEAMHELP;
		if (!bs->teamgoal_time) bs->teamgoal_time = FloatTime() + TEAM_HELP_TIME;
	}
	else {
		bs->ltgtype = LTG_TEAMACCOMPANY;
		if (!bs->teamgoal_time) bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
		bs->formation_dist = 128;
		bs->arrive_time = 0;
		//
		BotSetTeamStatus(bs);
		// remember last ordered task
		BotRememberLastOrderedTask(bs);
	}
	BotPrintTeamGoal(bs);
}
Пример #16
0
/*
=======================================================================================================================================
BotMatch_Camp
=======================================================================================================================================
*/
void BotMatch_Camp(bot_state_t *bs, bot_match_t *match) {
	int client, areanum;
	char netname[MAX_MESSAGE_SIZE];
	char itemname[MAX_MESSAGE_SIZE];
	aas_entityinfo_t entinfo;

	if (!TeamPlayIsOn()) {
		return;
	}
	// if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) {
		return;
	}

	trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	// asked for someone else
	client = FindClientByName(netname);
	// if there's no valid client with this name
	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// get the match variable
	trap_BotMatchVariable(match, KEYAREA, itemname, sizeof(itemname));
	// in CTF it could be the base
	if (match->subtype & ST_THERE) {
		// camp at the spot the bot is currently standing
		bs->teamgoal.entitynum = bs->entitynum;
		bs->teamgoal.areanum = bs->areanum;
		VectorCopy(bs->origin, bs->teamgoal.origin);
		VectorSet(bs->teamgoal.mins, -8, -8, -8);
		VectorSet(bs->teamgoal.maxs, 8, 8, 8);
	} else if (match->subtype & ST_HERE) {
		// if this is the bot self
		if (client == bs->client) {
			return;
		}

		bs->teamgoal.entitynum = -1;
		BotEntityInfo(client, &entinfo);
		// if info is valid (in PVS)
		if (entinfo.valid) {
			areanum = BotPointAreaNum(entinfo.origin);

			if (areanum && trap_AAS_AreaReachability(areanum)) {
				// NOTE: just cheat and assume the bot knows where the person is
				// if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, client)) {
				bs->teamgoal.entitynum = client;
				bs->teamgoal.areanum = areanum;
				VectorCopy(entinfo.origin, bs->teamgoal.origin);
				VectorSet(bs->teamgoal.mins, -8, -8, -8);
				VectorSet(bs->teamgoal.maxs, 8, 8, 8);
				//}
			}
		}
		// if the other is not visible
		if (bs->teamgoal.entitynum < 0) {
			BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);
			trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
			return;
		}
	} else if (!BotGetMessageTeamGoal(bs, itemname, &bs->teamgoal)) {
		// BotAI_BotInitialChat(bs, "cannotfind", itemname, NULL);
		// trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM);
		return;
	}
	// set the time to send a message to the team mates
	bs->teammessage_time = trap_AAS_Time() + 2 * random();
	// set the ltg type
	bs->ltgtype = LTG_CAMPORDER;
	// get the team goal time
	bs->teamgoal_time = BotGetTime(match);
	// set the team goal time
	if (!bs->teamgoal_time) {
		bs->teamgoal_time = trap_AAS_Time() + TEAM_CAMP_TIME;
	}
	// the teammate that requested the camping
	bs->teammate = client;
	// not arrived yet
	bs->arrive_time = 0;
#ifdef DEBUG
	BotPrintTeamGoal(bs);
#endif // DEBUG
}
Пример #17
0
void BotTeamSeekGoals( bot_state_t *bs ) {
	aas_entityinfo_t	entinfo;
	int	c;
	int	areanum;

	if ( bs->ltgtype == LTG_TEAMACCOMPANY && !bs->ordered ) {
		BotEntityInfo( bs->teammate, &entinfo );
		if ( !entinfo.valid || !( entinfo.powerups & ( 1 << PW_BATTLESUIT ) ) ) {
			bs->ltgtype = 0;
			return;
		}
		areanum = BotPointAreaNum( entinfo.origin );
		if ( !trap_AAS_AreaTravelTimeToGoalArea( bs->areanum, bs->origin, areanum, bs->tfl ) ) {
			bs->ltgtype = 0;
		}
		return;
	}
	if ( bs->owndecision_time < FloatTime() ) {
		c = BotTeamCarrierVisible( bs );
		if ( c >= 0 && ( bs->ltgtype != LTG_TEAMACCOMPANY || bs->teammate != c ) ) {
			BotRefuseOrder( bs );
			bs->decisionmaker = bs->client;
			bs->ordered = qfalse;
			bs->teammate = c;
			bs->teammatevisible_time = FloatTime();
			bs->teammessage_time = 0;
			bs->arrive_time = 1;

			bs->teamgoal_time = FloatTime() + 120;
			bs->ltgtype = LTG_TEAMACCOMPANY;
			bs->formation_dist = 70;
			BotSetTeamStatus( bs );
			bs->owndecision_time = FloatTime() + 5;
			return;
		}
	}
#if 0
	if ( BotTeamLeader( bs ) ) {
		return;
	}
	if ( bs->lastgoal_ltgtype ) {
		bs->teamgoal_time += 60;
	}
	if ( !bs->ordered && bs->lastgoal_ltgtype ) {
		bs->ltgtype = 0;
	}
	if ( bs->ltgtype == LTG_TEAMHELP ||
		bs->ltgtype == LTG_TEAMACCOMPANY ||
		bs->ltgtype == LTG_DEFENDKEYAREA ||
		bs->ltgtype == LTG_CAMPORDER ||
		bs->ltgtype == LTG_PATROL ||
		bs->ltgtype == LTG_GETITEM ) {
		return;
	}
	if ( BotSetLastOrderedTask( bs ) ) {
		return;
	}
	if ( bs->owndecision_time > FloatTime() ) {
		return;
	}
	if ( bs->ctfroam_time > FloatTime() ) {
		return;
	}
	if ( BotAggression( bs ) < 50 ) {
		return;
	}
	bs->teammessage_time = FloatTime() + 2 * random();

	bs->ltgtype = 0;
	bs->ctfroam_time = FloatTime() + CTF_ROAM_TIME;
	BotSetTeamStatus( bs );
	bs->owndecision_time = FloatTime() + 5;
#endif
}
Пример #18
0
/*
============
AICast_GetAvoid
============
*/
qboolean AICast_GetAvoid( cast_state_t *cs, bot_goal_t *goal, vec3_t outpos, qboolean reverse, int blockEnt ) {
	float yaw, oldyaw, distmoved, bestmoved, bestyaw;
	vec3_t bestpos;
	aicast_predictmove_t castmove;
	usercmd_t ucmd;
	qboolean enemyVisible;
	float angleDiff;
	// TTimo might be used uninitialized
	int starttraveltime = 0;
	int besttraveltime, traveltime;
	int invert;
	float inc;
	qboolean averting = qfalse;
	float maxYaw, simTime;
	static int lastTime;

	VectorCopy( vec3_origin, bestpos );

	//
	// if we are in the air, no chance of avoiding
	if ( cs->bs->cur_ps.groundEntityNum == ENTITYNUM_NONE && g_entities[cs->entityNum].waterlevel <= 1 ) {
		return qfalse;
	}
	//
	if ( cs->lastAvoid > level.time - rand() % 500 ) {
		return qfalse;
	}
	cs->lastAvoid = level.time + 50 + rand() % 500;
	//
	if ( lastTime == level.time ) {
		return qfalse;
	}
	lastTime = level.time;

	// if they have an enemy, and can currently see them, don't move out of their view
	enemyVisible =  ( cs->bs->enemy >= 0 ) &&
				   ( AICast_CheckAttack( cs, cs->bs->enemy, qfalse ) );
	//
	// look for a good direction to move out of the way
	bestmoved = 0;
	bestyaw = 360;
	besttraveltime = 9999999;
	if ( goal ) {
		starttraveltime = trap_AAS_AreaTravelTimeToGoalArea( cs->bs->areanum, cs->bs->origin, goal->areanum, cs->travelflags );
	}
	memcpy( &ucmd, &cs->bs->lastucmd, sizeof( usercmd_t ) );
	ucmd.forwardmove = 127;
	ucmd.rightmove = 0;
	ucmd.upmove = 0;
	if ( cs->dangerEntity >= 0 && cs->dangerEntityValidTime >= level.time ) {
		averting = qtrue;
	} else if ( !goal ) {
		averting = qtrue;   // not heading for a goal, so we must be getting out of someone's way
	}
	//
	maxYaw = 0;
	simTime = 1.2;
	//
	if ( averting ) {
		// avoiding danger, go anywhere!
		angleDiff = 300;
		inc = 60;
		invert = 1;
	} else {
		if ( level.time % 1000 < 500 ) {
			invert = 1;
		} else {
			invert = -1;
		}
		angleDiff = 140;
		inc = 35;
	}
	if ( blockEnt > aicast_maxclients ) {
		maxYaw = angleDiff;
		simTime = 0.5;
	}
	//
	for ( yaw = -angleDiff * invert; yaw*invert <= maxYaw; yaw += inc * invert ) {
		if ( !averting && !yaw ) {
			continue;
		}
		oldyaw = cs->bs->cur_ps.viewangles[YAW];
		cs->bs->cur_ps.viewangles[YAW] += yaw + reverse * 180;
		//
		ucmd.angles[YAW] = ANGLE2SHORT( AngleMod( cs->bs->cur_ps.viewangles[YAW] ) );
		//
		AICast_PredictMovement( cs, 5, 0.4, &castmove, &ucmd, -1 );
		// if we have a danger entity, try and get away from it at all costs
		if ( cs->dangerEntity >= 0 && cs->dangerEntityValidTime >= level.time ) {
			distmoved = Distance( castmove.endpos, cs->dangerEntityPos );
		} else if ( goal ) {
			//distmoved = 99999 - trap_AAS_AreaTravelTimeToGoalArea( BotPointAreaNum(castmove.endpos), castmove.endpos, goal->areanum, cs->travelflags );
			distmoved = 99999 - Distance( castmove.endpos, goal->origin );
		} else {
			distmoved = Distance( castmove.endpos, cs->bs->cur_ps.origin );
		}
		if (    ( distmoved > bestmoved )
				//&&	((cs->bs->origin[2] - castmove.endpos[2]) < 64)	// allow up, but not down (falling)
				&&  ( castmove.groundEntityNum != ENTITYNUM_NONE ) ) {
			// they all passed, check any other stuff
			if ( !enemyVisible || AICast_CheckAttackAtPos( cs->entityNum, cs->bs->enemy, castmove.endpos, qfalse, qfalse ) ) {
				if ( !goal || ( traveltime = trap_AAS_AreaTravelTimeToGoalArea( BotPointAreaNum( castmove.endpos ), castmove.endpos, goal->areanum, cs->travelflags ) ) < ( starttraveltime + 200 ) ) {
					bestyaw = yaw;
					bestmoved = distmoved;
					besttraveltime = traveltime;
					VectorCopy( castmove.endpos, bestpos );
				}
			}
		}
		//
		cs->bs->cur_ps.viewangles[YAW] = oldyaw;
	}
	//
	if ( bestmoved > 0 ) {
		VectorCopy( bestpos, outpos );
		return qtrue;
	} else {
		return qfalse;
	}

//G_Printf("GetAvoid: %i ms\n", -pretime + Sys_MilliSeconds() );
}
Пример #19
0
/*
==============
BotAI
==============
*/
int BotAI(int playernum, float thinktime) {
	bot_state_t *bs;
	char buf[1024], *args;
	int j;

	EA_ResetInput(playernum);
	//
	bs = botstates[playernum];
	if (!bs || !bs->inuse) {
		BotAI_Print(PRT_FATAL, "BotAI: player %d is not setup\n", playernum);
		return qfalse;
	}

	//retrieve the current player state
	if (!BotAI_GetPlayerState( playernum, &bs->cur_ps )) {
		BotAI_Print(PRT_FATAL, "BotAI: failed to get player state for player %d\n", playernum);
		return qfalse;
	}

	//retrieve any waiting server commands
	while( trap_BotGetServerCommand(playernum, buf, sizeof(buf)) ) {
		//have buf point to the command and args to the command arguments
		args = strchr( buf, ' ');
		if (!args) continue;
		*args++ = '\0';

		//remove color espace sequences from the arguments
		RemoveColorEscapeSequences( args );

		if (!Q_stricmp(buf, "cp "))
			{ /*CenterPrintf*/ }
		else if (!Q_stricmp(buf, "cs"))
			{ /*ConfigStringModified*/ }
		else if (!Q_stricmp(buf, "print")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_NORMAL, args);
		}
		else if (!Q_stricmp(buf, "chat") || !Q_stricmp(buf, "tell")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
		else if (!Q_stricmp(buf, "tchat")) {
			//remove first and last quote from the chat message
			memmove(args, args+1, strlen(args));
			args[strlen(args)-1] = '\0';
			BotQueueConsoleMessage(bs->cs, CMS_CHAT, args);
		}
#ifdef MISSIONPACK
		else if (!Q_stricmp(buf, "vchat")) {
			BotVoiceChatCommand(bs, SAY_ALL, args);
		}
		else if (!Q_stricmp(buf, "vtchat")) {
			BotVoiceChatCommand(bs, SAY_TEAM, args);
		}
		else if (!Q_stricmp(buf, "vtell")) {
			BotVoiceChatCommand(bs, SAY_TELL, args);
		}
#endif
		else if (!Q_stricmp(buf, "scores"))
			{ /*FIXME: parse scores?*/ }
		else if (!Q_stricmp(buf, "clientLevelShot"))
			{ /*ignore*/ }
	}
	//add the delta angles to the bot's current view angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] + SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//increase the local time of the bot
	bs->ltime += thinktime;
	//
	bs->thinktime = thinktime;
	//origin of the bot
	VectorCopy(bs->cur_ps.origin, bs->origin);
	//eye coordinates of the bot
	VectorCopy(bs->cur_ps.origin, bs->eye);
	bs->eye[2] += bs->cur_ps.viewheight;
	//get the area the bot is in
	bs->areanum = BotPointAreaNum(bs->origin);
	//the real AI
	BotDeathmatchAI(bs, thinktime);
	//set the weapon selection every AI frame
	EA_SelectWeapon(bs->playernum, bs->weaponnum);
	//subtract the delta angles
	for (j = 0; j < 3; j++) {
		bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
	}
	//everything was ok
	return qtrue;
}
Пример #20
0
// cyr_drop{
void BotMatch_DropCart(bot_state_t *bs, bot_match_t *match) {
	int client, areanum;
	char netname[MAX_MESSAGE_SIZE];
	aas_entityinfo_t entinfo;


	if (!TeamPlayIsOn()) return;
	//if not addressed to this bot
	if (!BotAddressedToBot(bs, match)) return;

	//get the netname
	trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	client = ClientFromName(netname);
	
	//if the bot doesn't know who to help (FindClientByName returned -1)
	if (client < 0) {
		BotAI_BotInitialChat(bs, "whois", netname, NULL);
		client = ClientFromName(netname);
		trap_BotEnterChat(bs->cs, client, CHAT_TELL);
		return;
	}
	//don't help or accompany yourself
	if (client == bs->client) {
		return;
	}
	//
	bs->teamgoal.entitynum = -1;
	BotEntityInfo(client, &entinfo);
	//if info is valid (in PVS)
	if (entinfo.valid) {
		areanum = BotPointAreaNum(entinfo.origin);
		if (areanum) {// && trap_AAS_AreaReachability(areanum)) {
			bs->teamgoal.entitynum = client;
			bs->teamgoal.areanum = areanum;
			VectorCopy(entinfo.origin, bs->teamgoal.origin);
			VectorSet(bs->teamgoal.mins, -8, -8, -8);
			VectorSet(bs->teamgoal.maxs, 8, 8, 8);
		}
	}

	if (bs->teamgoal.entitynum < 0) {
		BotAI_BotInitialChat(bs, "whereareyou", netname, NULL);
		client = ClientFromName(netname);
		trap_BotEnterChat(bs->cs, client, CHAT_TEAM);
		return;
	}
	//the team mate
	bs->teammate = client;
	//
	trap_BotMatchVariable(match, NETNAME, netname, sizeof(netname));
	//
	client = ClientFromName(netname);
	//the team mate who ordered
	bs->decisionmaker = client;
	// bs->ordered = qtrue;
	//bs->order_time = FloatTime();
	//last time the team mate was assumed visible
	bs->teammatevisible_time = FloatTime();
	//set the time to send a message to the team mates
	bs->teammessage_time = FloatTime() + 1 * random();
	//set the ltg type
	bs->ltgtype = LTG_GIVECART;
	//G_Printf("^4giving cart! \n");	// cyr 20055
	bs->teamgoal_time = FloatTime() + SYC_CART_EXCHANGE_TIME;
}