📄 be_ai_move.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/*****************************************************************************
* name: be_ai_move.c
*
* desc: bot movement AI
*
* $Archive: /MissionPack/code/botlib/be_ai_move.c $
*
*****************************************************************************/
#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_libvar.h"
#include "l_utils.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "../game/be_ea.h"
#include "../game/be_ai_goal.h"
#include "../game/be_ai_move.h"
//#define DEBUG_AI_MOVE
//#define DEBUG_ELEVATOR
//#define DEBUG_GRAPPLE
// bk001204 - redundant bot_avoidspot_t, see ../game/be_ai_move.h
//movement state
//NOTE: the moveflags MFL_ONGROUND, MFL_TELEPORTED, MFL_WATERJUMP and
// MFL_GRAPPLEPULL must be set outside the movement code
typedef struct bot_movestate_s
{
//input vars (all set outside the movement code)
vec3_t origin; //origin of the bot
vec3_t velocity; //velocity of the bot
vec3_t viewoffset; //view offset
int entitynum; //entity number of the bot
int client; //client number of the bot
float thinktime; //time the bot thinks
int presencetype; //presencetype of the bot
vec3_t viewangles; //view angles of the bot
//state vars
int areanum; //area the bot is in
int lastareanum; //last area the bot was in
int lastgoalareanum; //last goal area number
int lastreachnum; //last reachability number
vec3_t lastorigin; //origin previous cycle
int reachareanum; //area number of the reachabilty
int moveflags; //movement flags
int jumpreach; //set when jumped
float grapplevisible_time; //last time the grapple was visible
float lastgrappledist; //last distance to the grapple end
float reachability_time; //time to use current reachability
int avoidreach[MAX_AVOIDREACH]; //reachabilities to avoid
float avoidreachtimes[MAX_AVOIDREACH]; //times to avoid the reachabilities
int avoidreachtries[MAX_AVOIDREACH]; //number of tries before avoiding
//
bot_avoidspot_t avoidspots[MAX_AVOIDSPOTS]; //spots to avoid
int numavoidspots;
} bot_movestate_t;
//used to avoid reachability links for some time after being used
#define AVOIDREACH
#define AVOIDREACH_TIME 6 //avoid links for 6 seconds after use
#define AVOIDREACH_TRIES 4
//prediction times
#define PREDICTIONTIME_JUMP 3 //in seconds
#define PREDICTIONTIME_MOVE 2 //in seconds
//weapon indexes for weapon jumping
#define WEAPONINDEX_ROCKET_LAUNCHER 5
#define WEAPONINDEX_BFG 9
#define MODELTYPE_FUNC_PLAT 1
#define MODELTYPE_FUNC_BOB 2
#define MODELTYPE_FUNC_DOOR 3
#define MODELTYPE_FUNC_STATIC 4
libvar_t *sv_maxstep;
libvar_t *sv_maxbarrier;
libvar_t *sv_gravity;
libvar_t *weapindex_rocketlauncher;
libvar_t *weapindex_bfg10k;
libvar_t *weapindex_grapple;
libvar_t *entitytypemissile;
libvar_t *offhandgrapple;
libvar_t *cmd_grappleoff;
libvar_t *cmd_grappleon;
//type of model, func_plat or func_bobbing
int modeltypes[MAX_MODELS];
bot_movestate_t *botmovestates[MAX_CLIENTS+1];
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
int BotAllocMoveState(void)
{
int i;
for (i = 1; i <= MAX_CLIENTS; i++)
{
if (!botmovestates[i])
{
botmovestates[i] = GetClearedMemory(sizeof(bot_movestate_t));
return i;
} //end if
} //end for
return 0;
} //end of the function BotAllocMoveState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotFreeMoveState(int handle)
{
if (handle <= 0 || handle > MAX_CLIENTS)
{
botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
return;
} //end if
if (!botmovestates[handle])
{
botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
return;
} //end if
FreeMemory(botmovestates[handle]);
botmovestates[handle] = NULL;
} //end of the function BotFreeMoveState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
bot_movestate_t *BotMoveStateFromHandle(int handle)
{
if (handle <= 0 || handle > MAX_CLIENTS)
{
botimport.Print(PRT_FATAL, "move state handle %d out of range\n", handle);
return NULL;
} //end if
if (!botmovestates[handle])
{
botimport.Print(PRT_FATAL, "invalid move state %d\n", handle);
return NULL;
} //end if
return botmovestates[handle];
} //end of the function BotMoveStateFromHandle
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
void BotInitMoveState(int handle, bot_initmove_t *initmove)
{
bot_movestate_t *ms;
ms = BotMoveStateFromHandle(handle);
if (!ms) return;
VectorCopy(initmove->origin, ms->origin);
VectorCopy(initmove->velocity, ms->velocity);
VectorCopy(initmove->viewoffset, ms->viewoffset);
ms->entitynum = initmove->entitynum;
ms->client = initmove->client;
ms->thinktime = initmove->thinktime;
ms->presencetype = initmove->presencetype;
VectorCopy(initmove->viewangles, ms->viewangles);
//
ms->moveflags &= ~MFL_ONGROUND;
if (initmove->or_moveflags & MFL_ONGROUND) ms->moveflags |= MFL_ONGROUND;
ms->moveflags &= ~MFL_TELEPORTED;
if (initmove->or_moveflags & MFL_TELEPORTED) ms->moveflags |= MFL_TELEPORTED;
ms->moveflags &= ~MFL_WATERJUMP;
if (initmove->or_moveflags & MFL_WATERJUMP) ms->moveflags |= MFL_WATERJUMP;
ms->moveflags &= ~MFL_WALK;
if (initmove->or_moveflags & MFL_WALK) ms->moveflags |= MFL_WALK;
ms->moveflags &= ~MFL_GRAPPLEPULL;
if (initmove->or_moveflags & MFL_GRAPPLEPULL) ms->moveflags |= MFL_GRAPPLEPULL;
} //end of the function BotInitMoveState
//========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//========================================================================
float AngleDiff(float ang1, float ang2)
{
float diff;
diff = ang1 - ang2;
if (ang1 > ang2)
{
if (diff > 180.0) diff -= 360.0;
} //end if
else
{
if (diff < -180.0) diff += 360.0;
} //end else
return diff;
} //end of the function AngleDiff
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotFuzzyPointReachabilityArea(vec3_t origin)
{
int firstareanum, j, x, y, z;
int areas[10], numareas, areanum, bestareanum;
float dist, bestdist;
vec3_t points[10], v, end;
firstareanum = 0;
areanum = AAS_PointAreaNum(origin);
if (areanum)
{
firstareanum = areanum;
if (AAS_AreaReachability(areanum)) return areanum;
} //end if
VectorCopy(origin, end);
end[2] += 4;
numareas = AAS_TraceAreas(origin, end, areas, points, 10);
for (j = 0; j < numareas; j++)
{
if (AAS_AreaReachability(areas[j])) return areas[j];
} //end for
bestdist = 999999;
bestareanum = 0;
for (z = 1; z >= -1; z -= 1)
{
for (x = 1; x >= -1; x -= 1)
{
for (y = 1; y >= -1; y -= 1)
{
VectorCopy(origin, end);
end[0] += x * 8;
end[1] += y * 8;
end[2] += z * 12;
numareas = AAS_TraceAreas(origin, end, areas, points, 10);
for (j = 0; j < numareas; j++)
{
if (AAS_AreaReachability(areas[j]))
{
VectorSubtract(points[j], origin, v);
dist = VectorLength(v);
if (dist < bestdist)
{
bestareanum = areas[j];
bestdist = dist;
} //end if
} //end if
if (!firstareanum) firstareanum = areas[j];
} //end for
} //end for
} //end for
if (bestareanum) return bestareanum;
} //end for
return firstareanum;
} //end of the function BotFuzzyPointReachabilityArea
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotReachabilityArea(vec3_t origin, int client)
{
int modelnum, modeltype, reachnum, areanum;
aas_reachability_t reach;
vec3_t org, end, mins, maxs, up = {0, 0, 1};
bsp_trace_t bsptrace;
aas_trace_t trace;
//check if the bot is standing on something
AAS_PresenceTypeBoundingBox(PRESENCE_CROUCH, mins, maxs);
VectorMA(origin, -3, up, end);
bsptrace = AAS_Trace(origin, mins, maxs, end, client, CONTENTS_SOLID|CONTENTS_PLAYERCLIP);
if (!bsptrace.startsolid && bsptrace.fraction < 1 && bsptrace.ent != ENTITYNUM_NONE)
{
//if standing on the world the bot should be in a valid area
if (bsptrace.ent == ENTITYNUM_WORLD)
{
return BotFuzzyPointReachabilityArea(origin);
} //end if
modelnum = AAS_EntityModelindex(bsptrace.ent);
modeltype = modeltypes[modelnum];
//if standing on a func_plat or func_bobbing then the bot is assumed to be
//in the area the reachability points to
if (modeltype == MODELTYPE_FUNC_PLAT || modeltype == MODELTYPE_FUNC_BOB)
{
reachnum = AAS_NextModelReachability(0, modelnum);
if (reachnum)
{
AAS_ReachabilityFromNum(reachnum, &reach);
return reach.areanum;
} //end if
} //end else if
//if the bot is swimming the bot should be in a valid area
if (AAS_Swimming(origin))
{
return BotFuzzyPointReachabilityArea(origin);
} //end if
//
areanum = BotFuzzyPointReachabilityArea(origin);
//if the bot is in an area with reachabilities
if (areanum && AAS_AreaReachability(areanum)) return areanum;
//trace down till the ground is hit because the bot is standing on some other entity
VectorCopy(origin, org);
VectorCopy(org, end);
end[2] -= 800;
trace = AAS_TraceClientBBox(org, end, PRESENCE_CROUCH, -1);
if (!trace.startsolid)
{
VectorCopy(trace.endpos, org);
} //end if
//
return BotFuzzyPointReachabilityArea(org);
} //end if
//
return BotFuzzyPointReachabilityArea(origin);
} //end of the function BotReachabilityArea
//===========================================================================
// returns the reachability area the bot is in
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
/*
int BotReachabilityArea(vec3_t origin, int testground)
{
int firstareanum, i, j, x, y, z;
int areas[10], numareas, areanum, bestareanum;
float dist, bestdist;
vec3_t org, end, points[10], v;
aas_trace_t trace;
firstareanum = 0;
for (i = 0; i < 2; i++)
{
VectorCopy(origin, org);
//if test at the ground (used when bot is standing on an entity)
if (i > 0)
{
VectorCopy(origin, end);
end[2] -= 800;
trace = AAS_TraceClientBBox(origin, end, PRESENCE_CROUCH, -1);
if (!trace.startsolid)
{
VectorCopy(trace.endpos, org);
} //end if
} //end if
firstareanum = 0;
areanum = AAS_PointAreaNum(org);
if (areanum)
{
firstareanum = areanum;
if (AAS_AreaReachability(areanum)) return areanum;
} //end if
bestdist = 999999;
bestareanum = 0;
for (z = 1; z >= -1; z -= 1)
{
for (x = 1; x >= -1; x -= 1)
{
for (y = 1; y >= -1; y -= 1)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -