On trying to split this piece of code from ai_dmq3.c...
/*
==================
BotMapScripts
==================
*/
void BotMapScripts(bot_state_t *bs) {
char info[1024];
char mapname[128];
int i, shootbutton;
float aim_accuracy;
aas_entityinfo_t entinfo;
vec3_t dir;
trap_GetServerinfo(info, sizeof (info));
Q_strncpyz(mapname, Info_ValueForKey(info, "mapname"), sizeof (mapname));
if (Q_strequal(mapname, "q3tourney6") || Q_strequal(mapname, "q3tourney6_ctf") || Q_strequal(mapname, "mpq3tourney6")) {
vec3_t mins = {694, 200, 480}, maxs = {968, 472, 680};
vec3_t buttonorg = {304, 352, 920};
//NOTE: NEVER use the func_bobbing in q3tourney6
bs->tfl &= ~TFL_FUNCBOB;
//crush area is higher in mpq3tourney6
if (Q_strequal(mapname, "mpq3tourney6")) {
mins[2] += 64;
maxs[2] += 64;
}
//if the bot is in the bounding box of the crush area
if (bs->origin[0] > mins[0] && bs->origin[0] < maxs[0]) {
if (bs->origin[1] > mins[1] && bs->origin[1] < maxs[1]) {
if (bs->origin[2] > mins[2] && bs->origin[2] < maxs[2]) {
return;
}
}
}
shootbutton = qfalse;
//if an enemy is in the bounding box then shoot the button
for (i = 0; i < level.maxclients; i++) {
if (i == bs->client) continue;
//
BotEntityInfo(i, &entinfo);
//
if (!entinfo.valid) continue;
//if the enemy isn't dead and the enemy isn't the bot self
if (EntityIsDead(&entinfo) || entinfo.number == bs->entitynum) continue;
//
if (entinfo.origin[0] > mins[0] && entinfo.origin[0] < maxs[0]) {
if (entinfo.origin[1] > mins[1] && entinfo.origin[1] < maxs[1]) {
if (entinfo.origin[2] > mins[2] && entinfo.origin[2] < maxs[2]) {
//if there's a team mate below the crusher
if (BotSameTeam(bs, i)) {
shootbutton = qfalse;
break;
} else if (bs->enemy == i) {
shootbutton = qtrue;
}
}
}
}
}
if (shootbutton) {
bs->flags |= BFL_IDEALVIEWSET;
VectorSubtract(buttonorg, bs->eye, dir);
vectoangles(dir, bs->ideal_viewangles);
aim_accuracy = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_AIM_ACCURACY, 0, 1);
bs->ideal_viewangles[PITCH] += 8 * crandom() * (1 - aim_accuracy);
bs->ideal_viewangles[PITCH] = AngleMod(bs->ideal_viewangles[PITCH]);
bs->ideal_viewangles[YAW] += 8 * crandom() * (1 - aim_accuracy);
bs->ideal_viewangles[YAW] = AngleMod(bs->ideal_viewangles[YAW]);
//
if (InFieldOfVision(bs->viewangles, 20, bs->ideal_viewangles)) {
trap_EA_Attack(bs->client);
}
}
}
}
/*
==================
BotMapScripts
==================
*/
void BotMapScripts(bot_state_t *bs) {
char info[1024];
char mapname[128];
trap_GetServerinfo(info, sizeof (info));
Q_strncpyz(mapname, Info_ValueForKey(info, "mapname"), sizeof (mapname));
if (Q_strequal(mapname, "q3tourney6") || Q_strequal(mapname, "q3tourney6_ctf") || Q_strequal(mapname, "mpq3tourney6")) {
vec3_t mins = {694, 200, 480}, maxs = {968, 472, 680};
vec3_t buttonorg = {304, 352, 920};
//NOTE: NEVER use the func_bobbing in q3tourney6
bs->tfl &= ~TFL_FUNCBOB;
//crush area is higher in mpq3tourney6
if (Q_strequal(mapname, "mpq3tourney6")) {
mins[2] += 64;
maxs[2] += 64;
}
if (BotScript_EnemyIsAtLocation(bs,mins,maxs)) {
BotScript_ShootAt(bs,buttonorg);
}
}
}
/*
==================
BotScript_ShootAt
Tells a bot where to shoot at.
==================
*/
void BotScript_ShootAt(bot_state_t *bs, vec3_t target)
{
float aim_accuracy;
vec3_t dir;
bs->flags |= BFL_IDEALVIEWSET;
VectorSubtract(target, bs->eye, dir);
vectoangles(dir, bs->ideal_viewangles);
aim_accuracy = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_AIM_ACCURACY, 0, 1);
bs->ideal_viewangles[PITCH] += 8 * crandom() * (1 - aim_accuracy);
bs->ideal_viewangles[PITCH] = AngleMod(bs->ideal_viewangles[PITCH]);
bs->ideal_viewangles[YAW] += 8 * crandom() * (1 - aim_accuracy);
bs->ideal_viewangles[YAW] = AngleMod(bs->ideal_viewangles[YAW]);
//
if (InFieldOfVision(bs->viewangles, 20, bs->ideal_viewangles)) {
trap_EA_Attack(bs->client);
}
}
/*
==================
BotScript_EnemyIsAtLocation
Returns true if an enemy is inside of a location.
==================
*/
qboolean BotScript_EnemyIsAtLocation(bot_state_t *bs, vec3_t boxStart, vec3_t boxEnd)
{
int i;
aas_entityinfo_t entinfo;
if (bs->origin[0] > boxStart[0] && bs->origin[0] < boxEnd[0]) {
if (bs->origin[1] > boxStart[1] && bs->origin[1] < boxEnd[1]) {
if (bs->origin[2] > boxStart[2] && bs->origin[2] < boxEnd[2]) {
return qfalse;
}
}
}
//if an enemy is in the bounding box then shoot the button
for (i = 0; i < level.maxclients; i++) {
if (i == bs->client) continue;
//
BotEntityInfo(i, &entinfo);
//
if (!entinfo.valid) continue;
//if the enemy isn't dead and the enemy isn't the bot itself
if (EntityIsDead(&entinfo) || entinfo.number == bs->entitynum) continue;
//
if (entinfo.origin[0] > boxStart[0] && entinfo.origin[0] < boxEnd[0]) {
if (entinfo.origin[1] > boxStart[1] && entinfo.origin[1] < boxEnd[1]) {
if (entinfo.origin[2] > boxStart[2] && entinfo.origin[2] < boxEnd[2]) {
//if there's a team mate below the crusher
if (BotSameTeam(bs, i)) {
return qfalse;
break;
} else if (bs->enemy == i) {
return qtrue;
}
}
}
}
}
return qtrue;
}
I get lots of warnings and sometimes errors.