/* ================== BotVoiceChat_Defend ================== */ void BotVoiceChat_Defend(bot_state_t *bs, int client, int mode) { #ifdef MISSIONPACK if ( gametype == GT_OBELISK || gametype == GT_HARVESTER) { // switch(BotTeam(bs)) { case TEAM_RED: memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t)); break; case TEAM_BLUE: memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t)); break; default: return; } } else #endif if (gametype == GT_CTF #ifdef MISSIONPACK || gametype == GT_1FCTF #endif ) { // switch(BotTeam(bs)) { case TEAM_RED: memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t)); break; case TEAM_BLUE: memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t)); break; default: return; } } else { 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_DEFENDKEYAREA; //get the team goal time bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME; //away from defending bs->defendaway_time = 0; // BotSetTeamStatus(bs); // remember last ordered task BotRememberLastOrderedTask(bs); #ifdef DEBUG BotPrintTeamGoal(bs); #endif //DEBUG }
/* ================== BotMatch_CTF ================== */ void BotMatch_CTF(bot_state_t *bs, bot_match_t *match) { char flag[128], netname[MAX_NETNAME]; if (gametype == GT_CTF) { BotMatchVariable(match, FLAG, flag, sizeof(flag)); if (match->subtype & ST_GOTFLAG) { if (!Q_stricmp(flag, "red")) { bs->redflagstatus = 1; if (BotTeam(bs) == TEAM_BLUE) { BotMatchVariable(match, NETNAME, netname, sizeof(netname)); bs->flagcarrier = PlayerFromName(netname); } } else { bs->blueflagstatus = 1; if (BotTeam(bs) == TEAM_RED) { BotMatchVariable(match, NETNAME, netname, sizeof(netname)); bs->flagcarrier = PlayerFromName(netname); } } bs->flagstatuschanged = 1; bs->lastflagcapture_time = FloatTime(); } 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; } } #ifdef MISSIONPACK else if (gametype == GT_1FCTF) { if (match->subtype & ST_1FCTFGOTFLAG) { BotMatchVariable(match, NETNAME, netname, sizeof(netname)); bs->flagcarrier = PlayerFromName(netname); bs->lastflagcapture_time = FloatTime(); } } #endif }
/* ============= BotIsObserver ============= */ qboolean BotIsObserver(bot_state_t *bs) { char buf[MAX_INFO_STRING]; // Double checked for accuracy! if (bs->ps->pm_type == PM_SPECTATOR) return qtrue; return (BotTeam(bs) == TEAM_SPECTATOR); }
/* ============ BotEnemyBase ============ */ int BotEnemyBase(bot_state_t *bs) { // Some game types don't have bases defined if ( !(game_style & GS_BASE) ) return -1; switch (BotTeam(bs)) { case TEAM_RED: return BLUE_BASE; case TEAM_BLUE: return RED_BASE; default: return -1; } }
/* ================== 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 = NULL; if (gametype == GT_CTF || gametype == GT_1FCTF) { if (BotTeam(bs) == TEAM_RED) goal = &ctf_redflag; else goal = &ctf_blueflag; } if (!maxclients) maxclients = Cvar_VariableIntegerValue("sv_maxclients"); numteammates = 0; for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) { SV_SetConfigstring(CS_PLAYERS+i, 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]; } break; } } traveltimes[j] = traveltime; teammates[j] = i; numteammates++; if (numteammates >= maxteammates) break; } } return numteammates; }
/* ============ BotBothBases ============ */ void BotBothBases(bot_state_t *bs, int *us, int *them) { // Some game types don't have bases defined if ( !(game_style & GS_BASE) ) { *us = -1; *them = -1; } else if (BotTeam(bs) == TEAM_RED) { *us = RED_BASE; *them = BLUE_BASE; } else { *us = BLUE_BASE; *them = RED_BASE; } }
/* ================== Svcmd_BotTeamplayReport_f ================== */ void Svcmd_BotTeamplayReport_f(void) { int i; if (!bot_report.integer) { BotAI_Print(PRT_MESSAGE, "Must set bot_report 1 before using botreport command.\n"); return; } if (gametype >= GT_TEAM) { BotAI_Print(PRT_MESSAGE, S_COLOR_RED"RED\n"); for (i = 0; i < level.maxplayers; i++) { // if ( !botstates[i] || !botstates[i]->inuse ) continue; // if (BotTeam(botstates[i]) == TEAM_RED) { BotReportStatus(botstates[i]); } } BotAI_Print(PRT_MESSAGE, S_COLOR_BLUE"BLUE\n"); for (i = 0; i < level.maxplayers; i++) { // if ( !botstates[i] || !botstates[i]->inuse ) continue; // if (BotTeam(botstates[i]) == TEAM_BLUE) { BotReportStatus(botstates[i]); } } } else { for (i = 0; i < level.maxplayers; i++) { // if ( !botstates[i] || !botstates[i]->inuse ) continue; // BotReportStatus(botstates[i]); } } }
/* ================== BotCTFOrders ================== */ void BotCTFOrders(bot_state_t *bs) { int flagstatus; // if (BotTeam(bs) == 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; } }
/* ================== BotSetInfoConfigString ================== */ void BotSetInfoConfigString(bot_state_t *bs) { char goalname[MAX_MESSAGE_SIZE]; char netname[MAX_MESSAGE_SIZE]; char action[MAX_MESSAGE_SIZE]; char *leader, carrying[32], *cs; bot_goal_t goal; // PlayerName(bs->playernum, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L"; else leader = ""; strcpy(carrying, ""); if (gametype == GT_CTF) { if (BotCTFCarryingFlag(bs)) { strcpy(carrying, "F"); } } #ifdef MISSIONPACK else if (gametype == GT_1FCTF) { if (Bot1FCTFCarryingFlag(bs)) { strcpy(carrying, "F"); } } else if (gametype == GT_HARVESTER) { if (BotHarvesterCarryingCubes(bs)) { if (BotTeam(bs) == TEAM_RED) Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_REDCUBE]); else Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_BLUECUBE]); } } #endif switch(bs->ltgtype) { case LTG_TEAMHELP: { EasyPlayerName(bs->teammate, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "helping %s", goalname); break; } case LTG_TEAMACCOMPANY: { EasyPlayerName(bs->teammate, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "accompanying %s", goalname); break; } case LTG_DEFENDKEYAREA: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "defending %s", goalname); break; } case LTG_GETITEM: { BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "getting item %s", goalname); break; } case LTG_KILL: { PlayerName(bs->teamgoal.entitynum, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "killing %s", goalname); break; } case LTG_CAMP: case LTG_CAMPORDER: { Com_sprintf(action, sizeof(action), "camping"); break; } case LTG_PATROL: { Com_sprintf(action, sizeof(action), "patrolling"); break; } case LTG_GETFLAG: { Com_sprintf(action, sizeof(action), "capturing flag"); break; } case LTG_RUSHBASE: { Com_sprintf(action, sizeof(action), "rushing base"); break; } case LTG_RETURNFLAG: { Com_sprintf(action, sizeof(action), "returning flag"); break; } case LTG_ATTACKENEMYBASE: { Com_sprintf(action, sizeof(action), "attacking the enemy base"); break; } case LTG_HARVEST: { Com_sprintf(action, sizeof(action), "harvesting"); break; } default: { BotGetTopGoal(bs->gs, &goal); BotGoalName(goal.number, goalname, sizeof(goalname)); Com_sprintf(action, sizeof(action), "roaming %s", goalname); break; } } cs = va("l\\%s\\c\\%s\\a\\%s\\n\\%s", leader, carrying, action, bs->ainodename); trap_SetConfigstring (CS_BOTINFO + bs->playernum, cs); }
/* ================== BotReportStatus ================== */ void BotReportStatus(bot_state_t *bs) { char goalname[MAX_MESSAGE_SIZE]; char netname[MAX_MESSAGE_SIZE]; char *leader, flagstatus[32]; // ClientName(bs->client, netname, sizeof(netname)); if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L"; else leader = " "; strcpy(flagstatus, " "); if (gametype == GT_CTF) { if (BotCTFCarryingFlag(bs)) { if (BotTeam(bs) == TEAM_RED) strcpy(flagstatus, S_COLOR_RED"F "); else strcpy(flagstatus, S_COLOR_BLUE"F "); } } #if 1 //def MPACK else if (gametype == GT_1FCTF) { if (Bot1FCTFCarryingFlag(bs)) { if (BotTeam(bs) == TEAM_RED) strcpy(flagstatus, S_COLOR_RED"F "); else strcpy(flagstatus, S_COLOR_BLUE"F "); } } else if (gametype == GT_HARVESTER) { if (BotHarvesterCarryingCubes(bs)) { if (BotTeam(bs) == TEAM_RED) Com_sprintf(flagstatus, sizeof(flagstatus), S_COLOR_RED"%2d", bs->inventory[INVENTORY_REDCUBE]); else Com_sprintf(flagstatus, sizeof(flagstatus), S_COLOR_BLUE"%2d", bs->inventory[INVENTORY_BLUECUBE]); } } #endif switch(bs->ltgtype) { case LTG_TEAMHELP: { EasyClientName(bs->teammate, goalname, sizeof(goalname)); BotAI_Print(PRT_MESSAGE, "%-20s%s%s: helping %s\n", netname, leader, flagstatus, goalname); break; } case LTG_TEAMACCOMPANY: { EasyClientName(bs->teammate, goalname, sizeof(goalname)); BotAI_Print(PRT_MESSAGE, "%-20s%s%s: accompanying %s\n", netname, leader, flagstatus, goalname); break; } case LTG_DEFENDKEYAREA: { trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); BotAI_Print(PRT_MESSAGE, "%-20s%s%s: defending %s\n", netname, leader, flagstatus, goalname); break; } case LTG_GETITEM: { trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname)); BotAI_Print(PRT_MESSAGE, "%-20s%s%s: getting item %s\n", netname, leader, flagstatus, goalname); break; } case LTG_KILL: { ClientName(bs->teamgoal.entitynum, goalname, sizeof(goalname)); BotAI_Print(PRT_MESSAGE, "%-20s%s%s: killing %s\n", netname, leader, flagstatus, goalname); break; } case LTG_CAMP: case LTG_CAMPORDER: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: camping\n", netname, leader, flagstatus); break; } case LTG_PATROL: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: patrolling\n", netname, leader, flagstatus); break; } case LTG_GETFLAG: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: capturing flag\n", netname, leader, flagstatus); break; } case LTG_RUSHBASE: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: rushing base\n", netname, leader, flagstatus); break; } case LTG_RETURNFLAG: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: returning flag\n", netname, leader, flagstatus); break; } case LTG_ATTACKENEMYBASE: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: attacking the enemy base\n", netname, leader, flagstatus); break; } case LTG_HARVEST: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: harvesting\n", netname, leader, flagstatus); break; } default: { BotAI_Print(PRT_MESSAGE, "%-20s%s%s: roaming\n", netname, leader, flagstatus); break; } } }
void BotBalloonOrders(bot_state_t *bs) { int i, j; int index; int state; int capstate[MAX_BALLOONS]; int nummates; int mates[MAX_CLIENTS]; int numcap, numnmycap; float weight; // 0 - attack, 100 - defend //G_Printf("^1 orders for %d",BotTeam(bs)); // 20055 // get status of balloons numcap = numnmycap = 0; for(i=0; i < level.numBalloons; i++){ index = g_entities[ balloongoal[i].entitynum ].count; state = level.balloonState[index]; // status of goal i if( BotTeam(bs) == TEAM_RED && state == '1' || BotTeam(bs) == TEAM_BLUE && state == '2' ){ // own balloon capstate[i]=0; numcap++; } else if(BotTeam(bs) == TEAM_RED && state == '2' || BotTeam(bs) == TEAM_BLUE && state == '1'){ // nmy balloon capstate[i]=1; numnmycap++; } else{ // uncap balloon capstate[i]=2; } } //weight gets 0 if nmy controls and 1 if the bots team controls weight = ((numcap - numnmycap) + level.numBalloons ) / (2.0 * level.numBalloons) ; if(weight == 0) weight = 0.1f; if(weight == 1) weight = 0.9f; scorealert[BotTeam(bs)] = weight; //should also depend on scorediff and caplimit // istruct all, or only respawner if(! bs->orderclient){ nummates = BotGetTeammates( bs, mates, sizeof(mates) ); //G_Printf("teamorder\n"); // cyr 20055 } else{ char netname[MAX_NETNAME]; mates[0] = bs->orderclient -1; nummates = 1; EasyClientName(bs->orderclient -1, netname, sizeof(netname)); //G_Printf("individual order for %s \n", netname); // cyr 20055 bs->orderclient = 0; } for(i=0; i<nummates;i++){ // find best goal int bestgoal = 0; float bestdist, tt, wtt, multiplier; bestdist = 9999.9f; for(j=0; j<level.numBalloons;j++){ tt = BotClientTravelTimeToGoal( mates[i], &balloongoal[j] ); // prefer balloons based on current balloon-difference if(!capstate[j]){ // our balloon multiplier = weight; } else{ if(capstate[j] == 1) // nmy balloon multiplier = 1.0 - weight; else // uncap balloon multiplier = (1.0 - weight) / 2; } wtt = tt * multiplier * multiplier; G_Printf("%f .. %d -> %f -> %f , %d (%f)\n", weight, i, tt, wtt, capstate[j], multiplier); if(wtt < bestdist){ bestdist = wtt; bestgoal = j; } } BotInstructMate(bs, mates[i], bestgoal); } }