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