|
posted 11-03-98 2:37 AM CT (US)
Title: Railbomb Grenades Add-On
Difficulty: Easy
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 11-02-98
Note: Please give credit where credit is due.
======================================================
This tutorial is a
modification of the principles put forth
in my previously posted tutorial (Airial Laserdrone Unit).
This add-on adds additional firepower to your grenade. READ ON!
When you want to
activate your RailBomb, you hit your aliased
key and a message comes on the screen letting you know that your
grenades are now Railbombs. The grenade launches and bounces
around just like a regular grenade and even explodes just like
a regular grenade (distributing damage, etc) but out of the
explosion fireball comes railgun slugs (known as railtrails)
which are fired at ALL visible players within a 1000 unit radius.
This happens almost instantly!! COOL EFFECTS when multiple rails
come flying out of the fireball! So, if there are a bunch
players outside the explosion fireball damage radius (who think
that they've escaped from the grenade's explosion) but they are
within the 1000 unit search-n-fire radius of the grenade's
fireball, then they get railed!! Haha! They think they got
away from your grenade's explosion!! FOOLS!! If there are no
visible players within the defined radius, then no slugs are
fired from the grenade and the grenade explodes and acts just
like a regular grenade! Nobody will know the difference! And,
it doesn't cost you any cells or frags to convert your grenades
to railbombs!! Hit your aliased key and ALL your grenades are
converted to railbombs until you hit your aliased key again to
toggle them all off. Fire as many of these babies you want to!!
Okay, let's get
started..
============================================================
We need to add a new variable to your gclient_s struct. So,
at the bottom of that struct, add this:
int railbomb; //
1=ON, 0=OFF
This will be used to
toggle the railbomb ON/OFF
============================================================
We need to add
another MOD_* obituary flag. So, inside of
your g_local.h add the MOD_RAILBOMB flag as the next integer
in the numerical sequence as shown by example:
#define
MOD_CLUSTER_BOMBS 0x00000024 // Cluster Airstrike
#define MOD_ZYLON_GAS 0x00000025 // Gas Grenade
#define MOD_RAILSTRIKE 0x00000026 // BFG Nuke Airstrike
#define MOD_BFG_NUKE 0x00000027 // Railgun Airstrike
#define MOD_DECOY 0x00000028 // Decoy Blast
#define MOD_LASERDRONE 0x00000029 // LaserDrone Weapon
#define MOD_RAILBOMB 0x00000030 // NEW FLAG HERE
#define MOD_FRIENDLY_FIRE 0x10000000 // DON'T TOUCH THIS ONE!!
============================================================
Lets open you
g_weapons.c file and add these helper routines
to 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..
//======================================================
// 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);
}
//======================================================
//======================================================
//======================================================
/*
Spawns a trail of (type) from {start} to {end} and Broadcasts to all
in Potentially Visible Set from vector (origin)
TE_BFG_LASER -
Spawns a green laser
TE_BUBBLETRAIL - Spawns a trail of bubbles
TE_PLASMATRAIL - NOT IMPLEMENTED IN ENGINE
TE_RAILTRAIL - Spawns a blue spiral trail filled with white smoke
*/
//======================================================
void G_Spawn_Trails(int type, vec3_t start, vec3_t endpos, vec3_t origin ) {
gi.WriteByte(svc_temp_entity);
gi.WriteByte(type);
gi.WritePosition(start);
gi.WritePosition(endpos);
gi.multicast(origin, MULTICAST_PVS);
}
============================================================
============================================================
============================================================
Okay, let's make
some obituaries for your gameplay. Find your
ClientObituary() function in your p_client.c file and add the
following:
---------- FIND
THESE LINES HERE -------------
case
MOD_TARGET_BLASTER:
message="got blasted";
break;
------------ ADD THESE LINES HERE ------------
case MOD_RAILBOMB:
message="was railbombed";
break;
Further down in this
same function:
-------------- FIND
THESE LINES -----------
case MOD_G_SPLASH:
if (IsFemale(victim))
message="tripped on her own grenade";
else
message="tripped on his own grenade";
break;
----------- ADD
THESE LINES HERE -------------
case MOD_RAILBOMB:
if (IsFemale(victim))
message="got riveted by her railbomb";
else
message="got riveted by his railbomb";
break;
Still further down
in this same function:
---------- FIND
THESE LINES HERE -------------
case MOD_TELEFRAG:
message="tried to invade";
message2="'s personal space";
break;
--------- ADD THESE
LINES HERE ---------------
case MOD_RAILBOMB:
message="was riveted by";
message2="'s railbomb";
break;
Remember: You should
feel free to change these client
obituaries to whatever you think is more appropriate for
your particular mod..
============================================================
Okay, go into
InitClientPersistant() function in your p_client.c
file and add this line near the bottom:
client->railbomb=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 too:
self->client->railbomb=0;
// Turn OFF.
This will turn off
the railbombs when the player 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..
---------- IF-ELSE
STATEMENTS --------
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);
----------- ADD THESE LINES ------
else if (Q_stricmp(cmd, "railbomb") == 0) {
ent->client->railbomb=abs(ent->client->railbomb-1);
gi.centerprintf(ent,"RAILBOMBS %s!\n",ent->client->railbomb<1?"DISABLED":_x0022_ENABLED_x0022__x0029__x003b__x007d_>
else if .....
This will toggle the
railbombs on/off with a single stroke
of the player's aliased key.
============================================================
Open up your g_weapons.c file and find your grenade_explode()
function and add the lines as shown..
void
Grenade_Explode(edict_t *ent) {
----- FIND THE FIREBALL EXPLOSION CODE ------------
------ SHOULD LOOK SOMETHING LIKE THIS -------
gi.WritePosition(origin);
gi.multicast(ent->s.origin, MULTICAST_PHS);
-------- ADD THESE
LINES RIGHT AFTER IT! ---------
// Railbomb only if
activated by real Player..
if (G_EntExists(ent->owner))
if (ent->owner->client->railbomb)
Railbomb(ent);
This will activate
the Railbomb's search-n-rail function
if the railbomb flag is set by the grenade's owner...
============================================================
Lastly, in your
g_weapons.c file, at a point just above the
grenade_explode() function, add this new function:
//==================================================================
// Fires Rail Slugs into all visible players within 1000 unit radius
//==================================================================
void Railbomb(edict_t *grenade) {
edict_t *ent=NULL;
trace_t tr;
vec3_t dummy=(0,0,0);
vec3_t start,end;
int i;
grenade->viewheight
= 16; // required for visible() function??.
// Find (and rail)
ALL visible ents within 1000 unit radius...
for(i=0;i < game.maxclients;i++) {
ent=g_edicts+i+1;
if (!G_ClientInGame(ent)) continue;
if (ent==grenade) continue;
if (!ent->takedamage) continue;
if (!visible(grenade,ent)) continue;
if (!G_Within_Radius(grenade->s.origin, ent->s.origin, 1000)) continue;
VectorCopy(grenade->s.origin, start);
VectorCopy(ent->s.origin, end);
end[2]+=8;
tr=gi.trace(start, ent->mins, ent->maxs, end, NULL, MASK_SHOT);
G_Spawn_Trails(TE_RAILTRAIL, start, tr.endpos, tr.endpos);
if (G_EntExists(tr.ent) && (tr.ent->takedamage))
T_Damage(tr.ent, grenade->owner, grenade->owner, dummy, start, dummy, grenade->dmg,
1, 0, MOD_RAILBOMB);
} // end for
// return gracefully
to grenade_explode() function..
}
NOTE: The farther
the potential target is from the origin
of the grenade the less accurate the trace function gets!!
So, at farther and farther distances, the grenade tends to
miss. But, it's deadly accurate up close and personal!
============================================================
Be sure to add the following to your Autoexec.cfg file as
shown by example..
bind r
"railbomb"
That's it!!
If your grenade's
explosion doesn't kill the bastards then
THE RAIL SLUGS COMING OUT OF THE FIREBALL WILL!!
Have Fun!!
Philip
|