Whoa, it feels like I have to oil my fingers; my last tutorial came so long ago that they seem rusty.
Nevertheless, here I am, squeeky fingers and all. I have a different kind of lesson for you, one which deals with general QuakeC stuff as opposed to AI routines. I think it's pretty interesting stuff, though, and it will add more replay value to those aging Quake maps.
We will be creating a random weapon feature. In other words, weapons in the level will be randomly chosen and will be different every time you load the map. Not a big deal, but it proves simple to do, and it's kind of fun.
Of course all map entities are born through what we call "spawn routines" like item_shells() and weapon_lightning(). Note that the name of the spawn routine is the classname for the item, spelled exactly the same.
(Thus if you wanted to create your own custom map entity, say one named item_crackpipe, you would place this in the level. Next you would write in your code a routine with the same name, which might look something like this:
void() item_crackpipe = { setmodel(self, "progs/cracpipe.mdl"); setsize(self, VEC_HULL_MIN, VEC_HULL_MAX); };This would give your crackpipe a model and a size, thereby letting it be born into the Quake world. Remember that here the "self" entity is the pipe. Happy smoking.)
/*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32) */ void() weapon_supershotgun = { precache_model ("progs/g_shot.mdl"); setmodel (self, "progs/g_shot.mdl"); self.weapon = IT_SUPER_SHOTGUN; self.netname = "Double-barrelled Shotgun"; self.touch = weapon_touch; setsize (self, '-16 -16 0', '16 16 56'); StartItem (); };This is the first of six spawn routines for the weapons which show up on the maps. It initializes the super shotgun, as you can see. We want to stop it before it does this. Thus we will add something after the bracket, like such:
/*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32) */ void() weapon_supershotgun = { if (cvar("deathmatch") == 15) { random_weapon(); return; }If the console variable named "deathmatch is set to 15 -- our new random gun mode -- then we interrupt the subroutine, call our own, and leave. And we didn't even break a sweat.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void() random_weapon = // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { local float r; r = floor(random() * 6); if (r == 0) { precache_model ("progs/g_shot.mdl"); setmodel (self, "progs/g_shot.mdl"); self.weapon = IT_SUPER_SHOTGUN; self.netname = "Double-barrelled Shotgun"; self.classname = "weapon_supershotgun"; } if (r == 1) { precache_model ("progs/g_nail.mdl"); setmodel (self, "progs/g_nail.mdl"); self.weapon = IT_NAILGUN; self.netname = "nailgun"; self.classname = "weapon_nailgun"; } if (r == 2) { precache_model ("progs/g_nail2.mdl"); setmodel (self, "progs/g_nail2.mdl"); self.weapon = IT_SUPER_NAILGUN; self.netname = "Super Nailgun"; self.classname = "weapon_supernailgun"; } if (r == 3) { precache_model ("progs/g_rock.mdl"); setmodel (self, "progs/g_rock.mdl"); self.weapon = 3; self.netname = "Grenade Launcher"; self.classname = "weapon_grenadelauncher"; } if (r == 4) { precache_model ("progs/g_rock2.mdl"); setmodel (self, "progs/g_rock2.mdl"); self.weapon = 3; self.netname = "Rocket Launcher"; self.classname = "weapon_rocketlauncher"; } if (r == 5) { precache_model ("progs/g_light.mdl"); setmodel (self, "progs/g_light.mdl"); self.weapon = 3; self.netname = "Thunderbolt"; self.classname = "weapon_lightning"; } self.touch = weapon_touch; setsize (self, '-16 -16 0', '16 16 56'); StartItem (); };Told you it was simple. Pick a random integer. Initialize a weapon. Finish the entity. Add a bracket and semi-colon.