D:\cygwin\wf_fusion_src_r8\CVSROOT\WeaponsFactory\WF_AI_MarineSeekEnemy.c

/*
==============================================================================
The Weapons Factory - 
  
Modified code by Keith Pase

Copyright (C) 1997-2003 Weapons Factory Software

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

  Code by Keith Pase

  WF_AI_Marine_SeekEnemy.c -- Marine. The swiss army bot!
  

==============================================================================
*/

#include "..\game\g_local.h"
#include "..\game\m_player.h"

#include "..\FusionSource\fusionbot.h"

#define MarineEnemyCount 8

char *MarineEnemyType[MarineEnemyCount] = 
{
    "Player",
    "SentryGun",
    "laser_defense_gr",
    "proximity",
    "turret",
    "biosentry",
    "decoy",
    "depot"
};

edict_t *MarineBestEnemy (edict_t *enemy, vec3_t org, float rad, int wf_team)
{
    vec3_t  eorg;
    int     j;
    int     k = MarineEnemyCount + 1;
    int     weight;
    edict_t *bestenemy = NULL;

    rad = rad * g_radius->value;

    if (!enemy)
        enemy = world;
    else
        enemy++;

    for ( ; enemy < &game.edicts[game.numentities]; enemy++)
    {
        if (!trap_inPVS (enemy->s.origin, org))
            continue;
        if (!enemy->r.inuse)
            continue;
        if (enemy->r.solid == SOLID_NOT)
            continue;
        if (enemy->wf_team != wf_team)
            continue;
        for (j=0 ; j<3 ; j++)
            eorg[j] = org[j] - (enemy->s.origin[j] + (enemy->r.mins[j] + enemy->r.maxs[j])*0.5);
        if (VectorLength(eorg) > rad)
            continue;
        if (enemy->health <= 0)
            continue;

        for (k=0; k<MarineEnemyCount; k++)
        {
            if (strcmp(enemy->classname, MarineEnemyType[k]) == 0)
            {
                if (weight < k)
                {
                    weight = k;
                    bestenemy = enemy;
                }
            }
        }
    }

    if (bestenemy)
        return bestenemy;
    else
        return NULL;
}

qboolean WF_AI_MarineSeekEnemy(edict_t *fusionbot)
{
    edict_t     *bestenemy  = NULL;
    edict_t     *newenemy   = NULL;
    edict_t     *flag       = NULL;
    edict_t     *visibleflag= NULL;
    int         team;
    float       paranoidweight,weight,bestweight;
    vec3_t      dist;
    char        wav[250];

    if (fusionbot->wf_team == 1)
        team = 2;
    else
        team = 1;


    while ((bestenemy = MarineBestEnemy(bestenemy, fusionbot->s.origin, 750, team)) != NULL)
    {

        if  (fusionbot->r.client->pers.inventory[ITEMLIST_FLAG2]||fusionbot->r.client->pers.inventory[ITEMLIST_FLAG1])
        {
            if (!infront(fusionbot,bestenemy))
                return qfalse;
        }

        if (bestenemy->r.client)
        {
            if (fusionbot->r.client->compass_mode > 0)
            {
                while ((flag = findradius(flag, fusionbot->s.origin, 750)) != NULL)
                {
                    if  (
                        (fusionbot->wf_team == 2 && (strcmp(flag->classname, "team_CTF_blueflag") == 0) && fusionbot->r.client->compass_mode == 2)
                        ||
                        (fusionbot->wf_team == 1 && (strcmp(flag->classname, "team_CTF_redflag") == 0) && fusionbot->r.client->compass_mode == 2)
                        )
                    {
                        visibleflag = flag;
                    }
                }

                if (visibleflag)
                {
                    VectorSubtract(visibleflag->s.origin, bestenemy->s.origin, dist);
                    paranoidweight = VectorLength( dist );
                    bestenemy->enemydistance = paranoidweight;
                    bestenemy->enemyvelocity = sqrt(bestenemy->velocity[0]*bestenemy->velocity[0] + bestenemy->velocity[1]*bestenemy->velocity[1]);
                }

                VectorSubtract(fusionbot->s.origin, bestenemy->s.origin, dist);
                weight = VectorLength( dist );

                if  (
                    (infront(fusionbot,bestenemy)||(weight < 500 )) 
                    && 
                    (bestenemy->disguised == 0) 
                    &&
                    (!(bestenemy->r.client->pers.feign))
                    )
                {
                    if (weight < bestweight)
                    {
                        if (isspy(bestenemy))
                        {
                            bestenemy->disguisetargettime = level.time + 10;
                            if (fusionbot->lastteamspymsgtime < level.time)
                            {
                                sprintf(wav, "%s/d_spy.wav",classinfo[fusionbot->r.client->pers.player_class].name);
                                CTFSay_Team (fusionbot,"Enemy Spy Spotted at %l!");
                                Cmd_WFPlayTeam (fusionbot,wav,0);
                                fusionbot->lastteamspymsgtime = level.time + (bot_chattime->value * 6);
                            }
                        }

                        bestweight = weight;
                        newenemy = bestenemy;
                        continue;
                    }
                }
                else if (bestenemy->disguised)
                {
                    if (bestenemy->disguisetargettime < level.time)
                    {
                        newenemy = bestenemy;
                        continue;
                    }
                    else if (strcmp(bestenemy->r.client->pers.weapon->classname, "weapon_knife") == 0)
                    {
                        newenemy = bestenemy;
                        newenemy->disguisetargettime = level.time + 15;
                        continue;
                    }
                    else
                    {
                        if (bestenemy->enemydistance < (bestenemy->oldenemydistance - 10))
                        {
                            if (bestenemy->enemyvelocity > (bestenemy->oldenemyvelocity +10 ))
                            {
                                if (bestenemy->disguisetargeted > 5)
                                {
                                    newenemy = bestenemy;
                                    newenemy->disguisetargettime = level.time + 20;
                                }
                                bestenemy->oldenemydistance = bestenemy->enemydistance;
                                bestenemy->oldenemyvelocity = bestenemy->enemyvelocity;
                                bestenemy->disguisetargeted +=1;
                                if (fusionbot->lastteamspymsgtime < level.time)
                                {
                                    sprintf(wav, "%s/d_spy.wav",classinfo[fusionbot->r.client->pers.player_class].name);
                                    CTFSay_Team (fusionbot,"Enemy Spy Spotted at %l!");
                                    Cmd_WFPlayTeam (fusionbot,wav,0);
                                    fusionbot->lastteamspymsgtime = level.time + (bot_chattime->value * 3);
                                }
                            }
                            else
                            {
                                bestenemy->oldenemyvelocity = bestenemy->enemyvelocity;
                            }
                        }
                        else
                        {
                            bestenemy->oldenemydistance = bestenemy->enemydistance;
                        }
                    }
                }
                else if (bestenemy->r.client->pers.feign)
                {
                    if (random() > 0.25)
                    {
                        if (bestenemy->disguisetargettime > level.time)
                        {
                            newenemy = bestenemy;
                            continue;
                        }
                    }
                }
            }
        }
        newenemy = bestenemy;
    }

    if(newenemy)
    {
        fusionbot->enemy = newenemy;
        if (newenemy->disguisetargettime < level.time)
            newenemy->disguisetargeted = 0;
        return qtrue;
    }

    return qfalse;
}