Your bot ain't nothin if he ain't got no class.
Okay, so I'm not as slick as I want to sound: what I wanted to say is that your bot could be much cooler if he had a class. You know, player classes, like sniper, gansta, mage, whatever. Today, we're going to learn how to implement bot classes. Or die trying.
The last I heard, Quake 3: Arena, a sure-to-be-orgasmic bot game, included player classes. I'm sure they will resemble the standard, stereotypical classes of heavy/slow, medium/middle, and light/fast guy. I think most game characters, like a wizard or a marine, fall into one of these categories so, by God, we'll use these.
We could deal with dozens of player characteristics, but we will settle for these: health, speed, skin, weapon, and attack style. I think with these that we can create some pretty cool bot personalities. If you don't agree with me, you can bite me.
Note: if you go further, know that this tutorial requires you to have done the attack styles and bot speed lessons. Another note: teamplay will be taken out in this lesson, so if you use teamplay, read through it first. Also, this lesson assumes you have a player.mdl with three skins, the first representing the heavy guy, second the medium guy, and third the light guy. Find skins at ftp.cdrom.com/pub/quake/graphics/skin_textures/
First, we need a new variable to store our bot's class. Open up defs.qc and at the very bottom, put this strangely named float:
.float botclass;With that done, we can do most of our class work in one simple subroutine. With further ado, here it be:
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void(entity his) apply_bot_class = // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { // heavy/slow guy if (his.botclass == 0) { his.health = 125; his.max_health = 125; his.speed = 50; his.skin = 0; his.items = his.items & IT_ROCKET_LAUNCHER; his.weapon = IT_ROCKET_LAUNCHER; his.currentammo = his.ammo_rockets = 20; his.attack_state = 1; } // medium/middle guy if (his.botclass == 1) { his.health = 100; his.max_health = 100; his.speed = 250; his.skin = 1; his.items = his.items & IT_SUPER_SHOTGUN; his.weapon = IT_SUPER_SHOTGUN; his.currentammo = his.ammo_shells = 50; his.attack_state = 2; } // light/fast guy if (his.botclass == 2) { his.health = 75; his.max_health = 75; his.speed = 500; his.skin = 2; his.items = his.items & IT_SUPER_NAILGUN; his.weapon = IT_SUPER_NAILGUN; his.currentammo = his.ammo_nails = 100; his.attack_state = 3; } };If this was any simpler, it would bore you to sleep. As you can see, all we are doing is apply certain values to his traits depending on his class. It's black and white. It's a no-brainer. Place this code before the routine bot_name() near the end of tutor.qc.
void(float teem) create_bot =We have one parameter there now, called teem, but we need to add one. Change that line to this:
void(float teem, float which) create_bot =Okay, now go down to the line that reads give_random_weapon(bot); and delete it. In its place, put this code:
bot.botclass = which; apply_bot_class(bot);We set our bot's class, and then change his characteristics relevant to that class. Easy.
apply_bot_class(self);This is a bit different because the bot is now the self entity (when you create a bot, the player is the self entity). Remember, he retains his self.botclass even when he dies.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void() bot_strafe = // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ { bot_face(); bot_check_ammo(); if (self.botclass == 0) return; if (self.botclass == 1) back_up(); if (self.botclass == 2) bot_run_slide(); };This might be the neatest part of our bot class system. Like the Heavy Weapons Guy in Team Fortress, our heavy bot will not move while he fires. Our medium guy will move backwards, while our light dude will strafe. Thus, the player will be able to see his personality in action.
void(float teem) create_bot;Change that line to this one:
void(float teem, float which) create_bot;Next, scroll all the way down to the routine ImpulseCommands(). You will see some old crap like this:
if (self.impulse == 100) create_bot(0); if (self.impulse == 101) create_bot(1);What we will do is change that to this:
if (self.impulse == 100) create_bot(0, 0); if (self.impulse == 101) create_bot(0, 1); if (self.impulse == 102) create_bot(0, 2);O how I enjoy simple stuff. The player can now type impulse 100 to create a heavy bot, impulse 101 for a medium bot, or impulse 102 for a light bot. You will notice that our first parameter, the teamplay value, is always zero, so its not used.