00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "g_local.h"
00035 #include "botlib.h"
00036 #include "be_aas.h"
00037 #include "be_ea.h"
00038 #include "be_ai_char.h"
00039 #include "be_ai_chat.h"
00040 #include "be_ai_gen.h"
00041 #include "be_ai_goal.h"
00042 #include "be_ai_move.h"
00043 #include "be_ai_weap.h"
00044
00045 #include "ai_main.h"
00046 #include "ai_dmq3.h"
00047 #include "ai_chat.h"
00048 #include "ai_cmd.h"
00049 #include "ai_dmnet.h"
00050 #include "ai_team.h"
00051
00052 #include "chars.h"
00053 #include "inv.h"
00054 #include "syn.h"
00055 #include "match.h"
00056
00057
00058 #include "../../ui/menudef.h"
00059
00060
00061 #define AREACONTENTS_MOVER 1024
00062 #define AREACONTENTS_MODELNUMSHIFT 24
00063 #define AREACONTENTS_MAXMODELNUM 0xFF
00064 #define AREACONTENTS_MODELNUM (AREACONTENTS_MAXMODELNUM << AREACONTENTS_MODELNUMSHIFT)
00065
00066 #define IDEAL_ATTACKDIST 140
00067
00068 #define MAX_WAYPOINTS 128
00069
00070 bot_waypoint_t botai_waypoints[MAX_WAYPOINTS];
00071 bot_waypoint_t *botai_freewaypoints;
00072
00073
00074 int gametype;
00075 int maxclients;
00076
00077 vmCvar_t bot_grapple;
00078 vmCvar_t bot_rocketjump;
00079 vmCvar_t bot_fastchat;
00080 vmCvar_t bot_nochat;
00081 vmCvar_t bot_testrchat;
00082 vmCvar_t bot_challenge;
00083 vmCvar_t bot_predictobstacles;
00084 vmCvar_t g_spSkill;
00085
00086 extern vmCvar_t bot_developer;
00087
00088 vec3_t lastteleport_origin;
00089 float lastteleport_time;
00090 int max_bspmodelindex;
00091
00092
00093 bot_goal_t ctf_redflag;
00094 bot_goal_t ctf_blueflag;
00095 #ifdef MISSIONPACK
00096 bot_goal_t ctf_neutralflag;
00097 bot_goal_t redobelisk;
00098 bot_goal_t blueobelisk;
00099 bot_goal_t neutralobelisk;
00100 #endif
00101
00102 #define MAX_ALTROUTEGOALS 32
00103
00104 int altroutegoals_setup;
00105 aas_altroutegoal_t red_altroutegoals[MAX_ALTROUTEGOALS];
00106 int red_numaltroutegoals;
00107 aas_altroutegoal_t blue_altroutegoals[MAX_ALTROUTEGOALS];
00108 int blue_numaltroutegoals;
00109
00110
00111
00112
00113
00114
00115
00116 void BotSetUserInfo(bot_state_t *bs, char *key, char *value) {
00117 char userinfo[MAX_INFO_STRING];
00118
00119 trap_GetUserinfo(bs->client, userinfo, sizeof(userinfo));
00120 Info_SetValueForKey(userinfo, key, value);
00121 trap_SetUserinfo(bs->client, userinfo);
00122 ClientUserinfoChanged( bs->client );
00123 }
00124
00125
00126
00127
00128
00129
00130 int BotCTFCarryingFlag(bot_state_t *bs) {
00131 if (gametype != GT_CTF) return CTF_FLAG_NONE;
00132
00133 if (bs->inventory[INVENTORY_REDFLAG] > 0) return CTF_FLAG_RED;
00134 else if (bs->inventory[INVENTORY_BLUEFLAG] > 0) return CTF_FLAG_BLUE;
00135 return CTF_FLAG_NONE;
00136 }
00137
00138
00139
00140
00141
00142
00143 int BotTeam(bot_state_t *bs) {
00144 char info[1024];
00145
00146 if (bs->client < 0 || bs->client >= MAX_CLIENTS) {
00147
00148 return qfalse;
00149 }
00150 trap_GetConfigstring(CS_PLAYERS+bs->client, info, sizeof(info));
00151
00152 if (atoi(Info_ValueForKey(info, "t")) == TEAM_RED) return TEAM_RED;
00153 else if (atoi(Info_ValueForKey(info, "t")) == TEAM_BLUE) return TEAM_BLUE;
00154 return TEAM_FREE;
00155 }
00156
00157
00158
00159
00160
00161
00162 int BotOppositeTeam(bot_state_t *bs) {
00163 switch(BotTeam(bs)) {
00164 case TEAM_RED: return TEAM_BLUE;
00165 case TEAM_BLUE: return TEAM_RED;
00166 default: return TEAM_FREE;
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175 bot_goal_t *BotEnemyFlag(bot_state_t *bs) {
00176 if (BotTeam(bs) == TEAM_RED) {
00177 return &ctf_blueflag;
00178 }
00179 else {
00180 return &ctf_redflag;
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189 bot_goal_t *BotTeamFlag(bot_state_t *bs) {
00190 if (BotTeam(bs) == TEAM_RED) {
00191 return &ctf_redflag;
00192 }
00193 else {
00194 return &ctf_blueflag;
00195 }
00196 }
00197
00198
00199
00200
00201
00202
00203
00204 qboolean EntityIsDead(aas_entityinfo_t *entinfo) {
00205 playerState_t ps;
00206
00207 if (entinfo->number >= 0 && entinfo->number < MAX_CLIENTS) {
00208
00209 BotAI_GetClientState( entinfo->number, &ps );
00210 if (ps.pm_type != PM_NORMAL) return qtrue;
00211 }
00212 return qfalse;
00213 }
00214
00215
00216
00217
00218
00219
00220 qboolean EntityCarriesFlag(aas_entityinfo_t *entinfo) {
00221 if ( entinfo->powerups & ( 1 << PW_REDFLAG ) )
00222 return qtrue;
00223 if ( entinfo->powerups & ( 1 << PW_BLUEFLAG ) )
00224 return qtrue;
00225 #ifdef MISSIONPACK
00226 if ( entinfo->powerups & ( 1 << PW_NEUTRALFLAG ) )
00227 return qtrue;
00228 #endif
00229 return qfalse;
00230 }
00231
00232
00233
00234
00235
00236
00237 qboolean EntityIsInvisible(aas_entityinfo_t *entinfo) {
00238
00239 if (EntityCarriesFlag(entinfo)) {
00240 return qfalse;
00241 }
00242 if (entinfo->powerups & (1 << PW_INVIS)) {
00243 return qtrue;
00244 }
00245 return qfalse;
00246 }
00247
00248
00249
00250
00251
00252
00253 qboolean EntityIsShooting(aas_entityinfo_t *entinfo) {
00254 if (entinfo->flags & EF_FIRING) {
00255 return qtrue;
00256 }
00257 return qfalse;
00258 }
00259
00260
00261
00262
00263
00264
00265 qboolean EntityIsChatting(aas_entityinfo_t *entinfo) {
00266 if (entinfo->flags & EF_TALK) {
00267 return qtrue;
00268 }
00269 return qfalse;
00270 }
00271
00272
00273
00274
00275
00276
00277 qboolean EntityHasQuad(aas_entityinfo_t *entinfo) {
00278 if (entinfo->powerups & (1 << PW_QUAD)) {
00279 return qtrue;
00280 }
00281 return qfalse;
00282 }
00283
00284 #ifdef MISSIONPACK
00285
00286
00287
00288
00289
00290 qboolean EntityHasKamikaze(aas_entityinfo_t *entinfo) {
00291 if (entinfo->flags & EF_KAMIKAZE) {
00292 return qtrue;
00293 }
00294 return qfalse;
00295 }
00296
00297
00298
00299
00300
00301
00302 qboolean EntityCarriesCubes(aas_entityinfo_t *entinfo) {
00303 entityState_t state;
00304
00305 if (gametype != GT_HARVESTER)
00306 return qfalse;
00307
00308 BotAI_GetEntityState(entinfo->number, &state);
00309 if (state.generic1 > 0)
00310 return qtrue;
00311 return qfalse;
00312 }
00313
00314
00315
00316
00317
00318
00319 int Bot1FCTFCarryingFlag(bot_state_t *bs) {
00320 if (gametype != GT_1FCTF) return qfalse;
00321
00322 if (bs->inventory[INVENTORY_NEUTRALFLAG] > 0) return qtrue;
00323 return qfalse;
00324 }
00325
00326
00327
00328
00329
00330
00331 int BotHarvesterCarryingCubes(bot_state_t *bs) {
00332 if (gametype != GT_HARVESTER) return qfalse;
00333
00334 if (bs->inventory[INVENTORY_REDCUBE] > 0) return qtrue;
00335 if (bs->inventory[INVENTORY_BLUECUBE] > 0) return qtrue;
00336 return qfalse;
00337 }
00338 #endif
00339
00340
00341
00342
00343
00344
00345 void BotRememberLastOrderedTask(bot_state_t *bs) {
00346 if (!bs->ordered) {
00347 return;
00348 }
00349 bs->lastgoal_decisionmaker = bs->decisionmaker;
00350 bs->lastgoal_ltgtype = bs->ltgtype;
00351 memcpy(&bs->lastgoal_teamgoal, &bs->teamgoal, sizeof(bot_goal_t));
00352 bs->lastgoal_teammate = bs->teammate;
00353 }
00354
00355
00356
00357
00358
00359
00360 void BotSetTeamStatus(bot_state_t *bs) {
00361 #ifdef MISSIONPACK
00362 int teamtask;
00363 aas_entityinfo_t entinfo;
00364
00365 teamtask = TEAMTASK_PATROL;
00366
00367 switch(bs->ltgtype) {
00368 case LTG_TEAMHELP:
00369 break;
00370 case LTG_TEAMACCOMPANY:
00371 BotEntityInfo(bs->teammate, &entinfo);
00372 if ( ( (gametype == GT_CTF || gametype == GT_1FCTF) && EntityCarriesFlag(&entinfo))
00373 || ( gametype == GT_HARVESTER && EntityCarriesCubes(&entinfo)) ) {
00374 teamtask = TEAMTASK_ESCORT;
00375 }
00376 else {
00377 teamtask = TEAMTASK_FOLLOW;
00378 }
00379 break;
00380 case LTG_DEFENDKEYAREA:
00381 teamtask = TEAMTASK_DEFENSE;
00382 break;
00383 case LTG_GETFLAG:
00384 teamtask = TEAMTASK_OFFENSE;
00385 break;
00386 case LTG_RUSHBASE:
00387 teamtask = TEAMTASK_DEFENSE;
00388 break;
00389 case LTG_RETURNFLAG:
00390 teamtask = TEAMTASK_RETRIEVE;
00391 break;
00392 case LTG_CAMP:
00393 case LTG_CAMPORDER:
00394 teamtask = TEAMTASK_CAMP;
00395 break;
00396 case LTG_PATROL:
00397 teamtask = TEAMTASK_PATROL;
00398 break;
00399 case LTG_GETITEM:
00400 teamtask = TEAMTASK_PATROL;
00401 break;
00402 case LTG_KILL:
00403 teamtask = TEAMTASK_PATROL;
00404 break;
00405 case LTG_HARVEST:
00406 teamtask = TEAMTASK_OFFENSE;
00407 break;
00408 case LTG_ATTACKENEMYBASE:
00409 teamtask = TEAMTASK_OFFENSE;
00410 break;
00411 default:
00412 teamtask = TEAMTASK_PATROL;
00413 break;
00414 }
00415 BotSetUserInfo(bs, "teamtask", va("%d", teamtask));
00416 #endif
00417 }
00418
00419
00420
00421
00422
00423
00424 int BotSetLastOrderedTask(bot_state_t *bs) {
00425
00426 if (gametype == GT_CTF) {
00427
00428 if ( bs->lastgoal_ltgtype == LTG_RETURNFLAG ) {
00429 if ( BotTeam(bs) == TEAM_RED ) {
00430 if ( bs->redflagstatus == 0 ) {
00431 bs->lastgoal_ltgtype = 0;
00432 }
00433 }
00434 else {
00435 if ( bs->blueflagstatus == 0 ) {
00436 bs->lastgoal_ltgtype = 0;
00437 }
00438 }
00439 }
00440 }
00441
00442 if ( bs->lastgoal_ltgtype ) {
00443 bs->decisionmaker = bs->lastgoal_decisionmaker;
00444 bs->ordered = qtrue;
00445 bs->ltgtype = bs->lastgoal_ltgtype;
00446 memcpy(&bs->teamgoal, &bs->lastgoal_teamgoal, sizeof(bot_goal_t));
00447 bs->teammate = bs->lastgoal_teammate;
00448 bs->teamgoal_time = FloatTime() + 300;
00449 BotSetTeamStatus(bs);
00450
00451 if ( gametype == GT_CTF ) {
00452 if ( bs->ltgtype == LTG_GETFLAG ) {
00453 bot_goal_t *tb, *eb;
00454 int tt, et;
00455
00456 tb = BotTeamFlag(bs);
00457 eb = BotEnemyFlag(bs);
00458 tt = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, tb->areanum, TFL_DEFAULT);
00459 et = trap_AAS_AreaTravelTimeToGoalArea(bs->areanum, bs->origin, eb->areanum, TFL_DEFAULT);
00460
00461 if (et > tt) {
00462
00463 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00464 }
00465 }
00466 }
00467 return qtrue;
00468 }
00469 return qfalse;
00470 }
00471
00472
00473
00474
00475
00476
00477 void BotRefuseOrder(bot_state_t *bs) {
00478 if (!bs->ordered)
00479 return;
00480
00481 if ( bs->order_time && bs->order_time > FloatTime() - 10 ) {
00482 trap_EA_Action(bs->client, ACTION_NEGATIVE);
00483 BotVoiceChat(bs, bs->decisionmaker, VOICECHAT_NO);
00484 bs->order_time = 0;
00485 }
00486 }
00487
00488
00489
00490
00491
00492
00493 void BotCTFSeekGoals(bot_state_t *bs) {
00494 float rnd, l1, l2;
00495 int flagstatus, c;
00496 vec3_t dir;
00497 aas_entityinfo_t entinfo;
00498
00499
00500 if (BotCTFCarryingFlag(bs)) {
00501
00502 if (bs->ltgtype != LTG_RUSHBASE) {
00503 BotRefuseOrder(bs);
00504 bs->ltgtype = LTG_RUSHBASE;
00505 bs->teamgoal_time = FloatTime() + CTF_RUSHBASE_TIME;
00506 bs->rushbaseaway_time = 0;
00507 bs->decisionmaker = bs->client;
00508 bs->ordered = qfalse;
00509
00510 switch(BotTeam(bs)) {
00511 case TEAM_RED: VectorSubtract(bs->origin, ctf_blueflag.origin, dir); break;
00512 case TEAM_BLUE: VectorSubtract(bs->origin, ctf_redflag.origin, dir); break;
00513 default: VectorSet(dir, 999, 999, 999); break;
00514 }
00515
00516 if ( VectorLength(dir) < 128 ) {
00517
00518 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00519 } else {
00520
00521 bs->altroutegoal.areanum = 0;
00522 }
00523 BotSetUserInfo(bs, "teamtask", va("%d", TEAMTASK_OFFENSE));
00524 BotVoiceChat(bs, -1, VOICECHAT_IHAVEFLAG);
00525 }
00526 else if (bs->rushbaseaway_time > FloatTime()) {
00527 if (BotTeam(bs) == TEAM_RED) flagstatus = bs->redflagstatus;
00528 else flagstatus = bs->blueflagstatus;
00529
00530 if (flagstatus == 0) {
00531 bs->rushbaseaway_time = 0;
00532 }
00533 }
00534 return;
00535 }
00536
00537 if ( bs->ltgtype == LTG_TEAMACCOMPANY && !bs->ordered ) {
00538
00539 BotEntityInfo(bs->teammate, &entinfo);
00540 if (!EntityCarriesFlag(&entinfo)) {
00541 bs->ltgtype = 0;
00542 }
00543 }
00544
00545 if (BotTeam(bs) == TEAM_RED) flagstatus = bs->redflagstatus * 2 + bs->blueflagstatus;
00546 else flagstatus = bs->blueflagstatus * 2 + bs->redflagstatus;
00547
00548 if (flagstatus == 1) {
00549
00550 if (bs->owndecision_time < FloatTime()) {
00551
00552 if (!(bs->ltgtype == LTG_DEFENDKEYAREA &&
00553 (bs->teamgoal.number == ctf_redflag.number ||
00554 bs->teamgoal.number == ctf_blueflag.number))) {
00555
00556 c = BotTeamFlagCarrierVisible(bs);
00557 if (c >= 0 &&
00558
00559 (bs->ltgtype != LTG_TEAMACCOMPANY || bs->teammate != c)) {
00560
00561 BotRefuseOrder(bs);
00562
00563 bs->decisionmaker = bs->client;
00564 bs->ordered = qfalse;
00565
00566 bs->teammate = c;
00567
00568 bs->teammatevisible_time = FloatTime();
00569
00570 bs->teammessage_time = 0;
00571
00572 bs->arrive_time = 1;
00573
00574 BotVoiceChat(bs, bs->teammate, VOICECHAT_ONFOLLOW);
00575
00576 bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
00577 bs->ltgtype = LTG_TEAMACCOMPANY;
00578 bs->formation_dist = 3.5 * 32;
00579 BotSetTeamStatus(bs);
00580 bs->owndecision_time = FloatTime() + 5;
00581 }
00582 }
00583 }
00584 return;
00585 }
00586
00587 else if (flagstatus == 2) {
00588
00589 if (bs->owndecision_time < FloatTime()) {
00590
00591 c = BotEnemyFlagCarrierVisible(bs);
00592 if (c >= 0) {
00593
00594 }
00595
00596 if (bs->ltgtype != LTG_GETFLAG &&
00597 bs->ltgtype != LTG_RETURNFLAG &&
00598 bs->ltgtype != LTG_TEAMHELP &&
00599 bs->ltgtype != LTG_TEAMACCOMPANY &&
00600 bs->ltgtype != LTG_CAMPORDER &&
00601 bs->ltgtype != LTG_PATROL &&
00602 bs->ltgtype != LTG_GETITEM) {
00603
00604 BotRefuseOrder(bs);
00605 bs->decisionmaker = bs->client;
00606 bs->ordered = qfalse;
00607
00608 if (random() < 0.5) {
00609
00610 bs->ltgtype = LTG_GETFLAG;
00611 }
00612 else {
00613 bs->ltgtype = LTG_RETURNFLAG;
00614 }
00615
00616 bs->teammessage_time = 0;
00617
00618 bs->teamgoal_time = FloatTime() + CTF_GETFLAG_TIME;
00619
00620 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00621
00622 BotSetTeamStatus(bs);
00623 bs->owndecision_time = FloatTime() + 5;
00624 }
00625 }
00626 return;
00627 }
00628
00629 else if (flagstatus == 3) {
00630
00631 if (bs->owndecision_time < FloatTime()) {
00632
00633 if ( bs->ltgtype != LTG_RETURNFLAG && bs->ltgtype != LTG_TEAMACCOMPANY ) {
00634
00635 c = BotTeamFlagCarrierVisible(bs);
00636
00637 if (c >= 0) {
00638 BotRefuseOrder(bs);
00639
00640 bs->decisionmaker = bs->client;
00641 bs->ordered = qfalse;
00642
00643 bs->teammate = c;
00644
00645 bs->teammatevisible_time = FloatTime();
00646
00647 bs->teammessage_time = 0;
00648
00649 bs->arrive_time = 1;
00650
00651 BotVoiceChat(bs, bs->teammate, VOICECHAT_ONFOLLOW);
00652
00653 bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
00654 bs->ltgtype = LTG_TEAMACCOMPANY;
00655 bs->formation_dist = 3.5 * 32;
00656
00657 BotSetTeamStatus(bs);
00658 bs->owndecision_time = FloatTime() + 5;
00659 }
00660 else {
00661 BotRefuseOrder(bs);
00662 bs->decisionmaker = bs->client;
00663 bs->ordered = qfalse;
00664
00665 bs->teammessage_time = FloatTime() + 2 * random();
00666
00667 bs->ltgtype = LTG_RETURNFLAG;
00668
00669 bs->teamgoal_time = FloatTime() + CTF_RETURNFLAG_TIME;
00670
00671 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00672
00673 BotSetTeamStatus(bs);
00674 bs->owndecision_time = FloatTime() + 5;
00675 }
00676 }
00677 }
00678 return;
00679 }
00680
00681 if (BotTeamLeader(bs)) {
00682 return;
00683 }
00684
00685 if ( bs->lastgoal_ltgtype ) {
00686 bs->teamgoal_time += 60;
00687 }
00688
00689 if ( !bs->ordered && bs->lastgoal_ltgtype ) {
00690 bs->ltgtype = 0;
00691 }
00692
00693 if (bs->ltgtype == LTG_TEAMHELP ||
00694 bs->ltgtype == LTG_TEAMACCOMPANY ||
00695 bs->ltgtype == LTG_DEFENDKEYAREA ||
00696 bs->ltgtype == LTG_GETFLAG ||
00697 bs->ltgtype == LTG_RUSHBASE ||
00698 bs->ltgtype == LTG_RETURNFLAG ||
00699 bs->ltgtype == LTG_CAMPORDER ||
00700 bs->ltgtype == LTG_PATROL ||
00701 bs->ltgtype == LTG_GETITEM ||
00702 bs->ltgtype == LTG_MAKELOVE_UNDER ||
00703 bs->ltgtype == LTG_MAKELOVE_ONTOP) {
00704 return;
00705 }
00706
00707 if (BotSetLastOrderedTask(bs))
00708 return;
00709
00710 if (bs->owndecision_time > FloatTime())
00711 return;;
00712
00713 if (bs->ctfroam_time > FloatTime())
00714 return;
00715
00716 if (BotAggression(bs) < 50)
00717 return;
00718
00719 bs->teammessage_time = FloatTime() + 2 * random();
00720
00721 if (bs->teamtaskpreference & (TEAMTP_ATTACKER|TEAMTP_DEFENDER)) {
00722 if (bs->teamtaskpreference & TEAMTP_ATTACKER) {
00723 l1 = 0.7f;
00724 }
00725 else {
00726 l1 = 0.2f;
00727 }
00728 l2 = 0.9f;
00729 }
00730 else {
00731 l1 = 0.4f;
00732 l2 = 0.7f;
00733 }
00734
00735 rnd = random();
00736 if (rnd < l1 && ctf_redflag.areanum && ctf_blueflag.areanum) {
00737 bs->decisionmaker = bs->client;
00738 bs->ordered = qfalse;
00739 bs->ltgtype = LTG_GETFLAG;
00740
00741 bs->teamgoal_time = FloatTime() + CTF_GETFLAG_TIME;
00742
00743 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00744 BotSetTeamStatus(bs);
00745 }
00746 else if (rnd < l2 && ctf_redflag.areanum && ctf_blueflag.areanum) {
00747 bs->decisionmaker = bs->client;
00748 bs->ordered = qfalse;
00749
00750 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t));
00751 else memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t));
00752
00753 bs->ltgtype = LTG_DEFENDKEYAREA;
00754
00755 bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
00756 bs->defendaway_time = 0;
00757 BotSetTeamStatus(bs);
00758 }
00759 else {
00760 bs->ltgtype = 0;
00761
00762 bs->ctfroam_time = FloatTime() + CTF_ROAM_TIME;
00763 BotSetTeamStatus(bs);
00764 }
00765 bs->owndecision_time = FloatTime() + 5;
00766 #ifdef DEBUG
00767 BotPrintTeamGoal(bs);
00768 #endif //DEBUG
00769 }
00770
00771
00772
00773
00774
00775
00776 void BotCTFRetreatGoals(bot_state_t *bs) {
00777
00778 if (BotCTFCarryingFlag(bs)) {
00779
00780 if (bs->ltgtype != LTG_RUSHBASE) {
00781 BotRefuseOrder(bs);
00782 bs->ltgtype = LTG_RUSHBASE;
00783 bs->teamgoal_time = FloatTime() + CTF_RUSHBASE_TIME;
00784 bs->rushbaseaway_time = 0;
00785 bs->decisionmaker = bs->client;
00786 bs->ordered = qfalse;
00787 BotSetTeamStatus(bs);
00788 }
00789 }
00790 }
00791
00792 #ifdef MISSIONPACK
00793
00794
00795
00796
00797
00798 void Bot1FCTFSeekGoals(bot_state_t *bs) {
00799 aas_entityinfo_t entinfo;
00800 float rnd, l1, l2;
00801 int c;
00802
00803
00804 if (Bot1FCTFCarryingFlag(bs)) {
00805
00806 if (bs->ltgtype != LTG_RUSHBASE) {
00807 BotRefuseOrder(bs);
00808 bs->ltgtype = LTG_RUSHBASE;
00809 bs->teamgoal_time = FloatTime() + CTF_RUSHBASE_TIME;
00810 bs->rushbaseaway_time = 0;
00811 bs->decisionmaker = bs->client;
00812 bs->ordered = qfalse;
00813
00814 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
00815
00816 BotSetTeamStatus(bs);
00817 BotVoiceChat(bs, -1, VOICECHAT_IHAVEFLAG);
00818 }
00819 return;
00820 }
00821
00822 if ( bs->ltgtype == LTG_TEAMACCOMPANY && !bs->ordered ) {
00823
00824 BotEntityInfo(bs->teammate, &entinfo);
00825 if (!EntityCarriesFlag(&entinfo)) {
00826 bs->ltgtype = 0;
00827 }
00828 }
00829
00830 if (bs->neutralflagstatus == 1) {
00831 if (bs->owndecision_time < FloatTime()) {
00832
00833 if (bs->ltgtype != LTG_TEAMACCOMPANY) {
00834
00835 c = BotTeamFlagCarrierVisible(bs);
00836 if (c >= 0) {
00837 BotRefuseOrder(bs);
00838
00839 bs->decisionmaker = bs->client;
00840 bs->ordered = qfalse;
00841
00842 bs->teammate = c;
00843
00844 bs->teammatevisible_time = FloatTime();
00845
00846 bs->teammessage_time = 0;
00847
00848 bs->arrive_time = 1;
00849
00850 BotVoiceChat(bs, bs->teammate, VOICECHAT_ONFOLLOW);
00851
00852 bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
00853 bs->ltgtype = LTG_TEAMACCOMPANY;
00854 bs->formation_dist = 3.5 * 32;
00855 BotSetTeamStatus(bs);
00856 bs->owndecision_time = FloatTime() + 5;
00857 return;
00858 }
00859 }
00860
00861 if (bs->ltgtype == LTG_TEAMHELP ||
00862 bs->ltgtype == LTG_TEAMACCOMPANY ||
00863 bs->ltgtype == LTG_DEFENDKEYAREA ||
00864 bs->ltgtype == LTG_GETFLAG ||
00865 bs->ltgtype == LTG_RUSHBASE ||
00866 bs->ltgtype == LTG_CAMPORDER ||
00867 bs->ltgtype == LTG_PATROL ||
00868 bs->ltgtype == LTG_ATTACKENEMYBASE ||
00869 bs->ltgtype == LTG_GETITEM ||
00870 bs->ltgtype == LTG_MAKELOVE_UNDER ||
00871 bs->ltgtype == LTG_MAKELOVE_ONTOP) {
00872 return;
00873 }
00874
00875 if (bs->ltgtype != LTG_ATTACKENEMYBASE) {
00876 BotRefuseOrder(bs);
00877 bs->decisionmaker = bs->client;
00878 bs->ordered = qfalse;
00879
00880 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t));
00881 else memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t));
00882
00883 bs->ltgtype = LTG_ATTACKENEMYBASE;
00884
00885 bs->teamgoal_time = FloatTime() + TEAM_ATTACKENEMYBASE_TIME;
00886 BotSetTeamStatus(bs);
00887 bs->owndecision_time = FloatTime() + 5;
00888 }
00889 }
00890 return;
00891 }
00892
00893 else if (bs->neutralflagstatus == 2) {
00894 if (bs->owndecision_time < FloatTime()) {
00895 c = BotEnemyFlagCarrierVisible(bs);
00896 if (c >= 0) {
00897
00898 }
00899
00900 if (bs->ltgtype == LTG_TEAMHELP ||
00901 bs->ltgtype == LTG_TEAMACCOMPANY ||
00902 bs->ltgtype == LTG_CAMPORDER ||
00903 bs->ltgtype == LTG_PATROL ||
00904 bs->ltgtype == LTG_GETITEM) {
00905 return;
00906 }
00907
00908 if (bs->ltgtype != LTG_DEFENDKEYAREA) {
00909 BotRefuseOrder(bs);
00910 bs->decisionmaker = bs->client;
00911 bs->ordered = qfalse;
00912
00913 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t));
00914 else memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t));
00915
00916 bs->ltgtype = LTG_DEFENDKEYAREA;
00917
00918 bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
00919 bs->defendaway_time = 0;
00920 BotSetTeamStatus(bs);
00921 bs->owndecision_time = FloatTime() + 5;
00922 }
00923 }
00924 return;
00925 }
00926
00927 if (BotTeamLeader(bs)) {
00928 return;
00929 }
00930
00931 if ( bs->lastgoal_ltgtype ) {
00932 bs->teamgoal_time += 60;
00933 }
00934
00935 if ( !bs->ordered && bs->lastgoal_ltgtype ) {
00936 bs->ltgtype = 0;
00937 }
00938
00939 if (bs->ltgtype == LTG_TEAMHELP ||
00940 bs->ltgtype == LTG_TEAMACCOMPANY ||
00941 bs->ltgtype == LTG_DEFENDKEYAREA ||
00942 bs->ltgtype == LTG_GETFLAG ||
00943 bs->ltgtype == LTG_RUSHBASE ||
00944 bs->ltgtype == LTG_RETURNFLAG ||
00945 bs->ltgtype == LTG_CAMPORDER ||
00946 bs->ltgtype == LTG_PATROL ||
00947 bs->ltgtype == LTG_ATTACKENEMYBASE ||
00948 bs->ltgtype == LTG_GETITEM ||
00949 bs->ltgtype == LTG_MAKELOVE_UNDER ||
00950 bs->ltgtype == LTG_MAKELOVE_ONTOP) {
00951 return;
00952 }
00953
00954 if (BotSetLastOrderedTask(bs))
00955 return;
00956
00957 if (bs->owndecision_time > FloatTime())
00958 return;;
00959
00960 if (bs->ctfroam_time > FloatTime())
00961 return;
00962
00963 if (BotAggression(bs) < 50)
00964 return;
00965
00966 bs->teammessage_time = FloatTime() + 2 * random();
00967
00968 if (bs->teamtaskpreference & (TEAMTP_ATTACKER|TEAMTP_DEFENDER)) {
00969 if (bs->teamtaskpreference & TEAMTP_ATTACKER) {
00970 l1 = 0.7f;
00971 }
00972 else {
00973 l1 = 0.2f;
00974 }
00975 l2 = 0.9f;
00976 }
00977 else {
00978 l1 = 0.4f;
00979 l2 = 0.7f;
00980 }
00981
00982 rnd = random();
00983 if (rnd < l1 && ctf_neutralflag.areanum) {
00984 bs->decisionmaker = bs->client;
00985 bs->ordered = qfalse;
00986 bs->ltgtype = LTG_GETFLAG;
00987
00988 bs->teamgoal_time = FloatTime() + CTF_GETFLAG_TIME;
00989 BotSetTeamStatus(bs);
00990 }
00991 else if (rnd < l2 && ctf_redflag.areanum && ctf_blueflag.areanum) {
00992 bs->decisionmaker = bs->client;
00993 bs->ordered = qfalse;
00994
00995 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &ctf_redflag, sizeof(bot_goal_t));
00996 else memcpy(&bs->teamgoal, &ctf_blueflag, sizeof(bot_goal_t));
00997
00998 bs->ltgtype = LTG_DEFENDKEYAREA;
00999
01000 bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
01001 bs->defendaway_time = 0;
01002 BotSetTeamStatus(bs);
01003 }
01004 else {
01005 bs->ltgtype = 0;
01006
01007 bs->ctfroam_time = FloatTime() + CTF_ROAM_TIME;
01008 BotSetTeamStatus(bs);
01009 }
01010 bs->owndecision_time = FloatTime() + 5;
01011 #ifdef DEBUG
01012 BotPrintTeamGoal(bs);
01013 #endif //DEBUG
01014 }
01015
01016
01017
01018
01019
01020
01021 void Bot1FCTFRetreatGoals(bot_state_t *bs) {
01022
01023 if (Bot1FCTFCarryingFlag(bs)) {
01024
01025 if (bs->ltgtype != LTG_RUSHBASE) {
01026 BotRefuseOrder(bs);
01027 bs->ltgtype = LTG_RUSHBASE;
01028 bs->teamgoal_time = FloatTime() + CTF_RUSHBASE_TIME;
01029 bs->rushbaseaway_time = 0;
01030 bs->decisionmaker = bs->client;
01031 bs->ordered = qfalse;
01032
01033 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
01034 BotSetTeamStatus(bs);
01035 }
01036 }
01037 }
01038
01039
01040
01041
01042
01043
01044 void BotObeliskSeekGoals(bot_state_t *bs) {
01045 float rnd, l1, l2;
01046
01047
01048 if (BotTeamLeader(bs)) {
01049 return;
01050 }
01051
01052 if ( bs->lastgoal_ltgtype ) {
01053 bs->teamgoal_time += 60;
01054 }
01055
01056 if (bs->ltgtype == LTG_TEAMHELP ||
01057 bs->ltgtype == LTG_TEAMACCOMPANY ||
01058 bs->ltgtype == LTG_DEFENDKEYAREA ||
01059 bs->ltgtype == LTG_GETFLAG ||
01060 bs->ltgtype == LTG_RUSHBASE ||
01061 bs->ltgtype == LTG_RETURNFLAG ||
01062 bs->ltgtype == LTG_CAMPORDER ||
01063 bs->ltgtype == LTG_PATROL ||
01064 bs->ltgtype == LTG_ATTACKENEMYBASE ||
01065 bs->ltgtype == LTG_GETITEM ||
01066 bs->ltgtype == LTG_MAKELOVE_UNDER ||
01067 bs->ltgtype == LTG_MAKELOVE_ONTOP) {
01068 return;
01069 }
01070
01071 if (BotSetLastOrderedTask(bs))
01072 return;
01073
01074 if (bs->ctfroam_time > FloatTime())
01075 return;
01076
01077 if (BotAggression(bs) < 50)
01078 return;
01079
01080 bs->teammessage_time = FloatTime() + 2 * random();
01081
01082 if (bs->teamtaskpreference & (TEAMTP_ATTACKER|TEAMTP_DEFENDER)) {
01083 if (bs->teamtaskpreference & TEAMTP_ATTACKER) {
01084 l1 = 0.7f;
01085 }
01086 else {
01087 l1 = 0.2f;
01088 }
01089 l2 = 0.9f;
01090 }
01091 else {
01092 l1 = 0.4f;
01093 l2 = 0.7f;
01094 }
01095
01096 rnd = random();
01097 if (rnd < l1 && redobelisk.areanum && blueobelisk.areanum) {
01098 bs->decisionmaker = bs->client;
01099 bs->ordered = qfalse;
01100
01101 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t));
01102 else memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t));
01103
01104 bs->ltgtype = LTG_ATTACKENEMYBASE;
01105
01106 bs->teamgoal_time = FloatTime() + TEAM_ATTACKENEMYBASE_TIME;
01107
01108 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
01109 BotSetTeamStatus(bs);
01110 }
01111 else if (rnd < l2 && redobelisk.areanum && blueobelisk.areanum) {
01112 bs->decisionmaker = bs->client;
01113 bs->ordered = qfalse;
01114
01115 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t));
01116 else memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t));
01117
01118 bs->ltgtype = LTG_DEFENDKEYAREA;
01119
01120 bs->teamgoal_time = FloatTime() + TEAM_DEFENDKEYAREA_TIME;
01121 bs->defendaway_time = 0;
01122 BotSetTeamStatus(bs);
01123 }
01124 else {
01125 bs->ltgtype = 0;
01126
01127 bs->ctfroam_time = FloatTime() + CTF_ROAM_TIME;
01128 BotSetTeamStatus(bs);
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137 void BotGoHarvest(bot_state_t *bs) {
01138
01139 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot_goal_t));
01140 else memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t));
01141
01142 bs->ltgtype = LTG_HARVEST;
01143
01144 bs->teamgoal_time = FloatTime() + TEAM_HARVEST_TIME;
01145 bs->harvestaway_time = 0;
01146 BotSetTeamStatus(bs);
01147 }
01148
01149
01150
01151
01152
01153
01154 void BotObeliskRetreatGoals(bot_state_t *bs) {
01155
01156 }
01157
01158
01159
01160
01161
01162
01163 void BotHarvesterSeekGoals(bot_state_t *bs) {
01164 aas_entityinfo_t entinfo;
01165 float rnd, l1, l2;
01166 int c;
01167
01168
01169 if (BotHarvesterCarryingCubes(bs)) {
01170
01171 if (bs->ltgtype != LTG_RUSHBASE) {
01172 BotRefuseOrder(bs);
01173 bs->ltgtype = LTG_RUSHBASE;
01174 bs->teamgoal_time = FloatTime() + CTF_RUSHBASE_TIME;
01175 bs->rushbaseaway_time = 0;
01176 bs->decisionmaker = bs->client;
01177 bs->ordered = qfalse;
01178
01179 BotGetAlternateRouteGoal(bs, BotOppositeTeam(bs));
01180
01181 BotSetTeamStatus(bs);
01182 }
01183 return;
01184 }
01185
01186 if (BotTeamLeader(bs)) {
01187 return;
01188 }
01189
01190 if ( bs->ltgtype == LTG_TEAMACCOMPANY && !bs->ordered ) {
01191
01192 BotEntityInfo(bs->teammate, &entinfo);
01193 if (!EntityCarriesCubes(&entinfo)) {
01194 bs->ltgtype = 0;
01195 }
01196 }
01197
01198 if ( bs->lastgoal_ltgtype ) {
01199 bs->teamgoal_time += 60;
01200 }
01201
01202 if (bs->ltgtype == LTG_TEAMHELP ||
01203 bs->ltgtype == LTG_TEAMACCOMPANY ||
01204 bs->ltgtype == LTG_DEFENDKEYAREA ||
01205 bs->ltgtype == LTG_GETFLAG ||
01206 bs->ltgtype == LTG_CAMPORDER ||
01207 bs->ltgtype == LTG_PATROL ||
01208 bs->ltgtype == LTG_ATTACKENEMYBASE ||
01209 bs->ltgtype == LTG_HARVEST ||
01210 bs->ltgtype == LTG_GETITEM ||
01211 bs->ltgtype == LTG_MAKELOVE_UNDER ||
01212 bs->ltgtype == LTG_MAKELOVE_ONTOP) {
01213 return;
01214 }
01215
01216 if (BotSetLastOrderedTask(bs))
01217 return;
01218
01219 if (bs->ctfroam_time > FloatTime())
01220 return;
01221
01222 if (BotAggression(bs) < 50)
01223 return;
01224
01225 bs->teammessage_time = FloatTime() + 2 * random();
01226
01227 c = BotEnemyCubeCarrierVisible(bs);
01228 if (c >= 0) {
01229
01230 }
01231 if (bs->ltgtype != LTG_TEAMACCOMPANY) {
01232
01233 c = BotTeamCubeCarrierVisible(bs);
01234 if (c >= 0) {
01235
01236 bs->decisionmaker = bs->client;
01237 bs->ordered = qfalse;
01238
01239 bs->teammate = c;
01240
01241 bs->teammatevisible_time = FloatTime();
01242
01243 bs->teammessage_time = 0;
01244
01245 bs->arrive_time = 1;
01246
01247 BotVoiceChat(bs, bs->teammate, VOICECHAT_ONFOLLOW);
01248
01249 bs->teamgoal_time = FloatTime() + TEAM_ACCOMPANY_TIME;
01250 bs->ltgtype = LTG_TEAMACCOMPANY;
01251 bs->formation_dist = 3.5 * 32;
01252 BotSetTeamStatus(bs);
01253 return;
01254 }
01255 }
01256
01257 if (bs->teamtaskpreference & (TEAMTP_ATTACKER|TEAMTP_DEFENDER)) {
01258 if (bs->teamtaskpreference & TEAMTP_ATTACKER) {
01259 l1 = 0.7f;
01260 }
01261 else {
01262 l1 = 0.2f;
01263 }
01264 l2 = 0.9f;
01265 }
01266 else {
01267 l1 = 0.4f;
01268 l2 = 0.7f;
01269 }
01270
01271 rnd = random();
01272 if (rnd < l1 && redobelisk.areanum && blueobelisk.areanum) {
01273 bs->decisionmaker = bs->client;
01274 bs->ordered = qfalse;
01275 BotGoHarvest(bs);
01276 }
01277 else if (rnd < l2 && redobelisk.areanum && blueobelisk.areanum) {
01278 bs->decisionmaker = bs->client;
01279 bs->ordered = qfalse;
01280
01281 if (BotTeam(bs) == TEAM_RED) memcpy(&bs->teamgoal, &redobelisk, sizeof(bot_goal_t));
01282 else memcpy(&bs->teamgoal, &blueobelisk, sizeof(bot