Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ai_vcmd.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 //
00023 
00024 /*****************************************************************************
00025  * name:        ai_vcmd.c
00026  *
00027  * desc:        Quake3 bot AI
00028  *
00029  * $Archive: /MissionPack/code/game/ai_vcmd.c $
00030  *
00031  *****************************************************************************/
00032 
00033 #include "g_local.h"
00034 #include "botlib.h"
00035 #include "be_aas.h"
00036 #include "be_ea.h"
00037 #include "be_ai_char.h"
00038 #include "be_ai_chat.h"
00039 #include "be_ai_gen.h"
00040 #include "be_ai_goal.h"
00041 #include "be_ai_move.h"
00042 #include "be_ai_weap.h"
00043 //
00044 #include "ai_main.h"
00045 #include "ai_dmq3.h"
00046 #include "ai_chat.h"
00047 #include "ai_cmd.h"
00048 #include "ai_dmnet.h"
00049 #include "ai_team.h"
00050 #include "ai_vcmd.h"
00051 //
00052 #include "chars.h"              //characteristics
00053 #include "inv.h"                //indexes into the inventory
00054 #include "syn.h"                //synonyms
00055 #include "match.h"              //string matching types and vars
00056 
00057 // for the voice chats
00058 #include "../../ui/menudef.h"
00059 
00060 
00061 typedef struct voiceCommand_s
00062 {
00063     char *cmd;
00064     void (*func)(bot_state_t *bs, int client, int mode);
00065 } voiceCommand_t;
00066 
00067 /*
00068 ==================
00069 BotVoiceChat_GetFlag
00070 ==================
00071 */
00072 void BotVoiceChat_GetFlag(bot_state_t *bs, int client, int mode) {
00073     //
00074     if (gametype == GT_CTF) {
00075         if (!ctf_redflag.areanum || !ctf_blueflag.areanum)
00076             return;
00077     }
00078 #ifdef MISSIONPACK
00079     else if (gametype == GT_1FCTF) {
00080         if (!ctf_neutralflag.areanum || !ctf_redflag.areanum || !ctf_blueflag.areanum)
00081             return;
00082     }
00083 #endif
00084     else {
00085         return;
00086     }
00087     //
00088     bs->decisionmaker = client;
00089     bs->ordered = qtrue;
00090     bs->order_time = FloatTime();
00091     //set the time to send a message to the team mates
00092     bs->teammessage_time = FloatTime() + 2 * random();
00093     //set the ltg type
00094     bs->ltgtype = LTG_GETFLAG;
00095     //set the team goal time
00096     bs->teamgoal_time = FloatTime() + CTF_GETFLAG_TIME;
00097     // get an alternate route in ctf
00098     if (gametype == GT_CTF) {
00099         //get an alternative route goal towards the enemy base
00100         BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00101     }
00102     //
00103     BotSetTeamStatus(bs);
00104     // remember last ordered task
00105     BotRememberLastOrderedTask(bs);
00106 #ifdef DEBUG
00107     BotPrintTeamGoal(bs);
00108 #endif //DEBUG
00109 }
00110 
00111 /*
00112 ==================
00113 BotVoiceChat_Offense
00114 ==================
00115 */
00116 void BotVoiceChat_Offense(bot_state_t *bs, int client, int mode) {
00117     if ( gametype == GT_CTF
00118 #ifdef MISSIONPACK
00119         || gametype == GT_1FCTF
00120 #endif
00121         ) {
00122         BotVoiceChat_GetFlag(bs, client, mode);
00123         return;
00124     }
00125 #ifdef MISSIONPACK
00126     if (gametype == GT_HARVESTER) {
00127         //
00128         bs->decisionmaker = client;
00129         bs->ordered = qtrue;
00130         bs->order_time = FloatTime();
00131         //set the time to send a message to the team mates
00132         bs->teammessage_time = FloatTime() + 2 * random();
00133         //set the ltg type
00134         bs->ltgtype = LTG_HARVEST;
00135         //set the team goal time
00136         bs->teamgoal_time = FloatTime() + TEAM_HARVEST_TIME;
00137         bs->harvestaway_time = 0;
00138         //
00139         BotSetTeamStatus(bs);
00140         // remember last ordered task
00141         BotRememberLastOrderedTask(bs);
00142     }
00143     else
00144 #endif
00145     {
00146         //
00147         bs->decisionmaker = client;
00148         bs->ordered = qtrue;
00149         bs->order_time = FloatTime();
00150         //set the time to send a message to the team mates
00151         bs->teammessage_time = FloatTime() + 2 * random();
00152         //set the ltg type
00153         bs->ltgtype = LTG_ATTACKENEMYBASE;
00154         //set the team goal time
00155         bs->teamgoal_time = FloatTime() + TEAM_ATTACKENEMYBASE_TIME;
00156         bs->attackaway_time = 0;
00157         //
00158         BotSetTeamStatus(bs);
00159         // remember last ordered task
00160         BotRememberLastOrderedTask(bs);
00161     }
00162 #ifdef DEBUG
00163     BotPrintTeamGoal(bs);
00164 #endif //DEBUG
00165 }
00166 
00167 /*
00168 ==================
00169 BotVoiceChat_Defend
00170 ==================
00171 */
00172 void BotVoiceChat_Defend(bot_state_t *bs, int client, int mode) {
00173 #ifdef MISSIONPACK
00174     if ( gametype == GT_OBELISK || gametype == GT_HARVESTER) {
00175         //
00176         switch(BotTeam(bs)) {
00177             case TEAM_RED: memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t)); break;
00178             case TEAM_BLUE: memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t)); break;
00179             default: return;
00180         }
00181     }
00182     else
00183 #endif
00184         if (gametype == GT_CTF
00185 #ifdef MISSIONPACK
00186             || gametype == GT_1FCTF
00187 #endif
00188             ) {
00189         //
00190         switch(BotTeam(bs)) {
00191             case TEAM_RED: memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t)); break;
00192             case TEAM_BLUE: memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t)); break;
00193             default: return;
00194         }
00195     }
00196     else {
00197         return;
00198     }
00199     //
00200     bs->decisionmaker = client;
00201     bs->ordered = qtrue;
00202     bs->order_time = FloatTime();
00203     //set the time to send a message to the team mates
00204     bs->teammessage_time = FloatTime() + 2 * random();
00205     //set the ltg type
00206     bs->ltgtype = LTG_DEFENDKEYAREA;
00207     //get the team goal time
00208     bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
00209     //away from defending
00210     bs->defendaway_time = 0;
00211     //
00212     BotSetTeamStatus(bs);
00213     // remember last ordered task
00214     BotRememberLastOrderedTask(bs);
00215 #ifdef DEBUG
00216     BotPrintTeamGoal(bs);
00217 #endif //DEBUG
00218 }
00219 
00220 /*
00221 ==================
00222 BotVoiceChat_DefendFlag
00223 ==================
00224 */
00225 void BotVoiceChat_DefendFlag(bot_state_t *bs, int client, int mode) {
00226     BotVoiceChat_Defend(bs, client, mode);
00227 }
00228 
00229 /*
00230 ==================
00231 BotVoiceChat_Patrol
00232 ==================
00233 */
00234 void BotVoiceChat_Patrol(bot_state_t *bs, int client, int mode) {
00235     //
00236     bs->decisionmaker = client;
00237     //
00238     bs->ltgtype = 0;
00239     bs->lead_time = 0;
00240     bs->lastgoal_ltgtype = 0;
00241     //
00242     BotAI_BotInitialChat(bs, "dismissed", NULL);
00243     trap_BotEnterChat(bs->cs, client, CHAT_TELL);
00244     BotVoiceChatOnly(bs, -1, VOICECHAT_ONPATROL);
00245     //
00246     BotSetTeamStatus(bs);
00247 #ifdef DEBUG
00248     BotPrintTeamGoal(bs);
00249 #endif //DEBUG
00250 }
00251 
00252 /*
00253 ==================
00254 BotVoiceChat_Camp
00255 ==================
00256 */
00257 void BotVoiceChat_Camp(bot_state_t *bs, int client, int mode) {
00258     int areanum;
00259     aas_entityinfo_t entinfo;
00260     char netname[MAX_NETNAME];
00261 
00262     //
00263     bs->teamgoal.entitynum = -1;
00264     BotEntityInfo(client, &entinfo);
00265     //if info is valid (in PVS)
00266     if (entinfo.valid) {
00267         areanum = BotPointAreaNum(entinfo.origin);
00268         if (areanum) { // && trap_AAS_AreaReachability(areanum)) {
00269             //NOTE: just assume the bot knows where the person is
00270             //if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, client)) {
00271                 bs->teamgoal.entitynum = client;
00272                 bs->teamgoal.areanum = areanum;
00273                 VectorCopy(entinfo.origin, bs->teamgoal.origin);
00274                 VectorSet(bs->teamgoal.mins, -8, -8, -8);
00275                 VectorSet(bs->teamgoal.maxs, 8, 8, 8);
00276             //}
00277         }
00278     }
00279     //if the other is not visible
00280     if (bs->teamgoal.entitynum < 0) {
00281         BotAI_BotInitialChat(bs, "whereareyou", EasyClientName(client, netname, sizeof(netname)), NULL);
00282         trap_BotEnterChat(bs->cs, client, CHAT_TELL);
00283         return;
00284     }
00285     //
00286     bs->decisionmaker = client;
00287     bs->ordered = qtrue;
00288     bs->order_time = FloatTime();
00289     //set the time to send a message to the team mates
00290     bs->teammessage_time = FloatTime() + 2 * random();
00291     //set the ltg type
00292     bs->ltgtype = LTG_CAMPORDER;
00293     //get the team goal time
00294     bs->teamgoal_time = FloatTime() + TEAM_CAMP_TIME;
00295     //the teammate that requested the camping
00296     bs->teammate = client;
00297     //not arrived yet
00298     bs->arrive_time = 0;
00299     //
00300     BotSetTeamStatus(bs);
00301     // remember last ordered task
00302     BotRememberLastOrderedTask(bs);
00303 #ifdef DEBUG
00304     BotPrintTeamGoal(bs);
00305 #endif //DEBUG
00306 }
00307 
00308 /*
00309 ==================
00310 BotVoiceChat_FollowMe
00311 ==================
00312 */
00313 void BotVoiceChat_FollowMe(bot_state_t *bs, int client, int mode) {
00314     int areanum;
00315     aas_entityinfo_t entinfo;
00316     char netname[MAX_NETNAME];
00317 
00318     bs->teamgoal.entitynum = -1;
00319     BotEntityInfo(client, &entinfo);
00320     //if info is valid (in PVS)
00321     if (entinfo.valid) {
00322         areanum = BotPointAreaNum(entinfo.origin);
00323         if (areanum) { // && trap_AAS_AreaReachability(areanum)) {
00324             bs->teamgoal.entitynum = client;
00325             bs->teamgoal.areanum = areanum;
00326             VectorCopy(entinfo.origin, bs->teamgoal.origin);
00327             VectorSet(bs->teamgoal.mins, -8, -8, -8);
00328             VectorSet(bs->teamgoal.maxs, 8, 8, 8);
00329         }
00330     }
00331     //if the other is not visible
00332     if (bs->teamgoal.entitynum < 0) {
00333         BotAI_BotInitialChat(bs, "whereareyou", EasyClientName(client, netname, sizeof(netname)), NULL);
00334         trap_BotEnterChat(bs->cs, client, CHAT_TELL);
00335         return;
00336     }
00337     //
00338     bs->decisionmaker = client;
00339     bs->ordered = qtrue;
00340     bs->order_time = FloatTime();
00341     //the team mate
00342     bs->teammate = client;
00343     //last time the team mate was assumed visible
00344     bs->teammatevisible_time = FloatTime();
00345     //set the time to send a message to the team mates
00346     bs->teammessage_time = FloatTime() + 2 * random();
00347     //get the team goal time
00348     bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
00349     //set the ltg type
00350     bs->ltgtype = LTG_TEAMACCOMPANY;
00351     bs->formation_dist = 3.5 * 32;      //3.5 meter
00352     bs->arrive_time = 0;
00353     //
00354     BotSetTeamStatus(bs);
00355     // remember last ordered task
00356     BotRememberLastOrderedTask(bs);
00357 #ifdef DEBUG
00358     BotPrintTeamGoal(bs);
00359 #endif //DEBUG
00360 }
00361 
00362 /*
00363 ==================
00364 BotVoiceChat_FollowFlagCarrier
00365 ==================
00366 */
00367 void BotVoiceChat_FollowFlagCarrier(bot_state_t *bs, int client, int mode) {
00368     int carrier;
00369 
00370     carrier = BotTeamFlagCarrier(bs);
00371     if (carrier >= 0)
00372         BotVoiceChat_FollowMe(bs, carrier, mode);
00373 #ifdef DEBUG
00374     BotPrintTeamGoal(bs);
00375 #endif //DEBUG
00376 }
00377 
00378 /*
00379 ==================
00380 BotVoiceChat_ReturnFlag
00381 ==================
00382 */
00383 void BotVoiceChat_ReturnFlag(bot_state_t *bs, int client, int mode) {
00384     //if not in CTF mode
00385     if (
00386         gametype != GT_CTF
00387 #ifdef MISSIONPACK
00388         && gametype != GT_1FCTF
00389 #endif
00390         ) {
00391         return;
00392     }
00393     //
00394     bs->decisionmaker = client;
00395     bs->ordered = qtrue;
00396     bs->order_time = FloatTime();
00397     //set the time to send a message to the team mates
00398     bs->teammessage_time = FloatTime() + 2 * random();
00399     //set the ltg type
00400     bs->ltgtype = LTG_RETURNFLAG;
00401     //set the team goal time
00402     bs->teamgoal_time = FloatTime() + CTF_RETURNFLAG_TIME;
00403     bs->rushbaseaway_time = 0;
00404     BotSetTeamStatus(bs);
00405 #ifdef DEBUG
00406     BotPrintTeamGoal(bs);
00407 #endif //DEBUG
00408 }
00409 
00410 /*
00411 ==================
00412 BotVoiceChat_StartLeader
00413 ==================
00414 */
00415 void BotVoiceChat_StartLeader(bot_state_t *bs, int client, int mode) {
00416     ClientName(client, bs->teamleader, sizeof(bs->teamleader));
00417 }
00418 
00419 /*
00420 ==================
00421 BotVoiceChat_StopLeader
00422 ==================
00423 */
00424 void BotVoiceChat_StopLeader(bot_state_t *bs, int client, int mode) {
00425     char netname[MAX_MESSAGE_SIZE];
00426 
00427     if (!Q_stricmp(bs->teamleader, ClientName(client, netname, sizeof(netname)))) {
00428         bs->teamleader[0] = '\0';
00429         notleader[client] = qtrue;
00430     }
00431 }
00432 
00433 /*
00434 ==================
00435 BotVoiceChat_WhoIsLeader
00436 ==================
00437 */
00438 void BotVoiceChat_WhoIsLeader(bot_state_t *bs, int client, int mode) {
00439     char netname[MAX_MESSAGE_SIZE];
00440 
00441     if (!TeamPlayIsOn()) return;
00442 
00443     ClientName(bs->client, netname, sizeof(netname));
00444     //if this bot IS the team leader
00445     if (!Q_stricmp(netname, bs->teamleader)) {
00446         BotAI_BotInitialChat(bs, "iamteamleader", NULL);
00447         trap_BotEnterChat(bs->cs, 0, CHAT_TEAM);
00448         BotVoiceChatOnly(bs, -1, VOICECHAT_STARTLEADER);
00449     }
00450 }
00451 
00452 /*
00453 ==================
00454 BotVoiceChat_WantOnDefense
00455 ==================
00456 */
00457 void BotVoiceChat_WantOnDefense(bot_state_t *bs, int client, int mode) {
00458     char netname[MAX_NETNAME];
00459     int preference;
00460 
00461     preference = BotGetTeamMateTaskPreference(bs, client);
00462     preference &= ~TEAMTP_ATTACKER;
00463     preference |= TEAMTP_DEFENDER;
00464     BotSetTeamMateTaskPreference(bs, client, preference);
00465     //
00466     EasyClientName(client, netname, sizeof(netname));
00467     BotAI_BotInitialChat(bs, "keepinmind", netname, NULL);
00468     trap_BotEnterChat(bs->cs, client, CHAT_TELL);
00469     BotVoiceChatOnly(bs, client, VOICECHAT_YES);
00470     trap_EA_Action(bs->client, ACTION_AFFIRMATIVE);
00471 }
00472 
00473 /*
00474 ==================
00475 BotVoiceChat_WantOnOffense
00476 ==================
00477 */
00478 void BotVoiceChat_WantOnOffense(bot_state_t *bs, int client, int mode) {
00479     char netname[MAX_NETNAME];
00480     int preference;
00481 
00482     preference = BotGetTeamMateTaskPreference(bs, client);
00483     preference &= ~TEAMTP_DEFENDER;
00484     preference |= TEAMTP_ATTACKER;
00485     BotSetTeamMateTaskPreference(bs, client, preference);
00486     //
00487     EasyClientName(client, netname, sizeof(netname));
00488     BotAI_BotInitialChat(bs, "keepinmind", netname, NULL);
00489     trap_BotEnterChat(bs->cs, client, CHAT_TELL);
00490     BotVoiceChatOnly(bs, client, VOICECHAT_YES);
00491     trap_EA_Action(bs->client, ACTION_AFFIRMATIVE);
00492 }
00493 
00494 void BotVoiceChat_Dummy(bot_state_t *bs, int client, int mode) {
00495 }
00496 
00497 voiceCommand_t voiceCommands[] = {
00498     {VOICECHAT_GETFLAG, BotVoiceChat_GetFlag},
00499     {VOICECHAT_OFFENSE, BotVoiceChat_Offense },
00500     {VOICECHAT_DEFEND, BotVoiceChat_Defend },
00501     {VOICECHAT_DEFENDFLAG, BotVoiceChat_DefendFlag },
00502     {VOICECHAT_PATROL, BotVoiceChat_Patrol },
00503     {VOICECHAT_CAMP, BotVoiceChat_Camp },
00504     {VOICECHAT_FOLLOWME, BotVoiceChat_FollowMe },
00505     {VOICECHAT_FOLLOWFLAGCARRIER, BotVoiceChat_FollowFlagCarrier },
00506     {VOICECHAT_RETURNFLAG, BotVoiceChat_ReturnFlag },
00507     {VOICECHAT_STARTLEADER, BotVoiceChat_StartLeader },
00508     {VOICECHAT_STOPLEADER, BotVoiceChat_StopLeader },
00509     {VOICECHAT_WHOISLEADER, BotVoiceChat_WhoIsLeader },
00510     {VOICECHAT_WANTONDEFENSE, BotVoiceChat_WantOnDefense },
00511     {VOICECHAT_WANTONOFFENSE, BotVoiceChat_WantOnOffense },
00512     {NULL, BotVoiceChat_Dummy}
00513 };
00514 
00515 int BotVoiceChatCommand(bot_state_t *bs, int mode, char *voiceChat) {
00516     int i, voiceOnly, clientNum, color;
00517     char *ptr, buf[MAX_MESSAGE_SIZE], *cmd;
00518 
00519     if (!TeamPlayIsOn()) {
00520         return qfalse;
00521     }
00522 
00523     if ( mode == SAY_ALL ) {
00524         return qfalse;  // don't do anything with voice chats to everyone
00525     }
00526 
00527     Q_strncpyz(buf, voiceChat, sizeof(buf));
00528     cmd = buf;
00529     for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
00530     while (*cmd && *cmd <= ' ') *cmd++ = '\0';
00531     voiceOnly = atoi(ptr);
00532     for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
00533     while (*cmd && *cmd <= ' ') *cmd++ = '\0';
00534     clientNum = atoi(ptr);
00535     for (ptr = cmd; *cmd && *cmd > ' '; cmd++);
00536     while (*cmd && *cmd <= ' ') *cmd++ = '\0';
00537     color = atoi(ptr);
00538 
00539     if (!BotSameTeam(bs, clientNum)) {
00540         return qfalse;
00541     }
00542 
00543     for (i = 0; voiceCommands[i].cmd; i++) {
00544         if (!Q_stricmp(cmd, voiceCommands[i].cmd)) {
00545             voiceCommands[i].func(bs, clientNum, mode);
00546             return qtrue;
00547         }
00548     }
00549     return qfalse;
00550 }

Generated on Thu Aug 25 12:37:30 2005 for Quake III Arena by  doxygen 1.3.9.1