/* ================== BotMatch_CTF ================== */ void BotMatch_CTF( bot_state_t *bs, bot_match_t *match ) { char flag[128], netname[MAX_NETNAME]; trap_BotMatchVariable( match, FLAG, flag, sizeof( flag ) ); if ( match->subtype & ST_GOTFLAG ) { if ( !Q_stricmp( flag, "red" ) ) { bs->redflagstatus = 1; if ( BotCTFTeam( bs ) == CTF_TEAM_BLUE ) { trap_BotMatchVariable( match, NETNAME, netname, sizeof( netname ) ); bs->flagcarrier = ClientFromName( netname ); } } else { bs->blueflagstatus = 1; if ( BotCTFTeam( bs ) == CTF_TEAM_RED ) { trap_BotMatchVariable( match, NETNAME, netname, sizeof( netname ) ); bs->flagcarrier = ClientFromName( netname ); } } bs->flagstatuschanged = 1; } else if ( match->subtype & ST_CAPTUREDFLAG ) { bs->redflagstatus = 0; bs->blueflagstatus = 0; bs->flagcarrier = 0; bs->flagstatuschanged = 1; } else if ( match->subtype & ST_RETURNEDFLAG ) { if ( !Q_stricmp( flag, "red" ) ) { bs->redflagstatus = 0; } else { bs->blueflagstatus = 0;} bs->flagstatuschanged = 1; } }
/* ================== BotAI_BotInitialChat ================== */ void QDECL BotAI_BotInitialChat( bot_state_t *bs, char *type, ... ) { int i, mcontext; va_list ap; char *p; char *vars[MAX_MATCHVARIABLES]; memset( vars, 0, sizeof( vars ) ); va_start( ap, type ); p = va_arg( ap, char * ); for ( i = 0; i < MAX_MATCHVARIABLES; i++ ) { if ( !p ) { break; } vars[i] = p; p = va_arg( ap, char * ); } va_end( ap ); mcontext = CONTEXT_NORMAL | CONTEXT_NEARBYITEM | CONTEXT_NAMES; if ( BotCTFTeam( bs ) == CTF_TEAM_RED ) { mcontext |= CONTEXT_CTFREDTEAM; } else { mcontext |= CONTEXT_CTFBLUETEAM;} trap_BotInitialChat( bs->cs, type, mcontext, vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7] ); }
/* ================== BotSortTeamMatesByBaseTravelTime ================== */ int BotSortTeamMatesByBaseTravelTime( bot_state_t *bs, int *teammates, int maxteammates ) { int i, j, k, numteammates, traveltime; char buf[MAX_INFO_STRING]; static int maxclients; int traveltimes[MAX_CLIENTS]; bot_goal_t *goal; if ( BotCTFTeam( bs ) == CTF_TEAM_RED ) { goal = &ctf_redflag; } else { goal = &ctf_blueflag;} if ( !maxclients ) { maxclients = trap_Cvar_VariableIntegerValue( "sv_maxclients" ); } numteammates = 0; for ( i = 0; i < maxclients && i < MAX_CLIENTS; i++ ) { trap_GetConfigstring( CS_PLAYERS + i, buf, sizeof( buf ) ); //if no config string or no name if ( !strlen( buf ) || !strlen( Info_ValueForKey( buf, "n" ) ) ) { continue; } //skip spectators if ( atoi( Info_ValueForKey( buf, "t" ) ) == TEAM_SPECTATOR ) { continue; } // if ( BotSameTeam( bs, i ) ) { // traveltime = BotClientTravelTimeToGoal( i, goal ); // for ( j = 0; j < numteammates; j++ ) { if ( traveltime < traveltimes[j] ) { for ( k = numteammates; k > j; k-- ) { traveltimes[k] = traveltimes[k - 1]; teammates[k] = teammates[k - 1]; } traveltimes[j] = traveltime; teammates[j] = i; break; } } if ( j >= numteammates ) { traveltimes[j] = traveltime; teammates[j] = i; } numteammates++; if ( numteammates >= maxteammates ) { break; } } } return numteammates; }
/* ================== BotTeamAI ================== */ void BotTeamAI(bot_state_t *bs) { int numteammates, flagstatus; char netname[MAX_NETNAME]; if(!bs) return; // if (gametype != GT_TEAM && gametype != GT_CTF) return; //make sure we've got a valid team leader if (!BotValidTeamLeader(bs)) { // if (!bs->askteamleader_time && !bs->becometeamleader_time) { if (bs->entergame_time + 10 > trap_AAS_Time()) { bs->askteamleader_time = trap_AAS_Time() + 5 + random() * 10; } else { bs->becometeamleader_time = trap_AAS_Time() + 5 + random() * 10; } } if (bs->askteamleader_time && bs->askteamleader_time < trap_AAS_Time()) { //if asked for a team leader and no repsonse BotAI_BotInitialChat(bs, "whoisteamleader", NULL); trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM); bs->askteamleader_time = 0; bs->becometeamleader_time = trap_AAS_Time() + 15 + random() * 10; } if (bs->becometeamleader_time && bs->becometeamleader_time < trap_AAS_Time()) { BotAI_BotInitialChat(bs, "iamteamleader", NULL); trap_BotEnterChat(bs->cs, bs->client, CHAT_TEAM); ClientName(bs->client, netname, sizeof(netname)); strncpy(bs->teamleader, netname, sizeof(bs->teamleader)); bs->teamleader[sizeof(bs->teamleader)-1] = '\0'; bs->becometeamleader_time = 0; } return; } bs->askteamleader_time = 0; bs->becometeamleader_time = 0; //return if this bot is NOT the team leader ClientName(bs->client, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) != 0) return; // //if the game starts OR a new player comes onto the team OR a player leaves the team // numteammates = BotNumTeamMates(bs); //give orders switch(gametype) { case GT_TEAM: { if (bs->numteammates != numteammates || bs->forceorders) { bs->teamgiveorders_time = trap_AAS_Time(); bs->numteammates = numteammates; bs->forceorders = qfalse; } //if it's time to give orders if (bs->teamgiveorders_time < trap_AAS_Time() - 5) { BotTeamOrders(bs); // bs->teamgiveorders_time = 0; } break; } case GT_CTF: { //if the number of team mates changed or the flag status changed //or someone wants to know what to do if (bs->numteammates != numteammates || bs->flagstatuschanged || bs->forceorders) { bs->teamgiveorders_time = trap_AAS_Time(); bs->numteammates = numteammates; bs->flagstatuschanged = qfalse; bs->forceorders = qfalse; } //if there were no flag captures the last 3 minutes if (bs->lastflagcapture_time < trap_AAS_Time() - 240) { bs->lastflagcapture_time = trap_AAS_Time(); //randomly change the CTF strategy if (random() < 0.4) { bs->ctfstrategy ^= CTFS_PASSIVE; bs->teamgiveorders_time = trap_AAS_Time(); } } //if it's time to give orders if (bs->teamgiveorders_time && bs->teamgiveorders_time < trap_AAS_Time() - 3) { // if (BotCTFTeam(bs) == CTF_TEAM_RED) flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus; else flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus; // switch(flagstatus) { case 0: BotCTFOrders_BothFlagsAtBase(bs); break; case 1: BotCTFOrders_EnemyFlagNotAtBase(bs); break; case 2: BotCTFOrders_FlagNotAtBase(bs); break; case 3: BotCTFOrders_BothFlagsNotAtBase(bs); break; } // bs->teamgiveorders_time = 0; } break; } } }