Bobot_common.c (1)

/*----------------------------------------------------------------------------------------------------------
Rassemble les actions communes à toutes les classes
----------------------------------------------------------------------------------------------------------*/
#include "../game/g_local.h"
#include "bobot.h"
#include "bobot_utils.h"

/*----------------------------------------------------------------------------------------------------------
Joc : Fonction : BOBOT_COMMON_determineClosestEnemy Description : le bobot peut-il toucher quelqu'un ?
----------------------------------------------------------------------------------------------------------*/

void BOBOT_COMMON_determineClosestEnemy(gentity_t *bobot, gentity_t **closest, int *distance)
{    Sbobot            *bobotAI = &bobots[bobot->s.clientNum];
    gentity_t        *attacker,*ent;
    vec3_t            dir;
    int                i;
    vec_t            dist;
    vec_t            distMin,Detection_enemi;
    int                bestenemy;
    det_client_t    *enemies = bobotAI->enemies;
    int                inmyteam = (bobotAI->myteam == TEAM_ALLIES ? NODE_TEAM_ALLIES : NODE_TEAM_AXIS);

    if(g_SniperWar.integer)
        Detection_enemi=10000.0;
    else
    {    if(bobotAI->skill<=0)
            Detection_enemi=1000.0;
        else
            Detection_enemi=1000.0*bobotAI->skill;
    }
    //G_Say( bobot, NULL, SAY_ALL, va("Detection_enemi %f!",Detection_enemi));
    bestenemy = INVALID;
    *closest  = NULL;
    distMin  = Detection_enemi;//BOBOT_ENEMIES_DETECTION_MAX_DIST;

    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])                                        // si bobot est un covert déguisé et pas sur un mgnest
    {    if (!(nodes[bobot->current_node].type & NODE_PROTECTION))                            // ou dans un tank ou en protection, il ne le voit pas
        {    if(!(bobot->client->ps.eFlags & (EF_MG42_ACTIVE | EF_MOUNTEDTANK)))
                return;
        }
    }
   
    for(i=0; i < BOBOT_DETECT_MAX_ENEMIES; i++)
    {    ent = enemies[i].ent;
        if ((ent == NULL) || (ent->client == NULL) || (ent->health <= 0))
        { continue; }
        if(ent->client->ps.powerups[PW_OPS_DISGUISED])                                        // si c'est un ennemi covert déguisé il ne le voit pas
        {    if(random() < 0.01)
            {    if(bobot->client->sess.sessionTeam == TEAM_ALLIES)   
                    G_globalSound("sound/chat/allies/10b.wav");
                else
                    G_globalSound("sound/chat/axis/10b.wav");
            }
            continue;
        }
   
        dist = enemies[i].dist;
        if (enemies[i].ent == bobotAI->currentAction.ent)
        { dist = dist / 4; }                                                                // évite de changer de cible tout le temps
        if (dist < distMin)
        {    distMin = dist;
            bestenemy = i;
        }
    }
    if(bestenemy != INVALID)
    { *closest = enemies[bestenemy].ent; }
    attacker = bobot->client->attacker;

    if((attacker != NULL) && (attacker->client != NULL))                                        // si le bobot se fait attaquer
    {    if(!OnSameTeam(bobot,attacker))
        {    if((visible(bobot,attacker) || visible(attacker,bobot)) && attacker->health > 0)    // petit bug sinon le bobot garde...
            {    VectorSubtract(bobot->client->ps.origin, attacker->client->ps.origin, dir);        // la cible meme qd elle est plus visible
                dist = VectorLength(dir)/4;
                if (dist < distMin)                                                                //il attaque celui qui l'a attaqué
                {    distMin = dist;
                    *closest = attacker;
                }
            }
        }
        /* Le bot flingue un équipier non bot qui lui tire dessus exprès + de 3 fois */
        else
        {    if (bobotAI->HitByTeammate>=3)
            {    if((visible(bobot,attacker) || visible(attacker,bobot)) && attacker->health > 0)
                {    VectorSubtract(bobot->client->ps.origin, attacker->client->ps.origin, dir);
                    dist = VectorLength(dir)/4;
                    if (dist < distMin)
                    {    distMin = dist;
                        *closest = attacker;
                    }
                }
            }
        }
    }
    if(*closest != NULL)                                                                    // si il y a quelqu'un à attaquer
    { *distance = BOBOT_distancePercentage(distMin,Detection_enemi/*BOBOT_ENEMIES_DETECTION_MAX_DIST*/); }
    else
    { *distance = INVALID; }
}

/*----------------------------------------------------------------------------------------------------------
Fonction : BOBOT_COMMON_determineClosestTeammate. Description : Donne la distance du plus proche équipier
----------------------------------------------------------------------------------------------------------*/
int BOBOT_COMMON_determineClosestTeammate(Sbobot *bobotAI)
{    gentity_t    *teammate;
    int        i;
    vec_t        dist;
    vec_t        distMin = BOBOT_TEAMMATES_MAX_DIST;
    det_client_t    *teammates = bobotAI->teammates;

    for(i=0; i < BOBOT_DETECT_MAX_TEAMMATES; i++)
    {    teammate = teammates[i].ent;
        if ((teammate == NULL) || (teammate->client == NULL) || (teammate->health <= 0))
        { continue; }
        dist = teammates[i].dist;
        if (dist < distMin)
        { distMin = dist; }
    }
    return BOBOT_distancePercentage(distMin,BOBOT_TEAMMATES_MAX_DIST);
}

/*----------------------------------------------------------------------------------------------------------
Fonction : BOBOT_COMMON_chaseEnemy
Description :
poursuivre un ennemi que le bot ne voit plus. le bot se dirige vers la lastKnownPos de l'ennemi,
et demande à ses bras de viser la position que l'ennemi a eu juste après
(on fait comme si le bot avait prédit la position suivante de son ennemi)
----------------------------------------------------------------------------------------------------------*/
void BOBOT_COMMON_chaseEnemy(gentity_t *bobot,usercmd_t *ucmd)
{    vec3_t        dir,angles;
    Sbobot        *bobotAI = &bobots[bobot->s.clientNum];
    gentity_t    *enemy = bobotAI->currentAction.ent;

    /* Pas les ingénieurs */
    if(bobot->client->sess.playerType==PC_ENGINEER)
    {    BOBOT_AI_inhibitAction(&bobotAI->actions[CHASE_ENEMY]);
        bobotAI->state = BOT_STATE_POSITION;                                            // il s'arrête
        return;
    }

    // Pas les coverts déguisés
    if(bobot->client->ps.powerups[PW_OPS_DISGUISED])
    {    BOBOT_AI_inhibitAction(&bobotAI->actions[CHASE_ENEMY]);
        bobotAI->state = BOT_STATE_POSITION;                                            // il s'arrête
        return;
    }

    if((enemy == NULL) || (enemy->client == NULL) || (!enemy->inuse) || (enemy->client->ps.pm_type == PM_DEAD))
    {    BOBOT_AI_inhibitAction(&bobotAI->actions[CHASE_ENEMY]);
        bobotAI->state = BOT_STATE_POSITION;                                            // il s'arrête
        return;
    }
    if(enemy->r.svFlags & SVF_BOT)                                                        // on ne chasse que les joueurs humains
    {    BOBOT_AI_inhibitAction(&bobotAI->actions[CHASE_ENEMY]);
        bobotAI->state = BOT_STATE_POSITION;                                            // il s'arrête
        return;
    }
    if(BOBOT_AI_proposeActionToArms(bobotAI,BOBOT_OBEY_TO_ACTION,NULL))                    // si les bras le permettent, le bot vise la position de l'ennemi qu'il a prédite
    {    VectorSubtract(enemy->r.currentOrigin, bobot->client->ps.origin, dir);
        dir[2] -= bobot->client->ps.viewheight;                                            // et si on triche vraiment (si le bot vise son ennemi à travers...
        vectoangles (dir, angles);                                                        // les obstacles), ça se voit beaucoup ?
        AnglesSubtract (angles , bobot->s.angles , angles);
        BOBOT_MOVEMENT_ChangeBotAngle(angles,bobot);
    }
    VectorSubtract(bobotAI->currentAction.lastKnownPos,bobot->client->ps.origin,dir);
    if (VectorLength(dir) < 120)                                                        // si assez près du last known pos
    {    BOBOT_AI_inhibitAction(&bobotAI->actions[CHASE_ENEMY]);
        bobotAI->state = BOT_STATE_POSITION;                                            // il s'arrête
    }
    else
    { BOBOT_Move(bobot,ucmd); }                                                            // sinon il utilise son réseau de neurones pour éviter les obstacles
}

extern int BOBOT_FUZZY_determinePriorityToGiveHealth(Sbobot *bobotAI,gentity_t **chosenTeammate);
extern int BOBOT_FUZZY_determinePriorityToGiveAmmo(Sbobot *bobotAI,gentity_t **chosenTeammate);

/* Les bots soldats suivent un team mate qui l'appelle.*/
void BOBOT_COMMON_FollowMe(gentity_t *bobot,usercmd_t *ucmd)
{    vec3_t        dir;
    vec_t        dist;
    Sbobot        *bobotAI = &bobots[bobot->s.clientNum];
    gentity_t    *teammate = bobotAI->currentAction.ent;
    int            priority;

    if((teammate == NULL) || (teammate->client == NULL) || (!teammate->inuse))
    {    BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }

    if ((teammate->client->ps.pm_flags & PMF_LIMBO) || (teammate->client->ps.pm_type & PM_DEAD))
    {    BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }

    if(    bobotAI->currentAction.lastKnownPos!=teammate->r.currentOrigin)
    {    VectorCopy(teammate->r.currentOrigin,bobotAI->currentAction.lastKnownPos); }
    VectorSubtract(bobotAI->currentAction.lastKnownPos, bobot->client->ps.origin, dir);
    dist = VectorLength(dir);
   
    /*    Le medic va voir s'il a besoin de soin */
    switch (bobot->client->sess.playerType)
    {    case PC_MEDIC:
            if( level.time>bobotAI->TimeFollow)
            {    bobotAI->TimeFollow=0;
                G_Say(bobot, NULL, SAY_TEAM, va("Sorry %s I cannot to join you!",teammate->client->pers.netname));
                BOBOT_AI_endOfCurrentAction(bobotAI);
                return;
            }
            else
            {    if (dist > 150)
                {    BOBOT_Move(bobot,ucmd);    }
                else
                {    BOBOT_AI_endOfCurrentAction(bobotAI);
                    priority = BOBOT_FUZZY_determinePriorityToGiveHealth(bobotAI,&teammate);
                    if(priority != INVALID)
                    { BOBOT_AI_proposeAction(bobotAI,GIVE_HEALTH,INVALID,teammate,teammate->client->ps.origin,priority); }
                }
            }
        break;
        /*    Le field va voir s'il a besoin de munitions */
        case PC_FIELDOPS:
            if (teammate->client->ps.pm_type == PM_DEAD)
            {    BOBOT_AI_endOfCurrentAction(bobotAI);
                return;
            }
            if( level.time>bobotAI->TimeFollow)
            {    bobotAI->TimeFollow=0;
                G_Say(bobot, NULL, SAY_TEAM, va("Sorry %s I cannot to join you!",teammate->client->pers.netname));
                BOBOT_AI_endOfCurrentAction(bobotAI);
                return;
            }
            else
            {    if (dist > 150)
                {    BOBOT_Move(bobot,ucmd);    }
                else
                {    BOBOT_AI_endOfCurrentAction(bobotAI);
                    priority = BOBOT_FUZZY_determinePriorityToGiveAmmo(bobotAI,&teammate);
                    if(priority != INVALID)
                    { BOBOT_AI_proposeAction(bobotAI,GIVE_AMMO,INVALID,teammate,teammate->client->ps.origin,priority); }
                }
            }
        break;
        /* Soldat, covert escortent.*/
        case PC_SOLDIER:
        case PC_COVERTOPS:
            if (dist > 150)
            {    BOBOT_Move(bobot,ucmd);    }
        break;
    }
}

/* Les bots soldats suivent un team mate qui l'appelle.*/
void BOBOT_NeedBackup(gentity_t *bobot,usercmd_t *ucmd)
{    vec3_t        dir;
    vec_t        dist;
    Sbobot        *bobotAI = &bobots[bobot->s.clientNum];
    gentity_t    *teammate = bobotAI->currentAction.ent;

    if((teammate == NULL) || (teammate->client == NULL) || (!teammate->inuse))
    {    BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }

    if ((teammate->client->ps.pm_flags & PMF_LIMBO) || (teammate->client->ps.pm_type & PM_DEAD))
    {    BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }

    if( level.time>bobotAI->TimeFollow)
    {    bobotAI->TimeFollow=0;
        BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }
    if(    bobotAI->currentAction.lastKnownPos!=teammate->r.currentOrigin)
    {    VectorCopy(teammate->r.currentOrigin,bobotAI->currentAction.lastKnownPos); }
    VectorSubtract(bobotAI->currentAction.lastKnownPos, bobot->client->ps.origin, dir);
    dist = VectorLengthSquared(dir);

    if (dist > 2000)
    {    BOBOT_Move(bobot,ucmd);    }
    else
    {    bobotAI->TimeFollow=0;
        BOBOT_AI_endOfCurrentAction(bobotAI);
        return;
    }
}

/*----------------------------------------------------------------------------------------------------------
Fonction : BOBOT_COMMON_backupTeammate
Description : backup vers un équipier, tout en regardant là où regarde cet équipier
----------------------------------------------------------------------------------------------------------*/
void BOBOT_COMMON_backupTeammate(gentity_t *bobot,usercmd_t *ucmd)
{    vec3_t        dir,angles;
    Sbobot        *bobotAI = &bobots[bobot->s.clientNum];
    gentity_t    *teammate = bobotAI->currentAction.ent;
    qboolean    actionAuthorizedByArms;

    if((teammate == NULL) || (teammate->client->ps.pm_type == PM_DEAD) || (teammate->client == NULL) ||
       (!teammate->inuse) || (teammate->client->ps.pm_flags & PMF_LIMBO))
        {    BOBOT_AI_endOfCurrentAction(bobotAI);
            return;
        }

    /*    le déroulement de l'action dépend de la présence ou non d'un ennemi...
        S'il y en a un, les bras du bot donneront priorité au tir. */
    actionAuthorizedByArms = BOBOT_AI_proposeActionToArms(bobotAI,BOBOT_OBEY_TO_ACTION,NULL);
    // le bot vise la même chose que son équipier, si celui-ci à une arme en main et qu'il tire ou qu'il reload.
    if(actionAuthorizedByArms)
    {    if( (teammate->client->ps.weapon == teammate->client->sess.playerWeapon) ||
            (teammate->client->ps.weapon == teammate->client->sess.playerWeapon2))
        {    if((teammate->client->ps.weaponstate & WEAPON_FIRING) || (teammate->client->ps.weaponstate & WEAPON_RELOADING))
            {    AnglesSubtract(teammate->client->ps.viewangles, bobot->s.angles, angles);    //(jusqu'à ce qu'il voit un ennemi)
                BOBOT_MOVEMENT_ChangeBotAngle(angles,bobot);
            }
        }
    }
    VectorSubtract (teammate->r.currentOrigin, bobot->client->ps.origin, dir);        // et il va vers son équipier
    if (VectorLengthSquared(dir) > 20000)                                            // jusqu'à une certaine distance
    { BOBOT_Move(bobot,ucmd); }
}

/*----------------------------------------------------------------------------------------------------------
Pav: Renvoie le nombre de munitions restant
ps.ammoclip : Dans l'arme
ps.ammo        : En reserve
----------------------------------------------------------------------------------------------------------*/
int VerifierMunitions(gentity_t *bobot, weapon_t weapon)
{    int NbMunition;
   
    NbMunition = bobot->client->ps.ammoclip[BG_FindClipForWeapon(weapon)] + bobot->client->ps.ammo[BG_FindAmmoForWeapon(weapon)];
    return NbMunition;
}

/*------------------------------End part 1 look at part 2

Créer un site gratuit avec e-monsite - Signaler un contenu illicite sur ce site