Okay class, raise your hand if you think the weapons the Quake monsters use are boring...
Whoa, that's a lot of hands. We all agree, the grunts and enforcers and others have dumb pea-shooters for guns. Look at a mod like Killer Quake Pack. It was fun not only because it gave you new weapons, but because the enemy bots used these guns, too.
In this tutorial we will teach a grunt how to fire a new weapon, say a lavaball launcher. First, we'll start with taking a look at a player weapon subroutine, the rocket launcher for instance.
Open up WEAPONS.QC and scroll down until you see this:
/*
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
missile = spawn ();
================
W_FireRocket
================
*/
void() W_FireRocket =
{
local entity missile, mpuff;
missile.owner = self;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.solid = SOLID_BBOX;
missile.classname = "missile";
Let's look at the next part:
// set missile speed
makevectors (self.v_angle);
missile.velocity = aim(self, 1000);
missile.velocity = missile.velocity * 1000;
missile.angles = vectoangles(missile.velocity);
This won't work for the grunt, obviously, because he needs to aim at his enemy, and that may not be the nearest monster. But we can let him use the routine by changing that line to this:
if (self.classname == "grunt")
missile.velocity = normalize(self.enemy.origin - self.origin);
else missile.velocity = aim(self, 1000);
"If the guy who is using this routine is called a grunt, then he should aim straight at his enemy. Or if he's anything besides a grunt, he should use QuakeC's auto-aim feature."
That's easy, isn't it? With this modification, we could call this subroutine from the grunt's brain, and he would fire a rocket at his enemy. Honest. I'm not lying.
By the way, what that line of code does is draw a line from his location (self.origin) to his opponent's location (self.enemy.origin). Don't really worry what "normalize" means. It just sort of smooths out that line.
Now we are ready for the main event, the grunt's lavaball launcher. We want to replace his stupid shogtun routine with this new weapon. First, open up the file SOLIDIER.QC and scroll down until you see this:
void() army_fire =
ai_face();
{
local vector dir;
local entity en;
void() army_fire_old =
void() army_lavaball_touch =
// don't explode on owner
if (other == self.owner)
// disappear if it hits the sky
// do some damage
if (other.health)
T_RadiusDamage (self, self.owner, 120, other);
self.origin = self.origin - 8*normalize(self.velocity);
// a lava splash effect from Quake's boss
// turn into a spirite then disappear
void() army_fire =
// he should face his foe
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
// create a solid, flying entity
// what happens when the lavaball hits something
// here's the new model:
{
local float damg;
return;
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
damg = 100 + random()*20;
T_Damage (other, self, self.owner, damg );
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LAVASPLASH);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};
{
local entity missile, mpuff;
ai_face();
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.solid = SOLID_BBOX;
missile.classname = "missile";
// grunt fires straight at his enemy
missile.velocity = normalize(self.enemy.origin - self.origin);
missile.velocity = missile.velocity * 1000;
missile.angles = vectoangles(missile.velocity);
missile.touch = army_lavaball_touch;
missile.nextthink = time + 5;
missile.think = SUB_Remove;
setmodel (missile, "progs/lavaball.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin + v_forward*8 + '0 0 16');
};
Did all that make sense? The important thing to remember is this: when the player fires, he auto-aims, and monsters cannot use the auto-aim feature.
If you have some source code from a custom weapon that you like, just look for the line with aim() in it, and change it like we did.
Remember though, I'm not responsible for any psychological damage you may suffer when you see a lavaball explode in your face.