ai_team.c 65 KB

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