Inside3D tutorials.
Created By: James "Drywall" Layman
eMail: drywall@telefragged.com
Difficulty Scale: Easy


Step 1
This is an tutorial that makes Grunts fire weakened rockets at you. Once again, fire up that text editor. Now, open up "weapons.qc." Copy the void T_MissileTouch and place it right below itself. Then, rename it to T_GruntMisTouch. It should look like this: (and for those of you who have forgotten, blue is add and red is delete)
void() T_GruntMisTouch = //Changed from T_MissileTouch
{
    local float damg;

    if (other == self.owner)
        return; // don't explode on owner

    if (pointcontents(self.origin) == CONTENT_SKY)
    {
        remove(self);
        return;
    }

    damg = 10 + random()*2; //replace code that was virtually the same by a factor of 10

    if (other.health)
    {
        if (other.classname == "monster_shambler")
        damg = damg * 0.5; // mostly immune
        T_Damage (other, self, self.owner, damg );
    }

// don't do radius damage to the other, because all the damage
// was done in the impact
    T_RadiusDamage (self, self.owner, 10, other); //Changed from 120 to 10

// sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1,ATTN_NORM);
    self.origin = self.origin - 8*normalize(self.velocity);

    WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
    WriteByte (MSG_BROADCAST, TE_EXPLOSION);
    WriteCoord (MSG_BROADCAST, self.origin_x);
    WriteCoord (MSG_BROADCAST, self.origin_y);
    WriteCoord (MSG_BROADCAST, self.origin_z);

    BecomeExplosion ();
};
Now, what you just did was create an entire new 'touch' function for the Grunt's rocket, because you do NOT want grunt gibbage :) It makes for a damned hard level. So now instead of grunts firing rockets which do 120 damage, they fire 10 damage rockets.

Step 2
Now, copy the W_FireRocket void, as you did in step 2 with the T_MissileTouch void, and once again, place it right below itself, then change the W_FireRocket to W_GruntRocket. It looks like this:
/*
================
W_GruntRocket
================
*/

void() W_GruntRocket = //changed from W_FireRocket
{
    local entity missile, mpuff;

    self.currentammo = self.ammo_rockets = self.ammo_rockets - 1; //Grunts have no ammo that I can think of

    sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);

    self.punchangle_x = -2;

    missile = spawn ();
    missile.owner = self;
    missile.movetype = MOVETYPE_FLYMISSILE;
    missile.solid = SOLID_BBOX;
    missile.classname = "missile";

// set missile speed 

//DELETE THE LINES THAT WERE BETWEEN '//set misile speed' and 'missile.touch' with the 3 lines below
    missile.velocity = normalize(self.enemy.origin - self.origin);
    missile.velocity = missile.velocity * 600;
    missile.angles = vectoangles(missile.velocity);
    missile.touch = T_GruntMisTouch;

// set missile duration
    missile.nextthink = time + 5;
    missile.think = SUB_Remove;

    setmodel (missile, "progs/missile.mdl");
    setsize (missile, '0 0 0', '0 0 0');
    setorigin (missile, self.origin + v_forward*8 + '0 0 16');
};


Step 3
Ok, you're done with weapons.qc, save and close that, and open up "soldier.qc." Find the void "army_fire", and look for the line: "FireBullets (10, dir, '0.1 0.1 0');" Change this line to "W_GruntRocket();". Also, remove the variables that are inserted for the firebullets.
void() army_fire =
{
    local vector dir;
    local entity en;

    ai_face();

    sound (self, CHAN_WEAPON, "soldier/sattck1.wav", 1, ATTN_NORM);


//fire somewhat behind the player, so a dodging player is harder to hit
    en = self.enemy;
    dir = en.origin - en.velocity*0.2;
    dir = normalize (dir - self.origin);

    W_GruntRocket();
};


Step 4
Save the soldier.qc file, compile, and you're done! The grunts will now fire rockets at you, and they do a low enough level of damage that it's still balanced.