Inside3D tutorials.
Created By: Smoke2Much
eMail: smoke2much@Geocities.com
Difficulty Scale: Medium


Step 1
Ok, in this tutorial we're gonna create a DetPack bomb. Sounds cool? Then try it out! Find the Impulse Commands section under weapons.qc Copying the code already there add an impulse 20 that will goto DropDetpack as below:-
============
ImpulseCommands

============
*/
void() ImpulseCommands =
{
        if (self.impulse >= 1 && self.impulse <= 8)
                W_ChangeWeapon ();
        if (self.impulse == 9)
                CheatCommand ();
        if (self.impulse == 10)
                CycleWeaponCommand ();
        if (self.impulse == 11)
                ServerflagsCommand ();
     if (self.impulse == 20)         //This is the new impulse command
                DropDetpack ();         //This is where it will goto when the impulse is keyed in from the console
if (self.impulse == 255)
                QuadCheat ();
                
        self.impulse = 0;
};


Step 2
Now we need to add the routine called "DropDetpack" into Weapons.QC also. I have added it just above the section "Player Weapon Use" This is how it should look:-
void() DropDetpack =
{
        if (self.ammo_rockets >= 25)                                    //Check to see if player has 25+ rockets
        {

                self.ammo_rockets = self.ammo_rockets - 25;             //reduce rockets by 25
                        local entity    item;                           //create a variable called item

                item = spawn();                                         //spawn an item
                item.origin = self.origin - '0 0 24';                   //create item at 24 above player
        
                item.velocity_z = 300;                                  //items vertical velocity
                item.velocity_x = -100 + (random() * 200);              //Item is thrown in...
                item.velocity_y = -100 + (random() * 200);              //a random direction
        
                item.flags = FL_ITEM;
                item.solid = SOLID_TRIGGER;                             //Trigger an event when touched
                item.movetype = MOVETYPE_TOSS;                          //Movement type..ie. throw it !!
                setmodel (item, "progs/backpack.mdl");                  //Graphic to be thrown
                setsize (item, '-16 -16 0', '16 16 56');                //Set size of graphic
                item.owner = self;                                      //set item.owner to players ident
                item.touch = DetpackTouch;                              //if item is touched then goto DetpackTouch
        
                item.nextthink = time + 120;                            //After two minutes execute item.think
                item.think = DetpackExplode;                            //So after two minutes execute DetpackExplode
        }
        else                                            //Not Enough rockets...
        {
        sprint (self, "not enough ammo.\n");            //Print to player..."You ain't got enough ammo!!"
        return;                                         //return to game
        }

};


Step 3
OK. This now references two more routines :- DetpackTouch which will tell the pck to explode on enemy contact but not on owner contact, and DetpackExplode which will errrr... well work it out for yourself.

Because of the way that Quake C works, these two routines MUST be in the right order. QC will not goto a routine that it has not already seen. Ie. These two must go ABOVE the code we've already put in. But since we will need to reference DetpackExplode from DetpackTouch, DetpackExplode MUST go above DetpackTouch.

Here's my annotated source code...
void () DetpackExplode =
{
        T_RadiusDamage (self, self.owner, 1000, world);         //This will create the damage radius, a grenade
                                                                //does 120 but we want a BIG explosion.
                                                                //So we'll ues 1000 !! ;-)
        WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);              //Sets up a temporary entity
        WriteByte (MSG_BROADCAST, TE_EXPLOSION);                //Temporary entity is an explosion
        WriteCoord (MSG_BROADCAST, self.origin_x);              //Create at Backpack Origins(x)
        WriteCoord (MSG_BROADCAST, self.origin_y);              //Create at Backpack Origins(y)
        WriteCoord (MSG_BROADCAST, self.origin_z);              //Create at Backpack Origins(z)

        BecomeExplosion ();                                     //BANG !!!
};

void() DetpackTouch =
{
        if (other == self.owner)                                //If player touches their own detpack then ignore it
        {
                return;                                         //Return to game
        }
        if (other.takedamage == DAMAGE_AIM)                     //If player/monster who touches detpack can take damage
        {
                DetpackExplode();                               //BANG !!!
                return;                                         //Return to game.
        }
        if (self.velocity == '0 0 0')                           //If backpack isn't moving then:-
        {
                self.avelocity = '0 0 0';                       //prevent it moving angularly (I think ?!?!? )
        }
};

Right...this code needs to go right above our DropDetpack code. We're almost there !

Step 4
Final step !! Since we're using a new model within this area, we need to pre-cache it to ensure that it has the graphic available when it needs it. So underneath all of the sound_precache files at the top of weapons.qc add the following line...
        precache_sound ("weapons/grenade.wav"); // grenade launcher
        precache_sound ("weapons/bounce.wav");          // grenade bounce
        precache_sound ("weapons/shotgn2.wav"); // super shotgun
        precache_model ("progs/backpack.mdl");       // Backpack for DetPack
And that as they say "is all folks !!". Thanks for being interested. Compile up this code and run it under Quake. Either type in impulse 20 on the console or Bind a key to it. Have Fun!!