
Player Identification
Function
I have wanted
to put together a player identification function for some time but the recent
inquiries as to how to accomplish this seemed to have bumped it up on my
priority list so I looked into it to see what it would take. Well, it wasn't
that hard and really has alot of good uses!
How it works:
The player
hits their aliased key and toggles their player ID to be 'enabled'. A message
on their HUD lets them know that this has been enabled for them.. (This
function remains enabled until they hit their aliased key again). So, you hit
the same key ON/OFF.
Once enabled,
all players will be identified which are 'infront' of the player's current
position and within a 500 unit searching radius (which is pretty far!).
Once identified, useful information about that player will appear on your HUD
like this:
WildMAN (88) at 378 units
Where
'WildMAN' is the player's name, (88) is their current health, and the '378
units' is their distance from you!
Good stuff to know if a frag fight (especially how healthy the other player
is!). You can add other stuff to be displayed too! Whatever you think is
information which is important given your particular mod's setup.
Okay, let's get started..
Add in the blue code and take out the pink code.
First, we need to add a new variable to your gclient_s struct.
So, at the bottom of that struct, add this:
int id_on; // 1=ON, 0=OFF
This will be
used to toggle the ID Function ON/OFF.
Okay, go into InitClientPersistant() function in your p_client.c file and add
this line near the bottom:
client->id_on=0; // default to OFF.
This will set
the default to OFF each time the player enters the game..
Also in your p_client.c file, go into Player_Die() function and add this line
to the bottom:
self->client->id_on=0; // Turn OFF.
This will turn
off all the player's ID function when he dies..
Open up your g_cmds.c file and go near the bottom of your ClientCommand()
function and add the following as shown by example.. Your selection of commands
may differ, but just be sure to stick this one in there somewhere.
else if (Q_stricmp(cmd, "decoy") == 0 )
SP_Decoy(ent);
else if (Q_stricmp(cmd, "drone") == 0 )
Cmd_LaserDrone_f(ent);
else if (Q_stricmp(cmd, "teleport") == 0)
Cmd_Teleport_f(ent);
else if (Q_stricmp(cmd,
"id_on") == 0)
{
ent->client->id_on=abs(ent->client->id_on-1);
ent->->touch_debounce_time = level.time + 5.0;
gi.centerprintf(ent,"PLAYER ID %s!\n",
ent->client->id_on<1 ? "OFF":"ON");
}
else if .....
This will
toggle the ID function with a single stroke of
the player's aliased key and print a message to your HUD.
Lets open you
g_weapons.c file and add these helper routines
and the baton's source code somewhere near the top of the file.
NOTE: I've
used these helper routines in many of my previous
tutorials so you may already have them someplace in your source.
If you already do have them, then you don't need them anymore.
Your compiler should warn you that you've already got these
functions previously defined..
Okay, add the following text to the top of your g_weapons.c file.
//======================================================
// True if Ent is valid, has client, and edict_t inuse.
//======================================================
qboolean G_EntExists(edict_t *ent)
{
return ((ent) && (ent->client) &&
(ent->inuse));
}
//======================================================
// True if ent is not DEAD or DEAD or DEAD (and BURIED!)
//======================================================
qboolean G_ClientNotDead(edict_t *ent)
{
qboolean buried = true;
qboolean b1 = ent->client->ps.pmove.pm_type!=PM_DEAD;
qboolean b2 = ent->deadflag != DEAD_DEAD;
qboolean b3 = ent->health > 0;
return (b3||b2||b1) && (buried);
}
//======================================================
// True if ent is not DEAD and not just did a Respawn.
//======================================================
qboolean G_ClientInGame(edict_t *ent)
{
if (!G_EntExists(ent))
return false;
if (!G_ClientNotDead(ent))
return false;
return (ent->client->respawn_time + 5.0 <
level.time);
}
//======================================================
// True if start and end are within radius distance.
//======================================================
qboolean G_Within_Radius(vec3_t start, vec3_t end, float rad)
{
vec3_t eorg = {0,0,0};
int j;
for (j=0; j<3; j++)
eorg[j]=abs(start[j]-end[j]);
return (VectorLength(eorg) < rad);
}
Lastly, open
your p_client.c file and find your ClientThink() function..
At a point just above the ClientThink() function add this new function:
//=========================================================
void Player_Identification(edict_t *self)
{
int i;
int distance;
edict_t *player;
vec3_t forward;
// Allow scanning to
occur ONLY every 5 seconds..
if (self->touch_debounce_time > level.time) return;
// Don't allow
Dead/Respawning players to enable ID..
if (!G_ClientInGame(self))
{
self->client->id_on=0; // Turn OFF
return;
}
for (i=0; i <
game.maxclients; i++)
{
player = g_edicts + i + 1;
if
(!G_ClientInGame(player))
continue;
if (self == player)
continue;
if (!G_Within_Radius(self->s.origin,
player->s.origin, 500))
continue;
if (!infront(self, player))
continue;
VectorSubtract (self->s.origin,
player->s.origin, forward);
distance = (int)VectorLength(forward);
gi.cprintf (self, PRINT_HIGH,"%s (%d)
at %d units\n", player->client->pers.netname, player->health,
distance);
} // end for
// Don't want to be a
resouce hog for ClientThink!!
self->touch_debounce_time = level.time + 5.0;
}
This routine
will do the searching and identification processing.
Now, inside of you ClientThink() function we need to add a few lines as
indicated:
void
ClientThink(edict_t *ent, usercmd_t *ucmd)
{
gclient_t *client;
edict_t *other;
int i, j;
pmove_t pm;
level.current_entity = ent;
client = ent->client;
if (level.intermissiontime)
{
client->ps.pmove.pm_type =
PM_FREEZE;
// can exit intermission after five
seconds
if (level.time >
level.intermissiontime + 5.0 && (ucmd->buttons & BUTTON_ANY) )
level.exitintermission =
1;
return;
}
if
(ent->client->id_on)
Player_Identification(ent);
This will
activate your player ID function if you've got your id_on enabled. Since this
will happen each time the ClientThink() function is called for you (just about
every couple of frames) I needed to put a debounce_timer at the top of the
Player_Identification() function (as shown above) so that the ID'ing would not
drain computer processing and lag the system!!
Lastly..
Be sure to add the following to your Autoexec.cfg file as shown by example..
bind i
"id_on"
That's it!!
Enable your new ID function and ID THE BASTARDS
BEFORE YOU KILL'EM!
Have Fun!!