|
posted 11-24-98 4:02 PM CT (US)
Title: HighScore 'Ghost' Follower
Difficulty: Moderate
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 11-24-98
Note: Please give credit where credit is due.
======================================================
This is a takeoff of
my Ghost 'bot detection' stuff I put together a few months ago. I put this
together because I thought that a player should be able to visibly 'see' who
is the player on top of the frag-board! Currently there is no way to tell
just by looking at the scoreboard because in the game you really can't tell
exactly who that top-player is!! Well, now you can!!
How it works:
There is a
server-side variable which you set in your config file which toggles a Ghost
entity to follow around the player with the highest score! When the Ghost is
turned ON a particle effect will appear 50 units above the head of the player
with the highest score thereby letting everybody know who is on top of the
scoreboard!!
The Ghost entity
follows this player around as they move (except when they are dead,
respawning, or of course, have left the game). The Ghost is in a loop
checking every 1 second to see if another player has taken the top spot on
the board. If so, then they become the player which the Ghost will be
following around! The other players will see a sprinkle of particles above
the head of the player who is currently with the top score. This will give
the other players an opportunity to go and chase the bastard down (or avoid
him! Cowards!!).
NOTE: Code could
easily be inserted to give the player an extra frag or two if they kill the
player with the Ghost entity above their heads! You decide what is
appropriate for your particular mod.
Okay, let's get
started..
============================================================
Let's add a server config variable to your g_local.h file.
extern cvar_t
*g_select_empty;
extern cvar_t *dedicated;
extern cvar_t *sv_gravity;
extern cvar_t *sv_maxvelocity;
extern cvar_t *sv_bestplayer; //<=== NEW VAR HERE
============================================================
At the top of you g_main.c file we need to add this:
cvar_t
*sv_maxvelocity;
cvar_t *sv_gravity;
cvar_t *sv_bestplayer; // <== DECLARE VAR HERE
This will formally
declare the variable.
============================================================
In your InitGame() function add this line:
void InitGame(void)
{
// change anytime
vars
dmflags = gi.cvar("dmflags", "0", CVAR_SERVERINFO);
fraglimit = gi.cvar("fraglimit", "0", CVAR_SERVERINFO);
timelimit = gi.cvar("timelimit", "0", CVAR_SERVERINFO);
password = gi.cvar("password", "", CVAR_USERINFO);
--------- ADD THIS
ONE LINE RIGHT HERE -----------------
sv_bestplayer=gi.cvar("sv_bestplayer","1",CVAR_SERVERINFO);
This will set the variable's state.
============================================================
Lastly, open up your p_client.c file..
Okay, now add these
lines to your ClientBeginDeathmatch()
function as shown:
void
ClientBeginDeathmatch(edict_t *ent) {
static qboolean Ghost_Spawned=false; //<=== NEW LINE HERE
------------- ADD
THESE LINES RIGHT HERE --------------
// Create Ghost on
first Player connect.
if ((sv_bestplayer->value==1.0) && !Ghost_Spawned) {
Create_Ghost();
Ghost_Spawned=true; }
This will spawn the Ghost entity when the very first player
connects to your server..
============================================================
At the top of your p_client.c file, add these new routines:
NOTE: YOU MAY
ALREADY HAVE THESE HELPER ROUTINES!!!
//======================================================
// 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);
}
//=====================================================
//=========== FLAGGING BEST PLAYER ROUTINES ===========
//=====================================================
//=========================================================
// Returns Player with Highest Score.
//=========================================================
edict_t *BestScoreEnt(void) {
edict_t *bestplayer=NULL;
int i, bestscore=-999;
edict_t *ent;
// Search thru all
clients
for(i=0;i < game.maxclients; i++) {
ent=g_edicts+i+1;
if (!G_EntExists(ent)) continue;
if (ent->client->resp.score > bestscore) {
bestplayer=ent; // Found one!
bestscore=ent->client->resp.score; }
} // end for
return bestplayer;
}
//======================================================
// Ghost think routine.
//======================================================
void Ghost_Think(edict_t *Ghost) {
vec3_t start=(0,0,0);
vec3_t up;
edict_t *fPlayer=NULL;
// Unlink Ghost if
intermission..
if (level.intermissiontime >= level.time) {
gi.unlinkentity(Ghost);
return; }
// Check Scoreboard
every 1 sec.
if (Ghost->delay <= level.time) {
fPlayer=BestScoreEnt();
Ghost->delay =level.time + 1.0; }
// Move Ghost above
fPlayer.
if ((fPlayer!=NULL) && G_ClientInGame(fPlayer)) {
Ghost->svflags &= ~SVF_NOCLIENT; // Turn ON Ghost
AngleVectors(fPlayer->s.angles, NULL, NULL, up);
VectorMA(fPlayer->s.origin, 60, up, start);
VectorCopy(start, Ghost->s.origin); // Move Ghost
gi.linkentity(Ghost); } // Must update Ghost!
else
// No fPlayer to follow so..
// turn OFF Ghost temporarily
Ghost->nextthink = level.time + 0.1; // Every frame..
}
//======================================================
// Create Ghost Entity
//======================================================
void Create_Ghost(void) {
edict_t *Ghost;
Ghost=G_Spawn();
Ghost->owner=NULL;
Ghost->s.effects=EF_TELEPORTER; // Particle effect.
Ghost->model="";
Ghost->takedamage=DAMAGE_NO;
Ghost->movetype=MOVETYPE_NONE;
Ghost->solid=SOLID_NOT;
Ghost->s.modelindex = 0;
Ghost->s.modelindex2 = 0;
VectorClear(Ghost->mins);
VectorClear(Ghost->maxs);
Ghost->delay=0;
Ghost->think=Ghost_Think;
Ghost->nextthink = 1.0; // Start in 1 second.
gi.linkentity(Ghost);
}
===============================================================
Lastly..
Be sure to add the
following to your Autoexec.cfg file as
shown by example..
set sv_bestplayer 1
That's it!! Now get
out there and KILL THE BASTARD WITH
THE HIGHEST SCORE!!!
And if its you,
everybody is gonna be after your ass!!
Have Fun!!
philip
|