#include "g_local.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 "ai_dmq3.h"
#include "ai_chat.h"
#include "ai_cmd.h"
#include "ai_dmnet.h"
#include "ai_team.h"
#include "chars.h"
#include "inv.h"
#include "syn.h"
#include "match.h"
#include "../../ui/menudef.h"
Include dependency graph for ai_dmnet.c:

Go to the source code of this file.
|
|
Definition at line 60 of file ai_dmnet.c. |
|
|
Definition at line 65 of file ai_dmnet.c. |
|
||||||||||||
|
Definition at line 2140 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), bot_state_s::chase_time, FloatTime, and s. Referenced by AINode_Battle_Fight(), and AINode_Battle_Retreat(). 02140 {
02141 BotRecordNodeSwitch(bs, "battle chase", "", s);
02142 bs->chase_time = FloatTime();
02143 bs->ainode = AINode_Battle_Chase;
02144 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1963 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), bot_state_s::ms, s, and trap_BotResetLastAvoidReach(). Referenced by AINode_Battle_Chase(), AINode_Battle_NBG(), AINode_Battle_Retreat(), AINode_Seek_ActivateEntity(), AINode_Seek_LTG(), AINode_Seek_NBG(), and AINode_Stand(). 01963 {
01964 BotRecordNodeSwitch(bs, "battle fight", "", s);
01965 trap_BotResetLastAvoidReach(bs->ms);
01966 bs->ainode = AINode_Battle_Fight;
01967 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2469 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), and s. Referenced by AINode_Battle_Chase(), AINode_Battle_Retreat(), AINode_Seek_ActivateEntity(), and AINode_Seek_NBG(). 02469 {
02470 BotRecordNodeSwitch(bs, "battle NBG", "", s);
02471 bs->ainode = AINode_Battle_NBG;
02472 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 2280 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), and s. Referenced by AINode_Battle_Chase(), AINode_Battle_Fight(), AINode_Battle_NBG(), and AINode_Seek_LTG(). 02280 {
02281 BotRecordNodeSwitch(bs, "battle retreat", "", s);
02282 bs->ainode = AINode_Battle_Retreat;
02283 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1974 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), bot_state_s::flags, bot_state_s::ms, s, and trap_BotResetLastAvoidReach(). Referenced by AINode_Battle_Retreat(). 01974 {
01975 BotRecordNodeSwitch(bs, "battle fight", "", s);
01976 trap_BotResetLastAvoidReach(bs->ms);
01977 bs->ainode = AINode_Battle_Fight;
01978 bs->flags |= BFL_FIGHTSUICIDAL;
01979 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1130 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotChat_EndLevel(), BotRecordNodeSwitch(), BotResetState(), bot_state_s::chatto, bot_state_s::cs, s, and trap_BotEnterChat(). Referenced by AINode_Battle_Chase(), AINode_Battle_Fight(), AINode_Battle_NBG(), AINode_Battle_Retreat(), AINode_Seek_ActivateEntity(), AINode_Seek_LTG(), and AINode_Seek_NBG(). 01130 {
01131 BotRecordNodeSwitch(bs, "intermission", "", s);
01132 //reset the bot state
01133 BotResetState(bs);
01134 //check for end level chat
01135 if (BotChat_EndLevel(bs)) {
01136 trap_BotEnterChat(bs->cs, 0, bs->chatto);
01137 }
01138 bs->ainode = AINode_Intermission;
01139 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1165 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), BotResetState(), and s. Referenced by AINode_Battle_Chase(), AINode_Battle_Fight(), AINode_Battle_NBG(), AINode_Battle_Retreat(), AINode_Seek_ActivateEntity(), AINode_Seek_LTG(), and AINode_Seek_NBG(). 01165 {
01166 BotRecordNodeSwitch(bs, "observer", "", s);
01167 //reset the bot state
01168 BotResetState(bs);
01169 bs->ainode = AINode_Observer;
01170 }
|
Here is the call graph for this function:

|
||||||||||||
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1433 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), and s. Referenced by BotGoForActivateGoal(). 01433 {
01434 BotRecordNodeSwitch(bs, "activate entity", "", s);
01435 bs->ainode = AINode_Seek_ActivateEntity;
01436 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1776 of file ai_dmnet.c. References bot_state_s::ainode, bot_goal_t, bot_state_t, BotRecordNodeSwitch(), bot_state_s::gs, bot_goal_s::number, s, trap_BotGetTopGoal(), and trap_BotGoalName(). Referenced by AINode_Battle_Chase(), AINode_Battle_Fight(), AINode_Battle_Retreat(), AINode_Respawn(), AINode_Seek_NBG(), AINode_Stand(), and BotDeathmatchAI(). 01776 {
01777 bot_goal_t goal;
01778 char buf[144];
01779
01780 if (trap_BotGetTopGoal(bs->gs, &goal)) {
01781 trap_BotGoalName(goal.number, buf, 144);
01782 BotRecordNodeSwitch(bs, "seek LTG", buf, s);
01783 }
01784 else {
01785 BotRecordNodeSwitch(bs, "seek LTG", "no goal", s);
01786 }
01787 bs->ainode = AINode_Seek_LTG;
01788 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1643 of file ai_dmnet.c. References bot_state_s::ainode, bot_goal_t, bot_state_t, BotRecordNodeSwitch(), bot_state_s::gs, bot_goal_s::number, s, trap_BotGetTopGoal(), and trap_BotGoalName(). Referenced by AINode_Battle_NBG(), AINode_Seek_ActivateEntity(), AINode_Seek_LTG(), and BotGetLongTermGoal(). 01643 {
01644 bot_goal_t goal;
01645 char buf[144];
01646
01647 if (trap_BotGetTopGoal(bs->gs, &goal)) {
01648 trap_BotGoalName(goal.number, buf, 144);
01649 BotRecordNodeSwitch(bs, "seek NBG", buf, s);
01650 }
01651 else {
01652 BotRecordNodeSwitch(bs, "seek NBG", "no goal", s);
01653 }
01654 bs->ainode = AINode_Seek_NBG;
01655 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1190 of file ai_dmnet.c. References bot_state_s::ainode, bot_state_t, BotRecordNodeSwitch(), FloatTime, s, and bot_state_s::standfindenemy_time. Referenced by AINode_Battle_Fight(), AINode_Intermission(), AINode_Observer(), AINode_Seek_LTG(), BotCheckConsoleMessages(), and BotDeathmatchAI(). 01190 {
01191 BotRecordNodeSwitch(bs, "stand", "", s);
01192 bs->standfindenemy_time = FloatTime() + 1;
01193 bs->ainode = AINode_Stand;
01194 }
|
Here is the call graph for this function:

|
|
Definition at line 2151 of file ai_dmnet.c. References AIEnter_Battle_Fight(), AIEnter_Battle_NBG(), AIEnter_Battle_Retreat(), AIEnter_Intermission(), AIEnter_Observer(), AIEnter_Respawn(), AIEnter_Seek_LTG(), bot_goal_s::areanum, bot_state_s::areanum, bot_goal_t, bot_grapple, bot_moveresult_t, bot_state_t, BotAIBlocked(), BotAimAtEnemy(), BotCanAndWantsToRocketJump(), BotEntityVisible(), BotFindEnemy(), BotInLavaOrSlime(), BotIntermission(), BotIsDead(), BotIsObserver(), BotMapScripts(), BotNearbyGoal(), BotSetupForMovement(), BotUpdateBattleInventory(), BotWantsToRetreat(), bot_state_s::chase_time, bot_state_s::check_time, bot_state_s::enemy, bot_state_s::entitynum, bot_goal_s::entitynum, bot_state_s::eye, bot_moveresult_s::failure, bot_moveresult_s::flags, bot_state_s::flags, FloatTime, bot_moveresult_s::ideal_viewangles, bot_state_s::ideal_viewangles, vmCvar_t::integer, bot_state_s::lastenemyareanum, bot_state_s::lastenemyorigin, bot_state_s::ltg_time, bot_goal_s::maxs, bot_goal_s::mins, bot_moveresult_s::movedir, MOVERESULT_MOVEMENTVIEW, MOVERESULT_MOVEMENTVIEWSET, bot_state_s::ms, bot_state_s::nbg_time, bot_goal_s::origin, bot_state_s::origin, qfalse, range, bot_state_s::tfl, TFL_LAVA, trap_BotMovementViewTarget(), trap_BotMoveToGoal(), trap_BotResetAvoidReach(), trap_BotResetLastAvoidReach(), trap_BotTouchingGoal(), vec3_t, vectoangles(), VectorCopy, VectorSet, VectorSubtract, bot_state_s::viewangles, bot_moveresult_s::weapon, and bot_state_s::weaponnum. 02152 {
02153 bot_goal_t goal;
02154 vec3_t target, dir;
02155 bot_moveresult_t moveresult;
02156 float range;
02157
02158 if (BotIsObserver(bs)) {
02159 AIEnter_Observer(bs, "battle chase: observer");
02160 return qfalse;
02161 }
02162 //if in the intermission
02163 if (BotIntermission(bs)) {
02164 AIEnter_Intermission(bs, "battle chase: intermission");
02165 return qfalse;
02166 }
02167 //respawn if dead
02168 if (BotIsDead(bs)) {
02169 AIEnter_Respawn(bs, "battle chase: bot dead");
02170 return qfalse;
02171 }
02172 //if no enemy
02173 if (bs->enemy < 0) {
02174 AIEnter_Seek_LTG(bs, "battle chase: no enemy");
02175 return qfalse;
02176 }
02177 //if the enemy is visible
02178 if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, bs->enemy)) {
02179 AIEnter_Battle_Fight(bs, "battle chase");
02180 return qfalse;
02181 }
02182 //if there is another enemy
02183 if (BotFindEnemy(bs, -1)) {
02184 AIEnter_Battle_Fight(bs, "battle chase: better enemy");
02185 return qfalse;
02186 }
02187 //there is no last enemy area
02188 if (!bs->lastenemyareanum) {
02189 AIEnter_Seek_LTG(bs, "battle chase: no enemy area");
02190 return qfalse;
02191 }
02192 //
02193 bs->tfl = TFL_DEFAULT;
02194 if (bot_grapple.integer) bs->tfl |= TFL_GRAPPLEHOOK;
02195 //if in lava or slime the bot should be able to get out
02196 if (BotInLavaOrSlime(bs)) bs->tfl |= TFL_LAVA|TFL_SLIME;
02197 //
02198 if (BotCanAndWantsToRocketJump(bs)) {
02199 bs->tfl |= TFL_ROCKETJUMP;
02200 }
02201 //map specific code
02202 BotMapScripts(bs);
02203 //create the chase goal
02204 goal.entitynum = bs->enemy;
02205 goal.areanum = bs->lastenemyareanum;
02206 VectorCopy(bs->lastenemyorigin, goal.origin);
02207 VectorSet(goal.mins, -8, -8, -8);
02208 VectorSet(goal.maxs, 8, 8, 8);
02209 //if the last seen enemy spot is reached the enemy could not be found
02210 if (trap_BotTouchingGoal(bs->origin, &goal)) bs->chase_time = 0;
02211 //if there's no chase time left
02212 if (!bs->chase_time || bs->chase_time < FloatTime() - 10) {
02213 AIEnter_Seek_LTG(bs, "battle chase: time out");
02214 return qfalse;
02215 }
02216 //check for nearby goals periodicly
02217 if (bs->check_time < FloatTime()) {
02218 bs->check_time = FloatTime() + 1;
02219 range = 150;
02220 //
02221 if (BotNearbyGoal(bs, bs->tfl, &goal, range)) {
02222 //the bot gets 5 seconds to pick up the nearby goal item
02223 bs->nbg_time = FloatTime() + 0.1 * range + 1;
02224 trap_BotResetLastAvoidReach(bs->ms);
02225 AIEnter_Battle_NBG(bs, "battle chase: nbg");
02226 return qfalse;
02227 }
02228 }
02229 //
02230 BotUpdateBattleInventory(bs, bs->enemy);
02231 //initialize the movement state
02232 BotSetupForMovement(bs);
02233 //move towards the goal
02234 trap_BotMoveToGoal(&moveresult, bs->ms, &goal, bs->tfl);
02235 //if the movement failed
02236 if (moveresult.failure) {
02237 //reset the avoid reach, otherwise bot is stuck in current area
02238 trap_BotResetAvoidReach(bs->ms);
02239 //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
02240 bs->ltg_time = 0;
02241 }
02242 //
02243 BotAIBlocked(bs, &moveresult, qfalse);
02244 //
02245 if (moveresult.flags & (MOVERESULT_MOVEMENTVIEWSET|MOVERESULT_MOVEMENTVIEW|MOVERESULT_SWIMVIEW)) {
02246 VectorCopy(moveresult.ideal_viewangles, bs->ideal_viewangles);
02247 }
02248 else if (!(bs->flags & BFL_IDEALVIEWSET)) {
02249 if (bs->chase_time > FloatTime() - 2) {
02250 BotAimAtEnemy(bs);
02251 }
02252 else {
02253 if (trap_BotMovementViewTarget(bs->ms, &goal, bs->tfl, 300, target)) {
02254 VectorSubtract(target, bs->origin, dir);
02255 vectoangles(dir, bs->ideal_viewangles);
02256 }
02257 else {
02258 vectoangles(moveresult.movedir, bs->ideal_viewangles);
02259 }
02260 }
02261 bs->ideal_viewangles[2] *= 0.5;
02262 }
02263 //if the weapon is used for the bot movement
02264 if (moveresult.flags & MOVERESULT_MOVEMENTWEAPON) bs->weaponnum = moveresult.weapon;
02265 //if the bot is in the area the enemy was last seen in
02266 if (bs->areanum == bs->lastenemyareanum) bs->chase_time = 0;
02267 //if the bot wants to retreat (the bot could have been damage during the chase)
02268 if (BotWantsToRetreat(bs)) {
02269 AIEnter_Battle_Retreat(bs, "battle chase: wants to retreat");
02270 return qtrue;
02271 }
02272 return qtrue;
02273 }
|
Here is the call graph for this function:

|
|
Definition at line 1986 of file ai_dmnet.c. References aas_entityinfo_t, AIEnter_Battle_Chase(), AIEnter_Battle_Retreat(), AIEnter_Intermission(), AIEnter_Observer(), AIEnter_Respawn(), AIEnter_Seek_LTG(), AIEnter_Stand(), bot_grapple, bot_moveresult_t, bot_state_t, BotAI_Print(), BotAIBlocked(), BotAimAtEnemy(), BotAttackMove(), BotBattleUseItems(), BotCanAndWantsToRocketJump(), BotChat_EnemySuicide(), BotChat_HitNoDeath(), BotChat_HitNoKill(), BotChat_Kill(), BotChatTime(), BotCheckAttack(), BotChooseWeapon(), BotEntityInfo(), BotEntityVisible(), BotFindEnemy(), BotInLavaOrSlime(), BotIntermission(), BotIsDead(), BotIsObserver(), BotPointAreaNum(), BotUpdateBattleInventory(), BotWantsToChase(), BotWantsToRetreat(), bot_state_s::cur_ps, bot_state_s::enemy, bot_state_s::enemydeath_time, bot_state_s::enemysuicide, EntityIsDead(), EntityIsInvisible(), EntityIsShooting(), bot_state_s::entitynum, bot_state_s::eye, bot_moveresult_s::failure, bot_state_s::flags, FloatTime, vmCvar_t::integer, bot_state_s::inventory, bot_state_s::lastenemyareanum, bot_state_s::lastenemyorigin, bot_state_s::lastframe_health, bot_state_s::lasthitcount, bot_state_s::lastkilledplayer, bot_state_s::ltg_time, bot_state_s::ms, aas_entityinfo_s::origin, playerState_s::persistant, PRT_MESSAGE, qfalse, random, bot_state_s::stand_time, bot_state_s::tfl, TFL_LAVA, trap_AAS_AreaReachability(), trap_BotResetAvoidReach(), vec3_t, VectorCopy, and bot_state_s::viewangles. 01986 {
01987 int areanum;
01988 vec3_t target;
01989 aas_entityinfo_t entinfo;
01990 bot_moveresult_t moveresult;
01991
01992 if (BotIsObserver(bs)) {
01993 AIEnter_Observer(bs, "battle fight: observer");
01994 return qfalse;
01995 }
01996
01997 //if in the intermission
01998 if (BotIntermission(bs)) {
01999 AIEnter_Intermission(bs, "battle fight: intermission");
02000 return qfalse;
02001 }
02002 //respawn if dead
02003 if (BotIsDead(bs)) {
02004 AIEnter_Respawn(bs, "battle fight: bot dead");
02005 return qfalse;
02006 }
02007 //if there is another better enemy
02008 if (BotFindEnemy(bs, bs->enemy)) {
02009 #ifdef DEBUG
02010 BotAI_Print(PRT_MESSAGE, "found new better enemy\n");
02011 #endif
02012 }
02013 //if no enemy
02014 if (bs->enemy < 0) {
02015 AIEnter_Seek_LTG(bs, "battle fight: no enemy");
02016 return qfalse;
02017 }
02018 //
02019 BotEntityInfo(bs->enemy, &entinfo);
02020 //if the enemy is dead
02021 if (bs->enemydeath_time) {
02022 if (bs->enemydeath_time < FloatTime() - 1.0) {
02023 bs->enemydeath_time = 0;
02024 if (bs->enemysuicide) {
02025 BotChat_EnemySuicide(bs);
02026 }
02027 if (bs->lastkilledplayer == bs->enemy && BotChat_Kill(bs)) {
02028 bs->stand_time = FloatTime() + BotChatTime(bs);
02029 AIEnter_Stand(bs, "battle fight: enemy dead");
02030 }
02031 else {
02032 bs->ltg_time = 0;
02033 AIEnter_Seek_LTG(bs, "battle fight: enemy dead");
02034 }
02035 return qfalse;
02036 }
02037 }
02038 else {
02039 if (EntityIsDead(&entinfo)) {
02040 bs->enemydeath_time = FloatTime();
02041 }
02042 }
02043 //if the enemy is invisible and not shooting the bot looses track easily
02044 if (EntityIsInvisible(&entinfo) && !EntityIsShooting(&entinfo)) {
02045 if (random() < 0.2) {
02046 AIEnter_Seek_LTG(bs, "battle fight: invisible");
02047 return qfalse;
02048 }
02049 }
02050 //
02051 VectorCopy(entinfo.origin, target);
02052 // if not a player enemy
02053 if (bs->enemy >= MAX_CLIENTS) {
02054 #ifdef MISSIONPACK
02055 // if attacking an obelisk
02056 if ( bs->enemy == redobelisk.entitynum ||
02057 bs->enemy == blueobelisk.entitynum ) {
02058 target[2] += 16;
02059 }
02060 #endif
02061 }
02062 //update the reachability area and origin if possible
02063 areanum = BotPointAreaNum(target);
02064 if (areanum && trap_AAS_AreaReachability(areanum)) {
02065 VectorCopy(target, bs->lastenemyorigin);
02066 bs->lastenemyareanum = areanum;
02067 }
02068 //update the attack inventory values
02069 BotUpdateBattleInventory(bs, bs->enemy);
02070 //if the bot's health decreased
02071 if (bs->lastframe_health > bs->inventory[INVENTORY_HEALTH]) {
02072 if (BotChat_HitNoDeath(bs)) {
02073 bs->stand_time = FloatTime() + BotChatTime(bs);
02074 AIEnter_Stand(bs, "battle fight: chat health decreased");
02075 return qfalse;
02076 }
02077 }
02078 //if the bot hit someone
02079 if (bs->cur_ps.persistant[PERS_HITS] > bs->lasthitcount) {
02080 if (BotChat_HitNoKill(bs)) {
02081 bs->stand_time = FloatTime() + BotChatTime(bs);
02082 AIEnter_Stand(bs, "battle fight: chat hit someone");
02083 return qfalse;
02084 }
02085 }
02086 //if the enemy is not visible
02087 if (!BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, bs->enemy)) {
02088 if (BotWantsToChase(bs)) {
02089 AIEnter_Battle_Chase(bs, "battle fight: enemy out of sight");
02090 return qfalse;
02091 }
02092 else {
02093 AIEnter_Seek_LTG(bs, "battle fight: enemy out of sight");
02094 return qfalse;
02095 }
02096 }
02097 //use holdable items
02098 BotBattleUseItems(bs);
02099 //
02100 bs->tfl = TFL_DEFAULT;
02101 if (bot_grapple.integer) bs->tfl |= TFL_GRAPPLEHOOK;
02102 //if in lava or slime the bot should be able to get out
02103 if (BotInLavaOrSlime(bs)) bs->tfl |= TFL_LAVA|TFL_SLIME;
02104 //
02105 if (BotCanAndWantsToRocketJump(bs)) {
02106 bs->tfl |= TFL_ROCKETJUMP;
02107 }
02108 //choose the best weapon to fight with
02109 BotChooseWeapon(bs);
02110 //do attack movements
02111 moveresult = BotAttackMove(bs, bs->tfl);
02112 //if the movement failed
02113 if (moveresult.failure) {
02114 //reset the avoid reach, otherwise bot is stuck in current area
02115 trap_BotResetAvoidReach(bs->ms);
02116 //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
02117 bs->ltg_time = 0;
02118 }
02119 //
02120 BotAIBlocked(bs, &moveresult, qfalse);
02121 //aim at the enemy
02122 BotAimAtEnemy(bs);
02123 //attack the enemy if possible
02124 BotCheckAttack(bs);
02125 //if the bot wants to retreat
02126 if (!(bs->flags & BFL_FIGHTSUICIDAL)) {
02127 if (BotWantsToRetreat(bs)) {
02128 AIEnter_Battle_Retreat(bs, "battle fight: wants to retreat");
02129 return qtrue;
02130 }
02131 }
02132 return qtrue;
02133 }
|
Here is the call graph for this function:

|
|
Definition at line 2479 of file ai_dmnet.c. References aas_entityinfo_t, AIEnter_Battle_Fight(), AIEnter_Battle_Retreat(), AIEnter_Intermission(), AIEnter_Observer(), AIEnter_Respawn(), AIEnter_Seek_NBG(), bot_goal_t, bot_grapple, bot_moveresult_t, bot_state_t, BotAIBlocked(), BotAimAtEnemy(), BotCanAndWantsToRocketJump(), BotCheckAttack(), BotChooseWeapon(), BotEntityInfo(), BotEntityVisible(), BotInLavaOrSlime(), BotIntermission(), BotIsDead(), BotIsObserver(), BotMapScripts(), BotPointAreaNum(), BotReachedGoal(), BotSetupForMovement(), BotUpdateBattleInventory(), bot_state_s::character, CHARACTERISTIC_ATTACK_SKILL, bot_state_s::enemy, bot_state_s::enemyvisible_time, EntityIsDead(), bot_state_s::entitynum, bot_state_s::eye, bot_moveresult_s::failure, bot_moveresult_s::flags, bot_state_s::flags, FloatTime, bot_state_s::gs, bot_moveresult_s::ideal_viewangles, bot_state_s::ideal_viewangles, vmCvar_t::integer, bot_state_s::lastenemyareanum, bot_state_s::lastenemyorigin, bot_moveresult_s::movedir, MOVERESULT_MOVEMENTVIEW, bot_state_s::ms, bot_state_s::nbg_time, aas_entityinfo_s::origin, bot_state_s::origin, qfalse, bot_state_s::tfl, TFL_LAVA, trap_AAS_AreaReachability(), trap_BotGetTopGoal(), trap_BotMovementViewTarget(), trap_BotMoveToGoal(), trap_BotPopGoal(), trap_BotResetAvoidReach(), trap_Characteristic_BFloat(), vec3_t, vectoangles(), VectorCopy, VectorSubtract, bot_state_s::viewangles, bot_moveresult_s::weapon, and bot_state_s::weaponnum. 02479 {
02480 int areanum;
02481 bot_goal_t goal;
02482 aas_entityinfo_t entinfo;
02483 bot_moveresult_t moveresult;
02484 float attack_skill;
02485 vec3_t target, dir;
02486
02487 if (BotIsObserver(bs)) {
02488 AIEnter_Observer(bs, "battle nbg: observer");
02489 return qfalse;
02490 }
02491 //if in the intermission
02492 if (BotIntermission(bs)) {
02493 AIEnter_Intermission(bs, "battle nbg: intermission");
02494 return qfalse;
02495 }
02496 //respawn if dead
02497 if (BotIsDead(bs)) {
02498 AIEnter_Respawn(bs, "battle nbg: bot dead");
02499 return qfalse;
02500 }
02501 //if no enemy
02502 if (bs->enemy < 0) {
02503 AIEnter_Seek_NBG(bs, "battle nbg: no enemy");
02504 return qfalse;
02505 }
02506 //
02507 BotEntityInfo(bs->enemy, &entinfo);
02508 if (EntityIsDead(&entinfo)) {
02509 AIEnter_Seek_NBG(bs, "battle nbg: enemy dead");
02510 return qfalse;
02511 }
02512 //
02513 bs->tfl = TFL_DEFAULT;
02514 if (bot_grapple.integer) bs->tfl |= TFL_GRAPPLEHOOK;
02515 //if in lava or slime the bot should be able to get out
02516 if (BotInLavaOrSlime(bs)) bs->tfl |= TFL_LAVA|TFL_SLIME;
02517 //
02518 if (BotCanAndWantsToRocketJump(bs)) {
02519 bs->tfl |= TFL_ROCKETJUMP;
02520 }
02521 //map specific code
02522 BotMapScripts(bs);
02523 //update the last time the enemy was visible
02524 if (BotEntityVisible(bs->entitynum, bs->eye, bs->viewangles, 360, bs->enemy)) {
02525 bs->enemyvisible_time = FloatTime();
02526 VectorCopy(entinfo.origin, target);
02527 // if not a player enemy
02528 if (bs->enemy >= MAX_CLIENTS) {
02529 #ifdef MISSIONPACK
02530 // if attacking an obelisk
02531 if ( bs->enemy == redobelisk.entitynum ||
02532 bs->enemy == blueobelisk.entitynum ) {
02533 target[2] += 16;
02534 }
02535 #endif
02536 }
02537 //update the reachability area and origin if possible
02538 areanum = BotPointAreaNum(target);
02539 if (areanum && trap_AAS_AreaReachability(areanum)) {
02540 VectorCopy(target, bs->lastenemyorigin);
02541 bs->lastenemyareanum = areanum;
02542 }
02543 }
02544 //if the bot has no goal or touches the current goal
02545 if (!trap_BotGetTopGoal(bs->gs, &goal)) {
02546 bs->nbg_time = 0;
02547 }
02548 else if (BotReachedGoal(bs, &goal)) {
02549 bs->nbg_time = 0;
02550 }
02551 //
02552 if (bs->nbg_time < FloatTime()) {
02553 //pop the current goal from the stack
02554 trap_BotPopGoal(bs->gs);
02555 //if the bot still has a goal
02556 if (trap_BotGetTopGoal(bs->gs, &goal))
02557 AIEnter_Battle_Retreat(bs, "battle nbg: time out");
02558 else
02559 AIEnter_Battle_Fight(bs, "battle nbg: time out");
02560 //
02561 return qfalse;
02562 }
02563 //initialize the movement state
02564 BotSetupForMovement(bs);
02565 //move towards the goal
02566 trap_BotMoveToGoal(&moveresult, bs->ms, &goal, bs->tfl);
02567 //if the movement failed
02568 if (moveresult.failure) {
02569 //reset the avoid reach, otherwise bot is stuck in current area
02570 trap_BotResetAvoidReach(bs->ms);
02571 //BotAI_Print(PRT_MESSAGE, "movement failure %d\n", moveresult.traveltype);
02572 bs->nbg_time = 0;
02573 }
02574 |