~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/game/ai_team.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
===========================================================================
 
3
Copyright (C) 1999-2005 Id Software, Inc.
 
4
 
 
5
This file is part of Quake III Arena source code.
 
6
 
 
7
Quake III Arena source code is free software; you can redistribute it
 
8
and/or modify it under the terms of the GNU General Public License as
 
9
published by the Free Software Foundation; either version 2 of the License,
 
10
or (at your option) any later version.
 
11
 
 
12
Quake III Arena source code is distributed in the hope that it will be
 
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with Quake III Arena source code; if not, write to the Free Software
 
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
===========================================================================
 
21
*/
 
22
//
 
23
 
 
24
/*****************************************************************************
 
25
 * name:                ai_team.c
 
26
 *
 
27
 * desc:                Quake3 bot AI
 
28
 *
 
29
 * $Archive: /MissionPack/code/game/ai_team.c $
 
30
 *
 
31
 *****************************************************************************/
 
32
 
 
33
#include "g_local.h"
 
34
#include "../botlib/botlib.h"
 
35
#include "../botlib/be_aas.h"
 
36
#include "../botlib/be_ea.h"
 
37
#include "../botlib/be_ai_char.h"
 
38
#include "../botlib/be_ai_chat.h"
 
39
#include "../botlib/be_ai_gen.h"
 
40
#include "../botlib/be_ai_goal.h"
 
41
#include "../botlib/be_ai_move.h"
 
42
#include "../botlib/be_ai_weap.h"
 
43
//
 
44
#include "ai_main.h"
 
45
#include "ai_dmq3.h"
 
46
#include "ai_chat.h"
 
47
#include "ai_cmd.h"
 
48
#include "ai_dmnet.h"
 
49
#include "ai_team.h"
 
50
#include "ai_vcmd.h"
 
51
 
 
52
#include "match.h"
 
53
 
 
54
// for the voice chats
 
55
#include "../../ui/menudef.h"
 
56
 
 
57
//ctf task preferences for a client
 
58
typedef struct bot_ctftaskpreference_s
 
59
{
 
60
        char            name[36];
 
61
        int                     preference;
 
62
} bot_ctftaskpreference_t;
 
63
 
 
64
bot_ctftaskpreference_t ctftaskpreferences[MAX_CLIENTS];
 
65
 
 
66
 
 
67
/*
 
68
==================
 
69
BotValidTeamLeader
 
70
==================
 
71
*/
 
72
int BotValidTeamLeader(bot_state_t *bs) {
 
73
        if (!strlen(bs->teamleader)) return qfalse;
 
74
        if (ClientFromName(bs->teamleader) == -1) return qfalse;
 
75
        return qtrue;
 
76
}
 
77
 
 
78
/*
 
79
==================
 
80
BotNumTeamMates
 
81
==================
 
82
*/
 
83
int BotNumTeamMates(bot_state_t *bs) {
 
84
        int i, numplayers;
 
85
        char buf[MAX_INFO_STRING];
 
86
        static int maxclients;
 
87
 
 
88
        if (!maxclients)
 
89
                maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
 
90
 
 
91
        numplayers = 0;
 
92
        for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
 
93
                trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
 
94
                //if no config string or no name
 
95
                if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
 
96
                //skip spectators
 
97
                if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
 
98
                //
 
99
                if (BotSameTeam(bs, i)) {
 
100
                        numplayers++;
 
101
                }
 
102
        }
 
103
        return numplayers;
 
104
}
 
105
 
 
106
/*
 
107
==================
 
108
BotClientTravelTimeToGoal
 
109
==================
 
110
*/
 
111
int BotClientTravelTimeToGoal(int client, bot_goal_t *goal) {
 
112
        playerState_t ps;
 
113
        int areanum;
 
114
 
 
115
        BotAI_GetClientState(client, &ps);
 
116
        areanum = BotPointAreaNum(ps.origin);
 
117
        if (!areanum) return 1;
 
118
        return trap_AAS_AreaTravelTimeToGoalArea(areanum, ps.origin, goal->areanum, TFL_DEFAULT);
 
119
}
 
120
 
 
121
/*
 
122
==================
 
123
BotSortTeamMatesByBaseTravelTime
 
124
==================
 
125
*/
 
126
int BotSortTeamMatesByBaseTravelTime(bot_state_t *bs, int *teammates, int maxteammates) {
 
127
 
 
128
        int i, j, k, numteammates, traveltime;
 
129
        char buf[MAX_INFO_STRING];
 
130
        static int maxclients;
 
131
        int traveltimes[MAX_CLIENTS];
 
132
        bot_goal_t *goal = NULL;
 
133
 
 
134
        if (gametype == GT_CTF || gametype == GT_1FCTF) {
 
135
                if (BotTeam(bs) == TEAM_RED)
 
136
                        goal = &ctf_redflag;
 
137
                else
 
138
                        goal = &ctf_blueflag;
 
139
        }
 
140
#ifdef MISSIONPACK
 
141
        else {
 
142
                if (BotTeam(bs) == TEAM_RED)
 
143
                        goal = &redobelisk;
 
144
                else
 
145
                        goal = &blueobelisk;
 
146
        }
 
147
#endif
 
148
        if (!maxclients)
 
149
                maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
 
150
 
 
151
        numteammates = 0;
 
152
        for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
 
153
                trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
 
154
                //if no config string or no name
 
155
                if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
 
156
                //skip spectators
 
157
                if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
 
158
                //
 
159
                if (BotSameTeam(bs, i)) {
 
160
                        //
 
161
                        traveltime = BotClientTravelTimeToGoal(i, goal);
 
162
                        //
 
163
                        for (j = 0; j < numteammates; j++) {
 
164
                                if (traveltime < traveltimes[j]) {
 
165
                                        for (k = numteammates; k > j; k--) {
 
166
                                                traveltimes[k] = traveltimes[k-1];
 
167
                                                teammates[k] = teammates[k-1];
 
168
                                        }
 
169
                                        break;
 
170
                                }
 
171
                        }
 
172
                        traveltimes[j] = traveltime;
 
173
                        teammates[j] = i;
 
174
                        numteammates++;
 
175
                        if (numteammates >= maxteammates) break;
 
176
                }
 
177
        }
 
178
        return numteammates;
 
179
}
 
180
 
 
181
/*
 
182
==================
 
183
BotSetTeamMateTaskPreference
 
184
==================
 
185
*/
 
186
void BotSetTeamMateTaskPreference(bot_state_t *bs, int teammate, int preference) {
 
187
        char teammatename[MAX_NETNAME];
 
188
 
 
189
        ctftaskpreferences[teammate].preference = preference;
 
190
        ClientName(teammate, teammatename, sizeof(teammatename));
 
191
        strcpy(ctftaskpreferences[teammate].name, teammatename);
 
192
}
 
193
 
 
194
/*
 
195
==================
 
196
BotGetTeamMateTaskPreference
 
197
==================
 
198
*/
 
199
int BotGetTeamMateTaskPreference(bot_state_t *bs, int teammate) {
 
200
        char teammatename[MAX_NETNAME];
 
201
 
 
202
        if (!ctftaskpreferences[teammate].preference) return 0;
 
203
        ClientName(teammate, teammatename, sizeof(teammatename));
 
204
        if (Q_stricmp(teammatename, ctftaskpreferences[teammate].name)) return 0;
 
205
        return ctftaskpreferences[teammate].preference;
 
206
}
 
207
 
 
208
/*
 
209
==================
 
210
BotSortTeamMatesByTaskPreference
 
211
==================
 
212
*/
 
213
int BotSortTeamMatesByTaskPreference(bot_state_t *bs, int *teammates, int numteammates) {
 
214
        int defenders[MAX_CLIENTS], numdefenders;
 
215
        int attackers[MAX_CLIENTS], numattackers;
 
216
        int roamers[MAX_CLIENTS], numroamers;
 
217
        int i, preference;
 
218
 
 
219
        numdefenders = numattackers = numroamers = 0;
 
220
        for (i = 0; i < numteammates; i++) {
 
221
                preference = BotGetTeamMateTaskPreference(bs, teammates[i]);
 
222
                if (preference & TEAMTP_DEFENDER) {
 
223
                        defenders[numdefenders++] = teammates[i];
 
224
                }
 
225
                else if (preference & TEAMTP_ATTACKER) {
 
226
                        attackers[numattackers++] = teammates[i];
 
227
                }
 
228
                else {
 
229
                        roamers[numroamers++] = teammates[i];
 
230
                }
 
231
        }
 
232
        numteammates = 0;
 
233
        //defenders at the front of the list
 
234
        memcpy(&teammates[numteammates], defenders, numdefenders * sizeof(int));
 
235
        numteammates += numdefenders;
 
236
        //roamers in the middle
 
237
        memcpy(&teammates[numteammates], roamers, numroamers * sizeof(int));
 
238
        numteammates += numroamers;
 
239
        //attacker in the back of the list
 
240
        memcpy(&teammates[numteammates], attackers, numattackers * sizeof(int));
 
241
        numteammates += numattackers;
 
242
 
 
243
        return numteammates;
 
244
}
 
245
 
 
246
/*
 
247
==================
 
248
BotSayTeamOrders
 
249
==================
 
250
*/
 
251
void BotSayTeamOrderAlways(bot_state_t *bs, int toclient) {
 
252
        char teamchat[MAX_MESSAGE_SIZE];
 
253
        char buf[MAX_MESSAGE_SIZE];
 
254
        char name[MAX_NETNAME];
 
255
 
 
256
        //if the bot is talking to itself
 
257
        if (bs->client == toclient) {
 
258
                //don't show the message just put it in the console message queue
 
259
                trap_BotGetChatMessage(bs->cs, buf, sizeof(buf));
 
260
                ClientName(bs->client, name, sizeof(name));
 
261
                Com_sprintf(teamchat, sizeof(teamchat), EC"(%s"EC")"EC": %s", name, buf);
 
262
                trap_BotQueueConsoleMessage(bs->cs, CMS_CHAT, teamchat);
 
263
        }
 
264
        else {
 
265
                trap_BotEnterChat(bs->cs, toclient, CHAT_TELL);
 
266
        }
 
267
}
 
268
 
 
269
/*
 
270
==================
 
271
BotSayTeamOrders
 
272
==================
 
273
*/
 
274
void BotSayTeamOrder(bot_state_t *bs, int toclient) {
 
275
#ifdef MISSIONPACK
 
276
        // voice chats only
 
277
        char buf[MAX_MESSAGE_SIZE];
 
278
 
 
279
        trap_BotGetChatMessage(bs->cs, buf, sizeof(buf));
 
280
#else
 
281
        BotSayTeamOrderAlways(bs, toclient);
 
282
#endif
 
283
}
 
284
 
 
285
/*
 
286
==================
 
287
BotVoiceChat
 
288
==================
 
289
*/
 
290
void BotVoiceChat(bot_state_t *bs, int toclient, char *voicechat) {
 
291
#ifdef MISSIONPACK
 
292
        if (toclient == -1)
 
293
                // voice only say team
 
294
                trap_EA_Command(bs->client, va("vsay_team %s", voicechat));
 
295
        else
 
296
                // voice only tell single player
 
297
                trap_EA_Command(bs->client, va("vtell %d %s", toclient, voicechat));
 
298
#endif
 
299
}
 
300
 
 
301
/*
 
302
==================
 
303
BotVoiceChatOnly
 
304
==================
 
305
*/
 
306
void BotVoiceChatOnly(bot_state_t *bs, int toclient, char *voicechat) {
 
307
#ifdef MISSIONPACK
 
308
        if (toclient == -1)
 
309
                // voice only say team
 
310
                trap_EA_Command(bs->client, va("vosay_team %s", voicechat));
 
311
        else
 
312
                // voice only tell single player
 
313
                trap_EA_Command(bs->client, va("votell %d %s", toclient, voicechat));
 
314
#endif
 
315
}
 
316
 
 
317
/*
 
318
==================
 
319
BotSayVoiceTeamOrder
 
320
==================
 
321
*/
 
322
void BotSayVoiceTeamOrder(bot_state_t *bs, int toclient, char *voicechat) {
 
323
#ifdef MISSIONPACK
 
324
        BotVoiceChat(bs, toclient, voicechat);
 
325
#endif
 
326
}
 
327
 
 
328
/*
 
329
==================
 
330
BotCTFOrders
 
331
==================
 
332
*/
 
333
void BotCTFOrders_BothFlagsNotAtBase(bot_state_t *bs) {
 
334
        int numteammates, defenders, attackers, i, other;
 
335
        int teammates[MAX_CLIENTS];
 
336
        char name[MAX_NETNAME], carriername[MAX_NETNAME];
 
337
 
 
338
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
339
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
340
        //different orders based on the number of team mates
 
341
        switch(bs->numteammates) {
 
342
                case 1: break;
 
343
                case 2:
 
344
                {
 
345
                        //tell the one not carrying the flag to attack the enemy base
 
346
                        if (teammates[0] != bs->flagcarrier) other = teammates[0];
 
347
                        else other = teammates[1];
 
348
                        ClientName(other, name, sizeof(name));
 
349
                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
350
                        BotSayTeamOrder(bs, other);
 
351
                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
 
352
                        break;
 
353
                }
 
354
                case 3:
 
355
                {
 
356
                        //tell the one closest to the base not carrying the flag to accompany the flag carrier
 
357
                        if (teammates[0] != bs->flagcarrier) other = teammates[0];
 
358
                        else other = teammates[1];
 
359
                        ClientName(other, name, sizeof(name));
 
360
                        if ( bs->flagcarrier != -1 ) {
 
361
                                ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
362
                                if (bs->flagcarrier == bs->client) {
 
363
                                        BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
364
                                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWME);
 
365
                                }
 
366
                                else {
 
367
                                        BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
368
                                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWFLAGCARRIER);
 
369
                                }
 
370
                        }
 
371
                        else {
 
372
                                //
 
373
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
374
                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
 
375
                        }
 
376
                        BotSayTeamOrder(bs, other);
 
377
                        //tell the one furthest from the the base not carrying the flag to get the enemy flag
 
378
                        if (teammates[2] != bs->flagcarrier) other = teammates[2];
 
379
                        else other = teammates[1];
 
380
                        ClientName(other, name, sizeof(name));
 
381
                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
382
                        BotSayTeamOrder(bs, other);
 
383
                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_RETURNFLAG);
 
384
                        break;
 
385
                }
 
386
                default:
 
387
                {
 
388
                        defenders = (int) (float) numteammates * 0.4 + 0.5;
 
389
                        if (defenders > 4) defenders = 4;
 
390
                        attackers = (int) (float) numteammates * 0.5 + 0.5;
 
391
                        if (attackers > 5) attackers = 5;
 
392
                        if (bs->flagcarrier != -1) {
 
393
                                ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
394
                                for (i = 0; i < defenders; i++) {
 
395
                                        //
 
396
                                        if (teammates[i] == bs->flagcarrier) {
 
397
                                                continue;
 
398
                                        }
 
399
                                        //
 
400
                                        ClientName(teammates[i], name, sizeof(name));
 
401
                                        if (bs->flagcarrier == bs->client) {
 
402
                                                BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
403
                                                BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_FOLLOWME);
 
404
                                        }
 
405
                                        else {
 
406
                                                BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
407
                                                BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_FOLLOWFLAGCARRIER);
 
408
                                        }
 
409
                                        BotSayTeamOrder(bs, teammates[i]);
 
410
                                }
 
411
                        }
 
412
                        else {
 
413
                                for (i = 0; i < defenders; i++) {
 
414
                                        //
 
415
                                        if (teammates[i] == bs->flagcarrier) {
 
416
                                                continue;
 
417
                                        }
 
418
                                        //
 
419
                                        ClientName(teammates[i], name, sizeof(name));
 
420
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
421
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_GETFLAG);
 
422
                                        BotSayTeamOrder(bs, teammates[i]);
 
423
                                }
 
424
                        }
 
425
                        for (i = 0; i < attackers; i++) {
 
426
                                //
 
427
                                if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
428
                                        continue;
 
429
                                }
 
430
                                //
 
431
                                ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
432
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
433
                                BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
434
                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_RETURNFLAG);
 
435
                        }
 
436
                        //
 
437
                        break;
 
438
                }
 
439
        }
 
440
}
 
441
 
 
442
/*
 
443
==================
 
444
BotCTFOrders
 
445
==================
 
446
*/
 
447
void BotCTFOrders_FlagNotAtBase(bot_state_t *bs) {
 
448
        int numteammates, defenders, attackers, i;
 
449
        int teammates[MAX_CLIENTS];
 
450
        char name[MAX_NETNAME];
 
451
 
 
452
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
453
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
454
        //passive strategy
 
455
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
456
                //different orders based on the number of team mates
 
457
                switch(bs->numteammates) {
 
458
                        case 1: break;
 
459
                        case 2:
 
460
                        {
 
461
                                //both will go for the enemy flag
 
462
                                ClientName(teammates[0], name, sizeof(name));
 
463
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
464
                                BotSayTeamOrder(bs, teammates[0]);
 
465
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
 
466
                                //
 
467
                                ClientName(teammates[1], name, sizeof(name));
 
468
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
469
                                BotSayTeamOrder(bs, teammates[1]);
 
470
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
471
                                break;
 
472
                        }
 
473
                        case 3:
 
474
                        {
 
475
                                //keep one near the base for when the flag is returned
 
476
                                ClientName(teammates[0], name, sizeof(name));
 
477
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
478
                                BotSayTeamOrder(bs, teammates[0]);
 
479
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
480
                                //the other two get the flag
 
481
                                ClientName(teammates[1], name, sizeof(name));
 
482
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
483
                                BotSayTeamOrder(bs, teammates[1]);
 
484
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
485
                                //
 
486
                                ClientName(teammates[2], name, sizeof(name));
 
487
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
488
                                BotSayTeamOrder(bs, teammates[2]);
 
489
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
490
                                break;
 
491
                        }
 
492
                        default:
 
493
                        {
 
494
                                //keep some people near the base for when the flag is returned
 
495
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
496
                                if (defenders > 3) defenders = 3;
 
497
                                attackers = (int) (float) numteammates * 0.7 + 0.5;
 
498
                                if (attackers > 6) attackers = 6;
 
499
                                for (i = 0; i < defenders; i++) {
 
500
                                        //
 
501
                                        ClientName(teammates[i], name, sizeof(name));
 
502
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
503
                                        BotSayTeamOrder(bs, teammates[i]);
 
504
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
505
                                }
 
506
                                for (i = 0; i < attackers; i++) {
 
507
                                        //
 
508
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
509
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
510
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
511
                                        BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
 
512
                                }
 
513
                                //
 
514
                                break;
 
515
                        }
 
516
                }
 
517
        }
 
518
        else {
 
519
                //different orders based on the number of team mates
 
520
                switch(bs->numteammates) {
 
521
                        case 1: break;
 
522
                        case 2:
 
523
                        {
 
524
                                //both will go for the enemy flag
 
525
                                ClientName(teammates[0], name, sizeof(name));
 
526
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
527
                                BotSayTeamOrder(bs, teammates[0]);
 
528
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
 
529
                                //
 
530
                                ClientName(teammates[1], name, sizeof(name));
 
531
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
532
                                BotSayTeamOrder(bs, teammates[1]);
 
533
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
534
                                break;
 
535
                        }
 
536
                        case 3:
 
537
                        {
 
538
                                //everyone go for the flag
 
539
                                ClientName(teammates[0], name, sizeof(name));
 
540
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
541
                                BotSayTeamOrder(bs, teammates[0]);
 
542
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_GETFLAG);
 
543
                                //
 
544
                                ClientName(teammates[1], name, sizeof(name));
 
545
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
546
                                BotSayTeamOrder(bs, teammates[1]);
 
547
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
548
                                //
 
549
                                ClientName(teammates[2], name, sizeof(name));
 
550
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
551
                                BotSayTeamOrder(bs, teammates[2]);
 
552
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
553
                                break;
 
554
                        }
 
555
                        default:
 
556
                        {
 
557
                                //keep some people near the base for when the flag is returned
 
558
                                defenders = (int) (float) numteammates * 0.2 + 0.5;
 
559
                                if (defenders > 2) defenders = 2;
 
560
                                attackers = (int) (float) numteammates * 0.7 + 0.5;
 
561
                                if (attackers > 7) attackers = 7;
 
562
                                for (i = 0; i < defenders; i++) {
 
563
                                        //
 
564
                                        ClientName(teammates[i], name, sizeof(name));
 
565
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
566
                                        BotSayTeamOrder(bs, teammates[i]);
 
567
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
568
                                }
 
569
                                for (i = 0; i < attackers; i++) {
 
570
                                        //
 
571
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
572
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
573
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
574
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
575
                                }
 
576
                                //
 
577
                                break;
 
578
                        }
 
579
                }
 
580
        }
 
581
}
 
582
 
 
583
/*
 
584
==================
 
585
BotCTFOrders
 
586
==================
 
587
*/
 
588
void BotCTFOrders_EnemyFlagNotAtBase(bot_state_t *bs) {
 
589
        int numteammates, defenders, attackers, i, other;
 
590
        int teammates[MAX_CLIENTS];
 
591
        char name[MAX_NETNAME], carriername[MAX_NETNAME];
 
592
 
 
593
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
594
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
595
        //different orders based on the number of team mates
 
596
        switch(numteammates) {
 
597
                case 1: break;
 
598
                case 2:
 
599
                {
 
600
                        //tell the one not carrying the flag to defend the base
 
601
                        if (teammates[0] == bs->flagcarrier) other = teammates[1];
 
602
                        else other = teammates[0];
 
603
                        ClientName(other, name, sizeof(name));
 
604
                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
605
                        BotSayTeamOrder(bs, other);
 
606
                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
607
                        break;
 
608
                }
 
609
                case 3:
 
610
                {
 
611
                        //tell the one closest to the base not carrying the flag to defend the base
 
612
                        if (teammates[0] != bs->flagcarrier) other = teammates[0];
 
613
                        else other = teammates[1];
 
614
                        ClientName(other, name, sizeof(name));
 
615
                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
616
                        BotSayTeamOrder(bs, other);
 
617
                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
618
                        //tell the other also to defend the base
 
619
                        if (teammates[2] != bs->flagcarrier) other = teammates[2];
 
620
                        else other = teammates[1];
 
621
                        ClientName(other, name, sizeof(name));
 
622
                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
623
                        BotSayTeamOrder(bs, other);
 
624
                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
625
                        break;
 
626
                }
 
627
                default:
 
628
                {
 
629
                        //60% will defend the base
 
630
                        defenders = (int) (float) numteammates * 0.6 + 0.5;
 
631
                        if (defenders > 6) defenders = 6;
 
632
                        //30% accompanies the flag carrier
 
633
                        attackers = (int) (float) numteammates * 0.3 + 0.5;
 
634
                        if (attackers > 3) attackers = 3;
 
635
                        for (i = 0; i < defenders; i++) {
 
636
                                //
 
637
                                if (teammates[i] == bs->flagcarrier) {
 
638
                                        continue;
 
639
                                }
 
640
                                ClientName(teammates[i], name, sizeof(name));
 
641
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
642
                                BotSayTeamOrder(bs, teammates[i]);
 
643
                                BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
644
                        }
 
645
                        // if we have a flag carrier
 
646
                        if ( bs->flagcarrier != -1 ) {
 
647
                                ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
648
                                for (i = 0; i < attackers; i++) {
 
649
                                        //
 
650
                                        if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
651
                                                continue;
 
652
                                        }
 
653
                                        //
 
654
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
655
                                        if (bs->flagcarrier == bs->client) {
 
656
                                                BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
657
                                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWME);
 
658
                                        }
 
659
                                        else {
 
660
                                                BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
661
                                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWFLAGCARRIER);
 
662
                                        }
 
663
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
664
                                }
 
665
                        }
 
666
                        else {
 
667
                                for (i = 0; i < attackers; i++) {
 
668
                                        //
 
669
                                        if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
670
                                                continue;
 
671
                                        }
 
672
                                        //
 
673
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
674
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
675
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
676
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
677
                                }
 
678
                        }
 
679
                        //
 
680
                        break;
 
681
                }
 
682
        }
 
683
}
 
684
 
 
685
 
 
686
/*
 
687
==================
 
688
BotCTFOrders
 
689
==================
 
690
*/
 
691
void BotCTFOrders_BothFlagsAtBase(bot_state_t *bs) {
 
692
        int numteammates, defenders, attackers, i;
 
693
        int teammates[MAX_CLIENTS];
 
694
        char name[MAX_NETNAME];
 
695
 
 
696
        //sort team mates by travel time to base
 
697
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
698
        //sort team mates by CTF preference
 
699
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
700
        //passive strategy
 
701
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
702
                //different orders based on the number of team mates
 
703
                switch(numteammates) {
 
704
                        case 1: break;
 
705
                        case 2:
 
706
                        {
 
707
                                //the one closest to the base will defend the base
 
708
                                ClientName(teammates[0], name, sizeof(name));
 
709
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
710
                                BotSayTeamOrder(bs, teammates[0]);
 
711
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
712
                                //the other will get the flag
 
713
                                ClientName(teammates[1], name, sizeof(name));
 
714
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
715
                                BotSayTeamOrder(bs, teammates[1]);
 
716
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
717
                                break;
 
718
                        }
 
719
                        case 3:
 
720
                        {
 
721
                                //the one closest to the base will defend the base
 
722
                                ClientName(teammates[0], name, sizeof(name));
 
723
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
724
                                BotSayTeamOrder(bs, teammates[0]);
 
725
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
726
                                //the second one closest to the base will defend the base
 
727
                                ClientName(teammates[1], name, sizeof(name));
 
728
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
729
                                BotSayTeamOrder(bs, teammates[1]);
 
730
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
731
                                //the other will get the flag
 
732
                                ClientName(teammates[2], name, sizeof(name));
 
733
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
734
                                BotSayTeamOrder(bs, teammates[2]);
 
735
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
736
                                break;
 
737
                        }
 
738
                        default:
 
739
                        {
 
740
                                defenders = (int) (float) numteammates * 0.5 + 0.5;
 
741
                                if (defenders > 5) defenders = 5;
 
742
                                attackers = (int) (float) numteammates * 0.4 + 0.5;
 
743
                                if (attackers > 4) attackers = 4;
 
744
                                for (i = 0; i < defenders; i++) {
 
745
                                        //
 
746
                                        ClientName(teammates[i], name, sizeof(name));
 
747
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
748
                                        BotSayTeamOrder(bs, teammates[i]);
 
749
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
750
                                }
 
751
                                for (i = 0; i < attackers; i++) {
 
752
                                        //
 
753
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
754
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
755
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
756
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
757
                                }
 
758
                                //
 
759
                                break;
 
760
                        }
 
761
                }
 
762
        }
 
763
        else {
 
764
                //different orders based on the number of team mates
 
765
                switch(numteammates) {
 
766
                        case 1: break;
 
767
                        case 2:
 
768
                        {
 
769
                                //the one closest to the base will defend the base
 
770
                                ClientName(teammates[0], name, sizeof(name));
 
771
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
772
                                BotSayTeamOrder(bs, teammates[0]);
 
773
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
774
                                //the other will get the flag
 
775
                                ClientName(teammates[1], name, sizeof(name));
 
776
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
777
                                BotSayTeamOrder(bs, teammates[1]);
 
778
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
779
                                break;
 
780
                        }
 
781
                        case 3:
 
782
                        {
 
783
                                //the one closest to the base will defend the base
 
784
                                ClientName(teammates[0], name, sizeof(name));
 
785
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
786
                                BotSayTeamOrder(bs, teammates[0]);
 
787
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
788
                                //the others should go for the enemy flag
 
789
                                ClientName(teammates[1], name, sizeof(name));
 
790
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
791
                                BotSayTeamOrder(bs, teammates[1]);
 
792
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
793
                                //
 
794
                                ClientName(teammates[2], name, sizeof(name));
 
795
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
796
                                BotSayTeamOrder(bs, teammates[2]);
 
797
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
798
                                break;
 
799
                        }
 
800
                        default:
 
801
                        {
 
802
                                defenders = (int) (float) numteammates * 0.4 + 0.5;
 
803
                                if (defenders > 4) defenders = 4;
 
804
                                attackers = (int) (float) numteammates * 0.5 + 0.5;
 
805
                                if (attackers > 5) attackers = 5;
 
806
                                for (i = 0; i < defenders; i++) {
 
807
                                        //
 
808
                                        ClientName(teammates[i], name, sizeof(name));
 
809
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
810
                                        BotSayTeamOrder(bs, teammates[i]);
 
811
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
812
                                }
 
813
                                for (i = 0; i < attackers; i++) {
 
814
                                        //
 
815
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
816
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
817
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
818
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
819
                                }
 
820
                                //
 
821
                                break;
 
822
                        }
 
823
                }
 
824
        }
 
825
}
 
826
 
 
827
/*
 
828
==================
 
829
BotCTFOrders
 
830
==================
 
831
*/
 
832
void BotCTFOrders(bot_state_t *bs) {
 
833
        int flagstatus;
 
834
 
 
835
        //
 
836
        if (BotTeam(bs) == TEAM_RED) flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus;
 
837
        else flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus;
 
838
        //
 
839
        switch(flagstatus) {
 
840
                case 0: BotCTFOrders_BothFlagsAtBase(bs); break;
 
841
                case 1: BotCTFOrders_EnemyFlagNotAtBase(bs); break;
 
842
                case 2: BotCTFOrders_FlagNotAtBase(bs); break;
 
843
                case 3: BotCTFOrders_BothFlagsNotAtBase(bs); break;
 
844
        }
 
845
}
 
846
 
 
847
 
 
848
/*
 
849
==================
 
850
BotCreateGroup
 
851
==================
 
852
*/
 
853
void BotCreateGroup(bot_state_t *bs, int *teammates, int groupsize) {
 
854
        char name[MAX_NETNAME], leadername[MAX_NETNAME];
 
855
        int i;
 
856
 
 
857
        // the others in the group will follow the teammates[0]
 
858
        ClientName(teammates[0], leadername, sizeof(leadername));
 
859
        for (i = 1; i < groupsize; i++)
 
860
        {
 
861
                ClientName(teammates[i], name, sizeof(name));
 
862
                if (teammates[0] == bs->client) {
 
863
                        BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
864
                }
 
865
                else {
 
866
                        BotAI_BotInitialChat(bs, "cmd_accompany", name, leadername, NULL);
 
867
                }
 
868
                BotSayTeamOrderAlways(bs, teammates[i]);
 
869
        }
 
870
}
 
871
 
 
872
/*
 
873
==================
 
874
BotTeamOrders
 
875
 
 
876
  FIXME: defend key areas?
 
877
==================
 
878
*/
 
879
void BotTeamOrders(bot_state_t *bs) {
 
880
        int teammates[MAX_CLIENTS];
 
881
        int numteammates, i;
 
882
        char buf[MAX_INFO_STRING];
 
883
        static int maxclients;
 
884
 
 
885
        if (!maxclients)
 
886
                maxclients = trap_Cvar_VariableIntegerValue("sv_maxclients");
 
887
 
 
888
        numteammates = 0;
 
889
        for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
 
890
                trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
 
891
                //if no config string or no name
 
892
                if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n"))) continue;
 
893
                //skip spectators
 
894
                if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue;
 
895
                //
 
896
                if (BotSameTeam(bs, i)) {
 
897
                        teammates[numteammates] = i;
 
898
                        numteammates++;
 
899
                }
 
900
        }
 
901
        //
 
902
        switch(numteammates) {
 
903
                case 1: break;
 
904
                case 2:
 
905
                {
 
906
                        //nothing special
 
907
                        break;
 
908
                }
 
909
                case 3:
 
910
                {
 
911
                        //have one follow another and one free roaming
 
912
                        BotCreateGroup(bs, teammates, 2);
 
913
                        break;
 
914
                }
 
915
                case 4:
 
916
                {
 
917
                        BotCreateGroup(bs, teammates, 2);               //a group of 2
 
918
                        BotCreateGroup(bs, &teammates[2], 2);   //a group of 2
 
919
                        break;
 
920
                }
 
921
                case 5:
 
922
                {
 
923
                        BotCreateGroup(bs, teammates, 2);               //a group of 2
 
924
                        BotCreateGroup(bs, &teammates[2], 3);   //a group of 3
 
925
                        break;
 
926
                }
 
927
                default:
 
928
                {
 
929
                        if (numteammates <= 10) {
 
930
                                for (i = 0; i < numteammates / 2; i++) {
 
931
                                        BotCreateGroup(bs, &teammates[i*2], 2); //groups of 2
 
932
                                }
 
933
                        }
 
934
                        break;
 
935
                }
 
936
        }
 
937
}
 
938
 
 
939
#ifdef MISSIONPACK
 
940
 
 
941
/*
 
942
==================
 
943
Bot1FCTFOrders_FlagAtCenter
 
944
 
 
945
  X% defend the base, Y% get the flag
 
946
==================
 
947
*/
 
948
void Bot1FCTFOrders_FlagAtCenter(bot_state_t *bs) {
 
949
        int numteammates, defenders, attackers, i;
 
950
        int teammates[MAX_CLIENTS];
 
951
        char name[MAX_NETNAME];
 
952
 
 
953
        //sort team mates by travel time to base
 
954
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
955
        //sort team mates by CTF preference
 
956
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
957
        //passive strategy
 
958
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
959
                //different orders based on the number of team mates
 
960
                switch(numteammates) {
 
961
                        case 1: break;
 
962
                        case 2:
 
963
                        {
 
964
                                //the one closest to the base will defend the base
 
965
                                ClientName(teammates[0], name, sizeof(name));
 
966
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
967
                                BotSayTeamOrder(bs, teammates[0]);
 
968
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
969
                                //the other will get the flag
 
970
                                ClientName(teammates[1], name, sizeof(name));
 
971
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
972
                                BotSayTeamOrder(bs, teammates[1]);
 
973
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
974
                                break;
 
975
                        }
 
976
                        case 3:
 
977
                        {
 
978
                                //the one closest to the base will defend the base
 
979
                                ClientName(teammates[0], name, sizeof(name));
 
980
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
981
                                BotSayTeamOrder(bs, teammates[0]);
 
982
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
983
                                //the second one closest to the base will defend the base
 
984
                                ClientName(teammates[1], name, sizeof(name));
 
985
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
986
                                BotSayTeamOrder(bs, teammates[1]);
 
987
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
988
                                //the other will get the flag
 
989
                                ClientName(teammates[2], name, sizeof(name));
 
990
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
991
                                BotSayTeamOrder(bs, teammates[2]);
 
992
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
993
                                break;
 
994
                        }
 
995
                        default:
 
996
                        {
 
997
                                //50% defend the base
 
998
                                defenders = (int) (float) numteammates * 0.5 + 0.5;
 
999
                                if (defenders > 5) defenders = 5;
 
1000
                                //40% get the flag
 
1001
                                attackers = (int) (float) numteammates * 0.4 + 0.5;
 
1002
                                if (attackers > 4) attackers = 4;
 
1003
                                for (i = 0; i < defenders; i++) {
 
1004
                                        //
 
1005
                                        ClientName(teammates[i], name, sizeof(name));
 
1006
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1007
                                        BotSayTeamOrder(bs, teammates[i]);
 
1008
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1009
                                }
 
1010
                                for (i = 0; i < attackers; i++) {
 
1011
                                        //
 
1012
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1013
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1014
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1015
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1016
                                }
 
1017
                                //
 
1018
                                break;
 
1019
                        }
 
1020
                }
 
1021
        }
 
1022
        else { //agressive
 
1023
                //different orders based on the number of team mates
 
1024
                switch(numteammates) {
 
1025
                        case 1: break;
 
1026
                        case 2:
 
1027
                        {
 
1028
                                //the one closest to the base will defend the base
 
1029
                                ClientName(teammates[0], name, sizeof(name));
 
1030
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1031
                                BotSayTeamOrder(bs, teammates[0]);
 
1032
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1033
                                //the other will get the flag
 
1034
                                ClientName(teammates[1], name, sizeof(name));
 
1035
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1036
                                BotSayTeamOrder(bs, teammates[1]);
 
1037
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
1038
                                break;
 
1039
                        }
 
1040
                        case 3:
 
1041
                        {
 
1042
                                //the one closest to the base will defend the base
 
1043
                                ClientName(teammates[0], name, sizeof(name));
 
1044
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1045
                                BotSayTeamOrder(bs, teammates[0]);
 
1046
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1047
                                //the others should go for the enemy flag
 
1048
                                ClientName(teammates[1], name, sizeof(name));
 
1049
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1050
                                BotSayTeamOrder(bs, teammates[1]);
 
1051
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
1052
                                //
 
1053
                                ClientName(teammates[2], name, sizeof(name));
 
1054
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1055
                                BotSayTeamOrder(bs, teammates[2]);
 
1056
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
1057
                                break;
 
1058
                        }
 
1059
                        default:
 
1060
                        {
 
1061
                                //30% defend the base
 
1062
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
1063
                                if (defenders > 3) defenders = 3;
 
1064
                                //60% get the flag
 
1065
                                attackers = (int) (float) numteammates * 0.6 + 0.5;
 
1066
                                if (attackers > 6) attackers = 6;
 
1067
                                for (i = 0; i < defenders; i++) {
 
1068
                                        //
 
1069
                                        ClientName(teammates[i], name, sizeof(name));
 
1070
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1071
                                        BotSayTeamOrder(bs, teammates[i]);
 
1072
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1073
                                }
 
1074
                                for (i = 0; i < attackers; i++) {
 
1075
                                        //
 
1076
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1077
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1078
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1079
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1080
                                }
 
1081
                                //
 
1082
                                break;
 
1083
                        }
 
1084
                }
 
1085
        }
 
1086
}
 
1087
 
 
1088
/*
 
1089
==================
 
1090
Bot1FCTFOrders_TeamHasFlag
 
1091
 
 
1092
  X% towards neutral flag, Y% go towards enemy base and accompany flag carrier if visible
 
1093
==================
 
1094
*/
 
1095
void Bot1FCTFOrders_TeamHasFlag(bot_state_t *bs) {
 
1096
        int numteammates, defenders, attackers, i, other;
 
1097
        int teammates[MAX_CLIENTS];
 
1098
        char name[MAX_NETNAME], carriername[MAX_NETNAME];
 
1099
 
 
1100
        //sort team mates by travel time to base
 
1101
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
1102
        //sort team mates by CTF preference
 
1103
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
1104
        //passive strategy
 
1105
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
1106
                //different orders based on the number of team mates
 
1107
                switch(numteammates) {
 
1108
                        case 1: break;
 
1109
                        case 2:
 
1110
                        {
 
1111
                                //tell the one not carrying the flag to attack the enemy base
 
1112
                                if (teammates[0] == bs->flagcarrier) other = teammates[1];
 
1113
                                else other = teammates[0];
 
1114
                                ClientName(other, name, sizeof(name));
 
1115
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1116
                                BotSayTeamOrder(bs, other);
 
1117
                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_OFFENSE);
 
1118
                                break;
 
1119
                        }
 
1120
                        case 3:
 
1121
                        {
 
1122
                                //tell the one closest to the base not carrying the flag to defend the base
 
1123
                                if (teammates[0] != bs->flagcarrier) other = teammates[0];
 
1124
                                else other = teammates[1];
 
1125
                                ClientName(other, name, sizeof(name));
 
1126
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1127
                                BotSayTeamOrder(bs, other);
 
1128
                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
1129
                                //tell the one furthest from the base not carrying the flag to accompany the flag carrier
 
1130
                                if (teammates[2] != bs->flagcarrier) other = teammates[2];
 
1131
                                else other = teammates[1];
 
1132
                                ClientName(other, name, sizeof(name));
 
1133
                                if ( bs->flagcarrier != -1 ) {
 
1134
                                        ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
1135
                                        if (bs->flagcarrier == bs->client) {
 
1136
                                                BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
1137
                                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWME);
 
1138
                                        }
 
1139
                                        else {
 
1140
                                                BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
1141
                                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWFLAGCARRIER);
 
1142
                                        }
 
1143
                                }
 
1144
                                else {
 
1145
                                        //
 
1146
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1147
                                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_GETFLAG);
 
1148
                                }
 
1149
                                BotSayTeamOrder(bs, other);
 
1150
                                break;
 
1151
                        }
 
1152
                        default:
 
1153
                        {
 
1154
                                //30% will defend the base
 
1155
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
1156
                                if (defenders > 3) defenders = 3;
 
1157
                                //70% accompanies the flag carrier
 
1158
                                attackers = (int) (float) numteammates * 0.7 + 0.5;
 
1159
                                if (attackers > 7) attackers = 7;
 
1160
                                for (i = 0; i < defenders; i++) {
 
1161
                                        //
 
1162
                                        if (teammates[i] == bs->flagcarrier) {
 
1163
                                                continue;
 
1164
                                        }
 
1165
                                        ClientName(teammates[i], name, sizeof(name));
 
1166
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1167
                                        BotSayTeamOrder(bs, teammates[i]);
 
1168
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1169
                                }
 
1170
                                if (bs->flagcarrier != -1) {
 
1171
                                        ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
1172
                                        for (i = 0; i < attackers; i++) {
 
1173
                                                //
 
1174
                                                if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
1175
                                                        continue;
 
1176
                                                }
 
1177
                                                //
 
1178
                                                ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1179
                                                if (bs->flagcarrier == bs->client) {
 
1180
                                                        BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
1181
                                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWME);
 
1182
                                                }
 
1183
                                                else {
 
1184
                                                        BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
1185
                                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWFLAGCARRIER);
 
1186
                                                }
 
1187
                                                BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1188
                                        }
 
1189
                                }
 
1190
                                else {
 
1191
                                        for (i = 0; i < attackers; i++) {
 
1192
                                                //
 
1193
                                                if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
1194
                                                        continue;
 
1195
                                                }
 
1196
                                                //
 
1197
                                                ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1198
                                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1199
                                                BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1200
                                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1201
                                        }
 
1202
                                }
 
1203
                                //
 
1204
                                break;
 
1205
                        }
 
1206
                }
 
1207
        }
 
1208
        else { //agressive
 
1209
                //different orders based on the number of team mates
 
1210
                switch(numteammates) {
 
1211
                        case 1: break;
 
1212
                        case 2:
 
1213
                        {
 
1214
                                //tell the one not carrying the flag to defend the base
 
1215
                                if (teammates[0] == bs->flagcarrier) other = teammates[1];
 
1216
                                else other = teammates[0];
 
1217
                                ClientName(other, name, sizeof(name));
 
1218
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1219
                                BotSayTeamOrder(bs, other);
 
1220
                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
1221
                                break;
 
1222
                        }
 
1223
                        case 3:
 
1224
                        {
 
1225
                                //tell the one closest to the base not carrying the flag to defend the base
 
1226
                                if (teammates[0] != bs->flagcarrier) other = teammates[0];
 
1227
                                else other = teammates[1];
 
1228
                                ClientName(other, name, sizeof(name));
 
1229
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1230
                                BotSayTeamOrder(bs, other);
 
1231
                                BotSayVoiceTeamOrder(bs, other, VOICECHAT_DEFEND);
 
1232
                                //tell the one furthest from the base not carrying the flag to accompany the flag carrier
 
1233
                                if (teammates[2] != bs->flagcarrier) other = teammates[2];
 
1234
                                else other = teammates[1];
 
1235
                                ClientName(other, name, sizeof(name));
 
1236
                                ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
1237
                                if (bs->flagcarrier == bs->client) {
 
1238
                                        BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
1239
                                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWME);
 
1240
                                }
 
1241
                                else {
 
1242
                                        BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
1243
                                        BotSayVoiceTeamOrder(bs, other, VOICECHAT_FOLLOWFLAGCARRIER);
 
1244
                                }
 
1245
                                BotSayTeamOrder(bs, other);
 
1246
                                break;
 
1247
                        }
 
1248
                        default:
 
1249
                        {
 
1250
                                //20% will defend the base
 
1251
                                defenders = (int) (float) numteammates * 0.2 + 0.5;
 
1252
                                if (defenders > 2) defenders = 2;
 
1253
                                //80% accompanies the flag carrier
 
1254
                                attackers = (int) (float) numteammates * 0.8 + 0.5;
 
1255
                                if (attackers > 8) attackers = 8;
 
1256
                                for (i = 0; i < defenders; i++) {
 
1257
                                        //
 
1258
                                        if (teammates[i] == bs->flagcarrier) {
 
1259
                                                continue;
 
1260
                                        }
 
1261
                                        ClientName(teammates[i], name, sizeof(name));
 
1262
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1263
                                        BotSayTeamOrder(bs, teammates[i]);
 
1264
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1265
                                }
 
1266
                                ClientName(bs->flagcarrier, carriername, sizeof(carriername));
 
1267
                                for (i = 0; i < attackers; i++) {
 
1268
                                        //
 
1269
                                        if (teammates[numteammates - i - 1] == bs->flagcarrier) {
 
1270
                                                continue;
 
1271
                                        }
 
1272
                                        //
 
1273
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1274
                                        if (bs->flagcarrier == bs->client) {
 
1275
                                                BotAI_BotInitialChat(bs, "cmd_accompanyme", name, NULL);
 
1276
                                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWME);
 
1277
                                        }
 
1278
                                        else {
 
1279
                                                BotAI_BotInitialChat(bs, "cmd_accompany", name, carriername, NULL);
 
1280
                                                BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_FOLLOWFLAGCARRIER);
 
1281
                                        }
 
1282
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1283
                                }
 
1284
                                //
 
1285
                                break;
 
1286
                        }
 
1287
                }
 
1288
        }
 
1289
}
 
1290
 
 
1291
/*
 
1292
==================
 
1293
Bot1FCTFOrders_EnemyHasFlag
 
1294
 
 
1295
  X% defend the base, Y% towards neutral flag
 
1296
==================
 
1297
*/
 
1298
void Bot1FCTFOrders_EnemyHasFlag(bot_state_t *bs) {
 
1299
        int numteammates, defenders, attackers, i;
 
1300
        int teammates[MAX_CLIENTS];
 
1301
        char name[MAX_NETNAME];
 
1302
 
 
1303
        //sort team mates by travel time to base
 
1304
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
1305
        //sort team mates by CTF preference
 
1306
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
1307
        //passive strategy
 
1308
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
1309
                //different orders based on the number of team mates
 
1310
                switch(numteammates) {
 
1311
                        case 1: break;
 
1312
                        case 2:
 
1313
                        {
 
1314
                                //both defend the base
 
1315
                                ClientName(teammates[0], name, sizeof(name));
 
1316
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1317
                                BotSayTeamOrder(bs, teammates[0]);
 
1318
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1319
                                //
 
1320
                                ClientName(teammates[1], name, sizeof(name));
 
1321
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1322
                                BotSayTeamOrder(bs, teammates[1]);
 
1323
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1324
                                break;
 
1325
                        }
 
1326
                        case 3:
 
1327
                        {
 
1328
                                //the one closest to the base will defend the base
 
1329
                                ClientName(teammates[0], name, sizeof(name));
 
1330
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1331
                                BotSayTeamOrder(bs, teammates[0]);
 
1332
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1333
                                //the second one closest to the base will defend the base
 
1334
                                ClientName(teammates[1], name, sizeof(name));
 
1335
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1336
                                BotSayTeamOrder(bs, teammates[1]);
 
1337
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1338
                                //the other will also defend the base
 
1339
                                ClientName(teammates[2], name, sizeof(name));
 
1340
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1341
                                BotSayTeamOrder(bs, teammates[2]);
 
1342
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_DEFEND);
 
1343
                                break;
 
1344
                        }
 
1345
                        default:
 
1346
                        {
 
1347
                                //80% will defend the base
 
1348
                                defenders = (int) (float) numteammates * 0.8 + 0.5;
 
1349
                                if (defenders > 8) defenders = 8;
 
1350
                                //10% will try to return the flag
 
1351
                                attackers = (int) (float) numteammates * 0.1 + 0.5;
 
1352
                                if (attackers > 2) attackers = 2;
 
1353
                                for (i = 0; i < defenders; i++) {
 
1354
                                        //
 
1355
                                        ClientName(teammates[i], name, sizeof(name));
 
1356
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1357
                                        BotSayTeamOrder(bs, teammates[i]);
 
1358
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1359
                                }
 
1360
                                for (i = 0; i < attackers; i++) {
 
1361
                                        //
 
1362
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1363
                                        BotAI_BotInitialChat(bs, "cmd_returnflag", name, NULL);
 
1364
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1365
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1366
                                }
 
1367
                                //
 
1368
                                break;
 
1369
                        }
 
1370
                }
 
1371
        }
 
1372
        else { //agressive
 
1373
                //different orders based on the number of team mates
 
1374
                switch(numteammates) {
 
1375
                        case 1: break;
 
1376
                        case 2:
 
1377
                        {
 
1378
                                //the one closest to the base will defend the base
 
1379
                                ClientName(teammates[0], name, sizeof(name));
 
1380
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1381
                                BotSayTeamOrder(bs, teammates[0]);
 
1382
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1383
                                //the other will get the flag
 
1384
                                ClientName(teammates[1], name, sizeof(name));
 
1385
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1386
                                BotSayTeamOrder(bs, teammates[1]);
 
1387
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1388
                                break;
 
1389
                        }
 
1390
                        case 3:
 
1391
                        {
 
1392
                                //the one closest to the base will defend the base
 
1393
                                ClientName(teammates[0], name, sizeof(name));
 
1394
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1395
                                BotSayTeamOrder(bs, teammates[0]);
 
1396
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1397
                                //the others should go for the enemy flag
 
1398
                                ClientName(teammates[1], name, sizeof(name));
 
1399
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1400
                                BotSayTeamOrder(bs, teammates[1]);
 
1401
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1402
                                //
 
1403
                                ClientName(teammates[2], name, sizeof(name));
 
1404
                                BotAI_BotInitialChat(bs, "cmd_returnflag", name, NULL);
 
1405
                                BotSayTeamOrder(bs, teammates[2]);
 
1406
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
1407
                                break;
 
1408
                        }
 
1409
                        default:
 
1410
                        {
 
1411
                                //70% defend the base
 
1412
                                defenders = (int) (float) numteammates * 0.7 + 0.5;
 
1413
                                if (defenders > 8) defenders = 8;
 
1414
                                //20% try to return the flag
 
1415
                                attackers = (int) (float) numteammates * 0.2 + 0.5;
 
1416
                                if (attackers > 2) attackers = 2;
 
1417
                                for (i = 0; i < defenders; i++) {
 
1418
                                        //
 
1419
                                        ClientName(teammates[i], name, sizeof(name));
 
1420
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1421
                                        BotSayTeamOrder(bs, teammates[i]);
 
1422
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1423
                                }
 
1424
                                for (i = 0; i < attackers; i++) {
 
1425
                                        //
 
1426
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1427
                                        BotAI_BotInitialChat(bs, "cmd_returnflag", name, NULL);
 
1428
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1429
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1430
                                }
 
1431
                                //
 
1432
                                break;
 
1433
                        }
 
1434
                }
 
1435
        }
 
1436
}
 
1437
 
 
1438
/*
 
1439
==================
 
1440
Bot1FCTFOrders_EnemyDroppedFlag
 
1441
 
 
1442
  X% defend the base, Y% get the flag
 
1443
==================
 
1444
*/
 
1445
void Bot1FCTFOrders_EnemyDroppedFlag(bot_state_t *bs) {
 
1446
        int numteammates, defenders, attackers, i;
 
1447
        int teammates[MAX_CLIENTS];
 
1448
        char name[MAX_NETNAME];
 
1449
 
 
1450
        //sort team mates by travel time to base
 
1451
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
1452
        //sort team mates by CTF preference
 
1453
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
1454
        //passive strategy
 
1455
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
1456
                //different orders based on the number of team mates
 
1457
                switch(numteammates) {
 
1458
                        case 1: break;
 
1459
                        case 2:
 
1460
                        {
 
1461
                                //the one closest to the base will defend the base
 
1462
                                ClientName(teammates[0], name, sizeof(name));
 
1463
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1464
                                BotSayTeamOrder(bs, teammates[0]);
 
1465
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1466
                                //the other will get the flag
 
1467
                                ClientName(teammates[1], name, sizeof(name));
 
1468
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1469
                                BotSayTeamOrder(bs, teammates[1]);
 
1470
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
1471
                                break;
 
1472
                        }
 
1473
                        case 3:
 
1474
                        {
 
1475
                                //the one closest to the base will defend the base
 
1476
                                ClientName(teammates[0], name, sizeof(name));
 
1477
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1478
                                BotSayTeamOrder(bs, teammates[0]);
 
1479
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1480
                                //the second one closest to the base will defend the base
 
1481
                                ClientName(teammates[1], name, sizeof(name));
 
1482
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1483
                                BotSayTeamOrder(bs, teammates[1]);
 
1484
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1485
                                //the other will get the flag
 
1486
                                ClientName(teammates[2], name, sizeof(name));
 
1487
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1488
                                BotSayTeamOrder(bs, teammates[2]);
 
1489
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
1490
                                break;
 
1491
                        }
 
1492
                        default:
 
1493
                        {
 
1494
                                //50% defend the base
 
1495
                                defenders = (int) (float) numteammates * 0.5 + 0.5;
 
1496
                                if (defenders > 5) defenders = 5;
 
1497
                                //40% get the flag
 
1498
                                attackers = (int) (float) numteammates * 0.4 + 0.5;
 
1499
                                if (attackers > 4) attackers = 4;
 
1500
                                for (i = 0; i < defenders; i++) {
 
1501
                                        //
 
1502
                                        ClientName(teammates[i], name, sizeof(name));
 
1503
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1504
                                        BotSayTeamOrder(bs, teammates[i]);
 
1505
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1506
                                }
 
1507
                                for (i = 0; i < attackers; i++) {
 
1508
                                        //
 
1509
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1510
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1511
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1512
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_GETFLAG);
 
1513
                                }
 
1514
                                //
 
1515
                                break;
 
1516
                        }
 
1517
                }
 
1518
        }
 
1519
        else { //agressive
 
1520
                //different orders based on the number of team mates
 
1521
                switch(numteammates) {
 
1522
                        case 1: break;
 
1523
                        case 2:
 
1524
                        {
 
1525
                                //the one closest to the base will defend the base
 
1526
                                ClientName(teammates[0], name, sizeof(name));
 
1527
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1528
                                BotSayTeamOrder(bs, teammates[0]);
 
1529
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1530
                                //the other will get the flag
 
1531
                                ClientName(teammates[1], name, sizeof(name));
 
1532
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1533
                                BotSayTeamOrder(bs, teammates[1]);
 
1534
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
1535
                                break;
 
1536
                        }
 
1537
                        case 3:
 
1538
                        {
 
1539
                                //the one closest to the base will defend the base
 
1540
                                ClientName(teammates[0], name, sizeof(name));
 
1541
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1542
                                BotSayTeamOrder(bs, teammates[0]);
 
1543
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1544
                                //the others should go for the enemy flag
 
1545
                                ClientName(teammates[1], name, sizeof(name));
 
1546
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1547
                                BotSayTeamOrder(bs, teammates[1]);
 
1548
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_GETFLAG);
 
1549
                                //
 
1550
                                ClientName(teammates[2], name, sizeof(name));
 
1551
                                BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1552
                                BotSayTeamOrder(bs, teammates[2]);
 
1553
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_GETFLAG);
 
1554
                                break;
 
1555
                        }
 
1556
                        default:
 
1557
                        {
 
1558
                                //30% defend the base
 
1559
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
1560
                                if (defenders > 3) defenders = 3;
 
1561
                                //60% get the flag
 
1562
                                attackers = (int) (float) numteammates * 0.6 + 0.5;
 
1563
                                if (attackers > 6) attackers = 6;
 
1564
                                for (i = 0; i < defenders; i++) {
 
1565
                                        //
 
1566
                                        ClientName(teammates[i], name, sizeof(name));
 
1567
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1568
                                        BotSayTeamOrder(bs, teammates[i]);
 
1569
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1570
                                }
 
1571
                                for (i = 0; i < attackers; i++) {
 
1572
                                        //
 
1573
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1574
                                        BotAI_BotInitialChat(bs, "cmd_getflag", name, NULL);
 
1575
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1576
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_DEFEND);
 
1577
                                }
 
1578
                                //
 
1579
                                break;
 
1580
                        }
 
1581
                }
 
1582
        }
 
1583
}
 
1584
 
 
1585
/*
 
1586
==================
 
1587
Bot1FCTFOrders
 
1588
==================
 
1589
*/
 
1590
void Bot1FCTFOrders(bot_state_t *bs) {
 
1591
        switch(bs->neutralflagstatus) {
 
1592
                case 0: Bot1FCTFOrders_FlagAtCenter(bs); break;
 
1593
                case 1: Bot1FCTFOrders_TeamHasFlag(bs); break;
 
1594
                case 2: Bot1FCTFOrders_EnemyHasFlag(bs); break;
 
1595
                case 3: Bot1FCTFOrders_EnemyDroppedFlag(bs); break;
 
1596
        }
 
1597
}
 
1598
 
 
1599
/*
 
1600
==================
 
1601
BotObeliskOrders
 
1602
 
 
1603
  X% in defence Y% in offence
 
1604
==================
 
1605
*/
 
1606
void BotObeliskOrders(bot_state_t *bs) {
 
1607
        int numteammates, defenders, attackers, i;
 
1608
        int teammates[MAX_CLIENTS];
 
1609
        char name[MAX_NETNAME];
 
1610
 
 
1611
        //sort team mates by travel time to base
 
1612
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
1613
        //sort team mates by CTF preference
 
1614
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
1615
        //passive strategy
 
1616
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
1617
                //different orders based on the number of team mates
 
1618
                switch(numteammates) {
 
1619
                        case 1: break;
 
1620
                        case 2:
 
1621
                        {
 
1622
                                //the one closest to the base will defend the base
 
1623
                                ClientName(teammates[0], name, sizeof(name));
 
1624
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1625
                                BotSayTeamOrder(bs, teammates[0]);
 
1626
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1627
                                //the other will attack the enemy base
 
1628
                                ClientName(teammates[1], name, sizeof(name));
 
1629
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1630
                                BotSayTeamOrder(bs, teammates[1]);
 
1631
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1632
                                break;
 
1633
                        }
 
1634
                        case 3:
 
1635
                        {
 
1636
                                //the one closest to the base will defend the base
 
1637
                                ClientName(teammates[0], name, sizeof(name));
 
1638
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1639
                                BotSayTeamOrder(bs, teammates[0]);
 
1640
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1641
                                //the one second closest to the base also defends the base
 
1642
                                ClientName(teammates[1], name, sizeof(name));
 
1643
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1644
                                BotSayTeamOrder(bs, teammates[1]);
 
1645
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1646
                                //the other one attacks the enemy base
 
1647
                                ClientName(teammates[2], name, sizeof(name));
 
1648
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1649
                                BotSayTeamOrder(bs, teammates[2]);
 
1650
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_OFFENSE);
 
1651
                                break;
 
1652
                        }
 
1653
                        default:
 
1654
                        {
 
1655
                                //50% defend the base
 
1656
                                defenders = (int) (float) numteammates * 0.5 + 0.5;
 
1657
                                if (defenders > 5) defenders = 5;
 
1658
                                //40% attack the enemy base
 
1659
                                attackers = (int) (float) numteammates * 0.4 + 0.5;
 
1660
                                if (attackers > 4) attackers = 4;
 
1661
                                for (i = 0; i < defenders; i++) {
 
1662
                                        //
 
1663
                                        ClientName(teammates[i], name, sizeof(name));
 
1664
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1665
                                        BotSayTeamOrder(bs, teammates[i]);
 
1666
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1667
                                }
 
1668
                                for (i = 0; i < attackers; i++) {
 
1669
                                        //
 
1670
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1671
                                        BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1672
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1673
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_OFFENSE);
 
1674
                                }
 
1675
                                //
 
1676
                                break;
 
1677
                        }
 
1678
                }
 
1679
        }
 
1680
        else {
 
1681
                //different orders based on the number of team mates
 
1682
                switch(numteammates) {
 
1683
                        case 1: break;
 
1684
                        case 2:
 
1685
                        {
 
1686
                                //the one closest to the base will defend the base
 
1687
                                ClientName(teammates[0], name, sizeof(name));
 
1688
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1689
                                BotSayTeamOrder(bs, teammates[0]);
 
1690
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1691
                                //the other will attack the enemy base
 
1692
                                ClientName(teammates[1], name, sizeof(name));
 
1693
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1694
                                BotSayTeamOrder(bs, teammates[1]);
 
1695
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1696
                                break;
 
1697
                        }
 
1698
                        case 3:
 
1699
                        {
 
1700
                                //the one closest to the base will defend the base
 
1701
                                ClientName(teammates[0], name, sizeof(name));
 
1702
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1703
                                BotSayTeamOrder(bs, teammates[0]);
 
1704
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1705
                                //the others attack the enemy base
 
1706
                                ClientName(teammates[1], name, sizeof(name));
 
1707
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1708
                                BotSayTeamOrder(bs, teammates[1]);
 
1709
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1710
                                //
 
1711
                                ClientName(teammates[2], name, sizeof(name));
 
1712
                                BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1713
                                BotSayTeamOrder(bs, teammates[2]);
 
1714
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_OFFENSE);
 
1715
                                break;
 
1716
                        }
 
1717
                        default:
 
1718
                        {
 
1719
                                //30% defend the base
 
1720
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
1721
                                if (defenders > 3) defenders = 3;
 
1722
                                //70% attack the enemy base
 
1723
                                attackers = (int) (float) numteammates * 0.7 + 0.5;
 
1724
                                if (attackers > 7) attackers = 7;
 
1725
                                for (i = 0; i < defenders; i++) {
 
1726
                                        //
 
1727
                                        ClientName(teammates[i], name, sizeof(name));
 
1728
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1729
                                        BotSayTeamOrder(bs, teammates[i]);
 
1730
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1731
                                }
 
1732
                                for (i = 0; i < attackers; i++) {
 
1733
                                        //
 
1734
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1735
                                        BotAI_BotInitialChat(bs, "cmd_attackenemybase", name, NULL);
 
1736
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1737
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_OFFENSE);
 
1738
                                }
 
1739
                                //
 
1740
                                break;
 
1741
                        }
 
1742
                }
 
1743
        }
 
1744
}
 
1745
 
 
1746
/*
 
1747
==================
 
1748
BotHarvesterOrders
 
1749
 
 
1750
  X% defend the base, Y% harvest
 
1751
==================
 
1752
*/
 
1753
void BotHarvesterOrders(bot_state_t *bs) {
 
1754
        int numteammates, defenders, attackers, i;
 
1755
        int teammates[MAX_CLIENTS];
 
1756
        char name[MAX_NETNAME];
 
1757
 
 
1758
        //sort team mates by travel time to base
 
1759
        numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates));
 
1760
        //sort team mates by CTF preference
 
1761
        BotSortTeamMatesByTaskPreference(bs, teammates, numteammates);
 
1762
        //passive strategy
 
1763
        if (!(bs->ctfstrategy & CTFS_AGRESSIVE)) {
 
1764
                //different orders based on the number of team mates
 
1765
                switch(numteammates) {
 
1766
                        case 1: break;
 
1767
                        case 2:
 
1768
                        {
 
1769
                                //the one closest to the base will defend the base
 
1770
                                ClientName(teammates[0], name, sizeof(name));
 
1771
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1772
                                BotSayTeamOrder(bs, teammates[0]);
 
1773
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1774
                                //the other will harvest
 
1775
                                ClientName(teammates[1], name, sizeof(name));
 
1776
                                BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1777
                                BotSayTeamOrder(bs, teammates[1]);
 
1778
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1779
                                break;
 
1780
                        }
 
1781
                        case 3:
 
1782
                        {
 
1783
                                //the one closest to the base will defend the base
 
1784
                                ClientName(teammates[0], name, sizeof(name));
 
1785
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1786
                                BotSayTeamOrder(bs, teammates[0]);
 
1787
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1788
                                //the one second closest to the base also defends the base
 
1789
                                ClientName(teammates[1], name, sizeof(name));
 
1790
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1791
                                BotSayTeamOrder(bs, teammates[1]);
 
1792
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_DEFEND);
 
1793
                                //the other one goes harvesting
 
1794
                                ClientName(teammates[2], name, sizeof(name));
 
1795
                                BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1796
                                BotSayTeamOrder(bs, teammates[2]);
 
1797
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_OFFENSE);
 
1798
                                break;
 
1799
                        }
 
1800
                        default:
 
1801
                        {
 
1802
                                //50% defend the base
 
1803
                                defenders = (int) (float) numteammates * 0.5 + 0.5;
 
1804
                                if (defenders > 5) defenders = 5;
 
1805
                                //40% goes harvesting
 
1806
                                attackers = (int) (float) numteammates * 0.4 + 0.5;
 
1807
                                if (attackers > 4) attackers = 4;
 
1808
                                for (i = 0; i < defenders; i++) {
 
1809
                                        //
 
1810
                                        ClientName(teammates[i], name, sizeof(name));
 
1811
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1812
                                        BotSayTeamOrder(bs, teammates[i]);
 
1813
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1814
                                }
 
1815
                                for (i = 0; i < attackers; i++) {
 
1816
                                        //
 
1817
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1818
                                        BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1819
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1820
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_OFFENSE);
 
1821
                                }
 
1822
                                //
 
1823
                                break;
 
1824
                        }
 
1825
                }
 
1826
        }
 
1827
        else {
 
1828
                //different orders based on the number of team mates
 
1829
                switch(numteammates) {
 
1830
                        case 1: break;
 
1831
                        case 2:
 
1832
                        {
 
1833
                                //the one closest to the base will defend the base
 
1834
                                ClientName(teammates[0], name, sizeof(name));
 
1835
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1836
                                BotSayTeamOrder(bs, teammates[0]);
 
1837
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1838
                                //the other will harvest
 
1839
                                ClientName(teammates[1], name, sizeof(name));
 
1840
                                BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1841
                                BotSayTeamOrder(bs, teammates[1]);
 
1842
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1843
                                break;
 
1844
                        }
 
1845
                        case 3:
 
1846
                        {
 
1847
                                //the one closest to the base will defend the base
 
1848
                                ClientName(teammates[0], name, sizeof(name));
 
1849
                                BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1850
                                BotSayTeamOrder(bs, teammates[0]);
 
1851
                                BotSayVoiceTeamOrder(bs, teammates[0], VOICECHAT_DEFEND);
 
1852
                                //the others go harvesting
 
1853
                                ClientName(teammates[1], name, sizeof(name));
 
1854
                                BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1855
                                BotSayTeamOrder(bs, teammates[1]);
 
1856
                                BotSayVoiceTeamOrder(bs, teammates[1], VOICECHAT_OFFENSE);
 
1857
                                //
 
1858
                                ClientName(teammates[2], name, sizeof(name));
 
1859
                                BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1860
                                BotSayTeamOrder(bs, teammates[2]);
 
1861
                                BotSayVoiceTeamOrder(bs, teammates[2], VOICECHAT_OFFENSE);
 
1862
                                break;
 
1863
                        }
 
1864
                        default:
 
1865
                        {
 
1866
                                //30% defend the base
 
1867
                                defenders = (int) (float) numteammates * 0.3 + 0.5;
 
1868
                                if (defenders > 3) defenders = 3;
 
1869
                                //70% go harvesting
 
1870
                                attackers = (int) (float) numteammates * 0.7 + 0.5;
 
1871
                                if (attackers > 7) attackers = 7;
 
1872
                                for (i = 0; i < defenders; i++) {
 
1873
                                        //
 
1874
                                        ClientName(teammates[i], name, sizeof(name));
 
1875
                                        BotAI_BotInitialChat(bs, "cmd_defendbase", name, NULL);
 
1876
                                        BotSayTeamOrder(bs, teammates[i]);
 
1877
                                        BotSayVoiceTeamOrder(bs, teammates[i], VOICECHAT_DEFEND);
 
1878
                                }
 
1879
                                for (i = 0; i < attackers; i++) {
 
1880
                                        //
 
1881
                                        ClientName(teammates[numteammates - i - 1], name, sizeof(name));
 
1882
                                        BotAI_BotInitialChat(bs, "cmd_harvest", name, NULL);
 
1883
                                        BotSayTeamOrder(bs, teammates[numteammates - i - 1]);
 
1884
                                        BotSayVoiceTeamOrder(bs, teammates[numteammates - i - 1], VOICECHAT_OFFENSE);
 
1885
                                }
 
1886
                                //
 
1887
                                break;
 
1888
                        }
 
1889
                }
 
1890
        }
 
1891
}
 
1892
#endif
 
1893
 
 
1894
/*
 
1895
==================
 
1896
FindHumanTeamLeader
 
1897
==================
 
1898
*/
 
1899
int FindHumanTeamLeader(bot_state_t *bs) {
 
1900
        int i;
 
1901
 
 
1902
        for (i = 0; i < MAX_CLIENTS; i++) {
 
1903
                if ( g_entities[i].inuse ) {
 
1904
                        // if this player is not a bot
 
1905
                        if ( !(g_entities[i].r.svFlags & SVF_BOT) ) {
 
1906
                                // if this player is ok with being the leader
 
1907
                                if (!notleader[i]) {
 
1908
                                        // if this player is on the same team
 
1909
                                        if ( BotSameTeam(bs, i) ) {
 
1910
                                                ClientName(i, bs->teamleader, sizeof(bs->teamleader));
 
1911
                                                // if not yet ordered to do anything
 
1912
                                                if ( !BotSetLastOrderedTask(bs) ) {
 
1913
                                                        // go on defense by default
 
1914
                                                        BotVoiceChat_Defend(bs, i, SAY_TELL);
 
1915
                                                }
 
1916
                                                return qtrue;
 
1917
                                        }
 
1918
                                }
 
1919
                        }
 
1920
                }
 
1921
        }
 
1922
        return qfalse;
 
1923
}
 
1924
 
 
1925
/*
 
1926
==================
 
1927
BotTeamAI
 
1928
==================
 
1929
*/
 
1930
void BotTeamAI(bot_state_t *bs) {
 
1931
        int numteammates;
 
1932
        char netname[MAX_NETNAME];
 
1933
 
 
1934
        //
 
1935
        if ( gametype < GT_TEAM  )
 
1936
                return;
 
1937
        // make sure we've got a valid team leader
 
1938
        if (!BotValidTeamLeader(bs)) {
 
1939
                //
 
1940
                if (!FindHumanTeamLeader(bs)) {
 
1941
                        //
 
1942
                        if (!bs->askteamleader_time && !bs->becometeamleader_time) {
 
1943
                                if (bs->entergame_time + 10 > FloatTime()) {
 
1944
                                        bs->askteamleader_time = FloatTime() + 5 + random() * 10;
 
1945
                                }
 
1946
                                else {
 
1947
                                        bs->becometeamleader_time = FloatTime() + 5 + random() * 10;
 
1948
                                }
 
1949
                        }
 
1950
                        if (bs->askteamleader_time && bs->askteamleader_time < FloatTime()) {
 
1951
                                // if asked for a team leader and no response
 
1952
                                BotAI_BotInitialChat(bs, "whoisteamleader", NULL);
 
1953
                                trap_BotEnterChat(bs->cs, 0, CHAT_TEAM);
 
1954
                                bs->askteamleader_time = 0;
 
1955
                                bs->becometeamleader_time = FloatTime() + 8 + random() * 10;
 
1956
                        }
 
1957
                        if (bs->becometeamleader_time && bs->becometeamleader_time < FloatTime()) {
 
1958
                                BotAI_BotInitialChat(bs, "iamteamleader", NULL);
 
1959
                                trap_BotEnterChat(bs->cs, 0, CHAT_TEAM);
 
1960
                                BotSayVoiceTeamOrder(bs, -1, VOICECHAT_STARTLEADER);
 
1961
                                ClientName(bs->client, netname, sizeof(netname));
 
1962
                                strncpy(bs->teamleader, netname, sizeof(bs->teamleader));
 
1963
                                bs->teamleader[sizeof(bs->teamleader)] = '\0';
 
1964
                                bs->becometeamleader_time = 0;
 
1965
                        }
 
1966
                        return;
 
1967
                }
 
1968
        }
 
1969
        bs->askteamleader_time = 0;
 
1970
        bs->becometeamleader_time = 0;
 
1971
 
 
1972
        //return if this bot is NOT the team leader
 
1973
        ClientName(bs->client, netname, sizeof(netname));
 
1974
        if (Q_stricmp(netname, bs->teamleader) != 0) return;
 
1975
        //
 
1976
        numteammates = BotNumTeamMates(bs);
 
1977
        //give orders
 
1978
        switch(gametype) {
 
1979
                case GT_TEAM:
 
1980
                {
 
1981
                        if (bs->numteammates != numteammates || bs->forceorders) {
 
1982
                                bs->teamgiveorders_time = FloatTime();
 
1983
                                bs->numteammates = numteammates;
 
1984
                                bs->forceorders = qfalse;
 
1985
                        }
 
1986
                        //if it's time to give orders
 
1987
                        if (bs->teamgiveorders_time && bs->teamgiveorders_time < FloatTime() - 5) {
 
1988
                                BotTeamOrders(bs);
 
1989
                                //give orders again after 120 seconds
 
1990
                                bs->teamgiveorders_time = FloatTime() + 120;
 
1991
                        }
 
1992
                        break;
 
1993
                }
 
1994
                case GT_CTF:
 
1995
                {
 
1996
                        //if the number of team mates changed or the flag status changed
 
1997
                        //or someone wants to know what to do
 
1998
                        if (bs->numteammates != numteammates || bs->flagstatuschanged || bs->forceorders) {
 
1999
                                bs->teamgiveorders_time = FloatTime();
 
2000
                                bs->numteammates = numteammates;
 
2001
                                bs->flagstatuschanged = qfalse;
 
2002
                                bs->forceorders = qfalse;
 
2003
                        }
 
2004
                        //if there were no flag captures the last 3 minutes
 
2005
                        if (bs->lastflagcapture_time < FloatTime() - 240) {
 
2006
                                bs->lastflagcapture_time = FloatTime();
 
2007
                                //randomly change the CTF strategy
 
2008
                                if (random() < 0.4) {
 
2009
                                        bs->ctfstrategy ^= CTFS_AGRESSIVE;
 
2010
                                        bs->teamgiveorders_time = FloatTime();
 
2011
                                }
 
2012
                        }
 
2013
                        //if it's time to give orders
 
2014
                        if (bs->teamgiveorders_time && bs->teamgiveorders_time < FloatTime() - 3) {
 
2015
                                BotCTFOrders(bs);
 
2016
                                //
 
2017
                                bs->teamgiveorders_time = 0;
 
2018
                        }
 
2019
                        break;
 
2020
                }
 
2021
#ifdef MISSIONPACK
 
2022
                case GT_1FCTF:
 
2023
                {
 
2024
                        if (bs->numteammates != numteammates || bs->flagstatuschanged || bs->forceorders) {
 
2025
                                bs->teamgiveorders_time = FloatTime();
 
2026
                                bs->numteammates = numteammates;
 
2027
                                bs->flagstatuschanged = qfalse;
 
2028
                                bs->forceorders = qfalse;
 
2029
                        }
 
2030
                        //if there were no flag captures the last 4 minutes
 
2031
                        if (bs->lastflagcapture_time < FloatTime() - 240) {
 
2032
                                bs->lastflagcapture_time = FloatTime();
 
2033
                                //randomly change the CTF strategy
 
2034
                                if (random() < 0.4) {
 
2035
                                        bs->ctfstrategy ^= CTFS_AGRESSIVE;
 
2036
                                        bs->teamgiveorders_time = FloatTime();
 
2037
                                }
 
2038
                        }
 
2039
                        //if it's time to give orders
 
2040
                        if (bs->teamgiveorders_time && bs->teamgiveorders_time < FloatTime() - 2) {
 
2041
                                Bot1FCTFOrders(bs);
 
2042
                                //
 
2043
                                bs->teamgiveorders_time = 0;
 
2044
                        }
 
2045
                        break;
 
2046
                }
 
2047
                case GT_OBELISK:
 
2048
                {
 
2049
                        if (bs->numteammates != numteammates || bs->forceorders) {
 
2050
                                bs->teamgiveorders_time = FloatTime();
 
2051
                                bs->numteammates = numteammates;
 
2052
                                bs->forceorders = qfalse;
 
2053
                        }
 
2054
                        //if it's time to give orders
 
2055
                        if (bs->teamgiveorders_time && bs->teamgiveorders_time < FloatTime() - 5) {
 
2056
                                BotObeliskOrders(bs);
 
2057
                                //give orders again after 30 seconds
 
2058
                                bs->teamgiveorders_time = FloatTime() + 30;
 
2059
                        }
 
2060
                        break;
 
2061
                }
 
2062
                case GT_HARVESTER:
 
2063
                {
 
2064
                        if (bs->numteammates != numteammates || bs->forceorders) {
 
2065
                                bs->teamgiveorders_time = FloatTime();
 
2066
                                bs->numteammates = numteammates;
 
2067
                                bs->forceorders = qfalse;
 
2068
                        }
 
2069
                        //if it's time to give orders
 
2070
                        if (bs->teamgiveorders_time && bs->teamgiveorders_time < FloatTime() - 5) {
 
2071
                                BotHarvesterOrders(bs);
 
2072
                                //give orders again after 30 seconds
 
2073
                                bs->teamgiveorders_time = FloatTime() + 30;
 
2074
                        }
 
2075
                        break;
 
2076
                }
 
2077
#endif
 
2078
        }
 
2079
}
 
2080