/* ============== BotInterbreeding ============== */ void BotInterbreeding(void) { int i; trap_Cvar_Update(&bot_interbreedchar); if (!strlen(bot_interbreedchar.string)) return; //make sure we are in tournament mode if (gametype != GT_TOURNAMENT) { trap_Cvar_Set("g_gametype", va("%d", GT_TOURNAMENT)); ExitLevel(); return; } //shutdown all the bots for (i = 0; i < MAX_CLIENTS; i++) { if (botstates[i] && botstates[i]->inuse) { BotAIShutdownClient(botstates[i]->client, qfalse); } } //make sure all item weight configs are reloaded and Not shared trap_BotLibVarSet("bot_reloadcharacters", "1"); //add a number of bots using the desired bot character for (i = 0; i < bot_interbreedbots.integer; i++) { trap_SendConsoleCommand( EXEC_INSERT, va("addbot %s 4 free %i %s%d\n", bot_interbreedchar.string, i * 50, bot_interbreedchar.string, i) ); } // trap_Cvar_Set("bot_interbreedchar", ""); bot_interbreed = qtrue; }
/* ============== BotInitLibrary ============== */ int BotInitLibrary(void) { char buf[144]; //set the maxclients and maxentities library variables before calling BotSetupLibrary Com_sprintf(buf, sizeof(buf), "%d", level.maxplayers); 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); //bot developer mode and log file trap_BotLibVarSet("bot_developer", bot_developer.string); trap_Cvar_VariableStringBuffer("logfile", buf, sizeof(buf)); trap_BotLibVarSet("log", buf); //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); // #ifdef MISSIONPACK trap_PC_AddGlobalDefine("MISSIONPACK"); #endif //setup the bot library return trap_BotLibSetup(); }
/* ================== 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); trap_Cvar_Update(&bot_droppedweight); trap_Cvar_Update(&bot_offhandgrapple); trap_Cvar_Update(&bot_shownodechanges); trap_Cvar_Update(&bot_showteamgoals); trap_Cvar_Update(&bot_reloadcharacters); BotUpdateInfoConfigStrings(); if (bot_pause.integer) { // execute bot user commands every frame for( i = 0; i < level.maxplayers; i++ ) { if( !botstates[i] || !botstates[i]->inuse ) { continue; } if( g_entities[i].player->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]->playernum, &botstates[i]->lastucmd); } return qtrue; } if (bot_memorydump.integer) { trap_BotLibVarSet("memorydump", "1"); trap_Cvar_SetValue("bot_memorydump", 0); } if (bot_saveroutingcache.integer) { trap_BotLibVarSet("saveroutingcache", "1"); trap_Cvar_SetValue("bot_saveroutingcache", 0); } //check if bot interbreeding is activated BotInterbreeding(); //cap the bot think time if (bot_thinktime.integer > 200) { trap_Cvar_SetValue("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]; ent->botvalid = qfalse; 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->s.contents == CONTENTS_TRIGGER) { if (ent->touch == ProximityMine_Trigger) { trap_BotLibUpdateEntity(i, NULL); continue; } } #endif // ent->botvalid = qtrue; ent->update_time = trap_AAS_Time() - ent->ltime; ent->ltime = trap_AAS_Time(); // 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->r.absmin, state.absmins ); VectorCopy( ent->r.absmax, state.absmaxs ); state.type = ent->s.eType; state.flags = ent->s.eFlags; // if (ent->s.collisionType == CT_SUBMODEL) { state.solid = SOLID_BSP; //if the angles of the model changed if ( !VectorCompare( state.angles, ent->lastAngles ) ) { VectorCopy(state.angles, ent->lastAngles); state.relink = qtrue; } } else { state.solid = SOLID_BBOX; VectorCopy(state.angles, ent->lastAngles); } //previous frame visorigin VectorCopy( ent->visorigin, ent->lastvisorigin ); //if the origin changed if ( !VectorCompare( state.origin, ent->visorigin ) ) { VectorCopy( state.origin, ent->visorigin ); state.relink = qtrue; } //if the bounding box size changed if (!VectorCompare(ent->s.mins, ent->lastMins) || !VectorCompare(ent->s.maxs, ent->lastMaxs)) { VectorCopy( ent->s.mins, ent->lastMins ); VectorCopy( ent->s.maxs, ent->lastMaxs ); state.relink = qtrue; } // 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].player->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].player->pers.connected != CON_CONNECTED ) { continue; } BotUpdateInput(botstates[i], time, elapsed_time); trap_BotUserCommand(botstates[i]->playernum, &botstates[i]->lastucmd); } return qtrue; }
/* ================== BotAIStartFrame ================== */ int BotAIStartFrame( int time ) { int i; gentity_t *ent; bot_entitystate_t state; //entityState_t entitystate; //vec3_t mins = {-15, -15, -24}, maxs = {15, 15, 32}; int elapsed_time, thinktime; static int local_time; static int botlib_residual; static int lastbotthink_time; if ( g_gametype.integer != GT_SINGLE_PLAYER ) { 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 ); // Ridah, set the default AAS world trap_AAS_SetCurrentWorld( 0 ); trap_Cvar_Update( &memorydump ); if ( memorydump.integer ) { trap_BotLibVarSet( "memorydump", "1" ); trap_Cvar_Set( "memorydump", "0" ); } //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 ); // Ridah, only check the default world trap_AAS_SetCurrentWorld( 0 ); if ( !trap_AAS_Initialized() ) { return BLERR_NOERROR; } //update entities in the botlib for ( i = 0; i < MAX_GENTITIES; i++ ) { // Ridah, in single player, we only need client entity information if ( g_gametype.integer == GT_SINGLE_PLAYER && i > level.maxclients ) { break; } ent = &g_entities[i]; if ( !ent->inuse ) { continue; } if ( !ent->r.linked ) { continue; } if ( ent->r.svFlags & SVF_NOCLIENT ) { continue; } // memset( &state, 0, sizeof( bot_entitystate_t ) ); // VectorCopy( ent->r.currentOrigin, state.origin ); 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.weapAnim = ent->s.weapAnim; //----(SA) //----(SA) didn't want to comment in as I wasn't sure of any implications of changing the aas_entityinfo_t and bot_entitystate_t structures. state.weapon = ent->s.weapon; /* if (!BotAI_GetEntityState(i, &entitystate)) continue; // memset(&state, 0, sizeof(bot_entitystate_t)); // VectorCopy(entitystate.pos.trBase, state.origin); VectorCopy(entitystate.angles, state.angles); VectorCopy(ent->s.origin2, state.old_origin); //VectorCopy(ent->r.mins, state.mins); //VectorCopy(ent->r.maxs, state.maxs); state.type = entitystate.eType; state.flags = entitystate.eFlags; if (ent->r.bmodel) state.solid = SOLID_BSP; else state.solid = SOLID_BBOX; state.modelindex = entitystate.modelindex; state.modelindex2 = entitystate.modelindex2; state.frame = entitystate.frame; state.event = entitystate.event; state.eventParm = entitystate.eventParm; state.powerups = entitystate.powerups; state.legsAnim = entitystate.legsAnim; state.torsoAnim = entitystate.torsoAnim; state.weapon = entitystate.weapon; */ // trap_BotLibUpdateEntity( i, &state ); } BotAIRegularUpdate(); } // Ridah, in single player, don't need bot's thinking if ( g_gametype.integer == GT_SINGLE_PLAYER ) { return BLERR_NOERROR; } // execute scheduled bot AI for ( i = 0; i < MAX_CLIENTS; i++ ) { if ( !botstates[i] || !botstates[i]->inuse ) { continue; } // Ridah if ( g_entities[i].r.svFlags & SVF_CASTAI ) { continue; } // done. // botstates[i]->botthink_residual += elapsed_time; // if ( botstates[i]->botthink_residual >= thinktime ) { botstates[i]->botthink_residual -= thinktime; if ( !trap_AAS_Initialized() ) { return BLERR_NOERROR; } 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; } // Ridah if ( g_entities[i].r.svFlags & SVF_CASTAI ) { continue; } // done. if ( g_entities[i].client->pers.connected != CON_CONNECTED ) { continue; } BotUpdateInput( botstates[i], time ); trap_BotUserCommand( botstates[i]->client, &botstates[i]->lastucmd ); } return BLERR_NOERROR; }
/* ============== BotAISetupClient ============== */ int BotAISetupClient( int client, struct bot_settings_s *settings ) { char filename[MAX_PATH], name[MAX_PATH], gender[MAX_PATH]; bot_state_t *bs; int errnum; if ( !botstates[client] ) { botstates[client] = G_Alloc( sizeof( bot_state_t ) ); } bs = botstates[client]; if ( bs && bs->inuse ) { BotAI_Print( PRT_FATAL, "client %d already setup\n", client ); return qfalse; } if ( !trap_AAS_Initialized() ) { BotAI_Print( PRT_FATAL, "AAS not initialized\n" ); return qfalse; } //load the bot character bs->character = trap_BotLoadCharacter( settings->characterfile, settings->skill ); if ( !bs->character ) { BotAI_Print( PRT_FATAL, "couldn't load skill %f from %s\n", settings->skill, settings->characterfile ); return qfalse; } //copy the settings memcpy( &bs->settings, settings, sizeof( bot_settings_t ) ); //allocate a goal state bs->gs = trap_BotAllocGoalState( client ); //load the item weights trap_Characteristic_String( bs->character, CHARACTERISTIC_ITEMWEIGHTS, filename, MAX_PATH ); errnum = trap_BotLoadItemWeights( bs->gs, filename ); if ( errnum != BLERR_NOERROR ) { trap_BotFreeGoalState( bs->gs ); return qfalse; } //allocate a weapon state bs->ws = trap_BotAllocWeaponState(); //load the weapon weights trap_Characteristic_String( bs->character, CHARACTERISTIC_WEAPONWEIGHTS, filename, MAX_PATH ); errnum = trap_BotLoadWeaponWeights( bs->ws, filename ); if ( errnum != BLERR_NOERROR ) { trap_BotFreeGoalState( bs->gs ); trap_BotFreeWeaponState( bs->ws ); return qfalse; } //allocate a chat state bs->cs = trap_BotAllocChatState(); //load the chat file trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_FILE, filename, MAX_PATH ); trap_Characteristic_String( bs->character, CHARACTERISTIC_CHAT_NAME, name, MAX_PATH ); errnum = trap_BotLoadChatFile( bs->cs, filename, name ); if ( errnum != BLERR_NOERROR ) { trap_BotFreeChatState( bs->cs ); trap_BotFreeGoalState( bs->gs ); trap_BotFreeWeaponState( bs->ws ); return qfalse; } //get the gender characteristic trap_Characteristic_String( bs->character, CHARACTERISTIC_GENDER, gender, MAX_PATH ); //set the chat gender if ( *gender == 'f' || *gender == 'F' ) { trap_BotSetChatGender( bs->cs, CHAT_GENDERFEMALE ); } else if ( *gender == 'm' || *gender == 'M' ) { trap_BotSetChatGender( bs->cs, CHAT_GENDERMALE ); } else { trap_BotSetChatGender( bs->cs, CHAT_GENDERLESS );} bs->inuse = qtrue; bs->client = client; bs->entitynum = client; bs->setupcount = 4; bs->entergame_time = trap_AAS_Time(); bs->ms = trap_BotAllocMoveState(); bs->walker = trap_Characteristic_BFloat( bs->character, CHARACTERISTIC_WALKER, 0, 1 ); numbots++; if ( trap_Cvar_VariableIntegerValue( "bot_testichat" ) ) { trap_BotLibVarSet( "bot_testichat", "1" ); BotChatTest( bs ); } //NOTE: reschedule the bot thinking BotScheduleBotThink(); // 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 ); } //automatically launch WinBSPC if AAS file not available trap_Cvar_VariableStringBuffer( "autolaunchbspc", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "autolaunchbspc", "1" ); } // trap_Cvar_VariableStringBuffer( "g_gametype", buf, sizeof( buf ) ); if ( !strlen( buf ) ) { strcpy( buf, "0" ); } trap_BotLibVarSet( "g_gametype", buf ); // // Rafael gameskill trap_Cvar_VariableStringBuffer( "g_gameskill", buf, sizeof( buf ) ); if ( !strlen( buf ) ) { strcpy( buf, "0" ); } trap_BotLibVarSet( "g_gamekill", buf ); // done // trap_Cvar_VariableStringBuffer( "bot_developer", buf, sizeof( buf ) ); if ( !strlen( buf ) ) { strcpy( buf, "0" ); } trap_BotLibVarSet( "bot_developer", buf ); //log file trap_Cvar_VariableStringBuffer( "logfile", buf, sizeof( buf ) ); if ( !strlen( buf ) ) { strcpy( buf, "0" ); } trap_BotLibVarSet( "log", buf ); //no chatting trap_Cvar_VariableStringBuffer( "bot_nochat", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "nochat", buf ); } //forced clustering calculations trap_Cvar_VariableStringBuffer( "forceclustering", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "forceclustering", buf ); } //forced reachability calculations trap_Cvar_VariableStringBuffer( "forcereachability", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "forcereachability", buf ); } //force writing of AAS to file trap_Cvar_VariableStringBuffer( "forcewrite", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "forcewrite", buf ); } //no AAS optimization trap_Cvar_VariableStringBuffer( "nooptimize", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "nooptimize", buf ); } //number of reachabilities to calculate each frame trap_Cvar_VariableStringBuffer( "framereachability", buf, sizeof( buf ) ); if ( !strlen( buf ) ) { strcpy( buf, "20" ); } trap_BotLibVarSet( "framereachability", buf ); // 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 ); } //home directory trap_Cvar_VariableStringBuffer( "fs_homepath", buf, sizeof( buf ) ); if ( strlen( buf ) ) { trap_BotLibVarSet( "homedir", buf ); } //setup the bot library return trap_BotLibSetup(); }
/* ================= ConsoleCommand ================= */ qboolean ConsoleCommand( void ) { char cmd[MAX_TOKEN_CHARS]; trap_Argv( 0, cmd, sizeof( cmd ) ); if ( Q_stricmp (cmd, "entitylist") == 0 ) { Svcmd_EntityList_f(); return qtrue; } if ( Q_stricmp (cmd, "forceteam") == 0 ) { Svcmd_ForceTeam_f(); return qtrue; } if (Q_stricmp (cmd, "game_memory") == 0) { Svcmd_GameMem_f(); return qtrue; } if (Q_stricmp (cmd, "addbot") == 0) { Svcmd_AddBot_f(); return qtrue; } if (Q_stricmp (cmd, "botlist") == 0) { Svcmd_BotList_f(); return qtrue; } if (Q_stricmp (cmd, "abort_podium") == 0) { Svcmd_AbortPodium_f(); return qtrue; } if (Q_stricmp (cmd, "addip") == 0) { Svcmd_AddIP_f(); return qtrue; } if (Q_stricmp (cmd, "removeip") == 0) { Svcmd_RemoveIP_f(); return qtrue; } if (Q_stricmp (cmd, "listip") == 0) { trap_SendConsoleCommand( EXEC_NOW, "g_banIPs\n" ); return qtrue; } if(Q_stricmp (cmd, "setGametype") == 0) { Svcmd_SetGameType_f(); return qtrue; } if(Q_stricmp (cmd, "startcam") == 0) { Svcmd_StartCam(); return qtrue; } if(Q_stricmp (cmd, "stopcam") == 0) { Svcmd_StopCam(); return qtrue; } if(Q_stricmp (cmd, "camcmd") == 0) { Svcmd_CamCmd(); return qtrue; } if( !Q_stricmp( cmd, "initwp") ) { WaypointInit(); return qtrue; } if ( Q_stricmp( cmd, "blibset") == 0 ) { char key[MAX_TOKEN_CHARS]; char value[MAX_TOKEN_CHARS]; trap_Argv(1, key, sizeof(key) ); trap_Argv(2, value, sizeof(value) ); if(!strlen(key)) { G_Printf("missing key\n"); return qtrue; } if( !strlen(value) ) // use "1" as default strcpy( value, "1" ); trap_BotLibVarSet( key, value ); return qtrue; } if(wopSP_cmdCheck(cmd)) return qtrue; if (g_dedicated.integer) { if ( Q_stricmp( cmd, "ssay" ) == 0 ) { Svcmd_Say_f(); return qtrue; } if ( Q_stricmp( cmd, "stell" ) == 0 ) { Svcmd_Tell_f(); return qtrue; } if ( Q_stricmp( cmd, "scp" ) == 0 ) { Svcmd_ClientCommand_f( CCMD_CP ); return qtrue; } if ( Q_stricmp( cmd, "smp" ) == 0 ) { Svcmd_ClientCommand_f( CCMD_MP ); return qtrue; } if ( Q_stricmp( cmd, "sprint" ) == 0 ) { Svcmd_ClientCommand_f( CCMD_PRINT ); return qtrue; } // everything else will also be printed to clients trap_SendServerCommand( -1, va("print \"server: %s\n\"", ConcatArgs(0) ) ); return qtrue; } return qfalse; }
/* ============== 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_Cvar_VariableStringBuffer("logfile", buf, sizeof(buf)); trap_BotLibVarSet("log", buf); //no chatting trap_Cvar_VariableStringBuffer("bot_nochat", buf, sizeof(buf)); if (strlen(buf)) trap_BotLibVarSet("nochat", buf); //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); //home directory trap_Cvar_VariableStringBuffer("fs_homepath", buf, sizeof(buf)); if (strlen(buf)) trap_BotLibVarSet("homedir", buf); // #if 1 //def MPACK trap_BotLibDefine("MISSIONPACK"); #endif //setup the bot library return trap_BotLibSetup(); }
/* ================== 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; } #if 1 //def MPACK // 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; }
/* * BotAISetupClient */ int BotAISetupClient(int client, struct bot_settings_s *settings, qbool restart) { char filename[MAX_PATH], name[MAX_PATH], gender[MAX_PATH]; bot_state_t *bs; int errnum; if(!botstates[client]) botstates[client] = G_Alloc(sizeof(bot_state_t)); bs = botstates[client]; if(bs && bs->inuse){ BotAI_Print(PRT_FATAL, "BotAISetupClient: client %d already setup\n", client); return qfalse; } if(!trap_AAS_Initialized()){ BotAI_Print(PRT_FATAL, "AAS not initialized\n"); return qfalse; } /* load the bot character */ bs->character = trap_BotLoadCharacter(settings->characterfile, settings->skill); if(!bs->character){ BotAI_Print(PRT_FATAL, "couldn't load skill %f from %s\n", settings->skill, settings->characterfile); return qfalse; } /* copy the settings */ memcpy(&bs->settings, settings, sizeof(bot_settings_t)); /* allocate a goal state */ bs->gs = trap_BotAllocGoalState(client); /* load the item weights */ trap_Characteristic_String(bs->character, CHARACTERISTIC_ITEMWEIGHTS, filename, MAX_PATH); errnum = trap_BotLoadItemWeights(bs->gs, filename); if(errnum != BLERR_NOERROR){ trap_BotFreeGoalState(bs->gs); return qfalse; } /* allocate a weapon state */ bs->ws = trap_BotAllocWeaponState(); /* load the weapon weights */ trap_Characteristic_String(bs->character, CHARACTERISTIC_WEAPONWEIGHTS, filename, MAX_PATH); errnum = trap_BotLoadWeaponWeights(bs->ws, filename); if(errnum != BLERR_NOERROR){ trap_BotFreeGoalState(bs->gs); trap_BotFreeWeaponState(bs->ws); return qfalse; } /* allocate a chat state */ bs->cs = trap_BotAllocChatState(); /* load the chat file */ trap_Characteristic_String(bs->character, CHARACTERISTIC_CHAT_FILE, filename, MAX_PATH); trap_Characteristic_String(bs->character, CHARACTERISTIC_CHAT_NAME, name, MAX_PATH); errnum = trap_BotLoadChatFile(bs->cs, filename, name); if(errnum != BLERR_NOERROR){ trap_BotFreeChatState(bs->cs); trap_BotFreeGoalState(bs->gs); trap_BotFreeWeaponState(bs->ws); return qfalse; } /* get the gender characteristic */ trap_Characteristic_String(bs->character, CHARACTERISTIC_GENDER, gender, MAX_PATH); /* set the chat gender */ if(*gender == 'f' || *gender == 'F') trap_BotSetChatGender( bs->cs, CHAT_GENDERFEMALE); else if(*gender == 'm' || *gender == 'M') trap_BotSetChatGender( bs->cs, CHAT_GENDERMALE); else trap_BotSetChatGender(bs->cs, CHAT_GENDERLESS); bs->inuse = qtrue; bs->client = client; bs->entitynum = client; bs->setupcount = 4; bs->entergame_time = FloatTime(); bs->ms = trap_BotAllocMoveState(); bs->walker = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_WALKER, 0, 1); numbots++; if(trap_cvargeti("bot_testichat")){ trap_BotLibVarSet("bot_testichat", "1"); BotChatTest(bs); } /* NOTE: reschedule the bot thinking */ BotScheduleBotThink(); /* if interbreeding start with a mutation */ if(bot_interbreed) trap_BotMutateGoalFuzzyLogic(bs->gs, 1); /* if we kept the bot client */ if(restart) BotReadSessionData(bs); /* bot has been setup succesfully */ return qtrue; }