📄 ai_main.c
字号:
char goalname[MAX_MESSAGE_SIZE];
char netname[MAX_MESSAGE_SIZE];
char action[MAX_MESSAGE_SIZE];
char *leader, carrying[32], *cs;
bot_goal_t goal;
//
ClientName(bs->client, netname, sizeof(netname));
if (Q_stricmp(netname, bs->teamleader) == 0) leader = "L";
else leader = " ";
strcpy(carrying, " ");
if (gametype == GT_CTF) {
if (BotCTFCarryingFlag(bs)) {
strcpy(carrying, "F ");
}
}
#ifdef MISSIONPACK
else if (gametype == GT_1FCTF) {
if (Bot1FCTFCarryingFlag(bs)) {
strcpy(carrying, "F ");
}
}
else if (gametype == GT_HARVESTER) {
if (BotHarvesterCarryingCubes(bs)) {
if (BotTeam(bs) == TEAM_RED) Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_REDCUBE]);
else Com_sprintf(carrying, sizeof(carrying), "%2d", bs->inventory[INVENTORY_BLUECUBE]);
}
}
#endif
switch(bs->ltgtype) {
case LTG_TEAMHELP:
{
EasyClientName(bs->teammate, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "helping %s", goalname);
break;
}
case LTG_TEAMACCOMPANY:
{
EasyClientName(bs->teammate, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "accompanying %s", goalname);
break;
}
case LTG_DEFENDKEYAREA:
{
trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "defending %s", goalname);
break;
}
case LTG_GETITEM:
{
trap_BotGoalName(bs->teamgoal.number, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "getting item %s", goalname);
break;
}
case LTG_KILL:
{
ClientName(bs->teamgoal.entitynum, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "killing %s", goalname);
break;
}
case LTG_CAMP:
case LTG_CAMPORDER:
{
Com_sprintf(action, sizeof(action), "camping");
break;
}
case LTG_PATROL:
{
Com_sprintf(action, sizeof(action), "patrolling");
break;
}
case LTG_GETFLAG:
{
Com_sprintf(action, sizeof(action), "capturing flag");
break;
}
case LTG_RUSHBASE:
{
Com_sprintf(action, sizeof(action), "rushing base");
break;
}
case LTG_RETURNFLAG:
{
Com_sprintf(action, sizeof(action), "returning flag");
break;
}
case LTG_ATTACKENEMYBASE:
{
Com_sprintf(action, sizeof(action), "attacking the enemy base");
break;
}
case LTG_HARVEST:
{
Com_sprintf(action, sizeof(action), "harvesting");
break;
}
default:
{
trap_BotGetTopGoal(bs->gs, &goal);
trap_BotGoalName(goal.number, goalname, sizeof(goalname));
Com_sprintf(action, sizeof(action), "roaming %s", goalname);
break;
}
}
cs = va("l\\%s\\c\\%s\\a\\%s",
leader,
carrying,
action);
trap_SetConfigstring (CS_BOTINFO + bs->client, cs);
}
/*
==============
BotUpdateInfoConfigStrings
==============
*/
void BotUpdateInfoConfigStrings(void) {
int i;
char buf[MAX_INFO_STRING];
for (i = 0; i < maxclients && i < MAX_CLIENTS; i++) {
//
if ( !botstates[i] || !botstates[i]->inuse )
continue;
//
trap_GetConfigstring(CS_PLAYERS+i, buf, sizeof(buf));
//if no config string or no name
if (!strlen(buf) || !strlen(Info_ValueForKey(buf, "n")))
continue;
BotSetInfoConfigString(botstates[i]);
}
}
/*
==============
BotInterbreedBots
==============
*/
void BotInterbreedBots(void) {
float ranks[MAX_CLIENTS];
int parent1, parent2, child;
int i;
// get rankings for all the bots
for (i = 0; i < MAX_CLIENTS; i++) {
if ( botstates[i] && botstates[i]->inuse ) {
ranks[i] = botstates[i]->num_kills * 2 - botstates[i]->num_deaths;
}
else {
ranks[i] = -1;
}
}
if (trap_GeneticParentsAndChildSelection(MAX_CLIENTS, ranks, &parent1, &parent2, &child)) {
trap_BotInterbreedGoalFuzzyLogic(botstates[parent1]->gs, botstates[parent2]->gs, botstates[child]->gs);
trap_BotMutateGoalFuzzyLogic(botstates[child]->gs, 1);
}
// reset the kills and deaths
for (i = 0; i < MAX_CLIENTS; i++) {
if (botstates[i] && botstates[i]->inuse) {
botstates[i]->num_kills = 0;
botstates[i]->num_deaths = 0;
}
}
}
/*
==============
BotWriteInterbreeded
==============
*/
void BotWriteInterbreeded(char *filename) {
float rank, bestrank;
int i, bestbot;
bestrank = 0;
bestbot = -1;
// get the best bot
for (i = 0; i < MAX_CLIENTS; i++) {
if ( botstates[i] && botstates[i]->inuse ) {
rank = botstates[i]->num_kills * 2 - botstates[i]->num_deaths;
}
else {
rank = -1;
}
if (rank > bestrank) {
bestrank = rank;
bestbot = i;
}
}
if (bestbot >= 0) {
//write out the new goal fuzzy logic
trap_BotSaveGoalFuzzyLogic(botstates[bestbot]->gs, filename);
}
}
/*
==============
BotInterbreedEndMatch
add link back into ExitLevel?
==============
*/
void BotInterbreedEndMatch(void) {
if (!bot_interbreed) return;
bot_interbreedmatchcount++;
if (bot_interbreedmatchcount >= bot_interbreedcycle.integer) {
bot_interbreedmatchcount = 0;
//
trap_Cvar_Update(&bot_interbreedwrite);
if (strlen(bot_interbreedwrite.string)) {
BotWriteInterbreeded(bot_interbreedwrite.string);
trap_Cvar_Set("bot_interbreedwrite", "");
}
BotInterbreedBots();
}
}
/*
==============
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;
}
/*
==============
BotEntityInfo
==============
*/
void BotEntityInfo(int entnum, aas_entityinfo_t *info) {
trap_AAS_EntityInfo(entnum, info);
}
/*
==============
NumBots
==============
*/
int NumBots(void) {
return numbots;
}
/*
==============
BotTeamLeader
==============
*/
int BotTeamLeader(bot_state_t *bs) {
int leader;
leader = ClientFromName(bs->teamleader);
if (leader < 0) return qfalse;
if (!botstates[leader] || !botstates[leader]->inuse) return qfalse;
return qtrue;
}
/*
==============
AngleDifference
==============
*/
float AngleDifference(float ang1, float ang2) {
float diff;
diff = ang1 - ang2;
if (ang1 > ang2) {
if (diff > 180.0) diff -= 360.0;
}
else {
if (diff < -180.0) diff += 360.0;
}
return diff;
}
/*
==============
BotChangeViewAngle
==============
*/
float BotChangeViewAngle(float angle, float ideal_angle, float speed) {
float move;
angle = AngleMod(angle);
ideal_angle = AngleMod(ideal_angle);
if (angle == ideal_angle) return angle;
move = ideal_angle - angle;
if (ideal_angle > angle) {
if (move > 180.0) move -= 360.0;
}
else {
if (move < -180.0) move += 360.0;
}
if (move > 0) {
if (move > speed) move = speed;
}
else {
if (move < -speed) move = -speed;
}
return AngleMod(angle + move);
}
/*
==============
BotChangeViewAngles
==============
*/
void BotChangeViewAngles(bot_state_t *bs, float thinktime) {
float diff, factor, maxchange, anglespeed, disired_speed;
int i;
if (bs->ideal_viewangles[PITCH] > 180) bs->ideal_viewangles[PITCH] -= 360;
//
if (bs->enemy >= 0) {
factor = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_FACTOR, 0.01f, 1);
maxchange = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_VIEW_MAXCHANGE, 1, 1800);
}
else {
factor = 0.05f;
maxchange = 360;
}
if (maxchange < 240) maxchange = 240;
maxchange *= thinktime;
for (i = 0; i < 2; i++) {
//
if (bot_challenge.integer) {
//smooth slowdown view model
diff = abs(AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]));
anglespeed = diff * factor;
if (anglespeed > maxchange) anglespeed = maxchange;
bs->viewangles[i] = BotChangeViewAngle(bs->viewangles[i],
bs->ideal_viewangles[i], anglespeed);
}
else {
//over reaction view model
bs->viewangles[i] = AngleMod(bs->viewangles[i]);
bs->ideal_viewangles[i] = AngleMod(bs->ideal_viewangles[i]);
diff = AngleDifference(bs->viewangles[i], bs->ideal_viewangles[i]);
disired_speed = diff * factor;
bs->viewanglespeed[i] += (bs->viewanglespeed[i] - disired_speed);
if (bs->viewanglespeed[i] > 180) bs->viewanglespeed[i] = maxchange;
if (bs->viewanglespeed[i] < -180) bs->viewanglespeed[i] = -maxchange;
anglespeed = bs->viewanglespeed[i];
if (anglespeed > maxchange) anglespeed = maxchange;
if (anglespeed < -maxchange) anglespeed = -maxchange;
bs->viewangles[i] += anglespeed;
bs->viewangles[i] = AngleMod(bs->viewangles[i]);
//demping
bs->viewanglespeed[i] *= 0.45 * (1 - factor);
}
//BotAI_Print(PRT_MESSAGE, "ideal_angles %f %f\n", bs->ideal_viewangles[0], bs->ideal_viewangles[1], bs->ideal_viewangles[2]);`
//bs->viewangles[i] = bs->ideal_viewangles[i];
}
//bs->viewangles[PITCH] = 0;
if (bs->viewangles[PITCH] > 180) bs->viewangles[PITCH] -= 360;
//elementary action: view
trap_EA_View(bs->client, bs->viewangles);
}
/*
==============
BotInputToUserCommand
==============
*/
void BotInputToUserCommand(bot_input_t *bi, usercmd_t *ucmd, int delta_angles[3], int time) {
vec3_t angles, forward, right;
short temp;
int j;
//clear the whole structure
memset(ucmd, 0, sizeof(usercmd_t));
//
//Com_Printf("dir = %f %f %f speed = %f\n", bi->dir[0], bi->dir[1], bi->dir[2], bi->speed);
//the duration for the user command in milli seconds
ucmd->serverTime = time;
//
if (bi->actionflags & ACTION_DELAYEDJUMP) {
bi->actionflags |= ACTION_JUMP;
bi->actionflags &= ~ACTION_DELAYEDJUMP;
}
//set the buttons
if (bi->actionflags & ACTION_RESPAWN) ucmd->buttons = BUTTON_ATTACK;
if (bi->actionflags & ACTION_ATTACK) ucmd->buttons |= BUTTON_ATTACK;
if (bi->actionflags & ACTION_TALK) ucmd->buttons |= BUTTON_TALK;
if (bi->actionflags & ACTION_GESTURE) ucmd->buttons |= BUTTON_GESTURE;
if (bi->actionflags & ACTION_USE) ucmd->buttons |= BUTTON_USE_HOLDABLE;
if (bi->actionflags & ACTION_WALK) ucmd->buttons |= BUTTON_WALKING;
if (bi->actionflags & ACTION_AFFIRMATIVE) ucmd->buttons |= BUTTON_AFFIRMATIVE;
if (bi->actionflags & ACTION_NEGATIVE) ucmd->buttons |= BUTTON_NEGATIVE;
if (bi->actionflags & ACTION_GETFLAG) ucmd->buttons |= BUTTON_GETFLAG;
if (bi->actionflags & ACTION_GUARDBASE) ucmd->buttons |= BUTTON_GUARDBASE;
if (bi->actionflags & ACTION_PATROL) ucmd->buttons |= BUTTON_PATROL;
if (bi->actionflags & ACTION_FOLLOWME) ucmd->buttons |= BUTTON_FOLLOWME;
//
ucmd->weapon = bi->weapon;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -