ioquake / ioq3

The ioquake3 community effort to continue supporting/developing id's Quake III Arena
https://ioquake3.org/
GNU General Public License v2.0
2.42k stars 529 forks source link

Help: Decomposing BotMapScripts (ai_dmq3.c) #592

Closed NeonKnightOA closed 1 year ago

NeonKnightOA commented 1 year ago

Hi! I'm running into a problem.

On trying to split this piece of code from ai_dmq3.c for a project I work on...

/*
==================
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);
            }
        }
    }
}

Into this:

/*
==================
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.

What may I be doing wrong?

IcyChills commented 1 year ago

What errors are you getting?

Can't test my side as Q_strequal is not part of the code base and some definitions and redefitions for the functions must be made.

NuclearMonster commented 1 year ago

This looks like an interesting project and the best place to discuss developing it will be on our forums: https://discourse.ioquake.org/c/ioquake3/dev/4