D:\cygwin\wf_fusion_src_r8\CVSROOT\WeaponsFactory\wf_compass.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.

  Modified code by Keith Pase

  wf_compass.c -- Compass Code, Original concept sorta by Acrid-
  

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

#include "..\game\g_local.h"
//#include "bot_procs.h"// for carryingflag() simple ef_flag check /for a tutor replace here

#define COMPASS_Q2FEET        32

//if scanner code is removed use these, easier than making new functions
//#define SAFE_STRCAT(org,add,maxlen)    if ((strlen(org) + strlen(add)) < maxlen)    strcat(org,add);
//#define LAYOUT_MAX_LENGTH              1400


void CompassOff(gclient_t *client)
{
    client->pers.compass_active=0;
    client->compass_target = NULL;
    client->compass_mode = 0;
}

void FlagScan(edict_t *ent)
{
    edict_t *target;
    char *str;
    
    
    
    if ((ent->wf_team == 1) && (ent->r.client->compass_mode == 1)||
        (ent->wf_team == 2) && (ent->r.client->compass_mode == 2))
        str = "team_CTF_blueflag";
    else
        str = "team_CTF_redflag";
    
    //make sure its clear for rescan
    ent->r.client->compass_target= NULL;
    
    target = G_Find(NULL, FOFS(classname), str);


    if (!(!target))
    {
        
        
        //1st lookup Not at base ,check players or lookup from 1st target
        if (target->r.solid == SOLID_NOT)
        { 
            int i;
            extern gitem_t *flag1_item;
            extern gitem_t *flag2_item;

            
            //Not at base and not dropped
            for (i = 1; i <= maxclients->value; i++)
            {
                if ((ent->wf_team == 1) && (ent->r.client->compass_mode == 1)||
                    (ent->wf_team == 2) && (ent->r.client->compass_mode == 2))
                {
                    if (game.edicts[i].r.inuse &&
                        game.edicts[i].r.client->pers.inventory[ITEM_INDEX(flag2_item)]) 
                    {
                        // enemy has it
                        ent->r.client->compass_target = &game.edicts[i];
                        
                        // G_Printf("who %s\n",g_edicts[i].client->pers.netname); 
                        
                    }
                }
                else  //if (ent->wf_team == 2)
                {          
                    if (game.edicts[i].r.inuse &&
                        game.edicts[i].r.client->pers.inventory[ITEM_INDEX(flag1_item)]) 
                    {
                        // enemy has it
                        ent->r.client->compass_target = &game.edicts[i];
                        
                        //   G_Printf("who %s\n",g_edicts[i].client->pers.netname); 
                        
                    }
                }
            }
            
            //Not at base and noone has it
            if (!ent->r.client->compass_target)
            {
                    
                    while( target = G_Find(target, FOFS(classname), str))
                    
                    // Just incase of error
                    if (target->r.solid == SOLID_NOT)
                    {
                        //  target = NULL;
                        ent->r.client->compass_target = NULL;
                        G_Printf("target not solid\n");
                    }
                    else if (target->spawnflags & DROPPED_ITEM)
                    {
                        ent->r.client->compass_target = target;
                        // G_Printf("target solid1 %s\n",target->classname);
                    }
                    
            }
        }
        else //Flag is Solid
        {
            ent->r.client->compass_target = target;
            //      G_Printf("target solid2 %s\n",target->classname);
        }
    }
}
//void ShowCompass(edict_t *ent,char *layout)
void ShowCompass(edict_t *ent)
{


    edict_t *target;
//    char    stats[64];
    int     len;
    int     hd;
    vec3_t  v;
    vec3_t  dp;
    vec3_t  dp2;
    vec3_t  normal = {0,0,-1};
    int     pos;
    int     pitch;

    extern gitem_t *flag1_item;
    extern gitem_t *flag2_item;

    target = ent->r.client->compass_target;

    flag1_item = FindItemByClassname("team_CTF_redflag");
    flag2_item = FindItemByClassname("team_CTF_blueflag");


        if ((ent->r.client->pers.inventory[ITEM_INDEX(flag2_item)]) || (ent->r.client->pers.inventory[ITEM_INDEX(flag1_item)]))
        {
            if (ent->wf_team == 2 && ent->r.client->compass_mode == 1)
            {
                ent->r.client->compass_mode = 2;
                FlagScan(ent);
            }
            else if (ent->wf_team == 1 && ent->r.client->compass_mode == 1)
            {
                ent->r.client->compass_mode = 2;
                FlagScan(ent);
            }
//          else 
//              ent->r.client->compass_target = NULL;
        }

        if ((ent->wf_team == 1) && (ent->r.client->compass_mode == 1) && (!(strcmp(target->classname, "team_CTF_redflag") != 0)))
            FlagScan(ent);

        if ((ent->wf_team == 2) && (ent->r.client->compass_mode == 1) && (!(strcmp(target->classname, "team_CTF_blueflag") != 0)))
            FlagScan(ent);


//layout[0] = 0;
        if (!target) return;

        //If flag capped or dropped rescan
        if (target->r.client && !CarryingFlag(target))
        {   
            FlagScan(ent);
            if (!target) return;
        }

        //If flag picked up rescan
        if (target->r.solid == SOLID_NOT && !target->r.client)
        {
            FlagScan(ent);
            if (!target) return;
        }

        // calc player to decoy vector
        VectorSubtract (ent->s.origin, target->s.origin, v);

        // For the DIST
        len = VectorLength (v) / COMPASS_Q2FEET;
 

        hd = v[2];
        // Remove height component
//      v[2] = 0;

        // Normal vector to enemy
        VectorNormalize(v);

        // rotate round player view angle (yaw)
        RotatePointAroundVector( dp, normal, v, ent->s.angles[1]);

        RotatePointAroundVector( dp2, normal, v, ent->s.angles[0]);

        pos = ((dp[1] * 360)/4);
        

        if (pos < 0)
                pos = (pos + 360);

        if (!infront(ent, target))
        {
            pos = ((pos * -1) + 180);
            if (pos < 0)
            {
                pos = (pos + 360);
            }
        }

        pitch = ((dp2[2] * 74) + ((ent->s.angles[0]) * 1.6 ) * -1);

        ent->r.client->ps.persistant[PERS_COMPASS] = (pitch<<4)|(pos<<2)|(len<<8);


/*      
        Com_sprintf (stats, sizeof(stats),"xl %i yt %i compass models/compass.md3 c %i 0 %i", 6, 2, pitch, pos);
        SAFE_STRCAT(layout,stats,LAYOUT_MAX_LENGTH);


 //Distance background
        if ((ent->wf_team == 1) && (ent->r.client->compass_mode == 1)||
            (ent->wf_team == 2) && (ent->r.client->compass_mode == 2))
        {
            Com_sprintf (stats, sizeof(stats),"xl 5 yt 70 string \"%sDist:%i\" ", S_COLOR_CYAN, len ); 
            SAFE_STRCAT(layout,stats,LAYOUT_MAX_LENGTH);
        }
        else
        {
            Com_sprintf (stats, sizeof(stats),"xl 5 yt 70 string \"%sDist:%i\" ", S_COLOR_RED, len ); 
            SAFE_STRCAT(layout,stats,LAYOUT_MAX_LENGTH);
        }
*/
}

void Toggle_Compass(edict_t *ent, char *arg)
{
//  char string[1040];
//  char *s;


    if (!deathmatch->value)
        return;

    if ((!ent->r.client) || (ent->health <=0))
        return;

    ent->r.client->showscores = qfalse;
    ent->r.client->showinventory = qfalse;
    ent->r.client->showhelp = qfalse;

     if (ent->r.client->menu)
     { 
        PMenu_Close(ent);
        ent->r.client->update_chase = qtrue;
     }


    //Toggle off
    if ( (Q_stricmp(arg, "off") == 0) || (Q_stricmp(arg, "0") == 0) )
    {
        ent->r.client->pers.compass_active = 0;
        ent->r.client->compass_target = NULL;
        ent->r.client->compass_mode = 0;
        return;
    }
    //Target the enemy flag
    else if ((Q_stricmp(arg, "offense") == 0) || (Q_stricmp(arg, "1") == 0))
    {

        //What do we want to track?

        if (ent->wf_team == 1)
        {
            ent->r.client->compass_mode = 1;
            FlagScan(ent);
        }
        else if (ent->wf_team == 2)
        {
            ent->r.client->compass_mode = 2;
            FlagScan(ent);
        }
        else 
            ent->r.client->compass_target = NULL;
    }
    //Target your own flag
    else if ((Q_stricmp(arg, "defense") == 0) || (Q_stricmp(arg, "2") == 0))
    {
        //What do we want to track?

        if (ent->wf_team == 1)
        {
            ent->r.client->compass_mode = 2;
            FlagScan(ent);
        }
        else if (ent->wf_team == 2)
        {
            ent->r.client->compass_mode = 1;
            FlagScan(ent);
        }
        else 
            ent->r.client->compass_target = NULL;

    }
    else //cycle toggle
    {
     if (ent->r.client->compass_mode == 2)
        {
        ent->r.client->pers.compass_active = 0;
        ent->r.client->compass_target = NULL;
        ent->r.client->compass_mode = 0;
            return;
        }
     else
        { 
         ent->r.client->compass_mode = ent->r.client->compass_mode + 1;
         FlagScan(ent);
        }
    }


//  string[0] = 0;
    ent->r.client->pers.compass_active = 1;
/*
    s = DeathmatchScoreboardMessage (ent, ent->enemy);
    trap_Layout (ent, s);
*/
    
}