Created By: MrCool
eMail mrcool101@hotmail.com
Difficulty Scale Easy/Medium

Here's a Small Tutorial that will turn the rocket launcher into a Pipe bomb launcher.

You will need Visual C++ for this is what i used to do this.



Step 1



First open up g_weapons and add this code before the function "void fire_grenade":
void fire_pipe (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius)
{
        edict_t *grenade;
        vec3_t  dir;
        vec3_t  forward, right, up;

        vectoangles (aimdir, dir);
        AngleVectors (dir, forward, right, up);

        grenade = G_Spawn();
        VectorCopy (start, grenade->s.origin);
        VectorScale (aimdir, speed, grenade->velocity);
        VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity);
        VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity);
        VectorSet (grenade->avelocity, 300, 300, 300);
        grenade->movetype = MOVETYPE_BOUNCE;
        grenade->clipmask = MASK_SHOT;
        grenade->solid = SOLID_BBOX;
        grenade->s.effects |= EF_BLASTER;
        VectorClear (grenade->mins);
        VectorClear (grenade->maxs);
        grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2");
        grenade->owner = self;
        grenade->touch = Grenade_Touch;
        grenade->think = Grenade_Explode;
        grenade->dmg = damage;
        grenade->dmg_radius = damage_radius;
        grenade->classname = "pipebomb";

        gi.linkentity (grenade);

}

Then save and open up p_weapon.c and scroll down till you see "void Weapon_RocketLauncher"

delete that function and replace it with this.

void Weapon_RocketLauncher (edict_t *ent)
{
        static int      pause_frames[]  = {34, 51, 59, 0};
        static int      fire_frames[]   = {6, 0};

        Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_pipebomblauncher_fire);
}

Then above that code add this code:

void weapon_pipebomblauncher_fire (edict_t *ent)
{
        vec3_t  offset;
        vec3_t  forward, right;
        vec3_t  start;
        int             damage = 120;
        float   radius;

        radius = damage+50;
        if (is_quad)
                damage *= 4;

        VectorSet(offset, 8, 8, ent->viewheight-8);
        AngleVectors (ent->client->v_angle, forward, right, NULL);
        P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);

        VectorScale (forward, -2, ent->client->kick_origin);
        ent->client->kick_angles[0] = -1;

        fire_pipe (ent, start, forward, damage, 600, 5, radius);

        gi.WriteByte (svc_muzzleflash);
        gi.WriteShort (ent-g_edicts);
        gi.WriteByte (MZ_GRENADE | is_silenced);
        gi.multicast (ent->s.origin, MULTICAST_PVS);

        ent->client->ps.gunframe++;

        PlayerNoise(ent, start, PNOISE_WEAPON);

        ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;

}

Save and open up g_cmds.c and scroll down till you see "void Cmd_NoClip_f" And Above that

function add this code:

void Cmd_Pipe_f (edict_t *ent)
{
        edict_t *pipe;

        pipe = G_Find (world, FOFS(classname), "pipebomb");     
        while(pipe)
        {
                if(pipe->owner == ent)
                        pipe->nextthink = level.time;

                pipe = G_Find (pipe, FOFS(classname), "pipebomb");
        }
}

Then scroll down till you see "void ClientCommand" Find this line:

else if (Q_stricmp (cmd, "noclip") == 0)
                Cmd_Noclip_f (ent);

and right after it add this code:

else if (Q_stricmp (cmd, "detpipe") == 0)
Cmd_Pipe_f (ent);

Save and open up g_items.c and find this code:

/*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
*/
{
                "weapon_rocketlauncher",
                Pickup_Weapon,
                Use_Weapon,
                Drop_Weapon,
                Weapon_RocketLauncher,
                "misc/w_pkup.wav",
                "models/weapons/g_rocket/tris.md2", EF_ROTATE,
                "models/weapons/v_rocket/tris.md2",
/* icon */              "w_glauncher",
/* pickup */    "Rocket Launcher",
                0,
                1,
                "Rockets",
                IT_WEAPON,
                NULL,
                0,
/* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
        },

And replace it with this:

{
                "weapon_rocketlauncher",
                Pickup_Weapon,
                Use_Weapon,
                Drop_Weapon,
                Weapon_RocketLauncher,
                "misc/w_pkup.wav",
                "models/weapons/g_launch/tris.md2", EF_ROTATE,
                "models/weapons/v_launch/tris.md2",
/* icon */              "w_glauncher",
/* pickup */    "Rocket Launcher",
                0,
                1,
                "Grenades",
                IT_WEAPON,
                NULL,
                0,
/* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
        },

Save and open up g_local.h and find the line in blue and added the line in red after it.

void fire_bfg (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius);
void fire_pipe (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius);



Ending


Save and compile. then get the rocket launcher and shoot some grenades then type

cmd detpipe

in the console to detonate them.

Now let's take a look at what i did. Basicly to save time i copyied the Fire Grenade code and renamed it

to Fire_Pipe. I also changed the classname from grenade to pipebomb so it can be used to blow them up. I Also took out the grenade->nextthink function to stop it from blowing up until it's told to.


void fire_pipe (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius)
{
edict_t *grenade;
vec3_t dir;
vec3_t forward, right, up;

vectoangles (aimdir, dir);
AngleVectors (dir, forward, right, up);

grenade = G_Spawn(); // spawns the grenade
VectorCopy (start, grenade->s.origin);
VectorScale (aimdir, speed, grenade->velocity);
VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity);
VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity);
VectorSet (grenade->avelocity, 300, 300, 300);
grenade->movetype = MOVETYPE_BOUNCE;
grenade->clipmask = MASK_SHOT;
grenade->solid = SOLID_BBOX;
grenade->s.effects |= EF_BLASTER;
VectorClear (grenade->mins);
VectorClear (grenade->maxs);
grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2");
grenade->owner = self;
grenade->touch = Grenade_Touch;
grenade->think = Grenade_Explode;
grenade->dmg = damage;
grenade->dmg_radius = damage_radius;
grenade->classname = "pipebomb"; // changed the classname from grenade to pipebomb

gi.linkentity (grenade);

}

I Then changed the Weapon_RocketLauncher function to this. Which i changed the Weapon_Generic fire fucntion from weapon_rocketlauncher_fire to weapon_pipebomblauncher_fire.

void Weapon_RocketLauncher (edict_t *ent)
{
static int pause_frames[] = {34, 51, 59, 0};
static int fire_frames[] = {6, 0};

Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_pipebomblauncher_fire);
}

I then added this code . This sets up the angles and then calls the Fire pipe function to shoot the pipebomb.

void weapon_pipebomblauncher_fire (edict_t *ent)
{
vec3_t offset;
vec3_t forward, right;
vec3_t start;
int damage = 120;
float radius;

radius = damage+50;
if (is_quad)
damage *= 4;

VectorSet(offset, 8, 8, ent->viewheight-8);
AngleVectors (ent->client->v_angle, forward, right, NULL);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);

VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;

fire_pipe (ent, start, forward, damage, 600, 5, radius);

gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_GRENADE | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);

ent->client->ps.gunframe++;

PlayerNoise(ent, start, PNOISE_WEAPON);

ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;

}

Then i added in a command function so you can blow them up.

void Cmd_Pipe_f (edict_t *ent) // name of function
{
edict_t *pipe; //declares entity pipe

pipe = G_Find (world, FOFS(classname), "pipebomb"); // searches the world for a classname named pipebomb
while(pipe) // loops until no more of classname pipebomb
{
if(pipe->owner == ent) // checks to make sure they are yours
pipe->nextthink = level.time; // tells them to blowup

pipe = G_Find (pipe, FOFS(classname), "pipebomb"); // continue the search for pipebombs
}
}

Then i added in the actual command you need to type in the console.

else if (Q_stricmp (cmd, "detpipe") == 0) // checks to see if you type detpipe
Cmd_Pipe_f (ent); // if so executes the function we just made


We then changed the item that declares the rocketlauncher to fit the pipebombs

{
"weapon_rocketlauncher",
Pickup_Weapon,
Use_Weapon,
Drop_Weapon,
Weapon_RocketLauncher,
"misc/w_pkup.wav",
"models/weapons/g_launch/tris.md2", EF_ROTATE, // changed the model to the grenade launcher
"models/weapons/v_launch/tris.md2", // ditto
/* icon */ "w_glauncher",
/* pickup */ "Rocket Launcher",
0,
1,
"Grenades", // uses the ammo grenades instead of rockets
IT_WEAPON,
NULL,
0,
/* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
},

Tutorial html coding modified by legion.


If it is created, then it is copyrighted. Quake 2 Tutorial #9 is (c)1997-98 by MrCool
and the
Inside3D staff. The site is hosted by the one and only TeleFragged. Please direct any
flames, comments, or praises to the author. Any and all information found in this tutorial may
be used in any Quake modification provided that the author and the Inside3D staff are credited.