#include "g_local.h"#include "q_shared.h"#include "botlib.h"#include "be_aas.h"#include "be_ea.h"#include "be_ai_char.h"#include "be_ai_chat.h"#include "be_ai_gen.h"#include "be_ai_goal.h"#include "be_ai_move.h"#include "be_ai_weap.h"#include "ai_main.h"#include "w_saber.h"#include "chars.h"#include "inv.h"#include "syn.h"Go to the source code of this file.
|
|
|
|
|
Definition at line 43 of file ai_main.c. Referenced by BotAIStartFrame(), and BotScheduleBotThink(). |
|
|
|
|
|
Definition at line 1552 of file ai_main.c. Referenced by BotTrace_Strafe(), and StandardBotAI(). |
|
|
Definition at line 1551 of file ai_main.c. Referenced by BotTrace_Strafe(), and StandardBotAI(). |
|
|
Definition at line 5502 of file ai_main.c. References bot_state_t, bot_state_s::cur_ps, bot_state_s::doAltAttack, WEAPON_CHARGING_ALT, and playerState_s::weaponstate. Referenced by StandardBotAI().
05503 {
05504 if (bs->cur_ps.weaponstate != WEAPON_CHARGING_ALT &&
05505 bs->doAltAttack)
05506 {
05507 return 1;
05508 }
05509
05510 if (bs->cur_ps.weaponstate == WEAPON_CHARGING_ALT &&
05511 !bs->doAltAttack)
05512 {
05513 return 1;
05514 }
05515
05516 return 0;
05517 }
|
|
||||||||||||
|
Definition at line 425 of file ai_main.c. Referenced by BotChangeViewAngles(), and BotTrace_Strafe().
00425 {
00426 float diff;
00427
00428 diff = ang1 - ang2;
00429 if (ang1 > ang2) {
00430 if (diff > 180.0) diff -= 360.0;
00431 }
00432 else {
00433 if (diff < -180.0) diff += 360.0;
00434 }
00435 return diff;
00436 }
|
|
||||||||||||||||||||
|
Definition at line 5883 of file ai_main.c. References bot_state_t, botstates, bot_state_s::forceMove_Forward, bot_state_s::forceMove_Right, and bot_state_s::forceMove_Up. Referenced by ClientCommand().
05884 {
05885 bot_state_t *bs;
05886
05887 bs = botstates[bot];
05888
05889 if (!bs)
05890 { //not a bot
05891 return;
05892 }
05893
05894 if (forward != -1)
05895 {
05896 if (bs->forceMove_Forward)
05897 {
05898 bs->forceMove_Forward = 0;
05899 }
05900 else
05901 {
05902 bs->forceMove_Forward = forward;
05903 }
05904 }
05905 if (right != -1)
05906 {
05907 if (bs->forceMove_Right)
05908 {
05909 bs->forceMove_Right = 0;
05910 }
05911 else
05912 {
05913 bs->forceMove_Right = right;
05914 }
05915 }
05916 if (up != -1)
05917 {
05918 if (bs->forceMove_Up)
05919 {
05920 bs->forceMove_Up = 0;
05921 }
05922 else
05923 {
05924 bs->forceMove_Up = up;
05925 }
05926 }
05927 }
|
|
||||||||||||
|
Definition at line 696 of file ai_main.c. References AngleMod(), bot_state_t, BotAI_GetClientState(), BotAI_Print(), botstates, client, Com_Printf(), bot_state_s::cur_ps, playerState_s::delta_angles, bot_state_s::eye, vmCvar_t::integer, bot_state_s::inuse, bot_state_s::ltime, bot_state_s::origin, playerState_s::origin, PRT_FATAL, Q_stricmp(), qfalse, qtrue, RemoveColorEscapeSequences(), SHORT2ANGLE, StandardBotAI(), strchr(), bot_state_s::thinktime, trap_BotGetServerCommand(), trap_Cvar_Update(), trap_EA_ResetInput(), trap_Milliseconds(), VectorCopy, bot_state_s::viewangles, and playerState_s::viewheight. Referenced by BotAIStartFrame().
00696 {
00697 bot_state_t *bs;
00698 char buf[1024], *args;
00699 int j;
00700 #ifdef _DEBUG
00701 int start = 0;
00702 int end = 0;
00703 #endif
00704
00705 trap_EA_ResetInput(client);
00706 //
00707 bs = botstates[client];
00708 if (!bs || !bs->inuse) {
00709 BotAI_Print(PRT_FATAL, "BotAI: client %d is not setup\n", client);
00710 return qfalse;
00711 }
00712
00713 //retrieve the current client state
00714 BotAI_GetClientState( client, &bs->cur_ps );
00715
00716 //retrieve any waiting server commands
00717 while( trap_BotGetServerCommand(client, buf, sizeof(buf)) ) {
00718 //have buf point to the command and args to the command arguments
00719 args = strchr( buf, ' ');
00720 if (!args) continue;
00721 *args++ = '\0';
00722
00723 //remove color espace sequences from the arguments
00724 RemoveColorEscapeSequences( args );
00725
00726 if (!Q_stricmp(buf, "cp "))
00727 { /*CenterPrintf*/ }
00728 else if (!Q_stricmp(buf, "cs"))
00729 { /*ConfigStringModified*/ }
00730 else if (!Q_stricmp(buf, "scores"))
00731 { /*FIXME: parse scores?*/ }
00732 else if (!Q_stricmp(buf, "clientLevelShot"))
00733 { /*ignore*/ }
00734 }
00735 //add the delta angles to the bot's current view angles
00736 for (j = 0; j < 3; j++) {
00737 bs->viewangles[j] = AngleMod(bs->viewangles[j] + SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
00738 }
00739 //increase the local time of the bot
00740 bs->ltime += thinktime;
00741 //
00742 bs->thinktime = thinktime;
00743 //origin of the bot
00744 VectorCopy(bs->cur_ps.origin, bs->origin);
00745 //eye coordinates of the bot
00746 VectorCopy(bs->cur_ps.origin, bs->eye);
00747 bs->eye[2] += bs->cur_ps.viewheight;
00748 //get the area the bot is in
00749
00750 #ifdef _DEBUG
00751 start = trap_Milliseconds();
00752 #endif
00753 StandardBotAI(bs, thinktime);
00754 #ifdef _DEBUG
00755 end = trap_Milliseconds();
00756
00757 trap_Cvar_Update(&bot_debugmessages);
00758
00759 if (bot_debugmessages.integer)
00760 {
00761 Com_Printf("Single AI frametime: %i\n", (end - start));
00762 }
00763 #endif
00764
00765 //subtract the delta angles
00766 for (j = 0; j < 3; j++) {
00767 bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
00768 }
00769 //everything was ok
00770 return qtrue;
00771 }
|
|
||||||||||||
|
Definition at line 351 of file ai_main.c. References gentity_s::client, g_entities, gentity_t, gentity_s::inuse, memcpy(), playerState_t, gclient_s::ps, qfalse, and qtrue. Referenced by BotAI().
|
|
||||||||||||
|
Definition at line 371 of file ai_main.c. References entityState_t, g_entities, gentity_t, gentity_s::inuse, entityShared_t::linked, memcpy(), memset(), qfalse, qtrue, gentity_s::r, gentity_s::s, SVF_NOCLIENT, and entityShared_t::svFlags. Referenced by BotAI_GetSnapshotEntity().
00371 {
00372 gentity_t *ent;
00373
00374 ent = &g_entities[entityNum];
00375 memset( state, 0, sizeof(entityState_t) );
00376 if (!ent->inuse) return qfalse;
00377 if (!ent->r.linked) return qfalse;
00378 if (ent->r.svFlags & SVF_NOCLIENT) return qfalse;
00379 memcpy( state, &ent->s, sizeof(entityState_t) );
00380 return qtrue;
00381 }
|
|
||||||||||||||||
|
Definition at line 388 of file ai_main.c. References BotAI_GetEntityState(), entityState_t, memset(), and trap_BotGetSnapshotEntity().
00388 {
00389 int entNum;
00390
00391 entNum = trap_BotGetSnapshotEntity( clientNum, sequence );
00392 if ( entNum == -1 ) {
00393 memset(state, 0, sizeof(entityState_t));
00394 return -1;
00395 }
00396
00397 BotAI_GetEntityState( entNum, state );
00398
00399 return sequence + 1;
00400 }
|
|
||||||||||||||||
|
Definition at line 332 of file ai_main.c. References QDECL. Referenced by BotAI(), and BotAISetupClient().
00332 { return; }
|
|
|
Definition at line 966 of file ai_main.c. References BotResetState(), botstates, bot_state_s::inuse, MAX_CLIENTS, qtrue, and bot_state_s::setupcount. Referenced by G_InitGame().
00966 {
00967 int i;
00968
00969 for (i = 0; i < MAX_CLIENTS; i++) {
00970 if (botstates[i] && botstates[i]->inuse) {
00971 BotResetState( botstates[i] );
00972 botstates[i]->setupcount = 4;
00973 }
00974 }
00975
00976 return qtrue;
00977 }
|
|
||||||||||||||||
|
Definition at line 4607 of file ai_main.c. References bot_state_t, gentity_s::client, bot_state_s::currentEnemy, bot_state_s::eye, bot_state_s::frame_Enemy_Len, bot_state_s::goalAngles, gclient_s::ps, vec3_t, vectoangles(), VectorCopy, VectorNormalize(), VectorSubtract, and playerState_s::velocity. Referenced by StandardBotAI().
04608 {
04609 int x;
04610 vec3_t predictedSpot;
04611 vec3_t movementVector;
04612 vec3_t a, ang;
04613 float vtotal;
04614
04615 if (!bs->currentEnemy ||
04616 !bs->currentEnemy->client)
04617 {
04618 return;
04619 }
04620
04621 if (!bs->frame_Enemy_Len)
04622 {
04623 return;
04624 }
04625
04626 vtotal = 0;
04627
04628 if (bs->currentEnemy->client->ps.velocity[0] < 0)
04629 {
04630 vtotal += -bs->currentEnemy->client->ps.velocity[0];
04631 }
04632 else
04633 {
04634 vtotal += bs->currentEnemy->client->ps.velocity[0];
04635 }
04636
04637 if (bs->currentEnemy->client->ps.velocity[1] < 0)
04638 {
04639 vtotal += -bs->currentEnemy->client->ps.velocity[1];
04640 }
04641 else
04642 {
04643 vtotal += bs->currentEnemy->client->ps.velocity[1];
04644 }
04645
04646 if (bs->currentEnemy->client->ps.velocity[2] < 0)
04647 {
04648 vtotal += -bs->currentEnemy->client->ps.velocity[2];
04649 }
04650 else
04651 {
04652 vtotal += bs->currentEnemy->client->ps.velocity[2];
04653 }
04654
04655 //G_Printf("Leadin target with a velocity total of %f\n", vtotal);
04656
04657 VectorCopy(bs->currentEnemy->client->ps.velocity, movementVector);
04658
04659 VectorNormalize(movementVector);
04660
04661 x = bs->frame_Enemy_Len*leadAmount; //hardly calculated with an exact science, but it works
04662
04663 if (vtotal > 400)
04664 {
04665 vtotal = 400;
04666 }
04667
04668 if (vtotal)
04669 {
04670 x = (bs->frame_Enemy_Len*0.9)*leadAmount*(vtotal*0.0012); //hardly calculated with an exact science, but it works
04671 }
04672 else
04673 {
04674 x = (bs->frame_Enemy_Len*0.9)*leadAmount; //hardly calculated with an exact science, but it works
04675 }
04676
04677 predictedSpot[0] = headlevel[0] + (movementVector[0]*x);
04678 predictedSpot[1] = headlevel[1] + (movementVector[1]*x);
04679 predictedSpot[2] = headlevel[2] + (movementVector[2]*x);
04680
04681 VectorSubtract(predictedSpot, bs->eye, a);
04682 vectoangles(a, ang);
04683 VectorCopy(ang, bs->goalAngles);
04684 }
|
|
|
Definition at line 4687 of file ai_main.c. References botskills_s::accuracy, bot_state_s::aimOffsetAmtPitch, bot_state_s::aimOffsetAmtYaw, bot_state_s::aimOffsetTime, bot_state_t, BotMindTricked(), bot_state_s::client, bot_state_s::currentEnemy, bot_state_s::frame_Enemy_Vis, g_entities, bot_state_s::goalAngles, level, entityState_s::number, botskills_s::perfectaim, PITCH, entityState_s::pos, rand(), bot_state_s::revengeEnemy, bot_state_s::revengeHateLevel, gentity_s::s, bot_state_s::settings, bot_settings_s::skill, bot_state_s::skills, level_locals_t::time, trajectory_t::trDelta, and YAW. Referenced by StandardBotAI().
04688 {
04689 int i;
04690 float accVal;
04691 i = 0;
04692
04693 if (bs->skills.perfectaim)
04694 {
04695 return;
04696 }
04697
04698 if (bs->aimOffsetTime > level.time)
04699 {
04700 if (bs->aimOffsetAmtYaw)
04701 {
04702 bs->goalAngles[YAW] += bs->aimOffsetAmtYaw;
04703 }
04704
04705 if (bs->aimOffsetAmtPitch)
04706 {
04707 bs->goalAngles[PITCH] += bs->aimOffsetAmtPitch;
04708 }
04709
04710 while (i <= 2)
04711 {
04712 if (bs->goalAngles[i] > 360)
04713 {
04714 bs->goalAngles[i] -= 360;
04715 }
04716
04717 if (bs->goalAngles[i] < 0)
04718 {
04719 bs->goalAngles[i] += 360;
04720 }
04721
04722 i++;
04723 }
04724 return;
04725 }
04726
04727 accVal = bs->skills.accuracy/bs->settings.skill;
04728
04729 if (bs->currentEnemy && BotMindTricked(bs->client, bs->currentEnemy->s.number))
04730 { //having to judge where they are by hearing them, so we should be quite inaccurate here
04731 accVal *= 7;
04732
04733 if (accVal < 30)
04734 {
04735 accVal = 30;
04736 }
04737 }
04738
04739 if (bs->revengeEnemy && bs->revengeHateLevel &&
04740 bs->currentEnemy == bs->revengeEnemy)
04741 { //bot becomes more skilled as anger level raises
04742 accVal = accVal/bs->revengeHateLevel;
04743 }
04744
04745 if (bs->currentEnemy && bs->frame_Enemy_Vis)
04746 { //assume our goal is aiming at the enemy, seeing as he's visible and all
04747 if (!bs->currentEnemy->s.pos.trDelta[0] &&
04748 !bs->currentEnemy->s.pos.trDelta[1] &&
04749 !bs->currentEnemy->s.pos.trDelta[2])
04750 {
04751 accVal = 0; //he's not even moving, so he shouldn't really be hard to hit.
04752 }
04753 else
04754 {
04755 accVal += accVal*0.25; //if he's moving he's this much harder to hit
04756 }
04757
04758 if (g_entities[bs->client].s.pos.trDelta[0] ||
04759 g_entities[bs->client].s.pos.trDelta[1] ||
04760 g_entities[bs->client].s.pos.trDelta[2])
04761 {
04762 accVal += accVal*0.15; //make it somewhat harder to aim if we're moving also
04763 }
04764 }
04765
04766 if (accVal > 90)
04767 {
04768 accVal = 90;
04769 }
04770 if (accVal < 1)
04771 {
04772 accVal = 0;
04773 }
04774
04775 if (!accVal)
04776 {
04777 bs->aimOffsetAmtYaw = 0;
04778 bs->aimOffsetAmtPitch = 0;
04779 return;
04780 }
04781
04782 if (rand()%10 <= 5)
04783 {
04784 bs->aimOffsetAmtYaw = rand()%(int)accVal;
04785 }
04786 else
04787 {
04788 bs->aimOffsetAmtYaw = -(rand()%(int)accVal);
04789 }
04790
04791 if (rand()%10 <= 5)
04792 {
04793 bs->aimOffsetAmtPitch = rand()%(int)accVal;
04794 }
04795 else
04796 {
04797 bs->aimOffsetAmtPitch = -(rand()%(int)accVal);
04798 }
04799
04800 bs->aimOffsetTime = level.time + rand()%500 + 200;
04801 }
|
|
|
Definition at line 662 of file ai_main.c. References FloatTime, regularupdate_time, and trap_BotUpdateEntityItems().
00662 {
00663 if (regularupdate_time < FloatTime()) {
00664 trap_BotUpdateEntityItems();
00665 regularupdate_time = FloatTime() + 0.3;
00666 }
00667 }
|
|
|
Definition at line 7575 of file ai_main.c. References bot_attachments, bot_camp, bot_forcepowers, bot_forgimmick, bot_getinthecarrr, bot_honorableduelacceptance, bot_pvstype, bot_wp_clearweight, bot_wp_distconnect, bot_wp_edit, bot_wp_info, bot_wp_visconnect, botstates, CVAR_CHEAT, memset(), qfalse, qtrue, trap_BotLibSetup(), trap_Cvar_Register(), and trap_Cvar_Update(). Referenced by G_InitGame().
07575 {
07576 //rww - new bot cvars..
07577 trap_Cvar_Register(&bot_forcepowers, "bot_forcepowers", "1", CVAR_CHEAT);
07578 trap_Cvar_Register(&bot_forgimmick, "bot_forgimmick", "0", CVAR_CHEAT);
07579 trap_Cvar_Register(&bot_honorableduelacceptance, "bot_honorableduelacceptance", "0", CVAR_CHEAT);
07580 trap_Cvar_Register(&bot_pvstype, "bot_pvstype", "1", CVAR_CHEAT);
07581 #ifndef FINAL_BUILD
07582 trap_Cvar_Register(&bot_getinthecarrr, "bot_getinthecarrr", "0", 0);
07583 #endif
07584
07585 #ifdef _DEBUG
07586 trap_Cvar_Register(&bot_nogoals, "bot_nogoals", "0", CVAR_CHEAT);
07587 trap_Cvar_Register(&bot_debugmessages, "bot_debugmessages", "0", CVAR_CHEAT);
07588 #endif
07589
07590 trap_Cvar_Register(&bot_attachments, "bot_attachments", "1", 0);
07591 trap_Cvar_Register(&bot_camp, "bot_camp", "1", 0);
07592
07593 trap_Cvar_Register(&bot_wp_info, "bot_wp_info", "1", 0);
07594 trap_Cvar_Register(&bot_wp_edit, "bot_wp_edit", "0", CVAR_CHEAT);
07595 trap_Cvar_Register(&bot_wp_clearweight, "bot_wp_clearweight", "1", 0);
07596 trap_Cvar_Register(&bot_wp_distconnect, "bot_wp_distconnect", "1", 0);
07597 trap_Cvar_Register(&bot_wp_visconnect, "bot_wp_visconnect", "1", 0);
07598
07599 trap_Cvar_Update(&bot_forcepowers);
07600 //end rww
07601
07602 //if the game is restarted for a tournament
07603 if (restart) {
07604 return qtrue;
07605 }
07606
07607 //initialize the bot states
07608 memset( botstates, 0, sizeof(botstates) );
07609
07610 if (!trap_BotLibSetup())
07611 {
07612 return qfalse; //wts?!
07613 }
07614
07615 return qtrue;
07616 }
|
|
||||||||||||||||
|
|
Definition at line 7623 of file ai_main.c. References BotAIShutdownClient(), botstates, client, bot_state_s::inuse, MAX_CLIENTS, qtrue, and trap_BotLibShutdown(). Referenced by G_ShutdownGame().
07623 {
07624
07625 int i;
07626
07627 //if the game is restarted for a tournament
07628 if ( restart ) {
07629 //shutdown all the bots in the botlib
07630 for (i = 0; i < MAX_CLIENTS; i++) {
07631 if (botstates[i] && botstates[i]->inuse) {
07632 BotAIShutdownClient(botstates[i]->client, restart);
07633 }
07634 }
07635 //don't shutdown the bot library
07636 }
07637 else {
07638 trap_BotLibShutdown();
07639 }
07640 return qtrue;
07641 }
|
|
||||||||||||
|
Definition at line 891 of file ai_main.c. References bot_state_t, botstates, client, bot_state_s::gs, bot_state_s::inuse, memset(), bot_state_s::ms, numbots, qfalse, qtrue, trap_BotFreeGoalState(), trap_BotFreeMoveState(), trap_BotFreeWeaponState(), and bot_state_s::ws. Referenced by BotAIShutdown(), and ClientDisconnect().
00891 {
00892 bot_state_t *bs;
00893
00894 bs = botstates[client];
00895 if (!bs || !bs->inuse) {
00896 //BotAI_Print(PRT_ERROR, "BotAIShutdownClient: client %d already shutdown\n", client);
00897 return qfalse;
00898 }
00899
00900 trap_BotFreeMoveState(bs->ms);
00901 //free the goal state`
00902 trap_BotFreeGoalState(bs->gs);
00903 //free the weapon weights
00904 trap_BotFreeWeaponState(bs->ws);
00905 //
00906 //clear the bot state
00907 memset(bs, 0, sizeof(bot_state_t));
00908 //set the inuse flag to qfalse
00909 bs->inuse = qfalse;
00910 //there's one bot less
00911 numbots--;
00912 //everything went ok
00913 return qtrue;
00914 }
|
|
|
Definition at line 7492 of file ai_main.c. References bot_attachments, bot_camp, bot_forgimmick, bot_getinthecarrr, bot_honorableduelacceptance, bot_pvstype, BOT_THINK_TIME, bot_wp_info, BotAI(), BotScheduleBotThink(), botstates, bot_state_s::botthink_residual, BotUpdateInput(), BotWaypointRender(), gentity_s::client, client, CON_CONNECTED, clientPersistant_t::connected, G_CheckBotSpawn(), g_entities, gBotEdit, gUpdateVars, bot_state_s::inuse, level, MAX_CLIENTS, gclient_s::pers, qtrue, level_locals_t::time, trap_BotUserCommand(), trap_Cvar_Update(), and UpdateEventTracker(). Referenced by vmMain().
07492 {
07493 int i;
07494 int elapsed_time, thinktime;
07495 static int local_time;
07496 static int botlib_residual;
07497 static int lastbotthink_time;
07498
07499 if (gUpdateVars < level.time)
07500 {
07501 trap_Cvar_Update(&bot_pvstype);
07502 trap_Cvar_Update(&bot_camp);
07503 trap_Cvar_Update(&bot_attachments);
07504 trap_Cvar_Update(&bot_forgimmick);
07505 trap_Cvar_Update(&bot_honorableduelacceptance);
07506 #ifndef FINAL_BUILD
07507 trap_Cvar_Update(&bot_getinthecarrr);
07508 #endif
07509 gUpdateVars = level.time + 1000;
07510 }
07511
07512 G_CheckBotSpawn();
07513
07514 //rww - addl bot frame functions
07515 if (gBotEdit)
07516 {
07517 trap_Cvar_Update(&bot_wp_info);
07518 BotWaypointRender();
07519 }
07520
07521 UpdateEventTracker();
07522 //end rww
07523
07524 //cap the bot think time
07525 //if the bot think time changed we should reschedule the bots
07526 if (BOT_THINK_TIME != lastbotthink_time) {
07527 lastbotthink_time = BOT_THINK_TIME;
07528 BotScheduleBotThink();
07529 }
07530
07531 elapsed_time = time - local_time;
07532 local_time = time;
07533
07534 if (elapsed_time > BOT_THINK_TIME) thinktime = elapsed_time;
07535 else thinktime = BOT_THINK_TIME;
07536
07537 // execute scheduled bot AI
07538 for( i = 0; i < MAX_CLIENTS; i++ ) {
07539 if( !botstates[i] || !botstates[i]->inuse ) {
07540 continue;
07541 }
07542 //
07543 botstates[i]->botthink_residual += elapsed_time;
07544 //
07545 if ( botstates[i]->botthink_residual >= thinktime ) {
07546 botstates[i]->botthink_residual -= thinktime;
07547
07548 if (g_entities[i].client->pers.connected == CON_CONNECTED) {
07549 BotAI(i, (float) thinktime / 1000);
07550 }
07551 }
07552 }
07553
07554 // execute bot user commands every frame
07555 for( i = 0; i < MAX_CLIENTS; i++ ) {
07556 if( !botstates[i] || !botstates[i]->inuse ) {
07557 continue;
07558 }
07559 if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
07560 continue;
07561 }
07562
07563 BotUpdateInput(botstates[i], time, elapsed_time);
07564 trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
07565 }
07566
07567 return qtrue;
07568 }
|
|
||||||||||||||||
|
Definition at line 1945 of file ai_main.c. References bot_state_t, BotMindTricked(), bot_state_s::client, gentity_s::client, EV_ALT_FIRE, EV_FIRE_WEAPON, EV_FOOTSTEP, EV_FOOTSTEP_METAL, EV_FOOTWADE, EV_GLOBAL_SOUND, EV_JUMP, EV_ROLL, EV_SABER_ATTACK, EV_STEP_12, EV_STEP_16, EV_STEP_4, EV_STEP_8, playerState_s::footstepTime, gBotEventTracker, gentity_t, level, MAX_PS_EVENTS, entityState_s::number, playerState_s::otherSoundLen, playerState_s::otherSoundTime, gclient_s::ps, gentity_s::s, and level_locals_t::time. Referenced by ScanForEnemies().
01946 {
01947 float minlen;
01948
01949 if (!en || !en->client)
01950 {
01951 return 0;
01952 }
01953
01954 if (en && en->client && en->client->ps.otherSoundTime > level.time)
01955 { //they made a noise in recent time
01956 minlen = en->client->ps.otherSoundLen;
01957 goto checkStep;
01958 }
01959
01960 if (en && en->client && en->client->ps.footstepTime > level.time)
01961 { //they made a footstep
01962 minlen = 256;
01963 goto checkStep;
01964 }
01965
01966 if (gBotEventTracker[en->s.number].eventTime < level.time)
01967 { //no recent events to check
01968 return 0;
01969 }
01970
01971 switch(gBotEventTracker[en->s.number].events[gBotEventTracker[en->s.number].eventSequence & (MAX_PS_EVENTS-1)])
01972 { //did the last event contain a sound?
01973 case EV_GLOBAL_SOUND:
01974 minlen = 256;
01975 break;
01976 case EV_FIRE_WEAPON:
01977 case EV_ALT_FIRE:
01978 case EV_SABER_ATTACK:
01979 minlen = 512;
01980 break;
01981 case EV_STEP_4:
01982 case EV_STEP_8:
01983 case EV_STEP_12:
01984 case EV_STEP_16:
01985 case EV_FOOTSTEP:
01986 case EV_FOOTSTEP_METAL:
01987 case EV_FOOTWADE:
01988 minlen = 256;
01989 break;
01990 case EV_JUMP:
01991 case EV_ROLL:
01992 minlen = 256;
01993 break;
01994 default:
01995 minlen = 999999;
01996 break;
01997 }
01998 checkStep:
01999 if (BotMindTricked(bs->client, en->s.number))
02000 { //if mindtricked by this person, cut down on the minlen so they can't "hear" as well
02001 minlen /= 4;
02002 }
02003
02004 if (endist <= minlen)
02005 { //we heard it
02006 return 1;
02007 }
02008
02009 return 0;
02010 }
|
|
||||||||||||||||
|
Definition at line 443 of file ai_main.c. References AngleMod().
00443 {
00444 float move;
00445
00446 angle = AngleMod(angle);
00447 ideal_angle = AngleMod(ideal_angle);
00448 if (angle == ideal_angle) return angle;
00449 move = ideal_angle - angle;
00450 if (ideal_angle > angle) {
00451 if (move > 180.0) move -= 360.0;
00452 }
00453 else {
00454 if (move < -180.0) move += 360.0;
00455 }
00456 if (move > 0) {
00457 if (move > speed) move = speed;
00458 }
00459 else {
00460 if (move < -speed) move = -speed;
00461 }
00462 return AngleMod(angle + move);
00463 }
|
|
||||||||||||
|
Definition at line 470 of file ai_main.c. References AngleDifference(), AngleMod(), bot_state_t, bot_state_s::client, bot_state_s::currentEnemy, bot_state_s::frame_Enemy_Vis, bot_state_s::ideal_viewangles, botskills_s::maxturn, PITCH, bot_state_s::settings, bot_settings_s::skill, bot_state_s::skills, trap_EA_View(), botskills_s::turnspeed, botskills_s::turnspeed_combat, bot_state_s::viewangles, and bot_state_s::viewanglespeed. Referenced by BotUpdateInput().
00470 {
00471 float diff, factor, maxchange, anglespeed, disired_speed;
00472 int i;
00473
00474 if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360;
00475
00476 if (bs->currentEnemy && bs->frame_Enemy_Vis)
00477 {
00478 if (bs->settings.skill <= 1)
00479 {
00480 factor = (bs->skills.turnspeed_combat*0.4f)*bs->settings.skill;
00481 }
00482 else if (bs->settings.skill <= 2)
00483 {
00484 factor = (bs->skills.turnspeed_combat*0.6f)*bs->settings.skill;
00485 }
00486 else if (bs->settings.skill <= 3)
00487 {
00488 factor = (bs->skills.turnspeed_combat*0.8f)*bs->settings.skill;
00489 }
00490 else
00491 {
00492 factor = bs->skills.turnspeed_combat*bs->settings.skill;
00493 }
00494 }
00495 else
00496 {
00497 factor = bs->skills.turnspeed;
00498 }
00499
00500 if (factor > 1)
00501 {
00502 factor = 1;
00503 }
00504 if (factor < 0.001)
00505 {
00506 factor = 0.001f;
00507 }
00508
00509 maxchange = bs->skills.maxturn;
00510
00511 //if (maxchange < 240) maxchange = 240;
00512 maxchange *= thinktime;
00513 for (i = 0; i < 2; i++) {
00514 bs->viewangles[i] = AngleMod(bs->viewangles[i]);
00515 bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]);
00516 diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]);
00517 disired_speed = diff * factor;
00518 bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed);
00519 if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange;
00520 if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange;
00521 anglespeed = bs->viewanglespeed[i];
00522 if (anglespeed > maxchange) anglespeed = maxchange;
00523 if (anglespeed < -maxchange) anglespeed = -maxchange;
00524 bs->viewangles[i] += anglespeed;
00525 bs->viewangles[i] = AngleMod(bs->viewangles[i]);
00526 bs->viewanglespeed[i] *= 0.45 * (1 - factor);
00527 }
00528 if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360;
00529 trap_EA_View(bs->client, bs->viewangles);
00530 }
|
|
|
Definition at line 5726 of file ai_main.c. References BOT_PLANT_BLOW_DISTANCE, bot_state_t, gentity_s::client, bot_state_s::client, bot_state_s::currentEnemy, FOFS, bot_state_s::frame_Enemy_Vis, G_Find(), gentity_t, level, NULL, entityState_s::number, OrgVisible(), bot_state_s::origin, playerState_s::origin, gentity_s::parent, bot_state_s::plantContinue, bot_state_s::plantKillEmAll, entityState_s::pos, gclient_s::ps, gentity_s::s, level_locals_t::time, trajectory_t::trBase, vec3_t, and VectorSubtract. Referenced by StandardBotAI().
05727 {
05728 gentity_t *dp = NULL;
05729 gentity_t *myDet = NULL;
05730 vec3_t a;
05731 float enLen;
05732 float myLen;
05733
05734 while ( (dp = G_Find( dp, FOFS(classname), "detpack") ) != NULL )
05735 {
05736 if (dp && dp->parent && dp->parent->s.number == bs->client)
05737 {
05738 myDet = dp;
05739 break;
05740 }
05741 }
05742
05743 if (!myDet)
05744 {
05745 return;
05746 }
05747
05748 if (!bs->currentEnemy || !bs->currentEnemy->client || !bs->frame_Enemy_Vis)
05749 { //require the enemy to be visilbe just to be fair..
05750
05751 //unless..
05752 if (bs->currentEnemy && bs->currentEnemy->client &&
05753 (level.time - bs->plantContinue) < 5000)
05754 { //it's a fresh plant (within 5 seconds) so we should be able to guess
05755 goto stillmadeit;
05756 }
05757 return;
05758 }
05759
05760 stillmadeit:
05761
05762 VectorSubtract(bs->currentEnemy->client->ps.origin, myDet->s.pos.trBase, a);
05763 enLen = VectorLength(a);
05764
05765 VectorSubtract(bs->origin, myDet->s.pos.trBase, a);
05766 myLen = VectorLength(a);
05767
05768 if (enLen > myLen)
05769 {
05770 return;
05771 }
05772
05773 if (enLen < BOT_PLANT_BLOW_DISTANCE && OrgVisible(bs->currentEnemy->client->ps.origin, myDet->s.pos.trBase, bs->currentEnemy->s.number))
05774 { //we could just call the "blow all my detpacks" function here, but I guess that's cheating.
05775 bs->plantKillEmAll = level.time + 500;
05776 }
05777 }
|
|
|
Definition at line 1432 of file ai_main.c. References bot_state_t, bot_state_s::ctfState, CTFSTATE_DEFENDER, g_gametype, GT_CTF, GT_CTY, vmCvar_t::integer, qboolean, qfalse, and qtrue. Referenced by WPTouchRoutine().
01433 {
01434 if (g_gametype.integer != GT_CTF &&
01435 g_gametype.integer != GT_CTY)
01436 {
01437 return qfalse;
01438 }
01439
01440 if (bs->ctfState == CTFSTATE_DEFENDER)
01441 {
01442 return qtrue;
01443 }
01444
01445 return qfalse;
01446 }
|
|
||||||||||||
|
Definition at line 1861 of file ai_main.c. References bot_state_t, botstates, gentity_s::client, bot_state_s::client, playerState_s::clientNum, bot_state_s::currentEnemy, ENEMY_FORGET_MS, bot_state_s::enemySeenTime, g_entities, gclient_t, gentity_t, bot_state_s::lastAttacked, bot_state_s::lastHurt, level, MAX_CLIENTS, NULL, entityState_s::number, PassLovedOneCheck(), PassStandardEnemyChecks(), gclient_s::ps, gentity_s::s, and level_locals_t::time. Referenced by G_Damage().
01862 {
01863 bot_state_t *bs;
01864 bot_state_t *bs_a;
01865 int i;
01866
01867 if (!bot || !attacker || !attacker->client)
01868 {
01869 return;
01870 }
01871
01872 if (bot->ps.clientNum >= MAX_CLIENTS)
01873 { //an NPC.. do nothing for them.
01874 return;
01875 }
01876
01877 if (attacker->s.number >= MAX_CLIENTS)
01878 { //if attacker is an npc also don't care I suppose.
01879 return;
01880 }
01881
01882 bs_a = botstates[attacker->s.number];
01883
01884 if (bs_a)
01885 { //if the client attacking us is a bot as well
01886 bs_a->lastAttacked = &g_entities[bot->ps.clientNum];
01887 i = 0;
01888
01889 while (i < MAX_CLIENTS)
01890 {
01891 if (botstates[i] &&
01892 i != bs_a->client &&
01893 botstates[i]->lastAttacked == &g_entities[bot->ps.clientNum])
01894 {
01895 botstates[i]->lastAttacked = NULL;
01896 }
01897
01898 i++;
01899 }
01900 }
01901 else //got attacked by a real client, so no one gets rights to lastAttacked
01902 {
01903 i = 0;
01904
01905 while (i < MAX_CLIENTS)
01906 {
01907 if (botstates[i] &&
01908 botstates[i]->lastAttacked == &g_entities[bot->ps.clientNum])
01909 {
01910 botstates[i]->lastAttacked = NULL;
01911 }
01912
01913 i++;
01914 }
01915 }
01916
01917 bs = botstates[bot->ps.clientNum];
01918
01919 if (!bs)
01920 {
01921 return;
01922 }
01923
01924 bs->lastHurt = attacker;
01925
01926 if (bs->currentEnemy)
01927 { //we don't care about the guy attacking us if we have an enemy already
01928 return;
01929 }
01930
01931 if (!PassStandardEnemyChecks(bs, attacker))
01932 { //the person that hurt us is not a valid enemy
01933 return;
01934 }
01935
01936 if (PassLovedOneCheck(bs, attacker))
01937 { //the person that hurt us is the one we love!
01938 bs->currentEnemy = attacker;
01939 bs->enemySeenTime = level.time + ENEMY_FORGET_MS;
01940 }
01941 }
|
|
|
Definition at line 5390 of file ai_main.c. References bot_state_t, BotLovedOneDied(), botstates, bot_state_s::client, level_locals_t::clients, level, bot_state_s::loved, bot_state_s::lovednum, MAX_CLIENTS, botattachment_s::name, and strcmp(). Referenced by StandardBotAI().
05391 { //in case someone has an emotional attachment to us, we'll notify them
05392 int i = 0;
05393 int ltest = 0;
05394
05395 while (i < MAX_CLIENTS)
05396 {
05397 if (botstates[i] && botstates[i]->lovednum)
05398 {
05399 ltest = 0;
05400 while (ltest < botstates[i]->lovednum)
05401 {
05402 if (strcmp(level.clients[bs->client].pers.netname, botstates[i]->loved[ltest].name) == 0)
05403 {
05404 BotLovedOneDied(botstates[i], bs, botstates[i]->loved[ltest].level);
05405 break;
05406 }
05407
05408 ltest++;
05409 }
05410 }
05411
05412 i++;
05413 }
05414 }
|
|
|
Definition at line 2507 of file ai_main.c. References BASE_GUARD_DISTANCE, bot_state_t, bot_state_s::client, level_locals_t::clients, flagBlue, flagRed, level, wpobject_s::origin, bot_state_s::origin, TEAM_BLUE, TEAM_RED, vec3_t, VectorSubtract, bot_state_s::wpDestination, and wpobject_t. Referenced by CTFTakesPriority().
02508 {
02509 wpobject_t *flagPoint;
02510 vec3_t a;
02511
02512 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
02513 {
02514 flagPoint = flagRed;
02515 }
02516 else if (level.clients[bs->client].sess.sessionTeam == TEAM_BLUE)
02517 {
02518 flagPoint = flagBlue;
02519 }
02520 else
02521 {
02522 return 0;
02523 }
02524
02525 if (!flagPoint)
02526 {
02527 return 0;
02528 }
02529
02530 VectorSubtract(bs->origin, flagPoint->origin, a);
02531
02532 if (VectorLength(a) > BASE_GUARD_DISTANCE)
02533 {
02534 bs->wpDestination = flagPoint;
02535 }
02536
02537 return 1;
02538 }
|
|
|
Definition at line 4143 of file ai_main.c. References bot_state_t, bot_state_s::isSquadLeader, NULL, bot_state_s::squadLeader, bot_state_s::state_Forced, bot_state_s::teamplayState, and TEAMPLAYSTATE_REGROUP. Referenced by StandardBotAI().
04144 {
04145 if (bs->state_Forced)
04146 {
04147 bs->teamplayState = bs->state_Forced;
04148 }
04149
04150 if (bs->teamplayState == TEAMPLAYSTATE_REGROUP)
04151 { //force to find a new leader
04152 bs->squadLeader = NULL;
04153 bs->isSquadLeader = 0;
04154 }
04155 }
|
|
||||||||||||
|
Definition at line 407 of file ai_main.c. References aas_entityinfo_t, and trap_AAS_EntityInfo().
00407 {
00408 trap_AAS_EntityInfo(entnum, info);
00409 }
|
|
|
Definition at line 5029 of file ai_main.c. References AngleVectors(), bot_state_t, bot_state_s::currentEnemy, ENTITYNUM_NONE, trace_t::fraction, bot_state_s::frame_Enemy_Vis, bot_state_s::goalAngles, bot_state_s::goalPosition, MASK_SOLID, NULL, bot_state_s::origin, PITCH, rand(), ROLL, trap_Trace(), vec3_t, VectorCopy, and YAW. Referenced by StandardBotAI().
05030 {
05031 vec3_t b_angle, fwd, trto, mins, maxs;
05032 trace_t tr;
05033
05034 if (bs->currentEnemy && bs->frame_Enemy_Vis)
05035 {
05036 return 2; //we're busy
05037 }
05038
05039 mins[0] = -15;
05040 mins[1] = -15;
05041 mins[2] = 0;
05042 maxs[0] = 15;
05043 maxs[1] = 15;
05044 maxs[2] = 32;
05045
05046 bs->goalAngles[PITCH] = 0;
05047 bs->goalAngles[ROLL] = 0;
05048
05049 VectorCopy(bs->goalAngles, b_angle);
05050
05051 AngleVectors(b_angle, fwd, NULL, NULL);
05052
05053 trto[0] = bs->origin[0] + fwd[0]*16;
05054 trto[1] = bs->origin[1] + fwd[1]*16;
05055 trto[2] = bs->origin[2] + fwd[2]*16;
05056
05057 trap_Trace(&tr, bs->origin, mins, maxs, trto, ENTITYNUM_NONE, MASK_SOLID);
05058
05059 if (tr.fraction == 1)
05060 {
05061 VectorCopy(trto, bs->goalPosition);
05062 return 1; //success!
05063 }
05064 else
05065 {
05066 bs->goalAngles[YAW] = rand()%360;
05067 }
05068
05069 return 0;
05070 }
|
|
|
Definition at line 2541 of file ai_main.c. References BASE_GETENEMYFLAG_DISTANCE, bot_state_t, bot_state_s::client, level_locals_t::clients, flagBlue, flagRed, level, wpobject_s::origin, bot_state_s::origin, TEAM_BLUE, TEAM_RED, vec3_t, VectorSubtract, bot_state_s::wpDestination, and wpobject_t. Referenced by CTFTakesPriority().
02542 {
02543 wpobject_t *flagPoint;
02544 vec3_t a;
02545
02546 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
02547 {
02548 flagPoint = flagBlue;
02549 }
02550 else if (level.clients[bs->client].sess.sessionTeam == TEAM_BLUE)
02551 {
02552 flagPoint = flagRed;
02553 }
02554 else
02555 {
02556 return 0;
02557 }
02558
02559 if (!flagPoint)
02560 {
02561 return 0;
02562 }
02563
02564 VectorSubtract(bs->origin, flagPoint->origin, a);
02565
02566 if (VectorLength(a) > BASE_GETENEMYFLAG_DISTANCE)
02567 {
02568 bs->wpDestination = flagPoint;
02569 }
02570
02571 return 1;
02572 }
|
|
|
Definition at line 2575 of file ai_main.c. References bot_state_t, gentity_s::client, bot_state_s::client, level_locals_t::clients, g_entities, gentity_t, GetNearestVisibleWP(), gWPArray, wpobject_s::index, level, MAX_CLIENTS, NULL, OnSameTeam(), entityState_s::origin, playerState_s::origin, playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_REDFLAG, Q_irand(), gentity_s::s, TEAM_RED, level_locals_t::time, TotalTrailDistance(), vec3_t, VectorCopy, bot_state_s::wpCurrent, bot_state_s::wpDestination, and bot_state_s::wpDestSwitchTime. Referenced by CTFTakesPriority().
02576 {
02577 int i = 0;
02578 int myFlag = 0;
02579 int foundCarrier = 0;
02580 int tempInt = 0;
02581 gentity_t *ent = NULL;
02582 vec3_t usethisvec;
02583
02584 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
02585 {
02586 myFlag = PW_REDFLAG;
02587 }
02588 else
02589 {
02590 myFlag = PW_BLUEFLAG;
02591 }
02592
02593 while (i < MAX_CLIENTS)
02594 {
02595 ent = &g_entities[i];
02596
02597 if (ent && ent->client && ent->client->ps.powerups[myFlag] && !OnSameTeam(&g_entities[bs->client], ent))
02598 {
02599 foundCarrier = 1;
02600 break;
02601 }
02602
02603 i++;
02604 }
02605
02606 if (!foundCarrier)
02607 {
02608 return 0;
02609 }
02610
02611 if (!ent)
02612 {
02613 return 0;
02614 }
02615
02616 if (bs->wpDestSwitchTime < level.time)
02617 {
02618 if (ent->client)
02619 {
02620 VectorCopy(ent->client->ps.origin, usethisvec);
02621 }
02622 else
02623 {
02624 VectorCopy(ent->s.origin, usethisvec);
02625 }
02626
02627 tempInt = GetNearestVisibleWP(usethisvec, 0);
02628
02629 if (tempInt != -1 && TotalTrailDistance(bs->wpCurrent->index, tempInt, bs) != -1)
02630 {
02631 bs->wpDestination = gWPArray[tempInt];
02632 bs->wpDestSwitchTime = level.time + Q_irand(1000, 5000);
02633 }
02634 }
02635
02636 return 1;
02637 }
|
|
|
Definition at line 2706 of file ai_main.c. References BASE_FLAGWAIT_DISTANCE, bot_state_t, bot_state_s::client, level_locals_t::clients, flagBlue, flagRed, level, wpobject_s::origin, bot_state_s::origin, TEAM_BLUE, TEAM_RED, vec3_t, VectorSubtract, bot_state_s::wpDestination, and wpobject_t. Referenced by CTFTakesPriority().
02707 {
02708 wpobject_t *flagPoint;
02709 vec3_t a;
02710
02711 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
02712 {
02713 flagPoint = flagRed;
02714 }
02715 else if (level.clients[bs->client].sess.sessionTeam == TEAM_BLUE)
02716 {
02717 flagPoint = flagBlue;
02718 }
02719 else
02720 {
02721 return 0;
02722 }
02723
02724 if (!flagPoint)
02725 {
02726 return 0;
02727 }
02728
02729 VectorSubtract(bs->origin, flagPoint->origin, a);
02730
02731 if (VectorLength(a) > BASE_FLAGWAIT_DISTANCE)
02732 {
02733 bs->wpDestination = flagPoint;
02734 }
02735
02736 return 1;
02737 }
|
|
|
|
Definition at line 2641 of file ai_main.c. References bot_state_t, gentity_s::client, bot_state_s::client, level_locals_t::clients, g_entities, gentity_t, GetNearestVisibleWP(), gWPArray, wpobject_s::index, level, MAX_CLIENTS, NULL, OnSameTeam(), entityState_s::origin, playerState_s::origin, playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_REDFLAG, Q_irand(), gentity_s::s, TEAM_RED, level_locals_t::time, TotalTrailDistance(), vec3_t, VectorCopy, bot_state_s::wpCurrent, bot_state_s::wpDestination, and bot_state_s::wpDestSwitchTime. Referenced by CTFTakesPriority().
02642 {
02643 int i = 0;
02644 int enemyFlag = 0;
02645 int foundCarrier = 0;
02646 int tempInt = 0;
02647 gentity_t *ent = NULL;
02648 vec3_t usethisvec;
02649
02650 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
02651 {
02652 enemyFlag = PW_BLUEFLAG;
02653 }
02654 else
02655 {
02656 enemyFlag = PW_REDFLAG;
02657 }
02658
02659 while (i < MAX_CLIENTS)
02660 {
02661 ent = &g_entities[i];
02662
02663 if (ent && ent->client && ent->client->ps.powerups[enemyFlag] && OnSameTeam(&g_entities[bs->client], ent))
02664 {
02665 foundCarrier = 1;
02666 break;
02667 }
02668
02669 i++;
02670 }
02671
02672 if (!foundCarrier)
02673 {
02674 return 0;
02675 }
02676
02677 if (!ent)
02678 {
02679 return 0;
02680 }
02681
02682 if (bs->wpDestSwitchTime < level.time)
02683 {
02684 if (ent->client)
02685 {
02686 VectorCopy(ent->client->ps.origin, usethisvec);
02687 }
02688 else
02689 {
02690 VectorCopy(ent->s.origin, usethisvec);
02691 }
02692
02693 tempInt = GetNearestVisibleWP(usethisvec, 0);
02694
02695 if (tempInt != -1 && TotalTrailDistance(bs->wpCurrent->index, tempInt, bs) != -1)
02696 {
02697 bs->wpDestination = gWPArray[tempInt];
02698 bs->wpDestSwitchTime = level.time + Q_irand(1000, 5000);
02699 }
02700 }
02701
02702 return 1;
02703 }
|
|
||||||||||||
|
Definition at line 3500 of file ai_main.c. References playerState_s::ammo, wpobject_s::associated_entity, bot_state_t, bot_state_s::cur_ps, ENTITYNUM_NONE, g_entities, gentity_t, gitem_s::giTag, gitem_s::giType, IT_AMMO, IT_HOLDABLE, IT_POWERUP, IT_WEAPON, gentity_s::item, playerState_s::powerups, STAT_HOLDABLE_ITEMS, STAT_WEAPONS, playerState_s::stats, and wpobject_t. Referenced by GetBestIdleGoal().
03501 {
03502 gentity_t *as;
03503
03504 if (wp->associated_entity == ENTITYNUM_NONE)
03505 { //make it think this is an item we have so we don't go after nothing
03506 return 1;
03507 }
03508
03509 as = &g_entities[wp->associated_entity];
03510
03511 if (!as || !as->item)
03512 {
03513 return 0;
03514 }
03515
03516 if (as->item->giType == IT_WEAPON)
03517 {
03518 if (bs->cur_ps.stats[STAT_WEAPONS] & (1 << as->item->giTag))
03519 {
03520 return 1;
03521 }
03522
03523 return 0;
03524 }
03525 else if (as->item->giType == IT_HOLDABLE)
03526 {
03527 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << as->item->giTag))
03528 {
03529 return 1;
03530 }
03531
03532 return 0;
03533 }
03534 else if (as->item->giType == IT_POWERUP)
03535 {
03536 if (bs->cur_ps.powerups[as->item->giTag])
03537 {
03538 return 1;
03539 }
03540
03541 return 0;
03542 }
03543 else if (as->item->giType == IT_AMMO)
03544 {
03545 if (bs->cur_ps.ammo[as->item->giTag] > 10) //hack
03546 {
03547 return 1;
03548 }
03549
03550 return 0;
03551 }
03552
03553 return 0;
03554 }
|
|
||||||||||||||||||||||||
|
Definition at line 537 of file ai_main.c. References abs(), ACTION_ALT_ATTACK, ACTION_ATTACK, ACTION_CROUCH, ACTION_DELAYEDJUMP, ACTION_FORCEPOWER, ACTION_GESTURE, ACTION_JUMP, ACTION_MOVEBACK, ACTION_MOVEFORWARD, ACTION_MOVELEFT, ACTION_MOVERIGHT, ACTION_RESPAWN, ACTION_USE, ACTION_WALK, bot_input_s::actionflags, ANGLE2SHORT, usercmd_s::angles, AngleVectors(), bot_input_t, BUTTON_ALT_ATTACK, BUTTON_ATTACK, BUTTON_FORCEPOWER, BUTTON_GESTURE, BUTTON_USE, BUTTON_USE_HOLDABLE, BUTTON_WALKING, usercmd_s::buttons, bot_input_s::dir, DotProduct, usercmd_s::forwardmove, level, memset(), NULL, PITCH, Q_irand(), usercmd_s::rightmove, ROLL, usercmd_s::serverTime, bot_input_s::speed, level_locals_t::time, ucmd, usercmd_s::upmove, usercmd_t, vec3_t, bot_input_s::viewangles, usercmd_s::weapon, bot_input_s::weapon, WP_BRYAR_PISTOL, WP_NONE, and YAW. Referenced by BotUpdateInput().
00537 {
00538 vec3_t angles, forward, right;
00539 short temp;
00540 int j;
00541
00542 //clear the whole structure
00543 memset(ucmd, 0, sizeof(usercmd_t));
00544 //
00545 //Com_Printf("dir = %f %f %f speed = %f\n", bi->dir[0], bi->dir[1], bi->dir[2], bi->speed);
00546 //the duration for the user command in milli seconds
00547 ucmd->serverTime = time;
00548 //
00549 if (bi->actionflags & ACTION_DELAYEDJUMP) {
00550 bi->actionflags |= ACTION_JUMP;
00551 bi->actionflags &= ~ACTION_DELAYEDJUMP;
00552 }
00553 //set the buttons
00554 if (bi->actionflags & ACTION_RESPAWN) ucmd->buttons = BUTTON_ATTACK;
00555 if (bi->actionflags & ACTION_ATTACK) ucmd->buttons |= BUTTON_ATTACK;
00556 if (bi->actionflags & ACTION_ALT_ATTACK) ucmd->buttons |= BUTTON_ALT_ATTACK;
00557 // if (bi->actionflags & ACTION_TALK) ucmd->buttons |= BUTTON_TALK;
00558 if (bi->actionflags & ACTION_GESTURE) ucmd->buttons |= BUTTON_GESTURE;
00559 if (bi->actionflags & ACTION_USE) ucmd->buttons |= BUTTON_USE_HOLDABLE;
00560 if (bi->actionflags & ACTION_WALK) ucmd->buttons |= BUTTON_WALKING;
00561
00562 if (bi->actionflags & ACTION_FORCEPOWER) ucmd->buttons |= BUTTON_FORCEPOWER;
00563
00564 if (useTime < level.time && Q_irand(1, 10) < 5)
00565 { //for now just hit use randomly in case there's something useable around
00566 ucmd->buttons |= BUTTON_USE;
00567 }
00568 #if 0
00569 // Here's an interesting bit. The bots in TA used buttons to do additional gestures.
00570 // I ripped them out because I didn't want too many buttons given the fact that I was already adding some for JK2.
00571 // We can always add some back in if we want though.
00572 if (bi->actionflags & ACTION_AFFIRMATIVE) ucmd->buttons |= BUTTON_AFFIRMATIVE;
00573 if (bi->actionflags & ACTION_NEGATIVE) ucmd->buttons |= BUTTON_NEGATIVE;
00574 if (bi->actionflags & ACTION_GETFLAG) ucmd->buttons |= BUTTON_GETFLAG;
00575 if (bi->actionflags & ACTION_GUARDBASE) ucmd->buttons |= BUTTON_GUARDBASE;
00576 if (bi->actionflags & ACTION_PATROL) ucmd->buttons |= BUTTON_PATROL;
00577 if (bi->actionflags & ACTION_FOLLOWME) ucmd->buttons |= BUTTON_FOLLOWME;
00578 #endif //0
00579
00580 if (bi->weapon == WP_NONE)
00581 {
00582 #ifdef _DEBUG
00583 // Com_Printf("WARNING: Bot tried to use WP_NONE!\n");
00584 #endif
00585 bi->weapon = WP_BRYAR_PISTOL;
00586 }
00587
00588 //
00589 ucmd->weapon = bi->weapon;
00590 //set the view angles
00591 //NOTE: the ucmd->angles are the angles WITHOUT the delta angles
00592 ucmd->angles[PITCH] = ANGLE2SHORT(bi->viewangles[PITCH]);
00593 ucmd->angles[YAW] = ANGLE2SHORT(bi->viewangles[YAW]);
00594 ucmd->angles[ROLL] = ANGLE2SHORT(bi->viewangles[ROLL]);
00595 //subtract the delta angles
00596 for (j = 0; j < 3; j++) {
00597 temp = ucmd->angles[j] - delta_angles[j];
00598 ucmd->angles[j] = temp;
00599 }
00600 //NOTE: movement is relative to the REAL view angles
00601 //get the horizontal forward and right vector
00602 //get the pitch in the range [-180, 180]
00603 if (bi->dir[2]) angles[PITCH] = bi->viewangles[PITCH];
00604 else angles[PITCH] = 0;
00605 angles[YAW] = bi->viewangles[YAW];
00606 angles[ROLL] = 0;
00607 AngleVectors(angles, forward, right, NULL);
00608 //bot input speed is in the range [0, 400]
00609 bi->speed = bi->speed * 127 / 400;
00610 //set the view independent movement
00611 ucmd->forwardmove = DotProduct(forward, bi->dir) * bi->speed;
00612 ucmd->rightmove = DotProduct(right, bi->dir) * bi->speed;
00613 ucmd->upmove = abs((int)(forward[2])) * bi->dir[2] * bi->speed;
00614 //normal keyboard movement
00615 if (bi->actionflags & ACTION_MOVEFORWARD) ucmd->forwardmove += 127;
00616 if (bi->actionflags & ACTION_MOVEBACK) ucmd->forwardmove -= 127;
00617 if (bi->actionflags & ACTION_MOVELEFT) ucmd->rightmove -= 127;
00618 if (bi->actionflags & ACTION_MOVERIGHT) ucmd->rightmove += 127;
00619 //jump/moveup
00620 if (bi->actionflags & ACTION_JUMP) ucmd->upmove += 127;
00621 //crouch/movedown
00622 if (bi->actionflags & ACTION_CROUCH) ucmd->upmove -= 127;
00623 //
00624 //Com_Printf("forward = %d right = %d up = %d\n", ucmd.forwardmove, ucmd.rightmove, ucmd.upmove);
00625 //Com_Printf("ucmd->serverTime = %d\n", ucmd->serverTime);
00626 }
|
|
|
Definition at line 2301 of file ai_main.c. References BOT_RUN_HEALTH, bot_state_t, BotGetWeaponRange(), BWEAPONRANGE_MELEE, BWEAPONRANGE_SABER, bot_state_s::chickenWussCalculationTime, gentity_s::client, bot_state_s::client, bot_state_s::cur_ps, bot_state_s::currentEnemy, playerState_s::electrifyTime, playerState_s::fd, forcedata_s::forcePowersActive, FP_RAGE, bot_state_s::frame_Enemy_Len, g_entities, g_gametype, gLevelFlags, GT_CTF, GT_JEDIMASTER, GT_SINGLE_PLAYER, gentity_s::health, vmCvar_t::integer, playerState_s::isJediMaster, level, LEVELFLAG_IMUSTNTRUNAWAY, MAX_CHICKENWUSS_TIME, playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_REDFLAG, bot_state_s::saberSpecialist, level_locals_t::time, playerState_s::weapon, WP_BRYAR_PISTOL, WP_ROCKET_LAUNCHER, and WP_SABER. Referenced by GetIdealDestination(), and WPTouchRoutine().
02302 {
02303 int bWRange;
02304
02305 if (gLevelFlags & LEVELFLAG_IMUSTNTRUNAWAY)
02306 { //The level says we mustn't run away!
02307 return 0;
02308 }
02309
02310 if (g_gametype.integer == GT_SINGLE_PLAYER)
02311 { //"coop" (not really)
02312 return 0;
02313 }
02314
02315 if (g_gametype.integer == GT_JEDIMASTER && !bs->cur_ps.isJediMaster)
02316 { //Then you may know no fear.
02317 //Well, unless he's strong.
02318 if (bs->currentEnemy && bs->currentEnemy->client &&
02319 bs->currentEnemy->client->ps.isJediMaster &&
02320 bs->currentEnemy->health > 40 &&
02321 bs->cur_ps.weapon < WP_ROCKET_LAUNCHER)
02322 { //explosive weapons are most effective against the Jedi Master
02323 goto jmPass;
02324 }
02325 return 0;
02326 }
02327
02328 if (g_gametype.integer == GT_CTF && bs->currentEnemy && bs->currentEnemy->client)
02329 {
02330 if (bs->currentEnemy->client->ps.powerups[PW_REDFLAG] ||
02331 bs->currentEnemy->client->ps.powerups[PW_BLUEFLAG])
02332 { //don't be afraid of flag carriers, they must die!
02333 return 0;
02334 }
02335 }
02336
02337 jmPass:
02338 if (bs->chickenWussCalculationTime > level.time)
02339 {
02340 return 2; //don't want to keep going between two points...
02341 }
02342
02343 if (bs->cur_ps.fd.forcePowersActive & (1 << FP_RAGE))
02344 { //don't run while raging
02345 return 0;
02346 }
02347
02348 if (g_gametype.integer == GT_JEDIMASTER && !bs->cur_ps.isJediMaster)
02349 { //be frightened of the jedi master? I guess in this case.
02350 return 1;
02351 }
02352
02353 bs->chickenWussCalculationTime = level.time + MAX_CHICKENWUSS_TIME;
02354
02355 if (g_entities[bs->client].health < BOT_RUN_HEALTH)
02356 { //we're low on health, let's get away
02357 return 1;
02358 }
02359
02360 bWRange = BotGetWeaponRange(bs);
02361
02362 if (bWRange == BWEAPONRANGE_MELEE || bWRange == BWEAPONRANGE_SABER)
02363 {
02364 if (bWRange != BWEAPONRANGE_SABER || !bs->saberSpecialist)
02365 { //run away if we're using melee, or if we're using a saber and not a "saber specialist"
02366 return 1;
02367 }
02368 }
02369
02370 if (bs->cur_ps.weapon == WP_BRYAR_PISTOL)
02371 { //the bryar is a weak weapon, so just try to find a new one if it's what you're having to use
02372 return 1;
02373 }
02374
02375 if (bs->currentEnemy && bs->currentEnemy->client &&
02376 bs->currentEnemy->client->ps.weapon == WP_SABER &&
02377 bs->frame_Enemy_Len < 512 && bs->cur_ps.weapon != WP_SABER)
02378 { //if close to an enemy with a saber and not using a saber, then try to back off
02379 return 1;
02380 }
02381
02382 if ((level.time-bs->cur_ps.electrifyTime) < 16000)
02383 { //lightning is dangerous.
02384 return 1;
02385 }
02386
02387 //didn't run, reset the timer
02388 bs->chickenWussCalculationTime = 0;
02389
02390 return 0;
02391 }
|
|
||||||||||||||||
|
Definition at line 5315 of file ai_main.c. References bot_attachments, bot_state_t, BotDoChat(), bot_state_s::chatAltObject, bot_state_s::chatObject, bot_state_s::client, gentity_s::client, g_entities, g_gametype, GT_DUEL, GT_POWERDUEL, vmCvar_t::integer, IsTeamplay(), bot_state_s::lastHurt, bot_state_s::loved_death_thresh, NULL, entityState_s::number, OnSameTeam(), PassLovedOneCheck(), bot_state_s::revengeEnemy, bot_state_s::revengeHateLevel, and gentity_s::s. Referenced by BotDeathNotify().
05316 {
05317 if (!loved->lastHurt || !loved->lastHurt->client ||
05318 loved->lastHurt->s.number == loved->client)
05319 {
05320 return;
05321 }
05322
05323 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
05324 { //There is no love in 1-on-1
05325 return;
05326 }
05327
05328 if (!IsTeamplay())
05329 {
05330 if (lovelevel < 2)
05331 {
05332 return;
05333 }
05334 }
05335 else if (OnSameTeam(&g_entities[bs->client], loved->lastHurt))
05336 { //don't hate teammates no matter what
05337 return;
05338 }
05339
05340 if (loved->client == loved->lastHurt->s.number)
05341 {
05342 return;
05343 }
05344
05345 if (bs->client == loved->lastHurt->s.number)
05346 { //oops!
05347 return;
05348 }
05349
05350 if (!bot_attachments.integer)
05351 {
05352 return;
05353 }
05354
05355 if (!PassLovedOneCheck(bs, loved->lastHurt))
05356 { //a loved one killed a loved one.. you cannot hate them
05357 bs->chatObject = loved->lastHurt;
05358 bs->chatAltObject = &g_entities[loved->client];
05359 BotDoChat(bs, "LovedOneKilledLovedOne", 0);
05360 return;
05361 }
05362
05363 if (bs->revengeEnemy == loved->lastHurt)
05364 {
05365 if (bs->revengeHateLevel < bs->loved_death_thresh)
05366 {
05367 bs->revengeHateLevel++;
05368
05369 if (bs->revengeHateLevel == bs->loved_death_thresh)
05370 {
05371 //broke into the highest anger level
05372 //CHAT: Hatred section
05373 bs->chatObject = loved->lastHurt;
05374 bs->chatAltObject = NULL;
05375 BotDoChat(bs, "Hatred", 1);
05376 }
05377 }
05378 }
05379 else if (bs->revengeHateLevel < bs->loved_death_thresh-1)
05380 { //only switch hatred if we don't hate the existing revenge-enemy too much
05381 //CHAT: BelovedKilled section
05382 bs->chatObject = &g_entities[loved->client];
05383 bs->chatAltObject = loved->lastHurt;
05384 BotDoChat(bs, "BelovedKilled", 0);
05385 bs->revengeHateLevel = 0;
05386 bs->revengeEnemy = loved->lastHurt;
05387 }
05388 }
|
|
||||||||||||
|
Definition at line 279 of file ai_main.c. References gentity_s::client, playerState_s::fd, forcedata_t, forcedata_s::forceMindtrickTargetIndex, forcedata_s::forceMindtrickTargetIndex2, forcedata_s::forceMindtrickTargetIndex3, forcedata_s::forceMindtrickTargetIndex4, g_entities, and gclient_s::ps. Referenced by BotAimOffsetGoalAngles(), BotCanHear(), PassStandardEnemyChecks(), ScanForEnemies(), and StandardBotAI().
00280 {
00281 forcedata_t *fd;
00282
00283 if (!g_entities[enemyClient].client)
00284 {
00285 return 0;
00286 }
00287
00288 fd = &g_entities[enemyClient].client->ps.fd;
00289
00290 if (!fd)
00291 {
00292 return 0;
00293 }
00294
00295 if (botClient > 47)
00296 {
00297 if (fd->forceMindtrickTargetIndex4 & (1 << (botClient-48)))
00298 {
00299 return 1;
00300 }
00301 }
00302 else if (botClient > 31)
00303 {
00304 if (fd->forceMindtrickTargetIndex3 & (1 << (botClient-32)))
00305 {
00306 return 1;
00307 }
00308 }
00309 else if (botClient > 15)
00310 {
00311 if (fd->forceMindtrickTargetIndex2 & (1 << (botClient-16)))
00312 {
00313 return 1;
00314 }
00315 }
00316 else
00317 {
00318 if (fd->forceMindtrickTargetIndex & (1 << botClient))
00319 {
00320 return 1;
00321 }
00322 }
00323
00324 return 0;
00325 }
|
|
||||||||||||||||
|
Definition at line 184 of file ai_main.c. References BotDoChat(), BotReportStatus(), botstates, BotStraightTPOrderCheck(), bot_state_s::chatAltObject, bot_state_s::chatObject, bot_state_s::chatTeam, gentity_s::client, CTFSTATE_MAXCTFSTATES, CTFSTATE_NONE, g_entities, g_gametype, gentity_t, GT_CTF, GT_CTY, GT_SIEGE, GT_TEAM, vmCvar_t::integer, MAX_CLIENTS, NULL, OnSameTeam(), gclient_s::sess, SIEGESTATE_MAXSIEGESTATES, SIEGESTATE_NONE, bot_state_s::state_Forced, clientSession_t::teamLeader, TEAMPLAYSTATE_MAXTPSTATES, and TEAMPLAYSTATE_NONE.
00185 {
00186 int stateMin = 0;
00187 int stateMax = 0;
00188 int i = 0;
00189
00190 if (!ent || !ent->client || !ent->client->sess.teamLeader)
00191 {
00192 return;
00193 }
00194
00195 if (clientnum != -1 && !botstates[clientnum])
00196 {
00197 return;
00198 }
00199
00200 if (clientnum != -1 && !OnSameTeam(ent, &g_entities[clientnum]))
00201 {
00202 return;
00203 }
00204
00205 if (g_gametype.integer != GT_CTF && g_gametype.integer != GT_CTY && g_gametype.integer != GT_SIEGE &&
00206 g_gametype.integer != GT_TEAM)
00207 {
00208 return;
00209 }
00210
00211 if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY)
00212 {
00213 stateMin = CTFSTATE_NONE;
00214 stateMax = CTFSTATE_MAXCTFSTATES;
00215 }
00216 else if (g_gametype.integer == GT_SIEGE)
00217 {
00218 stateMin = SIEGESTATE_NONE;
00219 stateMax = SIEGESTATE_MAXSIEGESTATES;
00220 }
00221 else if (g_gametype.integer == GT_TEAM)
00222 {
00223 stateMin = TEAMPLAYSTATE_NONE;
00224 stateMax = TEAMPLAYSTATE_MAXTPSTATES;
00225 }
00226
00227 if ((ordernum < stateMin && ordernum != -1) || ordernum >= stateMax)
00228 {
00229 return;
00230 }
00231
00232 if (clientnum != -1)
00233 {
00234 if (ordernum == -1)
00235 {
00236 BotReportStatus(botstates[clientnum]);
00237 }
00238 else
00239 {
00240 BotStraightTPOrderCheck(ent, ordernum, botstates[clientnum]);
00241 botstates[clientnum]->state_Forced = ordernum;
00242 botstates[clientnum]->chatObject = ent;
00243 botstates[clientnum]->chatAltObject = NULL;
00244 if (BotDoChat(botstates[clientnum], "OrderAccepted", 1))
00245 {
00246 botstates[clientnum]->chatTeam = 1;
00247 }
00248 }
00249 }
00250 else
00251 {
00252 while (i < MAX_CLIENTS)
00253 {
00254 if (botstates[i] && OnSameTeam(ent, &g_entities[i]))
00255 {
00256 if (ordernum == -1)
00257 {
00258 BotReportStatus(botstates[i]);
00259 }
00260 else
00261 {
00262 BotStraightTPOrderCheck(ent, ordernum, botstates[i]);
00263 botstates[i]->state_Forced = ordernum;
00264 botstates[i]->chatObject = ent;
00265 botstates[i]->chatAltObject = NULL;
00266 if (BotDoChat(botstates[i], "OrderAccepted", 0))
00267 {
00268 botstates[i]->chatTeam = 1;
00269 }
00270 }
00271 }
00272
00273 i++;
00274 }
00275 }
00276 }
|
|
||||||||||||
|
Definition at line 1086 of file ai_main.c. References bot_pvstype, g_RMG, vmCvar_t::integer, qboolean, qfalse, qtrue, trap_InPVS(), vec3_t, and VectorSubtract. Referenced by GetNearestBadThing(), GetNearestVisibleWP(), ScanForEnemies(), and SiegeTakesPriority().
01087 {
01088 if (g_RMG.integer && bot_pvstype.integer)
01089 {
01090 vec3_t subPoint;
01091 VectorSubtract(p1, p2, subPoint);
01092
01093 if (VectorLength(subPoint) > 5000)
01094 {
01095 return qfalse;
01096 }
01097 return qtrue;
01098 }
01099
01100 return trap_InPVS(p1, p2);
01101 }
|
|
|
Definition at line 5618 of file ai_main.c. References bot_state_t, BotDoChat(), botstates, bot_state_s::canChat, bot_state_s::chatAltObject, bot_state_s::chatObject, bot_state_s::client, g_entities, MAX_CLIENTS, and NULL. Referenced by StandardBotAI().
05619 {
05620 int i = 0;
05621 int numhello = 0;
05622
05623 while (i < MAX_CLIENTS)
05624 {
05625 if (botstates[i] &&
05626 botstates[i]->canChat &&
05627 i != bs->client)
05628 {
05629 botstates[i]->chatObject = &g_entities[bs->client];
05630 botstates[i]->chatAltObject = NULL;
05631 if (BotDoChat(botstates[i], "ResponseGreetings", 0))
05632 {
05633 numhello++;
05634 }
05635 }
05636
05637 if (numhello > 3)
05638 { //don't let more than 4 bots say hello at once
05639 return;
05640 }
05641
05642 i++;
05643 }
05644 }
|
|
|
Definition at line 167 of file ai_main.c. References bot_state_t, bot_state_s::client, bot_state_s::ctfState, ctfStateDescriptions, g_gametype, GT_CTF, GT_CTY, GT_SIEGE, GT_TEAM, vmCvar_t::integer, bot_state_s::siegeState, siegeStateDescriptions, bot_state_s::teamplayState, teamplayStateDescriptions, and trap_EA_SayTeam(). Referenced by BotOrder().
00168 {
00169 if (g_gametype.integer == GT_TEAM)
00170 {
00171 trap_EA_SayTeam(bs->client, teamplayStateDescriptions[bs->teamplayState]);
00172 }
00173 else if (g_gametype.integer == GT_SIEGE)
00174 {
00175 trap_EA_SayTeam(bs->client, siegeStateDescriptions[bs->siegeState]);
00176 }
00177 else if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY)
00178 {
00179 trap_EA_SayTeam(bs->client, ctfStateDescriptions[bs->ctfState]);
00180 }
00181 }
|
|
|
Definition at line 924 of file ai_main.c. References bot_settings_t, bot_state_t, client, bot_state_s::client, bot_state_s::cur_ps, bot_state_s::entergame_time, bot_state_s::entitynum, bot_state_s::gs, bot_state_s::inuse, memcpy(), memset(), bot_state_s::ms, playerState_t, bot_state_s::settings, trap_BotResetAvoidGoals(), trap_BotResetAvoidReach(), trap_BotResetGoalState(), trap_BotResetMoveState(), trap_BotResetWeaponState(), and bot_state_s::ws. Referenced by BotAILoadMap().
00924 {
00925 int client, entitynum, inuse;
00926 int movestate, goalstate, weaponstate;
00927 bot_settings_t settings;
00928 playerState_t ps; //current player state
00929 float entergame_time;
00930
00931 //save some things that should not be reset here
00932 memcpy(&settings, &bs->settings, sizeof(bot_settings_t));
00933 memcpy(&ps, &bs->cur_ps, sizeof(playerState_t));
00934 inuse = bs->inuse;
00935 client = bs->client;
00936 entitynum = bs->entitynum;
00937 movestate = bs->ms;
00938 goalstate = bs->gs;
00939 weaponstate = bs->ws;
00940 entergame_time = bs->entergame_time;
00941 //reset the whole state
00942 memset(bs, 0, sizeof(bot_state_t));
00943 //copy back some state stuff that should not be reset
00944 bs->ms = movestate;
00945 bs->gs = goalstate;
00946 bs->ws = weaponstate;
00947 memcpy(&bs->cur_ps, &ps, sizeof(playerState_t));
00948 memcpy(&bs->settings, &settings, sizeof(bot_settings_t));
00949 bs->inuse = inuse;
00950 bs->client = client;
00951 bs->entitynum = entitynum;
00952 bs->entergame_time = entergame_time;
00953 //reset several states
00954 if (bs->ms) trap_BotResetMoveState(bs->ms);
00955 if (bs->gs) trap_BotResetGoalState(bs->gs);
00956 if (bs->ws) trap_BotResetWeaponState(bs->ws);
00957 if (bs->gs) trap_BotResetAvoidGoals(bs->gs);
00958 if (bs->ms) trap_BotResetAvoidReach(bs->ms);
00959 }
|
|
|
Definition at line 5585 of file ai_main.c. References bot_state_t, botstates, bot_state_s::client, gentity_s::client, g_entities, gentity_t, GetLoveLevel(), bot_state_s::isSquadLeader, IsTeamplay(), MAX_CLIENTS, OnSameTeam(), and bot_state_s::squadLeader. Referenced by StandardBotAI().
05586 { //bots will only automatically obtain a leader if it's another bot using this method.
05587 int i = 0;
05588 gentity_t *ent;
05589
05590 if (bs->isSquadLeader)
05591 {
05592 return;
05593 }
05594
05595 while (i < MAX_CLIENTS)
05596 {
05597 ent = &g_entities[i];
05598
05599 if (ent && ent->client && botstates[i] && botstates[i]->isSquadLeader && bs->client != i)
05600 {
05601 if (OnSameTeam(&g_entities[bs->client], ent))
05602 {
05603 bs->squadLeader = ent;
05604 break;
05605 }
05606 if (GetLoveLevel(bs, botstates[i]) > 1 && !IsTeamplay())
05607 { //ignore love status regarding squad leaders if we're in teamplay
05608 bs->squadLeader = ent;
05609 break;
05610 }
05611 }
05612
05613 i++;
05614 }
05615 }
|
|
|
Definition at line 778 of file ai_main.c. References BOT_THINK_TIME, botstates, bot_state_s::botthink_residual, bot_state_s::inuse, MAX_CLIENTS, and numbots. Referenced by BotAISetupClient(), and BotAIStartFrame().
00778 {
00779 int i, botnum;
00780
00781 botnum = 0;
00782
00783 for( i = 0; i < MAX_CLIENTS; i++ ) {
00784 if( !botstates[i] || !botstates[i]->inuse ) {
00785 continue;
00786 }
00787 //initialize the bot think residual time
00788 botstates[i]->botthink_residual = BOT_THINK_TIME * botnum / numbots;
00789 botnum++;
00790 }
00791 }
|
|
||||||||||||||||
|
Definition at line 5216 of file ai_main.c. References playerState_s::ammo, weaponData_s::ammoIndex, bot_state_t, BotSelectWeapon(), bot_state_s::client, bot_state_s::cur_ps, weaponData_s::energyPerShot, STAT_WEAPONS, playerState_s::stats, bot_state_s::virtualWeapon, playerState_s::weapon, weaponData, and WP_NUM_WEAPONS. Referenced by StandardBotAI().
05217 { //if !doselection then bot will only check if he has the specified weapon and return 1 (yes) or 0 (no)
05218 int i;
05219 int hasit = 0;
05220
05221 i = 0;
05222
05223 while (i < WP_NUM_WEAPONS)
05224 {
05225 if (bs->cur_ps.ammo[weaponData[i].ammoIndex] > weaponData[i].energyPerShot &&
05226 i == weapon &&
05227 (bs->cur_ps.stats[STAT_WEAPONS] & (1 << i)))
05228 {
05229 hasit = 1;
05230 break;
05231 }
05232
05233 i++;
05234 }
05235
05236 if (hasit && bs->cur_ps.weapon != weapon && doselection && bs->virtualWeapon != weapon)
05237 {
05238 bs->virtualWeapon = weapon;
05239 BotSelectWeapon(bs->client, weapon);
05240 //bs->cur_ps.weapon = weapon;
05241 //level.clients[bs->client].ps.weapon = weapon;
05242 return 2;
05243 }
05244
05245 if (hasit)
05246 {
05247 return 1;
05248 }
05249
05250 return 0;
05251 }
|
|
|
Definition at line 5123 of file ai_main.c. References playerState_s::ammo, weaponData_s::ammoIndex, bot_state_t, BotSelectWeapon(), BotWeaponSelectable(), bot_state_s::botWeaponWeights, bot_state_s::client, gentity_s::client, bot_state_s::cur_ps, bot_state_s::currentEnemy, weaponData_s::energyPerShot, bot_state_s::frame_Enemy_Len, gclient_s::ps, STAT_WEAPONS, playerState_s::stats, bot_state_s::virtualWeapon, playerState_s::weapon, weaponData, WP_BLASTER, WP_BOWCASTER, WP_BRYAR_PISTOL, WP_DEMP2, WP_DISRUPTOR, WP_NUM_WEAPONS, WP_REPEATER, WP_ROCKET_LAUNCHER, WP_SABER, and WP_THERMAL. Referenced by StandardBotAI().
05124 {
05125 int i;
05126 int bestweight = -1;
05127 int bestweapon = 0;
05128
05129 i = 0;
05130
05131 while (i < WP_NUM_WEAPONS)
05132 {
05133 if (bs->cur_ps.ammo[weaponData[i].ammoIndex] >= weaponData[i].energyPerShot &&
05134 bs->botWeaponWeights[i] > bestweight &&
05135 (bs->cur_ps.stats[STAT_WEAPONS] & (1 << i)))
05136 {
05137 if (i == WP_THERMAL)
05138 { //special case..
05139 if (bs->currentEnemy && bs->frame_Enemy_Len < 700)
05140 {
05141 bestweight = bs->botWeaponWeights[i];
05142 bestweapon = i;
05143 }
05144 }
05145 else
05146 {
05147 bestweight = bs->botWeaponWeights[i];
05148 bestweapon = i;
05149 }
05150 }
05151
05152 i++;
05153 }
05154
05155 if ( bs->currentEnemy && bs->frame_Enemy_Len < 300 &&
05156 (bestweapon == WP_BRYAR_PISTOL || bestweapon == WP_BLASTER || bestweapon == WP_BOWCASTER) &&
05157 (bs->cur_ps.stats[STAT_WEAPONS] & (1 << WP_SABER)) )
05158 {
05159 bestweapon = WP_SABER;
05160 bestweight = 1;
05161 }
05162
05163 if ( bs->currentEnemy && bs->frame_Enemy_Len > 300 &&
05164 bs->currentEnemy->client && bs->currentEnemy->client->ps.weapon != WP_SABER &&
05165 (bestweapon == WP_SABER) )
05166 { //if the enemy is far away, and we have our saber selected, see if we have any good distance weapons instead
05167 if (BotWeaponSelectable(bs, WP_DISRUPTOR))
05168 {
05169 bestweapon = WP_DISRUPTOR;
05170 bestweight = 1;
05171 }
05172 else if (BotWeaponSelectable(bs, WP_ROCKET_LAUNCHER))
05173 {
05174 bestweapon = WP_ROCKET_LAUNCHER;
05175 bestweight = 1;
05176 }
05177 else if (BotWeaponSelectable(bs, WP_BOWCASTER))
05178 {
05179 bestweapon = WP_BOWCASTER;
05180 bestweight = 1;
05181 }
05182 else if (BotWeaponSelectable(bs, WP_BLASTER))
05183 {
05184 bestweapon = WP_BLASTER;
05185 bestweight = 1;
05186 }
05187 else if (BotWeaponSelectable(bs, WP_REPEATER))
05188 {
05189 bestweapon = WP_REPEATER;
05190 bestweight = 1;
05191 }
05192 else if (BotWeaponSelectable(bs, WP_DEMP2))
05193 {
05194 bestweapon = WP_DEMP2;
05195 bestweight = 1;
05196 }
05197 }
05198
05199 //assert(bs->cur_ps.weapon > 0 && bestweapon > 0);
05200
05201 if (bestweight != -1 && bs->cur_ps.weapon != bestweapon && bs->virtualWeapon != bestweapon)
05202 {
05203 bs->virtualWeapon = bestweapon;
05204 BotSelectWeapon(bs->client, bestweapon);
05205 //bs->cur_ps.weapon = bestweapon;
05206 //level.clients[bs->client].ps.weapon = bestweapon;
05207 return 1;
05208 }
05209
05210 //assert(bs->cur_ps.weapon > 0);
05211
05212 return 0;
05213 }
|
|
|
Definition at line 5254 of file ai_main.c. References bot_state_t, BotSelectWeapon(), bot_state_s::client, bot_state_s::cur_ps, bot_state_s::virtualWeapon, and playerState_s::weapon.
05255 {
05256 if (bs->cur_ps.weapon != 1 && bs->virtualWeapon != 1)
05257 {
05258 bs->virtualWeapon = 1;
05259 BotSelectWeapon(bs->client, 1);
05260 //bs->cur_ps.weapon = 1;
05261 //level.clients[bs->client].ps.weapon = 1;
05262 return 1;
05263 }
05264
05265 return 0;
05266 }
|
|
||||||||||||
|
Definition at line 157 of file ai_main.c. References client, trap_EA_SelectWeapon(), and WP_NONE. Referenced by BotSelectChoiceWeapon(), BotSelectIdealWeapon(), BotSelectMelee(), and BotTryAnotherWeapon().
00158 {
00159 if (weapon <= WP_NONE)
00160 {
00161 // assert(0);
00162 return;
00163 }
00164 trap_EA_SelectWeapon(client, weapon);
00165 }
|
|
||||||||||||||||
|
Definition at line 128 of file ai_main.c. References bot_state_t, gentity_t, bot_state_s::isSquadLeader, NULL, bot_state_s::squadLeader, bot_state_s::teamplayState, TEAMPLAYSTATE_ASSISTING, TEAMPLAYSTATE_FOLLOWING, and bot_state_s::wpDestSwitchTime. Referenced by BotOrder().
00129 {
00130 switch (ordernum)
00131 {
00132 case 0:
00133 if (bs->squadLeader == ent)
00134 {
00135 bs->teamplayState = 0;
00136 bs->squadLeader = NULL;
00137 }
00138 break;
00139 case TEAMPLAYSTATE_FOLLOWING:
00140 bs->teamplayState = ordernum;
00141 bs->isSquadLeader = 0;
00142 bs->squadLeader = ent;
00143 bs->wpDestSwitchTime = 0;
00144 break;
00145 case TEAMPLAYSTATE_ASSISTING:
00146 bs->teamplayState = ordernum;
00147 bs->isSquadLeader = 0;
00148 bs->squadLeader = ent;
00149 bs->wpDestSwitchTime = 0;
00150 break;
00151 default:
00152 bs->teamplayState = ordernum;
00153 break;
00154 }
00155 }
|
|
|
Definition at line 5833 of file ai_main.c. References AngleVectors(), bot_state_t, bot_state_s::client, trace_t::fraction, MASK_SOLID, NULL, bot_state_s::origin, trap_Trace(), vec3_t, and bot_state_s::viewangles. Referenced by StandardBotAI().
05834 {
05835 trace_t tr;
05836 vec3_t fwd;
05837
05838 AngleVectors(bs->viewangles, fwd, NULL, NULL);
05839
05840 fwd[0] = bs->origin[0]+(fwd[0]*64);
05841 fwd[1] = bs->origin[1]+(fwd[1]*64);
05842 fwd[2] = bs->origin[2]+(fwd[2]*64);
05843
05844 trap_Trace(&tr, bs->origin, NULL, NULL, fwd, bs->client, MASK_SOLID);
05845
05846 if (tr.fraction != 1)
05847 {
05848 return 1;
05849 }
05850
05851 return 0;
05852 }
|
|
||||||||||||
|
Definition at line 1702 of file ai_main.c. References AngleVectors(), bot_state_t, bot_state_s::client, trace_t::fraction, MASK_PLAYERSOLID, NULL, bot_state_s::origin, trap_Trace(), vec3_t, vectoangles(), VectorCopy, and VectorSubtract. Referenced by StandardBotAI().
01703 {
01704 vec3_t mins, maxs, a, fwd, traceto_mod, tracefrom_mod;
01705 trace_t tr;
01706
01707 VectorSubtract(traceto, bs->origin, a);
01708 vectoangles(a, a);
01709
01710 AngleVectors(a, fwd, NULL, NULL);
01711
01712 traceto_mod[0] = bs->origin[0] + fwd[0]*4;
01713 traceto_mod[1] = bs->origin[1] + fwd[1]*4;
01714 traceto_mod[2] = bs->origin[2] + fwd[2]*4;
01715
01716 mins[0] = -15;
01717 mins[1] = -15;
01718 mins[2] = -23;
01719 maxs[0] = 15;
01720 maxs[1] = 15;
01721 maxs[2] = 8;
01722
01723 trap_Trace(&tr, bs->origin, mins, maxs, traceto_mod, bs->client, MASK_PLAYERSOLID);
01724
01725 if (tr.fraction != 1)
01726 {
01727 return 0;
01728 }
01729
01730 VectorCopy(bs->origin, tracefrom_mod);
01731
01732 tracefrom_mod[2] += 31;//33;
01733 traceto_mod[2] += 31;//33;
01734
01735 mins[0] = -15;
01736 mins[1] = -15;
01737 mins[2] = 0;
01738 maxs[0] = 15;
01739 maxs[1] = 15;
01740 maxs[2] = 32;
01741
01742 trap_Trace(&tr, tracefrom_mod, mins, maxs, traceto_mod, bs->client, MASK_PLAYERSOLID);
01743
01744 if (tr.fraction != 1)
01745 {
01746 return 1;
01747 }
01748
01749 return 0;
01750 }
|
|
||||||||||||
|
Definition at line 1638 of file ai_main.c. References AngleVectors(), bot_state_t, BotGetWeaponRange(), botstates, BWEAPONRANGE_MELEE, BWEAPONRANGE_SABER, bot_state_s::client, bot_state_s::currentEnemy, trace_t::entityNum, trace_t::fraction, bot_state_s::jumpTime, level, MASK_PLAYERSOLID, MAX_CLIENTS, NULL, entityState_s::number, bot_state_s::origin, gentity_s::s, level_locals_t::time, trap_Trace(), vec3_t, vectoangles(), VectorCopy, and VectorSubtract. Referenced by StandardBotAI().
01639 {
01640 vec3_t mins, maxs, a, fwd, traceto_mod, tracefrom_mod;
01641 trace_t tr;
01642 int orTr;
01643
01644 VectorSubtract(traceto, bs->origin, a);
01645 vectoangles(a, a);
01646
01647 AngleVectors(a, fwd, NULL, NULL);
01648
01649 traceto_mod[0] = bs->origin[0] + fwd[0]*4;
01650 traceto_mod[1] = bs->origin[1] + fwd[1]*4;
01651 traceto_mod[2] = bs->origin[2] + fwd[2]*4;
01652
01653 mins[0] = -15;
01654 mins[1] = -15;
01655 mins[2] = -18;
01656 maxs[0] = 15;
01657 maxs[1] = 15;
01658 maxs[2] = 32;
01659
01660 trap_Trace(&tr, bs->origin, mins, maxs, traceto_mod, bs->client, MASK_PLAYERSOLID);
01661
01662 if (tr.fraction == 1)
01663 {
01664 return 0;
01665 }
01666
01667 orTr = tr.entityNum;
01668
01669 VectorCopy(bs->origin, tracefrom_mod);
01670
01671 tracefrom_mod[2] += 41;
01672 traceto_mod[2] += 41;
01673
01674 mins[0] = -15;
01675 mins[1] = -15;
01676 mins[2] = 0;
01677 maxs[0] = 15;
01678 maxs[1] = 15;
01679 maxs[2] = 8;
01680
01681 trap_Trace(&tr, tracefrom_mod, mins, maxs, traceto_mod, bs->client, MASK_PLAYERSOLID);
01682
01683 if (tr.fraction == 1)
01684 {
01685 if (orTr >= 0 && orTr < MAX_CLIENTS && botstates[orTr] && botstates[orTr]->jumpTime > level.time)
01686 {
01687 return 0; //so bots don't try to jump over each other at the same time
01688 }
01689
01690 if (bs->currentEnemy && bs->currentEnemy->s.number == orTr && (BotGetWeaponRange(bs) == BWEAPONRANGE_SABER || BotGetWeaponRange(bs) == BWEAPONRANGE_MELEE))
01691 {
01692 return 0;
01693 }
01694
01695 return 1;
01696 }
01697
01698 return 0;
01699 }
|
|
||||||||||||
|
Definition at line 1556 of file ai_main.c. References AngleDifference(), AngleVectors(), bot_state_t, bot_state_s::client, bot_state_s::cur_ps, DEFAULT_MAXS_2, ENTITYNUM_NONE, trace_t::fraction, playerState_s::groundEntityNum, MASK_PLAYERSOLID, bot_state_s::origin, playerMaxs, playerMins, STRAFEAROUND_LEFT, STRAFEAROUND_RIGHT, trap_Trace(), vec3_t, vectoangles(), VectorCopy, VectorNormalize(), VectorSubtract, bot_state_s::viewangles, and YAW. Referenced by StandardBotAI().
01557 {
01558 vec3_t playerMins = {-15, -15, /*DEFAULT_MINS_2*/-8};
01559 vec3_t playerMaxs = {15, 15, DEFAULT_MAXS_2};
01560 vec3_t from, to;
01561 vec3_t dirAng, dirDif;
01562 vec3_t forward, right;
01563 trace_t tr;
01564
01565 if (bs->cur_ps.groundEntityNum == ENTITYNUM_NONE)
01566 { //don't do this in the air, it can be.. dangerous.
01567 return 0;
01568 }
01569
01570 VectorSubtract(traceto, bs->origin, dirAng);
01571 VectorNormalize(dirAng);
01572 vectoangles(dirAng, dirAng);
01573
01574 if (AngleDifference(bs->viewangles[YAW], dirAng[YAW]) > 60 ||
01575 AngleDifference(bs->viewangles[YAW], dirAng[YAW]) < -60)
01576 { //If we aren't facing the direction we're going here, then we've got enough excuse to be too stupid to strafe around anyway
01577 return 0;
01578 }
01579
01580 VectorCopy(bs->origin, from);
01581 VectorCopy(traceto, to);
01582
01583 VectorSubtract(to, from, dirDif);
01584 VectorNormalize(dirDif);
01585 vectoangles(dirDif, dirDif);
01586
01587 AngleVectors(dirDif, forward, 0, 0);
01588
01589 to[0] = from[0] + forward[0]*32;
01590 to[1] = from[1] + forward[1]*32;
01591 to[2] = from[2] + forward[2]*32;
01592
01593 trap_Trace(&tr, from, playerMins, playerMaxs, to, bs->client, MASK_PLAYERSOLID);
01594
01595 if (tr.fraction == 1)
01596 {
01597 return 0;
01598 }
01599
01600 AngleVectors(dirAng, 0, right, 0);
01601
01602 from[0] += right[0]*32;
01603 from[1] += right[1]*32;
01604 from[2] += right[2]*16;
01605
01606 to[0] += right[0]*32;
01607 to[1] += right[1]*32;
01608 to[2] += right[2]*32;
01609
01610 trap_Trace(&tr, from, playerMins, playerMaxs, to, bs->client, MASK_PLAYERSOLID);
01611
01612 if (tr.fraction == 1)
01613 {
01614 return STRAFEAROUND_RIGHT;
01615 }
01616
01617 from[0] -= right[0]*64;
01618 from[1] -= right[1]*64;
01619 from[2] -= right[2]*64;
01620
01621 to[0] -= right[0]*64;
01622 to[1] -= right[1]*64;
01623 to[2] -= right[2]*64;
01624
01625 trap_Trace(&tr, from, playerMins, playerMaxs, to, bs->client, MASK_PLAYERSOLID);
01626
01627 if (tr.fraction == 1)
01628 {
01629 return STRAFEAROUND_LEFT;
01630 }
01631
01632 return 0;
01633 }
|
|
|
Definition at line 5072 of file ai_main.c. References playerState_s::ammo, weaponData_s::ammoIndex, bot_state_t, BotSelectWeapon(), bot_state_s::client, bot_state_s::cur_ps, weaponData_s::energyPerShot, STAT_WEAPONS, playerState_s::stats, bot_state_s::virtualWeapon, playerState_s::weapon, weaponData, and WP_NUM_WEAPONS. Referenced by StandardBotAI().
05073 { //out of ammo, resort to the first weapon we come across that has ammo
05074 int i;
05075
05076 i = 1;
05077
05078 while (i < WP_NUM_WEAPONS)
05079 {
05080 if (bs->cur_ps.ammo[weaponData[i].ammoIndex] >= weaponData[i].energyPerShot &&
05081 (bs->cur_ps.stats[STAT_WEAPONS] & (1 << i)))
05082 {
05083 bs->virtualWeapon = i;
05084 BotSelectWeapon(bs->client, i);
05085 //bs->cur_ps.weapon = i;
05086 //level.clients[bs->client].ps.weapon = i;
05087 return 1;
05088 }
05089
05090 i++;
05091 }
05092
05093 if (bs->cur_ps.weapon != 1 && bs->virtualWeapon != 1)
05094 { //should always have this.. shouldn't we?
05095 bs->virtualWeapon = 1;
05096 BotSelectWeapon(bs->client, 1);
05097 //bs->cur_ps.weapon = 1;
05098 //level.clients[bs->client].ps.weapon = 1;
05099 return 1;
05100 }
05101
05102 return 0;
05103 }
|
|
||||||||||||||||
|
Definition at line 633 of file ai_main.c. References ACTION_ATTACK, ACTION_RESPAWN, bot_input_s::actionflags, AngleMod(), bot_input_t, bot_state_t, BotChangeViewAngles(), BotInputToUserCommand(), BUTTON_ATTACK, usercmd_s::buttons, bot_state_s::client, bot_state_s::cur_ps, playerState_s::delta_angles, bot_state_s::lastucmd, bot_state_s::noUseTime, SHORT2ANGLE, trap_EA_GetInput(), and bot_state_s::viewangles. Referenced by BotAIStartFrame().
00633 {
00634 bot_input_t bi;
00635 int j;
00636
00637 //add the delta angles to the bot's current view angles
00638 for (j = 0; j < 3; j++) {
00639 bs->viewangles[j] = AngleMod(bs->viewangles[j] + SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
00640 }
00641 //change the bot view angles
00642 BotChangeViewAngles(bs, (float) elapsed_time / 1000);
00643 //retrieve the bot input
00644 trap_EA_GetInput(bs->client, (float) time / 1000, &bi);
00645 //respawn hack
00646 if (bi.actionflags & ACTION_RESPAWN) {
00647 if (bs->lastucmd.buttons & BUTTON_ATTACK) bi.actionflags &= ~(ACTION_RESPAWN|ACTION_ATTACK);
00648 }
00649 //convert the bot input to a usercmd
00650 BotInputToUserCommand(&bi, &bs->lastucmd, bs->cur_ps.delta_angles, time, bs->noUseTime);
00651 //subtract the delta angles
00652 for (j = 0; j < 3; j++) {
00653 bs->viewangles[j] = AngleMod(bs->viewangles[j] - SHORT2ANGLE(bs->cur_ps.delta_angles[j]));
00654 }
00655 }
|
|
|
Definition at line 5780 of file ai_main.c. References BG_GetItemIndexByTag(), bot_state_t, bot_state_s::client, level_locals_t::clients, bot_state_s::cur_ps, bot_state_s::currentEnemy, bot_state_s::frame_Enemy_Vis, g_entities, HI_MEDPAC, HI_MEDPAC_BIG, HI_SEEKER, HI_SENTRY_GUN, HI_SHIELD, IT_HOLDABLE, level, bot_state_s::runningToEscapeThreat, STAT_HOLDABLE_ITEM, STAT_HOLDABLE_ITEMS, and playerState_s::stats. Referenced by StandardBotAI().
05781 {
05782 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_MEDPAC))
05783 {
05784 if (g_entities[bs->client].health <= 75)
05785 {
05786 bs->cur_ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_MEDPAC, IT_HOLDABLE);
05787 goto wantuseitem;
05788 }
05789 }
05790 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_MEDPAC_BIG))
05791 {
05792 if (g_entities[bs->client].health <= 50)
05793 {
05794 bs->cur_ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_MEDPAC_BIG, IT_HOLDABLE);
05795 goto wantuseitem;
05796 }
05797 }
05798 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SEEKER))
05799 {
05800 if (bs->currentEnemy && bs->frame_Enemy_Vis)
05801 {
05802 bs->cur_ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_SEEKER, IT_HOLDABLE);
05803 goto wantuseitem;
05804 }
05805 }
05806 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SENTRY_GUN))
05807 {
05808 if (bs->currentEnemy && bs->frame_Enemy_Vis)
05809 {
05810 bs->cur_ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_SENTRY_GUN, IT_HOLDABLE);
05811 goto wantuseitem;
05812 }
05813 }
05814 if (bs->cur_ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SHIELD))
05815 {
05816 if (bs->currentEnemy && bs->frame_Enemy_Vis && bs->runningToEscapeThreat)
05817 { //this will (hopefully) result in the bot placing the shield down while facing
05818 //the enemy and running away
05819 bs->cur_ps.stats[STAT_HOLDABLE_ITEM] = BG_GetItemIndexByTag(HI_SHIELD, IT_HOLDABLE);
05820 goto wantuseitem;
05821 }
05822 }
05823
05824 return 0;
05825
05826 wantuseitem:
05827 level.clients[bs->client].ps.stats[STAT_HOLDABLE_ITEM] = bs->cur_ps.stats[STAT_HOLDABLE_ITEM];
05828
05829 return 1;
05830 }
|
|
|
Definition at line 5855 of file ai_main.c. References WP_DEMP2, WP_DET_PACK, WP_DISRUPTOR, WP_MELEE, WP_ROCKET_LAUNCHER, WP_STUN_BATON, WP_THERMAL, and WP_TRIP_MINE. Referenced by StandardBotAI().
05856 {
05857 switch (weapon)
05858 {
05859 case WP_STUN_BATON:
05860 case WP_MELEE:
05861 return 0;
05862 case WP_DISRUPTOR:
05863 return 0;
05864 case WP_DEMP2:
05865 return 0;
05866 case WP_ROCKET_LAUNCHER:
05867 return 0;
05868 case WP_THERMAL:
05869 return 0;
05870 case WP_TRIP_MINE:
05871 return 0;
05872 case WP_DET_PACK:
05873 return 0;
05874 default:
05875 return 1;
05876 }
05877 }
|
|
|
Definition at line 4570 of file ai_main.c. References bot_state_t, bot_state_s::cur_ps, playerState_s::weapon, WP_BLASTER, WP_BOWCASTER, WP_BRYAR_PISTOL, WP_DEMP2, WP_REPEATER, WP_ROCKET_LAUNCHER, and WP_THERMAL. Referenced by StandardBotAI().
04571 {
04572 int weap = bs->cur_ps.weapon;
04573
04574 if (weap == WP_BRYAR_PISTOL)
04575 {
04576 return 0.5;
04577 }
04578 if (weap == WP_BLASTER)
04579 {
04580 return 0.35;
04581 }
04582 if (weap == WP_BOWCASTER)
04583 {
04584 return 0.5;
04585 }
04586 if (weap == WP_REPEATER)
04587 {
04588 return 0.45;
04589 }
04590 if (weap == WP_THERMAL)
04591 {
04592 return 0.5;
04593 }
04594 if (weap == WP_DEMP2)
04595 {
04596 return 0.35;
04597 }
04598 if (weap == WP_ROCKET_LAUNCHER)
04599 {
04600 return 0.7;
04601 }
04602
04603 return 0;
04604 }
|
|
||||||||||||
|
Definition at line 5106 of file ai_main.c. References playerState_s::ammo, weaponData_s::ammoIndex, bot_state_t, bot_state_s::cur_ps, weaponData_s::energyPerShot, qboolean, qfalse, qtrue, STAT_WEAPONS, playerState_s::stats, weaponData, and WP_NONE. Referenced by BotSelectIdealWeapon().
05107 {
05108 if (weapon == WP_NONE)
05109 {
05110 return qfalse;
05111 }
05112
05113 if (bs->cur_ps.ammo[weaponData[weapon].ammoIndex] >= weaponData[weapon].energyPerShot &&
05114 (bs->cur_ps.stats[STAT_WEAPONS] & (1 << weapon)))
05115 {
05116 return qtrue;
05117 }
05118
05119 return qfalse;
05120 }
|
|
|
Definition at line 5538 of file ai_main.c. References AngleVectors(), bot_state_t, botstates, gentity_s::client, bot_state_s::client, trace_t::entityNum, bot_state_s::eye, trace_t::fraction, g_entities, gentity_t, GetLoveLevel(), IsTeamplay(), MASK_PLAYERSOLID, MAX_CLIENTS, NULL, entityState_s::number, OnSameTeam(), gentity_s::s, trap_Trace(), vec3_t, VectorCopy, and bot_state_s::viewangles. Referenced by StandardBotAI().
05539 {
05540 vec3_t fwd;
05541 vec3_t trfrom, trto;
05542 vec3_t mins, maxs;
05543 gentity_t *trent;
05544 trace_t tr;
05545
05546 mins[0] = -3;
05547 mins[1] = -3;
05548 mins[2] = -3;
05549
05550 maxs[0] = 3;
05551 maxs[1] = 3;
05552 maxs[2] = 3;
05553
05554 AngleVectors(bs->viewangles, fwd, NULL, NULL);
05555
05556 VectorCopy(bs->eye, trfrom);
05557
05558 trto[0] = trfrom[0] + fwd[0]*2048;
05559 trto[1] = trfrom[1] + fwd[1]*2048;
05560 trto[2] = trfrom[2] + fwd[2]*2048;
05561
05562 trap_Trace(&tr, trfrom, mins, maxs, trto, bs->client, MASK_PLAYERSOLID);
05563
05564 if (tr.fraction != 1 && tr.entityNum <= MAX_CLIENTS)
05565 {
05566 trent = &g_entities[tr.entityNum];
05567
05568 if (trent && trent->client)
05569 {
05570 if (IsTeamplay() && OnSameTeam(&g_entities[bs->client], trent))
05571 {
05572 return trent;
05573 }
05574
05575 if (botstates[trent->s.number] && GetLoveLevel(bs, botstates[trent->s.number]) > 1)
05576 {
05577 return trent;
05578 }
05579 }
05580 }
05581
05582 return NULL;
05583 }
|
|
||||||||||||
|
Definition at line 1053 of file ai_main.c. References gentity_s::classname, trace_t::entityNum, trace_t::fraction, g_entities, gentity_t, MASK_SOLID, NULL, strstr(), trap_Trace(), vec3_t, and VectorCopy. Referenced by StandardBotAI(), and WaitingForNow().
01054 {
01055 gentity_t *fent;
01056 vec3_t under;
01057 trace_t tr;
01058
01059 VectorCopy(org, under);
01060
01061 under[2] -= 64;
01062
01063 trap_Trace(&tr, org, NULL, NULL, under, ignore, MASK_SOLID);
01064
01065 if (tr.fraction == 1)
01066 {
01067 return 0;
01068 }
01069
01070 fent = &g_entities[tr.entityNum];
01071
01072 if (!fent)
01073 {
01074 return 0;
01075 }
01076
01077 if (strstr(fent->classname, "func_"))
01078 {
01079 return 1; //there's a func brush here
01080 }
01081
01082 return 0;
01083 }
|
|
||||||||||||
|
Definition at line 1263 of file ai_main.c. References bot_state_s::beStill, bot_state_t, bot_state_s::cur_ps, playerState_s::fd, bot_state_s::forceJumpChargeTime, bot_state_s::forceJumping, wpneighbor_s::forceJumpTo, forcedata_s::forcePowerLevel, FP_LEVITATION, gWPArray, wpobject_s::index, bot_state_s::jDelay, bot_state_s::jumpTime, level, wpobject_s::neighbornum, wpobject_s::neighbors, wpneighbor_s::num, level_locals_t::time, TotalTrailDistance(), bot_state_s::wpCurrent, bot_state_s::wpDestination, bot_state_s::wpDirection, and bot_state_s::wpSwitchTime. Referenced by WPTouchRoutine().
01264 {
01265 float bestlen;
01266 float checklen;
01267 int bestindex;
01268 int i;
01269 int fj;
01270
01271 i = 0;
01272 fj = 0;
01273
01274 if (!bs->wpDestination)
01275 {
01276 return;
01277 }
01278
01279 //set our traversal direction based on the index of the point
01280 if (newwpindex < bs->wpDestination->index)
01281 {
01282 bs->wpDirection = 0;
01283 }
01284 else if (newwpindex > bs->wpDestination->index)
01285 {
01286 bs->wpDirection = 1;
01287 }
01288
01289 //can't switch again yet
01290 if (bs->wpSwitchTime > level.time)
01291 {
01292 return;
01293 }
01294
01295 //no neighboring points to check off of
01296 if (!gWPArray[newwpindex]->neighbornum)
01297 {
01298 return;
01299 }
01300
01301 //get the trail distance for our wp
01302 bestindex = newwpindex;
01303 bestlen = TotalTrailDistance(newwpindex, bs->wpDestination->index, bs);
01304
01305 while (i < gWPArray[newwpindex]->neighbornum)
01306 { //now go through the neighbors and check the distance to the desired point from each neighbor
01307 checklen = TotalTrailDistance(gWPArray[newwpindex]->neighbors[i].num, bs->wpDestination->index, bs);
01308
01309 if (checklen < bestlen-64 || bestlen == -1)
01310 { //this path covers less distance, let's take it instead
01311 if (bs->cur_ps.fd.forcePowerLevel[FP_LEVITATION] >= gWPArray[newwpindex]->neighbors[i].forceJumpTo)
01312 {
01313 bestlen = checklen;
01314 bestindex = gWPArray[newwpindex]->neighbors[i].num;
01315
01316 if (gWPArray[newwpindex]->neighbors[i].forceJumpTo)
01317 {
01318 fj = gWPArray[newwpindex]->neighbors[i].forceJumpTo;
01319 }
01320 else
01321 {
01322 fj = 0;
01323 }
01324 }
01325 }
01326
01327 i++;
01328 }
01329
01330 if (bestindex != newwpindex && bestindex != -1)
01331 { //we found a path we want to switch to, let's do it
01332 bs->wpCurrent = gWPArray[bestindex];
01333 bs->wpSwitchTime = level.time + 3000;
01334
01335 if (fj)
01336 { //do we have to force jump to get to this neighbor?
01337 #ifndef FORCEJUMP_INSTANTMETHOD
01338 bs->forceJumpChargeTime = level.time + 1000;
01339 bs->beStill = level.time + 1000;
01340 bs->forceJumping = bs->forceJumpChargeTime;
01341 #else
01342 bs->beStill = level.time + 500;
01343 bs->jumpTime = level.time + fj*1200;
01344 bs->jDelay = level.time + 200;
01345 bs->forceJumping = bs->jumpTime;
01346 #endif
01347 }
01348 }
01349 }
|
|
|
Definition at line 2766 of file g_cmds.c.
02767 {
02768 trace_t tr;
02769 vec3_t forward, fwdOrg;
02770
02771 if (!g_privateDuel.integer)
02772 {
02773 return;
02774 }
02775
02776 if (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL)
02777 { //rather pointless in this mode..
02778 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NODUEL_GAMETYPE")) );
02779 return;
02780 }
02781
02782 //if (g_gametype.integer >= GT_TEAM && g_gametype.integer != GT_SIEGE)
02783 if (g_gametype.integer >= GT_TEAM)
02784 { //no private dueling in team modes
02785 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "NODUEL_GAMETYPE")) );
02786 return;
02787 }
02788
02789 if (ent->client->ps.duelTime >= level.time)
02790 {
02791 return;
02792 }
02793
02794 if (ent->client->ps.weapon != WP_SABER)
02795 {
02796 return;
02797 }
02798
02799 /*
02800 if (!ent->client->ps.saberHolstered)
02801 { //must have saber holstered at the start of the duel
02802 return;
02803 }
02804 */
02805 //NOTE: No longer doing this..
02806
02807 if (ent->client->ps.saberInFlight)
02808 {
02809 return;
02810 }
02811
02812 if (ent->client->ps.duelInProgress)
02813 {
02814 return;
02815 }
02816
02817 //New: Don't let a player duel if he just did and hasn't waited 10 seconds yet (note: If someone challenges him, his duel timer will reset so he can accept)
02818 if (ent->client->ps.fd.privateDuelTime > level.time)
02819 {
02820 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "CANTDUEL_JUSTDID")) );
02821 return;
02822 }
02823
02824 if (G_OtherPlayersDueling())
02825 {
02826 trap_SendServerCommand( ent-g_entities, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "CANTDUEL_BUSY")) );
02827 return;
02828 }
02829
02830 AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL );
02831
02832 fwdOrg[0] = ent->client->ps.origin[0] + forward[0]*256;
02833 fwdOrg[1] = ent->client->ps.origin[1] + forward[1]*256;
02834 fwdOrg[2] = (ent->client->ps.origin[2]+ent->client->ps.viewheight) + forward[2]*256;
02835
02836 trap_Trace(&tr, ent->client->ps.origin, NULL, NULL, fwdOrg, ent->s.number, MASK_PLAYERSOLID);
02837
02838 if (tr.fraction != 1 && tr.entityNum < MAX_CLIENTS)
02839 {
02840 gentity_t *challenged = &g_entities[tr.entityNum];
02841
02842 if (!challenged || !challenged->client || !challenged->inuse ||
02843 challenged->health < 1 || challenged->client->ps.stats[STAT_HEALTH] < 1 ||
02844 challenged->client->ps.weapon != WP_SABER || challenged->client->ps.duelInProgress ||
02845 challenged->client->ps.saberInFlight)
02846 {
02847 return;
02848 }
02849
02850 if (g_gametype.integer >= GT_TEAM && OnSameTeam(ent, challenged))
02851 {
02852 return;
02853 }
02854
02855 if (challenged->client->ps.duelIndex == ent->s.number && challenged->client->ps.duelTime >= level.time)
02856 {
02857 trap_SendServerCommand( /*challenged-g_entities*/-1, va("print \"%s %s %s!\n\"", challenged->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELACCEPT"), ent->client->pers.netname) );
02858
02859 ent->client->ps.duelInProgress = qtrue;
02860 challenged->client->ps.duelInProgress = qtrue;
02861
02862 ent->client->ps.duelTime = level.time + 2000;
02863 challenged->client->ps.duelTime = level.time + 2000;
02864
02865 G_AddEvent(ent, EV_PRIVATE_DUEL, 1);
02866 G_AddEvent(challenged, EV_PRIVATE_DUEL, 1);
02867
02868 //Holster their sabers now, until the duel starts (then they'll get auto-turned on to look cool)
02869
02870 if (!ent->client->ps.saberHolstered)
02871 {
02872 if (ent->client->saber[0].soundOff)
02873 {
02874 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOff);
02875 }
02876 if (ent->client->saber[1].soundOff &&
02877 ent->client->saber[1].model[0])
02878 {
02879 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02880 }
02881 ent->client->ps.weaponTime = 400;
02882 ent->client->ps.saberHolstered = 2;
02883 }
02884 if (!challenged->client->ps.saberHolstered)
02885 {
02886 if (challenged->client->saber[0].soundOff)
02887 {
02888 G_Sound(challenged, CHAN_AUTO, challenged->client->saber[0].soundOff);
02889 }
02890 if (challenged->client->saber[1].soundOff &&
02891 challenged->client->saber[1].model[0])
02892 {
02893 G_Sound(challenged, CHAN_AUTO, challenged->client->saber[1].soundOff);
02894 }
02895 challenged->client->ps.weaponTime = 400;
02896 challenged->client->ps.saberHolstered = 2;
02897 }
02898 }
02899 else
02900 {
02901 //Print the message that a player has been challenged in private, only announce the actual duel initiation in private
02902 trap_SendServerCommand( challenged-g_entities, va("cp \"%s %s\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELCHALLENGE")) );
02903 trap_SendServerCommand( ent-g_entities, va("cp \"%s %s\n\"", G_GetStringEdString("MP_SVGAME", "PLDUELCHALLENGED"), challenged->client->pers.netname) );
02904 }
02905
02906 challenged->client->ps.fd.privateDuelTime = 0; //reset the timer in case this player just got out of a duel. He should still be able to accept the challenge.
02907
02908 ent->client->ps.forceHandExtend = HANDEXTEND_DUELCHALLENGE;
02909 ent->client->ps.forceHandExtendTime = level.time + 1000;
02910
02911 ent->client->ps.duelIndex = challenged->s.number;
02912 ent->client->ps.duelTime = level.time + 5000;
02913 }
02914 }
|
|
|
Definition at line 2467 of file g_cmds.c.
02468 {
02469 if (ent->client->ps.fd.forceGripCripple)
02470 { //if they are being gripped, don't let them unholster their saber
02471 if (ent->client->ps.saberHolstered)
02472 {
02473 return;
02474 }
02475 }
02476
02477 if (ent->client->ps.saberInFlight)
02478 {
02479 if (ent->client->ps.saberEntityNum)
02480 { //turn it off in midair
02481 saberKnockDown(&g_entities[ent->client->ps.saberEntityNum], ent, ent);
02482 }
02483 return;
02484 }
02485
02486 if (ent->client->ps.forceHandExtend != HANDEXTEND_NONE)
02487 {
02488 return;
02489 }
02490
02491 if (ent->client->ps.weapon != WP_SABER)
02492 {
02493 return;
02494 }
02495
02496 // if (ent->client->ps.duelInProgress && !ent->client->ps.saberHolstered)
02497 // {
02498 // return;
02499 // }
02500
02501 if (ent->client->ps.duelTime >= level.time)
02502 {
02503 return;
02504 }
02505
02506 if (ent->client->ps.saberLockTime >= level.time)
02507 {
02508 return;
02509 }
02510
02511 if (ent->client && ent->client->ps.weaponTime < 1)
02512 {
02513 if (ent->client->ps.saberHolstered == 2)
02514 {
02515 ent->client->ps.saberHolstered = 0;
02516
02517 if (ent->client->saber[0].soundOn)
02518 {
02519 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOn);
02520 }
02521 if (ent->client->saber[1].soundOn)
02522 {
02523 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOn);
02524 }
02525 }
02526 else
02527 {
02528 ent->client->ps.saberHolstered = 2;
02529 if (ent->client->saber[0].soundOff)
02530 {
02531 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOff);
02532 }
02533 if (ent->client->saber[1].soundOff &&
02534 ent->client->saber[1].model[0])
02535 {
02536 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOff);
02537 }
02538 //prevent anything from being done for 400ms after holster
02539 ent->client->ps.weaponTime = 400;
02540 }
02541 }
02542 }
|
|
||||||||||||
|
Definition at line 4885 of file ai_main.c. References bot_state_s::altChargeTime, bot_state_t, BotGetWeaponRange(), BWEAPONRANGE_MELEE, BWEAPONRANGE_SABER, gentity_s::client, bot_state_s::cur_ps, bot_state_s::currentEnemy, bot_state_s::doAltAttack, bot_state_s::doAttack, bot_state_s::eye, bot_state_s::frame_Enemy_Len, InFieldOfVision(), level, MELEE_ATTACK_RANGE, entityState_s::origin, playerState_s::origin, gclient_s::ps, Q_irand(), gentity_s::s, SABER_ATTACK_RANGE, ShouldSecondaryFire(), level_locals_t::time, vec3_t, vectoangles(), VectorCopy, VectorSubtract, bot_state_s::viewangles, playerState_s::weapon, WEAPON_CHARGING, WEAPON_CHARGING_ALT, playerState_s::weaponChargeTime, playerState_s::weaponstate, WP_ROCKET_LAUNCHER, and WP_THERMAL. Referenced by StandardBotAI().
04886 {
04887 vec3_t eorg, a;
04888 int secFire;
04889 float fovcheck;
04890
04891 if (!bs->currentEnemy)
04892 {
04893 return 0;
04894 }
04895
04896 if (bs->currentEnemy->client)
04897 {
04898 VectorCopy(bs->currentEnemy->client->ps.origin, eorg);
04899 }
04900 else
04901 {
04902 VectorCopy(bs->currentEnemy->s.origin, eorg);
04903 }
04904
04905 VectorSubtract(eorg, bs->eye, a);
04906 vectoangles(a, a);
04907
04908 if (BotGetWeaponRange(bs) == BWEAPONRANGE_SABER)
04909 {
04910 if (bs->frame_Enemy_Len <= SABER_ATTACK_RANGE)
04911 {
04912 bs->doAttack = 1;
04913 }
04914 }
04915 else if (BotGetWeaponRange(bs) == BWEAPONRANGE_MELEE)
04916 {
04917 if (bs->frame_Enemy_Len <= MELEE_ATTACK_RANGE)
04918 {
04919 bs->doAttack = 1;
04920 }
04921 }
04922 else
04923 {
04924 if (bs->cur_ps.weapon == WP_THERMAL || bs->cur_ps.weapon == WP_ROCKET_LAUNCHER)
04925 { //be careful with the hurty weapons
04926 fovcheck = 40;
04927
04928 if (bs->cur_ps.weaponstate == WEAPON_CHARGING_ALT &&
04929 bs->cur_ps.weapon == WP_ROCKET_LAUNCHER)
04930 { //if we're charging the weapon up then we can hold fire down within a normal fov
04931 fovcheck = 60;
04932 }
04933 }
04934 else
04935 {
04936 fovcheck = 60;
04937 }
04938
04939 if (bs->cur_ps.weaponstate == WEAPON_CHARGING ||
04940 bs->cur_ps.weaponstate == WEAPON_CHARGING_ALT)
04941 {
04942 fovcheck = 160;
04943 }
04944
04945 if (bs->frame_Enemy_Len < 128)
04946 {
04947 fovcheck *= 2;
04948 }
04949
04950 if (InFieldOfVision(bs->viewangles, fovcheck, a))
04951 {
04952 if (bs->cur_ps.weapon == WP_THERMAL)
04953 {
04954 if (((level.time - bs->cur_ps.weaponChargeTime) < (bs->frame_Enemy_Len*2) &&
04955 (level.time - bs->cur_ps.weaponChargeTime) < 4000 &&
04956 bs->frame_Enemy_Len > 64) ||
04957 (bs->cur_ps.weaponstate != WEAPON_CHARGING &&
04958 bs->cur_ps.weaponstate != WEAPON_CHARGING_ALT))
04959 {
04960 if (bs->cur_ps.weaponstate != WEAPON_CHARGING && bs->cur_ps.weaponstate != WEAPON_CHARGING_ALT)
04961 {
04962 if (bs->frame_Enemy_Len > 512 && bs->frame_Enemy_Len < 800)
04963 {
04964 bs->doAltAttack = 1;
04965 //bs->doAttack = 1;
04966 }
04967 else
04968 {
04969 bs->doAttack = 1;
04970 //bs->doAltAttack = 1;
04971 }
04972 }
04973
04974 if (bs->cur_ps.weaponstate == WEAPON_CHARGING)
04975 {
04976 bs->doAttack = 1;
04977 }
04978 else if (bs->cur_ps.weaponstate == WEAPON_CHARGING_ALT)
04979 {
04980 bs->doAltAttack = 1;
04981 }
04982 }
04983 }
04984 else
04985 {
04986 secFire = ShouldSecondaryFire(bs);
04987
04988 if (bs->cur_ps.weaponstate != WEAPON_CHARGING_ALT &&
04989 bs->cur_ps.weaponstate != WEAPON_CHARGING)
04990 {
04991 bs->altChargeTime = Q_irand(500, 1000);
04992 }
04993
04994 if (secFire == 1)
04995 {
04996 bs->doAltAttack = 1;
04997 }
04998 else if (!secFire)
04999 {
05000 if (bs->cur_ps.weapon != WP_THERMAL)
05001 {
05002 if (bs->cur_ps.weaponstate != WEAPON_CHARGING ||
05003 bs->altChargeTime > (level.time - bs->cur_ps.weaponChargeTime))
05004 {
05005 bs->doAttack = 1;
05006 }
05007 }
05008 else
05009 {
05010 bs->doAttack = 1;
05011 }
05012 }
05013
05014 if (secFire == 2)
05015 { //released a charge
05016 return 1;
05017 }
05018 }
05019 }
05020 }
05021
05022 return 0;
05023 }
|
|
|
Definition at line 4252 of file ai_main.c. References bot_state_t, CommanderBotCTFAI(), CommanderBotSiegeAI(), CommanderBotTeamplayAI(), g_gametype, GT_CTF, GT_CTY, GT_SIEGE, GT_TEAM, and vmCvar_t::integer. Referenced by StandardBotAI().
04253 {
04254 if (g_gametype.integer == GT_CTF || g_gametype.integer == GT_CTY)
04255 {
04256 CommanderBotCTFAI(bs);
04257 }
04258 else if (g_gametype.integer == GT_SIEGE)
04259 {
04260 CommanderBotSiegeAI(bs);
04261 }
04262 else if (g_gametype.integer == GT_TEAM)
04263 {
04264 CommanderBotTeamplayAI(bs);
04265 }
04266 }
|
|
|
Definition at line 3911 of file ai_main.c. References bot_state_t, botstates, gentity_s::client, bot_state_s::client, level_locals_t::clients, bot_state_s::ctfState, CTFSTATE_ATTACKER, CTFSTATE_DEFENDER, CTFSTATE_GETFLAGHOME, CTFSTATE_GUARDCARRIER, CTFSTATE_RETRIEVAL, g_entities, gentity_t, level, MAX_CLIENTS, entityState_s::number, OnSameTeam(), playerState_s::powerups, gclient_s::ps, PW_BLUEFLAG, PW_REDFLAG, gentity_s::s, bot_state_s::squadLeader, and TEAM_RED. Referenced by CommanderBotAI().
03912 {
03913 int i = 0;
03914 gentity_t *ent;
03915 int squadmates = 0;
03916 gentity_t *squad[MAX_CLIENTS];
03917 int defendAttackPriority = 0; //0 == attack, 1 == defend
03918 int guardDefendPriority = 0; //0 == defend, 1 == guard
03919 int attackRetrievePriority = 0; //0 == retrieve, 1 == attack
03920 int myFlag = 0;
03921 int enemyFlag = 0;
03922 int enemyHasOurFlag = 0;
03923 int weHaveEnemyFlag = 0;
03924 int numOnMyTeam = 0;
03925 int numOnEnemyTeam = 0;
03926 int numAttackers = 0;
03927 int numDefenders = 0;
03928
03929 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
03930 {
03931 myFlag = PW_REDFLAG;
03932 }
03933 else
03934 {
03935 myFlag = PW_BLUEFLAG;
03936 }
03937
03938 if (level.clients[bs->client].sess.sessionTeam == TEAM_RED)
03939 {
03940 enemyFlag = PW_BLUEFLAG;
03941 }
03942 else
03943 {
03944 enemyFlag = PW_REDFLAG;
03945 }
03946
03947 while (i < MAX_CLIENTS)
03948 {
03949 ent = &g_entities[i];
03950
03951 if (ent && ent->client)
03952 {
03953 if (ent->client->ps.powerups[enemyFlag] && OnSameTeam(&g_entities[bs->client], ent))
03954 {
03955 weHaveEnemyFlag = 1;
03956 }
03957 else if (ent->client->ps.powerups[myFlag] && !OnSameTeam(&g_entities[bs->client], ent))
03958 {
03959 enemyHasOurFlag = 1;
03960 }
03961
03962 if (OnSameTeam(&g_entities[bs->client], ent))
03963 {
03964 numOnMyTeam++;
03965 }
03966 else
03967 {
03968 numOnEnemyTeam++;
03969 }
03970
03971 if (botstates[ent->s.number])
03972 {
03973 if (botstates[ent->s.number]->ctfState == CTFSTATE_ATTACKER ||
03974 botstates[ent->s.number]->ctfState == CTFSTATE_RETRIEVAL)
03975 {
03976 numAttackers++;
03977 }
03978 else
03979 {
03980 numDefenders++;
03981 }
03982 }
03983 else
03984 { //assume real players to be attackers in our logic
03985 numAttackers++;
03986 }
03987 }
03988 i++;
03989 }
03990
03991 i = 0;
03992
03993 while (i < MAX_CLIENTS)
03994 {
03995 ent = &g_entities[i];
03996
03997 if (ent && ent->client && botstates[i] && botstates[i]->squadLeader && botstates[i]->squadLeader->s.number == bs->client && i != bs->client)
03998 {
03999 squad[squadmates] = ent;
04000 squadmates++;
04001 }
04002
04003 i++;
04004 }
04005
04006 squad[squadmates] = &g_entities[bs->client];
04007 squadmates++;
04008
04009 i = 0;
04010
04011 if (enemyHasOurFlag && !weHaveEnemyFlag)
04012 { //start off with an attacker instead of a retriever if we don't have the enemy flag yet so that they can't capture it first.
04013 //after that we focus on getting our flag back.
04014 attackRetrievePriority = 1;
04015 }
04016
04017 while (i < squadmates)
04018 {
04019 if (squad[i] && squad[i]->client && botstates[squad[i]->s.number])
04020 {
04021 if (botstates[squad[i]->s.number]->ctfState != CTFSTATE_GETFLAGHOME)
04022 { //never tell a bot to stop trying to bring the flag to the base
04023 if (defendAttackPriority)
04024 {
04025 if (weHaveEnemyFlag)
04026 {
04027 if (guardDefendPriority)
04028 {
04029 botstates[squad[i]->s.number]->ctfState = CTFSTATE_GUARDCARRIER;
04030 guardDefendPriority = 0;
04031 }
04032 else
04033 {
04034 botstates[squad[i]->s.number]->ctfState = CTFSTATE_DEFENDER;
04035 guardDefendPriority = 1;
04036 }
04037 }
04038 else
04039 {
04040 botstates[squad[i]->s.number]->ctfState = CTFSTATE_DEFENDER;
04041 }
04042 defendAttackPriority = 0;
04043 }
04044 else
04045 {
04046 if (enemyHasOurFlag)
04047 {
04048 if (attackRetrievePriority)
04049 {
04050 botstates[squad[i]->s.number]->ctfState = CTFSTATE_ATTACKER;
04051 attackRetrievePriority = 0;
04052 }
04053 else
04054 {
04055 botstates[squad[i]->s.number]->ctfState = CTFSTATE_RETRIEVAL;
04056 attackRetrievePriority = 1;
04057 }
04058 }
04059 else
04060 {
04061 botstates[squad[i]->s.number]->ctfState = CTFSTATE_ATTACKER;
04062 }
04063 defendAttackPriority = 1;
04064 }
04065 }
04066 else if ((numOnMyTeam < 2 || !numAttackers) && enemyHasOurFlag)
04067 { //I'm the only one on my team who will attack and the enemy has my flag, I have to go after him
04068 botstates[squad[i]->s.number]->ctfState = CTFSTATE_RETRIEVAL;
04069 }
04070 }
04071
04072 i++;
04073 }
04074 }
|
|
|
Definition at line 4077 of file ai_main.c. References bot_state_t, botstates, bot_state_s::client, gentity_s::client, g_entities, gentity_t, bot_state_s::isSquadLeader, MAX_CLIENTS, entityState_s::number, OnSameTeam(), gentity_s::s, bot_state_s::siegeState, and bot_state_s::state_Forced. Referenced by CommanderBotAI().
04078 {
04079 int i = 0;
04080 int squadmates = 0;
04081 int commanded = 0;
04082 int teammates = 0;
04083 gentity_t *squad[MAX_CLIENTS];
04084 gentity_t *ent;
04085 bot_state_t *bst;
04086
04087 while (i < MAX_CLIENTS)
04088 {
04089 ent = &g_entities[i];
04090
04091 if (ent && ent->client && OnSameTeam(&g_entities[bs->client], ent) && botstates[ent->s.number])
04092 {
04093 bst = botstates[ent->s.number];
04094
04095 if (bst && !bst->isSquadLeader && !bst->state_Forced)
04096 {
04097 squad[squadmates] = ent;
04098 squadmates++;
04099 }
04100 else if (bst && !bst->isSquadLeader && bst->state_Forced)
04101 { //count them as commanded
04102 commanded++;
04103 }
04104 }
04105
04106 if (ent && ent->client && OnSameTeam(&g_entities[bs->client], ent))
04107 {
04108 teammates++;
04109 }
04110
04111 i++;
04112 }
04113
04114 if (!squadmates)
04115 {
04116 return;
04117 }
04118
04119 //tell squad mates to do what I'm doing, up to half of team, let the other half make their own decisions
04120 i = 0;
04121
04122 while (i < squadmates && squad[i])
04123 {
04124 bst = botstates[squad[i]->s.number];
04125
04126 if (commanded > teammates/2)
04127 {
04128 break;
04129 }
04130
04131 if (bst)
04132 {
04133 bst->state_Forced = bs->siegeState;
04134 bst->siegeState = bs->siegeState;
04135 commanded++;
04136 }
04137
04138 i++;
04139 }
04140 }
|
|
|
Definition at line 4158 of file ai_main.c. References bot_state_t, botstates, bot_state_s::client, gentity_s::client, g_entities, gentity_t, gentity_s::health, bot_state_s::isSquadLeader, level, MAX_CLIENTS, entityState_s::number, OnSameTeam(), Q_irand(), gentity_s::s, bot_state_s::squadCannotLead, bot_state_s::squadLeader, bot_state_s::squadRegroupInterval, bot_state_s::state_Forced, bot_state_s::teamplayState, TEAMPLAYSTATE_ASSISTING, TEAMPLAYSTATE_FOLLOWING, TEAMPLAYSTATE_REGROUP, and level_locals_t::time. Referenced by CommanderBotAI().
04159 {
04160 int i = 0;
04161 int squadmates = 0;
04162 int teammates = 0;
04163 int teammate_indanger = -1;
04164 int teammate_helped = 0;
04165 int foundsquadleader = 0;
04166 int worsthealth = 50;
04167 gentity_t *squad[MAX_CLIENTS];
04168 gentity_t *ent;
04169 bot_state_t *bst;
04170
04171 while (i < MAX_CLIENTS)
04172 {
04173 ent = &g_entities[i];
04174
04175 if (ent && ent->client && OnSameTeam(&g_entities[bs->client], ent) && botstates[ent->s.number])
04176 {
04177 bst = botstates[ent->s.number];
04178
04179 if (foundsquadleader && bst && bst->isSquadLeader)
04180 { //never more than one squad leader
04181 bst->isSquadLeader = 0;
04182 }
04183
04184 if (bst && !bst->isSquadLeader)
04185 {
04186 squad[squadmates] = ent;
04187 squadmates++;
04188 }
04189 else if (bst)
04190 {
04191 foundsquadleader = 1;
04192 }
04193 }
04194
04195 if (ent && ent->client && OnSameTeam(&g_entities[bs->client], ent))
04196 {
04197 teammates++;
04198
04199 if (ent->health < worsthealth)
04200 {
04201 teammate_indanger = ent->s.number;
04202 worsthealth = ent->health;
04203 }
04204 }
04205
04206 i++;
04207 }
04208
04209 if (!squadmates)
04210 {
04211 return;
04212 }
04213
04214 i = 0;
04215
04216 while (i < squadmates && squad[i])
04217 {
04218 bst = botstates[squad[i]->s.number];
04219
04220 if (bst && !bst->state_Forced)
04221 { //only order if this guy is not being ordered directly by the real player team leader
04222 if (teammate_indanger >= 0 && !teammate_helped)
04223 { //send someone out to help whoever needs help most at the moment
04224 bst->teamplayState = TEAMPLAYSTATE_ASSISTING;
04225 bst->squadLeader = &g_entities[teammate_indanger];
04226 teammate_helped = 1;
04227 }
04228 else if ((teammate_indanger == -1 || teammate_helped) && bst->teamplayState == TEAMPLAYSTATE_ASSISTING)
04229 { //no teammates need help badly, but this guy is trying to help them anyway, so stop
04230 bst->teamplayState = TEAMPLAYSTATE_FOLLOWING;
04231 bst->squadLeader = &g_entities[bs->client];
04232 }
04233
04234 if (bs->squadRegroupInterval < level.time && Q_irand(1, 10) < 5)
04235 { //every so often tell the squad to regroup for the sake of variation
04236 if (bst->teamplayState == TEAMPLAYSTATE_FOLLOWING)
04237 {
04238 bst->teamplayState = TEAMPLAYSTATE_REGROUP;
04239 }
04240
04241 bs->isSquadLeader = 0;
04242 bs->squadCannotLead = level.time + 500;
04243 bs->squadRegroupInterval = level.time + Q_irand(45000, 65000);
04244 }
04245 }
04246
04247 i++;
04248 }
04249 }
|
|
|
Definition at line 5647 of file ai_main.c. References BOT_FLAG_GET_DISTANCE, bot_state_t, gentity_s::classname, bot_state_s::client, droppedBlueFlag, droppedRedFlag, trace_t::entityNum, FL_DROPPED_ITEM, flagBlue, flagRed, gentity_s::flags, trace_t::fraction, gentity_t, bot_state_s::goalPosition, MASK_SOLID, NULL, entityState_s::number, bot_state_s::origin, entityState_s::pos, gentity_s::s, bot_state_s::staticFlagSpot, strcmp(), trap_Trace(), trajectory_t::trBase, vec3_t, VectorCopy, VectorSubtract, bot_state_s::wantFlag, and bot_state_s::wpDestination. Referenced by StandardBotAI().
05648 {
05649 int diddrop = 0;
05650 gentity_t *desiredDrop = NULL;
05651 vec3_t a, mins, maxs;
05652 trace_t tr;
05653
05654 mins[0] = -15;
05655 mins[1] = -15;
05656 mins[2] = -7;
05657 maxs[0] = 15;
05658 maxs[1] = 15;
05659 maxs[2] = 7;
05660
05661 if (bs->wantFlag && (bs->wantFlag->flags & FL_DROPPED_ITEM))
05662 {
05663 if (bs->staticFlagSpot[0] == bs->wantFlag->s.pos.trBase[0] &&
05664 bs->staticFlagSpot[1] == bs->wantFlag->s.pos.trBase[1] &&
05665 bs->staticFlagSpot[2] == bs->wantFlag->s.pos.trBase[2])
05666 {
05667 VectorSubtract(bs->origin, bs->wantFlag->s.pos.trBase, a);
05668
05669 if (VectorLength(a) <= BOT_FLAG_GET_DISTANCE)
05670 {
05671 VectorCopy(bs->wantFlag->s.pos.trBase, bs->goalPosition);
05672 return;
05673 }
05674 else
05675 {
05676 bs->wantFlag = NULL;
05677 }
05678 }
05679 else
05680 {
05681 bs->wantFlag = NULL;
05682 }
05683 }
05684 else if (bs->wantFlag)
05685 {
05686 bs->wantFlag = NULL;
05687 }
05688
05689 if (flagRed && flagBlue)
05690 {
05691 if (bs->wpDestination == flagRed ||
05692 bs->wpDestination == flagBlue)
05693 {
05694 if (bs->wpDestination == flagRed && droppedRedFlag && (droppedRedFlag->flags & FL_DROPPED_ITEM) && droppedRedFlag->classname && strcmp(droppedRedFlag->classname, "freed") != 0)
05695 {
05696 desiredDrop = droppedRedFlag;
05697 diddrop = 1;
05698 }
05699 if (bs->wpDestination == flagBlue && droppedBlueFlag && (droppedBlueFlag->flags & FL_DROPPED_ITEM) && droppedBlueFlag->classname && strcmp(droppedBlueFlag->classname, "freed") != 0)
05700 {
05701 desiredDrop = droppedBlueFlag;
05702 diddrop = 1;
05703 }
05704
05705 if (diddrop && desiredDrop)
05706 {
05707 VectorSubtract(bs->origin, desiredDrop->s.pos.trBase, a);
05708
05709 if (VectorLength(a) <= BOT_FLAG_GET_DISTANCE)
05710 {
05711 trap_Trace(&tr, bs->origin, mins, maxs, desiredDrop->s.pos.trBase, bs->client, MASK_SOLID);
05712
05713 if (tr.fraction == 1 || tr.entityNum == desiredDrop->s.number)
05714 {
05715 VectorCopy(desiredDrop->s.pos.trBase, bs->goalPosition);
05716 VectorCopy(desiredDrop->s.pos.trBase, bs->staticFlagSpot);
05717 return;
05718 }
05719 }
05720 }
05721 }
05722 }
05723 }
|
|
|
Definition at line 2804 of file ai_main.c. References BOT_MAX_WEAPON_CHASE_CTF, BOT_MAX_WEAPON_GATHER_TIME, bot_state_t, BotDefendFlag(), BotGetEnemyFlag(), BotGetFlagBack(), BotGetFlagHome(), |