📄 ai_main.c
字号:
trap_BotFreeCharacter(bs->character);
//
BotFreeWaypoints(bs->checkpoints);
BotFreeWaypoints(bs->patrolpoints);
//clear activate goal stack
BotClearActivateGoalStack(bs);
//clear the bot state
memset(bs, 0, sizeof(bot_state_t));
//set the inuse flag to qfalse
bs->inuse = qfalse;
//there's one bot less
numbots--;
//everything went ok
return qtrue;
}
/*
==============
BotResetState
called when a bot enters the intermission or observer mode and
when the level is changed
==============
*/
void BotResetState(bot_state_t *bs) {
int client, entitynum, inuse;
int movestate, goalstate, chatstate, weaponstate;
bot_settings_t settings;
int character;
playerState_t ps; //current player state
float entergame_time;
//save some things that should not be reset here
memcpy(&settings, &bs->settings, sizeof(bot_settings_t));
memcpy(&ps, &bs->cur_ps, sizeof(playerState_t));
inuse = bs->inuse;
client = bs->client;
entitynum = bs->entitynum;
character = bs->character;
movestate = bs->ms;
goalstate = bs->gs;
chatstate = bs->cs;
weaponstate = bs->ws;
entergame_time = bs->entergame_time;
//free checkpoints and patrol points
BotFreeWaypoints(bs->checkpoints);
BotFreeWaypoints(bs->patrolpoints);
//reset the whole state
memset(bs, 0, sizeof(bot_state_t));
//copy back some state stuff that should not be reset
bs->ms = movestate;
bs->gs = goalstate;
bs->cs = chatstate;
bs->ws = weaponstate;
memcpy(&bs->cur_ps, &ps, sizeof(playerState_t));
memcpy(&bs->settings, &settings, sizeof(bot_settings_t));
bs->inuse = inuse;
bs->client = client;
bs->entitynum = entitynum;
bs->character = character;
bs->entergame_time = entergame_time;
//reset several states
if (bs->ms) trap_BotResetMoveState(bs->ms);
if (bs->gs) trap_BotResetGoalState(bs->gs);
if (bs->ws) trap_BotResetWeaponState(bs->ws);
if (bs->gs) trap_BotResetAvoidGoals(bs->gs);
if (bs->ms) trap_BotResetAvoidReach(bs->ms);
}
/*
==============
BotAILoadMap
==============
*/
int BotAILoadMap( int restart ) {
int i;
vmCvar_t mapname;
if (!restart) {
trap_Cvar_Register( &mapname, "mapname", "", CVAR_SERVERINFO | CVAR_ROM );
trap_BotLibLoadMap( mapname.string );
}
for (i = 0; i < MAX_CLIENTS; i++) {
if (botstates[i] && botstates[i]->inuse) {
BotResetState( botstates[i] );
botstates[i]->setupcount = 4;
}
}
BotSetupDeathmatchAI();
return qtrue;
}
#ifdef MISSIONPACK
void ProximityMine_Trigger( gentity_t *trigger, gentity_t *other, trace_t *trace );
#endif
/*
==================
BotAIStartFrame
==================
*/
int BotAIStartFrame(int time) {
int i;
gentity_t *ent;
bot_entitystate_t state;
int elapsed_time, thinktime;
static int local_time;
static int botlib_residual;
static int lastbotthink_time;
G_CheckBotSpawn();
trap_Cvar_Update(&bot_rocketjump);
trap_Cvar_Update(&bot_grapple);
trap_Cvar_Update(&bot_fastchat);
trap_Cvar_Update(&bot_nochat);
trap_Cvar_Update(&bot_testrchat);
trap_Cvar_Update(&bot_thinktime);
trap_Cvar_Update(&bot_memorydump);
trap_Cvar_Update(&bot_saveroutingcache);
trap_Cvar_Update(&bot_pause);
trap_Cvar_Update(&bot_report);
if (bot_report.integer) {
// BotTeamplayReport();
// trap_Cvar_Set("bot_report", "0");
BotUpdateInfoConfigStrings();
}
if (bot_pause.integer) {
// execute bot user commands every frame
for( i = 0; i < MAX_CLIENTS; i++ ) {
if( !botstates[i] || !botstates[i]->inuse ) {
continue;
}
if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
continue;
}
botstates[i]->lastucmd.forwardmove = 0;
botstates[i]->lastucmd.rightmove = 0;
botstates[i]->lastucmd.upmove = 0;
botstates[i]->lastucmd.buttons = 0;
botstates[i]->lastucmd.serverTime = time;
trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
}
return qtrue;
}
if (bot_memorydump.integer) {
trap_BotLibVarSet("memorydump", "1");
trap_Cvar_Set("bot_memorydump", "0");
}
if (bot_saveroutingcache.integer) {
trap_BotLibVarSet("saveroutingcache", "1");
trap_Cvar_Set("bot_saveroutingcache", "0");
}
//check if bot interbreeding is activated
BotInterbreeding();
//cap the bot think time
if (bot_thinktime.integer > 200) {
trap_Cvar_Set("bot_thinktime", "200");
}
//if the bot think time changed we should reschedule the bots
if (bot_thinktime.integer != lastbotthink_time) {
lastbotthink_time = bot_thinktime.integer;
BotScheduleBotThink();
}
elapsed_time = time - local_time;
local_time = time;
botlib_residual += elapsed_time;
if (elapsed_time > bot_thinktime.integer) thinktime = elapsed_time;
else thinktime = bot_thinktime.integer;
// update the bot library
if ( botlib_residual >= thinktime ) {
botlib_residual -= thinktime;
trap_BotLibStartFrame((float) time / 1000);
if (!trap_AAS_Initialized()) return qfalse;
//update entities in the botlib
for (i = 0; i < MAX_GENTITIES; i++) {
ent = &g_entities[i];
if (!ent->inuse) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
if (!ent->r.linked) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
if (ent->r.svFlags & SVF_NOCLIENT) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
// do not update missiles
if (ent->s.eType == ET_MISSILE && ent->s.weapon != WP_GRAPPLING_HOOK) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
// do not update event only entities
if (ent->s.eType > ET_EVENTS) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
#ifdef MISSIONPACK
// never link prox mine triggers
if (ent->r.contents == CONTENTS_TRIGGER) {
if (ent->touch == ProximityMine_Trigger) {
trap_BotLibUpdateEntity(i, NULL);
continue;
}
}
#endif
//
memset(&state, 0, sizeof(bot_entitystate_t));
//
VectorCopy(ent->r.currentOrigin, state.origin);
if (i < MAX_CLIENTS) {
VectorCopy(ent->s.apos.trBase, state.angles);
} else {
VectorCopy(ent->r.currentAngles, state.angles);
}
VectorCopy(ent->s.origin2, state.old_origin);
VectorCopy(ent->r.mins, state.mins);
VectorCopy(ent->r.maxs, state.maxs);
state.type = ent->s.eType;
state.flags = ent->s.eFlags;
if (ent->r.bmodel) state.solid = SOLID_BSP;
else state.solid = SOLID_BBOX;
state.groundent = ent->s.groundEntityNum;
state.modelindex = ent->s.modelindex;
state.modelindex2 = ent->s.modelindex2;
state.frame = ent->s.frame;
state.event = ent->s.event;
state.eventParm = ent->s.eventParm;
state.powerups = ent->s.powerups;
state.legsAnim = ent->s.legsAnim;
state.torsoAnim = ent->s.torsoAnim;
state.weapon = ent->s.weapon;
//
trap_BotLibUpdateEntity(i, &state);
}
BotAIRegularUpdate();
}
floattime = trap_AAS_Time();
// execute scheduled bot AI
for( i = 0; i < MAX_CLIENTS; i++ ) {
if( !botstates[i] || !botstates[i]->inuse ) {
continue;
}
//
botstates[i]->botthink_residual += elapsed_time;
//
if ( botstates[i]->botthink_residual >= thinktime ) {
botstates[i]->botthink_residual -= thinktime;
if (!trap_AAS_Initialized()) return qfalse;
if (g_entities[i].client->pers.connected == CON_CONNECTED) {
BotAI(i, (float) thinktime / 1000);
}
}
}
// execute bot user commands every frame
for( i = 0; i < MAX_CLIENTS; i++ ) {
if( !botstates[i] || !botstates[i]->inuse ) {
continue;
}
if( g_entities[i].client->pers.connected != CON_CONNECTED ) {
continue;
}
BotUpdateInput(botstates[i], time, elapsed_time);
trap_BotUserCommand(botstates[i]->client, &botstates[i]->lastucmd);
}
return qtrue;
}
/*
==============
BotInitLibrary
==============
*/
int BotInitLibrary(void) {
char buf[144];
//set the maxclients and maxentities library variables before calling BotSetupLibrary
trap_Cvar_VariableStringBuffer("sv_maxclients", buf, sizeof(buf));
if (!strlen(buf)) strcpy(buf, "8");
trap_BotLibVarSet("maxclients", buf);
Com_sprintf(buf, sizeof(buf), "%d", MAX_GENTITIES);
trap_BotLibVarSet("maxentities", buf);
//bsp checksum
trap_Cvar_VariableStringBuffer("sv_mapChecksum", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("sv_mapChecksum", buf);
//maximum number of aas links
trap_Cvar_VariableStringBuffer("max_aaslinks", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("max_aaslinks", buf);
//maximum number of items in a level
trap_Cvar_VariableStringBuffer("max_levelitems", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("max_levelitems", buf);
//game type
trap_Cvar_VariableStringBuffer("g_gametype", buf, sizeof(buf));
if (!strlen(buf)) strcpy(buf, "0");
trap_BotLibVarSet("g_gametype", buf);
//bot developer mode and log file
trap_BotLibVarSet("bot_developer", bot_developer.string);
trap_BotLibVarSet("log", buf);
//no chatting
trap_Cvar_VariableStringBuffer("bot_nochat", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("nochat", "0");
//visualize jump pads
trap_Cvar_VariableStringBuffer("bot_visualizejumppads", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("bot_visualizejumppads", buf);
//forced clustering calculations
trap_Cvar_VariableStringBuffer("bot_forceclustering", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("forceclustering", buf);
//forced reachability calculations
trap_Cvar_VariableStringBuffer("bot_forcereachability", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("forcereachability", buf);
//force writing of AAS to file
trap_Cvar_VariableStringBuffer("bot_forcewrite", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("forcewrite", buf);
//no AAS optimization
trap_Cvar_VariableStringBuffer("bot_aasoptimize", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("aasoptimize", buf);
//
trap_Cvar_VariableStringBuffer("bot_saveroutingcache", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("saveroutingcache", buf);
//reload instead of cache bot character files
trap_Cvar_VariableStringBuffer("bot_reloadcharacters", buf, sizeof(buf));
if (!strlen(buf)) strcpy(buf, "0");
trap_BotLibVarSet("bot_reloadcharacters", buf);
//base directory
trap_Cvar_VariableStringBuffer("fs_basepath", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("basedir", buf);
//game directory
trap_Cvar_VariableStringBuffer("fs_game", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("gamedir", buf);
//cd directory
trap_Cvar_VariableStringBuffer("fs_cdpath", buf, sizeof(buf));
if (strlen(buf)) trap_BotLibVarSet("cddir", buf);
//
#ifdef MISSIONPACK
trap_BotLibDefine("MISSIONPACK");
#endif
//setup the bot library
return trap_BotLibSetup();
}
/*
==============
BotAISetup
==============
*/
int BotAISetup( int restart ) {
int errnum;
trap_Cvar_Register(&bot_thinktime, "bot_thinktime", "100", CVAR_CHEAT);
trap_Cvar_Register(&bot_memorydump, "bot_memorydump", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_saveroutingcache, "bot_saveroutingcache", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_pause, "bot_pause", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_report, "bot_report", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_testsolid, "bot_testsolid", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_testclusters, "bot_testclusters", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_developer, "bot_developer", "0", CVAR_CHEAT);
trap_Cvar_Register(&bot_interbreedchar, "bot_interbreedchar", "", 0);
trap_Cvar_Register(&bot_interbreedbots, "bot_interbreedbots", "10", 0);
trap_Cvar_Register(&bot_interbreedcycle, "bot_interbreedcycle", "20", 0);
trap_Cvar_Register(&bot_interbreedwrite, "bot_interbreedwrite", "", 0);
//if the game is restarted for a tournament
if (restart) {
return qtrue;
}
//initialize the bot states
memset( botstates, 0, sizeof(botstates) );
errnum = BotInitLibrary();
if (errnum != BLERR_NOERROR) return qfalse;
return qtrue;
}
/*
==============
BotAIShutdown
==============
*/
int BotAIShutdown( int restart ) {
int i;
//if the game is restarted for a tournament
if ( restart ) {
//shutdown all the bots in the botlib
for (i = 0; i < MAX_CLIENTS; i++) {
if (botstates[i] && botstates[i]->inuse) {
BotAIShutdownClient(botstates[i]->client, restart);
}
}
//don't shutdown the bot library
}
else {
trap_BotLibShutdown();
}
return qtrue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -