00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 "match.h"
00053
00054
00055 #include "../../ui/menudef.h"
00056
00057
00058 typedef struct bot_ctftaskpreference_s
00059 {
00060 char name[36];
00061 int preference;
00062 } bot_ctftaskpreference_t;
00063
00064 bot_ctftaskpreference_t ctftaskpreferences[MAX_CLIENTS];
00065
00066
00067
00068
00069
00070
00071
00072 int BotValidTeamLeader(bot_state_t *bs) {
00073 if (!strlen(bs->teamleader)) return qfalse;
00074 if (ClientFromName(bs->teamleader) == -1) return qfalse;
00075 return qtrue;
00076 }
00077
00078
00079
00080
00081
00082
00083 int BotNumTeamMates(bot_state_t *bs) {
00084 int i, numplayers;
00085 char buf[MAX_INFO_STRING];
00086 static int maxclients;
00087
00088 if (!maxclients)
00089 maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
00090
00091 numplayers = 0;
00092 for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
00093 trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
00094
00095 if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
00096
00097 if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
00098
00099 if (BotSameTeam(bs, i)) {
00100 numplayers++;
00101 }
00102 }
00103 return numplayers;
00104 }
00105
00106
00107
00108
00109
00110
00111 int BotClientTravelTimeToGoal(int client, bot_goal_t *goal) {
00112 playerState_t ps;
00113 int areanum;
00114
00115 BotAI_GetClientState(client, &ps);
00116 areanum = BotPointAreaNum(ps.origin);
00117 if (!areanum) return 1;
00118 return trap_AAS_AreaTravelTimeToGoalArea(areanum, ps.origin, goal->areanum, TFL_DEFAULT);
00119 }
00120
00121
00122
00123
00124
00125
00126 int BotSortTeamMatesByBaseTravelTime(bot_state_t *bs, int *teammates, int maxteammates) {
00127
00128 int i, j, k, numteammates, traveltime;
00129 char buf[MAX_INFO_STRING];
00130 static int maxclients;
00131 int traveltimes[MAX_CLIENTS];
00132 bot_goal_t *goal = NULL;
00133
00134 if (gametype == GT_CTF || gametype == GT_1FCTF) {
00135 if (BotTeam(bs) == TEAM_RED)
00136 goal = &ctf_redflag;
00137 else
00138 goal = &ctf_blueflag;
00139 }
00140 #ifdef MISSIONPACK
00141 else {
00142 if (BotTeam(bs) == TEAM_RED)
00143 goal = &redobelisk;
00144 else
00145 goal = &blueobelisk;
00146 }
00147 #endif
00148 if (!maxclients)
00149 maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
00150
00151 numteammates = 0;
00152 for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
00153 trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
00154
00155 if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
00156
00157 if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
00158
00159 if (BotSameTeam(bs, i)) {
00160
00161 traveltime = BotClientTravelTimeToGoal(i, goal);
00162
00163 for (j = 0; j < numteammates; j++) {
00164 if (traveltime < traveltimes[j]) {
00165 for (k = numteammates; k > j; k--) {
00166 traveltimes[k] = traveltimes[k-1];
00167 teammates[k] = teammates[k-1];
00168 }
00169 break;
00170 }
00171 }
00172 traveltimes[j] = traveltime;
00173 teammates[j] = i;
00174 numteammates++;
00175 if (numteammates >= maxteammates) break;
00176 }
00177 }
00178 return numteammates;
00179 }
00180
00181
00182
00183
00184
00185
00186 void BotSetTeamMateTaskPreference(bot_state_t *bs, int teammate, int preference) {
00187 char teammatename[MAX_NETNAME];
00188
00189 ctftaskpreferences[teammate].preference = preference;
00190 ClientName(teammate, teammatename, sizeof(teammatename));
00191 strcpy(ctftaskpreferences[teammate].name, teammatename);
00192 }
00193
00194
00195
00196
00197
00198
00199 int BotGetTeamMateTaskPreference(bot_state_t *bs, int teammate) {
00200 char teammatename[MAX_NETNAME];
00201
00202 if (!ctftaskpreferences[teammate].preference) return 0;
00203 ClientName(teammate, teammatename, sizeof(teammatename));
00204 if (Q_stricmp(teammatename, ctftaskpreferences[teammate].name)) return 0;
00205 return ctftaskpreferences[teammate].preference;
00206 }
00207
00208
00209
00210
00211
00212
00213 int BotSortTeamMatesByTaskPreference(bot_state_t *bs, int *teammates, int numteammates) {
00214 int defenders[MAX_CLIENTS], numdefenders;
00215 int attackers[MAX_CLIENTS], numattackers;
00216 int roamers[MAX_CLIENTS], numroamers;
00217 int i, preference;
00218
00219 numdefenders = numattackers = numroamers = 0;
00220 for (i = 0; i < numteammates; i++) {
00221 preference = BotGetTeamMateTaskPreference(bs, teammates[i]);
00222 if (preference & TEAMTP_DEFENDER) {
00223 defenders[numdefenders++] = teammates[i];
00224 }
00225 else if (preference & TEAMTP_ATTACKER) {
00226 attackers[numattackers++] = teammates[i];
00227 }
00228 else {
00229 roamers[numroamers++] = teammates[i];
00230 }
00231 }
00232 numteammates = 0;
00233
00234 memcpy(&teammates[numteammates], defenders, numdefenders * sizeof(int));
00235 numteammates += numdefenders;
00236
00237 memcpy(&teammates[numteammates], roamers, numroamers * sizeof(int));
00238 numteammates += numroamers;
00239
00240 memcpy(&teammates[numteammates], attackers, numattackers * sizeof(int));
00241 numteammates += numattackers;
00242
00243 return numteammates;
00244 }
00245
00246
00247
00248
00249
00250
00251 void BotSayTeamOrderAlways(bot_state_t *bs, int toclient) {
00252 char teamchat[MAX_MESSAGE_SIZE];
00253 char buf[MAX_MESSAGE_SIZE];
00254 char name[MAX_NETNAME];
00255
00256
00257 if (bs->client == toclient) {
00258
00259 trap_BotGetChatMessage(bs->cs, buf, sizeof(buf));
00260 ClientName(bs->client, name, sizeof(name));
00261 Com_sprintf(teamchat, sizeof(teamchat), EC"(%s"EC")"EC": %s", name, buf);
00262 trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, teamchat);
00263 }
00264 else {
00265 trap_BotEnterChat(bs->cs, toclient, CHAT_TELL);
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274 void BotSayTeamOrder(bot_state_t *bs, int toclient) {
00275 #ifdef MISSIONPACK
00276
00277 char buf[MAX_MESSAGE_SIZE];
00278
00279 trap_BotGetChatMessage(bs->cs, buf, sizeof(buf));
00280 #else
00281 BotSayTeamOrderAlways(bs, toclient);
00282 #endif
00283 }
00284
00285
00286
00287
00288
00289
00290 void BotVoiceChat(bot_state_t *bs, int toclient, char *voicechat) {
00291 #ifdef MISSIONPACK
00292 if (toclient == -1)
00293
00294 trap_EA_Command(bs->client, va("vsay_team %s", voicechat));
00295 else
00296
00297 trap_EA_Command(bs->client, va("vtell %d %s", toclient, voicechat));
00298 #endif
00299 }
00300
00301
00302
00303
00304
00305
00306 void BotVoiceChatOnly(bot_state_t *bs, int toclient, char *voicechat) {
00307 #ifdef MISSIONPACK
00308 if (toclient == -1)
00309
00310 trap_EA_Command(bs->client, va("vosay_team %s", voicechat));
00311 else
00312
00313 trap_EA_Command(bs->client, va("votell %d %s", toclient, voicechat));
00314 #endif
00315 }
00316
00317
00318
00319
00320
00321
00322 void BotSayVoiceTeamOrder(bot_state_t *bs, int toclient, char *voicechat) {
00323 #ifdef MISSIONPACK
00324 BotVoiceChat(bs, toclient, voicechat);
00325 #endif
00326 }
00327
00328
00329
00330
00331
00332
00333 void BotCTFOrders_BothFlagsNotAtBase(bot_state_t *bs) {
00334 int numteammates, defenders, attackers, i, other;
00335 int teammates[MAX_CLIENTS];
00336 char name[MAX_NETNAME], carriername[MAX_NETNAME];
00337
00338 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
00339 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
00340
00341 switch(bs->numteammates) {
00342 case 1: break;
00343 case 2:
00344 {
00345
00346 if (teammates[0] != bs->flagcarrier) other = teammates[0];
00347 else other = teammates[1];
00348 ClientName(other, name, sizeof(name));
00349 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00350 BotSayTeamOrder(bs, other);
00351 BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
00352 break;
00353 }
00354 case 3:
00355 {
00356
00357 if (teammates[0] != bs->flagcarrier) other = teammates[0];
00358 else other = teammates[1];
00359 ClientName(other, name, sizeof(name));
00360 if ( bs->flagcarrier != -1 ) {
00361 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
00362 if (bs->flagcarrier == bs->client) {
00363 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
00364 BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWME);
00365 }
00366 else {
00367 BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
00368 BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWFLAGCARRIER);
00369 }
00370 }
00371 else {
00372
00373 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00374 BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
00375 }
00376 BotSayTeamOrder(bs, other);
00377
00378 if (teammates[2] != bs->flagcarrier) other = teammates[2];
00379 else other = teammates[1];
00380 ClientName(other, name, sizeof(name));
00381 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00382 BotSayTeamOrder(bs, other);
00383 BotSayVoiceTeamOrder(bs, other, VOICECHAT_RETURNFLAG);
00384 break;
00385 }
00386 default:
00387 {
00388 defenders = (int) (float) numteammates * 0.4 + 0.5;
00389 if (defenders > 4) defenders = 4;
00390 attackers = (int) (float) numteammates * 0.5 + 0.5;
00391 if (attackers > 5) attackers = 5;
00392 if (bs->flagcarrier != -1) {
00393 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
00394 for (i = 0; i < defenders; i++) {
00395
00396 if (teammates[i] == bs->flagcarrier) {
00397 continue;
00398 }
00399
00400 ClientName(teammates[i], name, sizeof(name));
00401 if (bs->flagcarrier == bs->client) {
00402 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
00403 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_FOLLOWME);
00404 }
00405 else {
00406 BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
00407 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_FOLLOWFLAGCARRIER);
00408 }
00409 BotSayTeamOrder(bs, teammates[i]);
00410 }
00411 }
00412 else {
00413 for (i = 0; i < defenders; i++) {
00414
00415 if (teammates[i] == bs->flagcarrier) {
00416 continue;
00417 }
00418
00419 ClientName(teammates[i], name, sizeof(name));
00420 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00421 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_GETFLAG);
00422 BotSayTeamOrder(bs, teammates[i]);
00423 }
00424 }
00425 for (i = 0; i < attackers; i++) {
00426
00427 if (teammates[numteammates - i - 1] == bs->flagcarrier) {
00428 continue;
00429 }
00430
00431 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00432 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00433 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00434 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_RETURNFLAG);
00435 }
00436
00437 break;
00438 }
00439 }
00440 }
00441
00442
00443
00444
00445
00446
00447 void BotCTFOrders_FlagNotAtBase(bot_state_t *bs) {
00448 int numteammates, defenders, attackers, i;
00449 int teammates[MAX_CLIENTS];
00450 char name[MAX_NETNAME];
00451
00452 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
00453 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
00454
00455 if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
00456
00457 switch(bs->numteammates) {
00458 case 1: break;
00459 case 2:
00460 {
00461
00462 ClientName(teammates[0], name, sizeof(name));
00463 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00464 BotSayTeamOrder(bs, teammates[0]);
00465 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
00466
00467 ClientName(teammates[1], name, sizeof(name));
00468 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00469 BotSayTeamOrder(bs, teammates[1]);
00470 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00471 break;
00472 }
00473 case 3:
00474 {
00475
00476 ClientName(teammates[0], name, sizeof(name));
00477 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00478 BotSayTeamOrder(bs, teammates[0]);
00479 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00480
00481 ClientName(teammates[1], name, sizeof(name));
00482 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00483 BotSayTeamOrder(bs, teammates[1]);
00484 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00485
00486 ClientName(teammates[2], name, sizeof(name));
00487 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00488 BotSayTeamOrder(bs, teammates[2]);
00489 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
00490 break;
00491 }
00492 default:
00493 {
00494
00495 defenders = (int) (float) numteammates * 0.3 + 0.5;
00496 if (defenders > 3) defenders = 3;
00497 attackers = (int) (float) numteammates * 0.7 + 0.5;
00498 if (attackers > 6) attackers = 6;
00499 for (i = 0; i < defenders; i++) {
00500
00501 ClientName(teammates[i], name, sizeof(name));
00502 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00503 BotSayTeamOrder(bs, teammates[i]);
00504 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
00505 }
00506 for (i = 0; i < attackers; i++) {
00507
00508 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00509 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00510 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00511 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
00512 }
00513
00514 break;
00515 }
00516 }
00517 }
00518 else {
00519
00520 switch(bs->numteammates) {
00521 case 1: break;
00522 case 2:
00523 {
00524
00525 ClientName(teammates[0], name, sizeof(name));
00526 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00527 BotSayTeamOrder(bs, teammates[0]);
00528 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
00529
00530 ClientName(teammates[1], name, sizeof(name));
00531 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00532 BotSayTeamOrder(bs, teammates[1]);
00533 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00534 break;
00535 }
00536 case 3:
00537 {
00538
00539 ClientName(teammates[0], name, sizeof(name));
00540 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00541 BotSayTeamOrder(bs, teammates[0]);
00542 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
00543
00544 ClientName(teammates[1], name, sizeof(name));
00545 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00546 BotSayTeamOrder(bs, teammates[1]);
00547 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00548
00549 ClientName(teammates[2], name, sizeof(name));
00550 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00551 BotSayTeamOrder(bs, teammates[2]);
00552 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
00553 break;
00554 }
00555 default:
00556 {
00557
00558 defenders = (int) (float) numteammates * 0.2 + 0.5;
00559 if (defenders > 2) defenders = 2;
00560 attackers = (int) (float) numteammates * 0.7 + 0.5;
00561 if (attackers > 7) attackers = 7;
00562 for (i = 0; i < defenders; i++) {
00563
00564 ClientName(teammates[i], name, sizeof(name));
00565 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00566 BotSayTeamOrder(bs, teammates[i]);
00567 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
00568 }
00569 for (i = 0; i < attackers; i++) {
00570
00571 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00572 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00573 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00574 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
00575 }
00576
00577 break;
00578 }
00579 }
00580 }
00581 }
00582
00583
00584
00585
00586
00587
00588 void BotCTFOrders_EnemyFlagNotAtBase(bot_state_t *bs) {
00589 int numteammates, defenders, attackers, i, other;
00590 int teammates[MAX_CLIENTS];
00591 char name[MAX_NETNAME], carriername[MAX_NETNAME];
00592
00593 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
00594 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
00595
00596 switch(numteammates) {
00597 case 1: break;
00598 case 2:
00599 {
00600
00601 if (teammates[0] == bs->flagcarrier) other = teammates[1];
00602 else other = teammates[0];
00603 ClientName(other, name, sizeof(name));
00604 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00605 BotSayTeamOrder(bs, other);
00606 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
00607 break;
00608 }
00609 case 3:
00610 {
00611
00612 if (teammates[0] != bs->flagcarrier) other = teammates[0];
00613 else other = teammates[1];
00614 ClientName(other, name, sizeof(name));
00615 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00616 BotSayTeamOrder(bs, other);
00617 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
00618
00619 if (teammates[2] != bs->flagcarrier) other = teammates[2];
00620 else other = teammates[1];
00621 ClientName(other, name, sizeof(name));
00622 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00623 BotSayTeamOrder(bs, other);
00624 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
00625 break;
00626 }
00627 default:
00628 {
00629
00630 defenders = (int) (float) numteammates * 0.6 + 0.5;
00631 if (defenders > 6) defenders = 6;
00632
00633 attackers = (int) (float) numteammates * 0.3 + 0.5;
00634 if (attackers > 3) attackers = 3;
00635 for (i = 0; i < defenders; i++) {
00636
00637 if (teammates[i] == bs->flagcarrier) {
00638 continue;
00639 }
00640 ClientName(teammates[i], name, sizeof(name));
00641 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00642 BotSayTeamOrder(bs, teammates[i]);
00643 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
00644 }
00645
00646 if ( bs->flagcarrier != -1 ) {
00647 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
00648 for (i = 0; i < attackers; i++) {
00649
00650 if (teammates[numteammates - i - 1] == bs->flagcarrier) {
00651 continue;
00652 }
00653
00654 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00655 if (bs->flagcarrier == bs->client) {
00656 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
00657 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWME);
00658 }
00659 else {
00660 BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
00661 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWFLAGCARRIER);
00662 }
00663 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00664 }
00665 }
00666 else {
00667 for (i = 0; i < attackers; i++) {
00668
00669 if (teammates[numteammates - i - 1] == bs->flagcarrier) {
00670 continue;
00671 }
00672
00673 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00674 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00675 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
00676 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00677 }
00678 }
00679
00680 break;
00681 }
00682 }
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 void BotCTFOrders_BothFlagsAtBase(bot_state_t *bs) {
00692 int numteammates, defenders, attackers, i;
00693 int teammates[MAX_CLIENTS];
00694 char name[MAX_NETNAME];
00695
00696
00697 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
00698
00699 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
00700
00701 if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
00702
00703 switch(numteammates) {
00704 case 1: break;
00705 case 2:
00706 {
00707
00708 ClientName(teammates[0], name, sizeof(name));
00709 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00710 BotSayTeamOrder(bs, teammates[0]);
00711 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00712
00713 ClientName(teammates[1], name, sizeof(name));
00714 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00715 BotSayTeamOrder(bs, teammates[1]);
00716 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00717 break;
00718 }
00719 case 3:
00720 {
00721
00722 ClientName(teammates[0], name, sizeof(name));
00723 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00724 BotSayTeamOrder(bs, teammates[0]);
00725 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00726
00727 ClientName(teammates[1], name, sizeof(name));
00728 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00729 BotSayTeamOrder(bs, teammates[1]);
00730 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
00731
00732 ClientName(teammates[2], name, sizeof(name));
00733 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00734 BotSayTeamOrder(bs, teammates[2]);
00735 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
00736 break;
00737 }
00738 default:
00739 {
00740 defenders = (int) (float) numteammates * 0.5 + 0.5;
00741 if (defenders > 5) defenders = 5;
00742 attackers = (int) (float) numteammates * 0.4 + 0.5;
00743 if (attackers > 4) attackers = 4;
00744 for (i = 0; i < defenders; i++) {
00745
00746 ClientName(teammates[i], name, sizeof(name));
00747 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00748 BotSayTeamOrder(bs, teammates[i]);
00749 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
00750 }
00751 for (i = 0; i < attackers; i++) {
00752
00753 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00754 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00755 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00756 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
00757 }
00758
00759 break;
00760 }
00761 }
00762 }
00763 else {
00764
00765 switch(numteammates) {
00766 case 1: break;
00767 case 2:
00768 {
00769
00770 ClientName(teammates[0], name, sizeof(name));
00771 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00772 BotSayTeamOrder(bs, teammates[0]);
00773 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00774
00775 ClientName(teammates[1], name, sizeof(name));
00776 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00777 BotSayTeamOrder(bs, teammates[1]);
00778 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00779 break;
00780 }
00781 case 3:
00782 {
00783
00784 ClientName(teammates[0], name, sizeof(name));
00785 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00786 BotSayTeamOrder(bs, teammates[0]);
00787 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00788
00789 ClientName(teammates[1], name, sizeof(name));
00790 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00791 BotSayTeamOrder(bs, teammates[1]);
00792 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00793
00794 ClientName(teammates[2], name, sizeof(name));
00795 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00796 BotSayTeamOrder(bs, teammates[2]);
00797 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
00798 break;
00799 }
00800 default:
00801 {
00802 defenders = (int) (float) numteammates * 0.4 + 0.5;
00803 if (defenders > 4) defenders = 4;
00804 attackers = (int) (float) numteammates * 0.5 + 0.5;
00805 if (attackers > 5) attackers = 5;
00806 for (i = 0; i < defenders; i++) {
00807
00808 ClientName(teammates[i], name, sizeof(name));
00809 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00810 BotSayTeamOrder(bs, teammates[i]);
00811 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
00812 }
00813 for (i = 0; i < attackers; i++) {
00814
00815 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
00816 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00817 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
00818 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
00819 }
00820
00821 break;
00822 }
00823 }
00824 }
00825 }
00826
00827
00828
00829
00830
00831
00832 void BotCTFOrders(bot_state_t *bs) {
00833 int flagstatus;
00834
00835
00836 if (BotTeam(bs) == TEAM_RED) flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus;
00837 else flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus;
00838
00839 switch(flagstatus) {
00840 case 0: BotCTFOrders_BothFlagsAtBase(bs); break;
00841 case 1: BotCTFOrders_EnemyFlagNotAtBase(bs); break;
00842 case 2: BotCTFOrders_FlagNotAtBase(bs); break;
00843 case 3: BotCTFOrders_BothFlagsNotAtBase(bs); break;
00844 }
00845 }
00846
00847
00848
00849
00850
00851
00852
00853 void BotCreateGroup(bot_state_t *bs, int *teammates, int groupsize) {
00854 char name[MAX_NETNAME], leadername[MAX_NETNAME];
00855 int i;
00856
00857
00858 ClientName(teammates[0], leadername, sizeof(leadername));
00859 for (i = 1; i < groupsize; i++)
00860 {
00861 ClientName(teammates[i], name, sizeof(name));
00862 if (teammates[0] == bs->client) {
00863 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
00864 }
00865 else {
00866 BotAI_BotInitialChat(bs, "cmd_accompany", name, leadername, NULL);
00867 }
00868 BotSayTeamOrderAlways(bs, teammates[i]);
00869 }
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879 void BotTeamOrders(bot_state_t *bs) {
00880 int teammates[MAX_CLIENTS];
00881 int numteammates, i;
00882 char buf[MAX_INFO_STRING];
00883 static int maxclients;
00884
00885 if (!maxclients)
00886 maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
00887
00888 numteammates = 0;
00889 for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
00890 trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
00891
00892 if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
00893
00894 if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
00895
00896 if (BotSameTeam(bs, i)) {
00897 teammates[numteammates] = i;
00898 numteammates++;
00899 }
00900 }
00901
00902 switch(numteammates) {
00903 case 1: break;
00904 case 2:
00905 {
00906
00907 break;
00908 }
00909 case 3:
00910 {
00911
00912 BotCreateGroup(bs, teammates, 2);
00913 break;
00914 }
00915 case 4:
00916 {
00917 BotCreateGroup(bs, teammates, 2);
00918 BotCreateGroup(bs, &teammates[2], 2);
00919 break;
00920 }
00921 case 5:
00922 {
00923 BotCreateGroup(bs, teammates, 2);
00924 BotCreateGroup(bs, &teammates[2], 3);
00925 break;
00926 }
00927 default:
00928 {
00929 if (numteammates <= 10) {
00930 for (i = 0; i < numteammates / 2; i++) {
00931 BotCreateGroup(bs, &teammates[i*2], 2);
00932 }
00933 }
00934 break;
00935 }
00936 }
00937 }
00938
00939 #ifdef MISSIONPACK
00940
00941
00942
00943
00944
00945
00946
00947
00948 void Bot1FCTFOrders_FlagAtCenter(bot_state_t *bs) {
00949 int numteammates, defenders, attackers, i;
00950 int teammates[MAX_CLIENTS];
00951 char name[MAX_NETNAME];
00952
00953
00954 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
00955
00956 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
00957
00958 if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
00959
00960 switch(numteammates) {
00961 case 1: break;
00962 case 2:
00963 {
00964
00965 ClientName(teammates[0], name, sizeof(name));
00966 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00967 BotSayTeamOrder(bs, teammates[0]);
00968 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00969
00970 ClientName(teammates[1], name, sizeof(name));
00971 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00972 BotSayTeamOrder(bs, teammates[1]);
00973 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
00974 break;
00975 }
00976 case 3:
00977 {
00978
00979 ClientName(teammates[0], name, sizeof(name));
00980 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00981 BotSayTeamOrder(bs, teammates[0]);
00982 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00983
00984 ClientName(teammates[1], name, sizeof(name));
00985 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
00986 BotSayTeamOrder(bs, teammates[1]);
00987 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
00988
00989 ClientName(teammates[2], name, sizeof(name));
00990 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
00991 BotSayTeamOrder(bs, teammates[2]);
00992 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
00993 break;
00994 }
00995 default:
00996 {
00997
00998 defenders = (int) (float) numteammates * 0.5 + 0.5;
00999 if (defenders > 5) defenders = 5;
01000
01001 attackers = (int) (float) numteammates * 0.4 + 0.5;
01002 if (attackers > 4) attackers = 4;
01003 for (i = 0; i < defenders; i++) {
01004
01005 ClientName(teammates[i], name, sizeof(name));
01006 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01007 BotSayTeamOrder(bs, teammates[i]);
01008 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
01009 }
01010 for (i = 0; i < attackers; i++) {
01011
01012 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
01013 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01014 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
01015 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
01016 }
01017
01018 break;
01019 }
01020 }
01021 }
01022 else {
01023
01024 switch(numteammates) {
01025 case 1: break;
01026 case 2:
01027 {
01028
01029 ClientName(teammates[0], name, sizeof(name));
01030 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01031 BotSayTeamOrder(bs, teammates[0]);
01032 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
01033
01034 ClientName(teammates[1], name, sizeof(name));
01035 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01036 BotSayTeamOrder(bs, teammates[1]);
01037 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
01038 break;
01039 }
01040 case 3:
01041 {
01042
01043 ClientName(teammates[0], name, sizeof(name));
01044 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01045 BotSayTeamOrder(bs, teammates[0]);
01046 BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
01047
01048 ClientName(teammates[1], name, sizeof(name));
01049 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01050 BotSayTeamOrder(bs, teammates[1]);
01051 BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
01052
01053 ClientName(teammates[2], name, sizeof(name));
01054 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01055 BotSayTeamOrder(bs, teammates[2]);
01056 BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
01057 break;
01058 }
01059 default:
01060 {
01061
01062 defenders = (int) (float) numteammates * 0.3 + 0.5;
01063 if (defenders > 3) defenders = 3;
01064
01065 attackers = (int) (float) numteammates * 0.6 + 0.5;
01066 if (attackers > 6) attackers = 6;
01067 for (i = 0; i < defenders; i++) {
01068
01069 ClientName(teammates[i], name, sizeof(name));
01070 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01071 BotSayTeamOrder(bs, teammates[i]);
01072 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
01073 }
01074 for (i = 0; i < attackers; i++) {
01075
01076 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
01077 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01078 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
01079 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
01080 }
01081
01082 break;
01083 }
01084 }
01085 }
01086 }
01087
01088
01089
01090
01091
01092
01093
01094
01095 void Bot1FCTFOrders_TeamHasFlag(bot_state_t *bs) {
01096 int numteammates, defenders, attackers, i, other;
01097 int teammates[MAX_CLIENTS];
01098 char name[MAX_NETNAME], carriername[MAX_NETNAME];
01099
01100
01101 numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
01102
01103 BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
01104
01105 if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
01106
01107 switch(numteammates) {
01108 case 1: break;
01109 case 2:
01110 {
01111
01112 if (teammates[0] == bs->flagcarrier) other = teammates[1];
01113 else other = teammates[0];
01114 ClientName(other, name, sizeof(name));
01115 BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
01116 BotSayTeamOrder(bs, other);
01117 BotSayVoiceTeamOrder(bs, other, VOICECHAT_OFFENSE);
01118 break;
01119 }
01120 case 3:
01121 {
01122
01123 if (teammates[0] != bs->flagcarrier) other = teammates[0];
01124 else other = teammates[1];
01125 ClientName(other, name, sizeof(name));
01126 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01127 BotSayTeamOrder(bs, other);
01128 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
01129
01130 if (teammates[2] != bs->flagcarrier) other = teammates[2];
01131 else other = teammates[1];
01132 ClientName(other, name, sizeof(name));
01133 if ( bs->flagcarrier != -1 ) {
01134 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
01135 if (bs->flagcarrier == bs->client) {
01136 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
01137 BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWME);
01138 }
01139 else {
01140 BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
01141 BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWFLAGCARRIER);
01142 }
01143 }
01144 else {
01145
01146 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01147 BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
01148 }
01149 BotSayTeamOrder(bs, other);
01150 break;
01151 }
01152 default:
01153 {
01154
01155 defenders = (int) (float) numteammates * 0.3 + 0.5;
01156 if (defenders > 3) defenders = 3;
01157
01158 attackers = (int) (float) numteammates * 0.7 + 0.5;
01159 if (attackers > 7) attackers = 7;
01160 for (i = 0; i < defenders; i++) {
01161
01162 if (teammates[i] == bs->flagcarrier) {
01163 continue;
01164 }
01165 ClientName(teammates[i], name, sizeof(name));
01166 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01167 BotSayTeamOrder(bs, teammates[i]);
01168 BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
01169 }
01170 if (bs->flagcarrier != -1) {
01171 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
01172 for (i = 0; i < attackers; i++) {
01173
01174 if (teammates[numteammates - i - 1] == bs->flagcarrier) {
01175 continue;
01176 }
01177
01178 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
01179 if (bs->flagcarrier == bs->client) {
01180 BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
01181 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWME);
01182 }
01183 else {
01184 BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
01185 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWFLAGCARRIER);
01186 }
01187 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
01188 }
01189 }
01190 else {
01191 for (i = 0; i < attackers; i++) {
01192
01193 if (teammates[numteammates - i - 1] == bs->flagcarrier) {
01194 continue;
01195 }
01196
01197 ClientName(teammates[numteammates - i - 1], name, sizeof(name));
01198 BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
01199 BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
01200 BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
01201 }
01202 }
01203
01204 break;
01205 }
01206 }
01207 }
01208 else {
01209
01210 switch(numteammates) {
01211 case 1: break;
01212 case 2:
01213 {
01214
01215 if (teammates[0] == bs->flagcarrier) other = teammates[1];
01216 else other = teammates[0];
01217 ClientName(other, name, sizeof(name));
01218 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01219 BotSayTeamOrder(bs, other);
01220 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
01221 break;
01222 }
01223 case 3:
01224 {
01225
01226 if (teammates[0] != bs->flagcarrier) other = teammates[0];
01227 else other = teammates[1];
01228 ClientName(other, name, sizeof(name));
01229 BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
01230 BotSayTeamOrder(bs, other);
01231 BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
01232
01233 if (teammates[2] != bs->flagcarrier) other = teammates[2];
01234 else other = teammates[1];
01235 ClientName(other, name, sizeof(name));
01236 ClientName(bs->flagcarrier, carriername, sizeof(carriername));
01237 if (bs->flagcarrier == bs->