Quake Style - Quake 2 Tutorials
Tech Power Up Mayhem - TPUM - Part 2
Tech Power Up Gameplay
|
Tech Power Up Gameplay:
If you have ever played CTF, you have seen those four strange items which give you special powers, like automatic regeneration of your health up to 150 health. These are called "tech power ups" in Quake 2, but that idea has been around much longer: in Quake 1, people adding their own powerups called them "runes" and the game "artifact quake" (check http://singe.telefragged.com).
There are two kind of "runes": Those which are active as soon as you picked them up (like those in Quake 2 CTF) and those you need to use, i.e., bind a key, then press that key whenever an enemy is near or any other particular occasion. Those runes appear at random places and respawn after a while. You can only own and use one rune at a time; if you want to switch runes, you have to drop your current one first.
Requirements:
The stuff we did in the previous parts of "Tech Power Up Mayhem". This series of tutorials builds up step-by-step and you must have done any previous pages before adding this one!
Basic work / Source code notes:
One reason the CTF source is necessary is simply to avoid the coding of all the routines which spawn and respawn the runes at random places, picking up, dropping, checking if you already have one, etc. All that was done by Zoid before and, as they say, don't invent the wheel again!
Here's some important source code note: We have found one point where different source bases may influence these tutorials. The latest CTF source I found does not have the viewable weapons patch included. Our tutorials are build so that you can use this CTF source right away. If you added CTF functionality to the 3.20 source yourself or start from an already "patched" CTf source (that does mean, including viewable weapons), you need one more line within each item we add to the item structure in g_items.c to settle for the extended g_items struct; note that this line already is included in all the tuts but out-commented: In case you need it, simply activate it.
Download CTF source
Download 3.20 source
We need only very little work done to adjust general functionality to all/most of the runes. Let's get started:
Add in the blue code and take out the pink code. Regular yellow code is Zoid's original stuff.
In g_local.h add this line at the end of g_clients struct, right after Zoid's qboolean update_chase;
int rune_count;
We will do some nasty things with the runes and to avoid people overusing them, we have to limit the maximum amount that particular rune can be used; we'll use rune_count to check that.
Open q_shared.h and add the following line:
#define STAT_LAYOUTS 13
#define STAT_FRAGS 14
#define STAT_FLASHES 15 // cleared each frame, 1 = health, 2 = armor
#define STAT_RUNE_STRING 16
As we not only have four runes like in Q2CTF, but will add a few (and there are basically no limits except your imagination - my mod has 30 runes included), we'll have to find an easy way to identify the currently owned rune: The HUD. The STAT_RUNE_STRING holds the place for this information. Note: In case you have used "16" already, you may use another higher number as well; in that case, be sure to replace "16" with the new number not only here, but also in the p_hud.c modification we'll do a little later.
Two lines need to be added to g_cmds.c. At the very end of ClientCommand() we need:
else if (Q_stricmp (cmd, "userune") == 0)
Rune_Use (ent);
else // anything that doesn't match a command will be a chat
Cmd_Say_f (ent, false, true);
We will add runes later which need to be used, so we need a command we can bind a key too. Now open your g_ctf.c file; the first function we have to take a look at is CTFPickup_Tech():
// client only gets one tech
other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
other->client->ctf_regentime = level.time;
other->client->rune_count=0;
By adding this line, we'll make sure that rune_count is reset as soon as the rune is picked up. Now move on to CTFDrop_Tech():
edict_t *tech;
ent->client->rune_count = 0;
Adding this kinda puts us on the safe side - if a rune is dropped, rune_count is set back to 0. Next we add a new function at the end of g_ctf.c:
//Returns currently owned rune
gitem_t * HUD_ShowRune(edict_t *ent)
{
gitem_t *tech=0;
int i=0;
ent->client->ps.stats[STAT_CTF_TECH] = 0;
while (tnames[i])
{
if ((tech = FindItemByClassname(tnames[i])) != NULL &&
ent->client->pers.inventory[ITEM_INDEX(tech)])
return tech;
i++;
}
return 0;
}
If we have runes we need to use by pressing a key, we need a function for that, so add another one right after HUD_ShowRune():
void Rune_Use(edict_t *ent)
{
int index;
gitem_t *it;
char *rune_msg;
// say "no rune or automatically activated rune" if there is no
// special usage (=pressing a button) needed or if player
// doesn't own a rune
// otherwise just call the using function for that specific rune
rune_msg="No rune or automatically activated rune";
gi.centerprintf(ent, "s\n", rune_msg);
}
This is the function that gets the name of the currently owned rune so we can display it in the HUD. Now search for your ctf_statusbar and add this:
"stat_string 27 "
"endif "
// runes
"if 16 "
"xl 2 "
"yb -28 "
"string \"Rune:\" "
"xl 2 "
"yb -11 "
"stat_string 16 "
"endif "
;
That makes sure we know which rune we own all the time. Finally we delete a line from CTFHasTech():
if (level.time - who->client->ctf_lasttechmsg > 2) {
gi.centerprintf(who, "You already have a TECH powerup.");
who->client->ctf_lasttechmsg = level.time;
}
Since you'll be able to check your rune right in the HUD, there is no need anymore for displaying this message; it's enough if we aren't able to pick up a second rune. Also, if you put in 10 or 15 runes, that message would be displayed much too often and get very annoying. Now we're done in g_ctf.c. Be sure to add the following lines to g_ctf.h:
gitem_t *HUD_ShowRune(edict_t *ent);
void Rune_Use(edict_t *ent);
We're almost done with the basics without even adding a rune! Open p_hud.c where we have to do some work at G_SetStats() right after the declarations:
gitem_t *item;
int index, cells;
int power_armor_type;
item = HUD_ShowRune(ent);
if(item)
ent->client->ps.stats[STAT_RUNE_STRING] = CS_ITEMS+ITEM_INDEX(item);
else
ent->client->ps.stats[STAT_RUNE_STRING] = 0;
That done, we need to add some code to your dm_statusbar in g_spawn.c:
// frags
"xr -50 "
"yt 2 "
"num 3 14"
// runes
"if 16 "
"xl 2 "
"yb -28 "
"string \"Rune:\" "
"xl 2 "
"yb -11 "
"stat_string 16 "
"endif "
;
Ok. Compile it and put the gamex86.dll in your mod's game folder - be sure to bind a key to "drop tech" in your autoexec.cfg if you haven't already, and one to "userune", which will be very important for our next tut. What we now have is a base to set our runes in. The only thing visible by now is the name of the rune in the HUD, being displayed in the lower left corner of your screen. The name displayed is taken from g_items.c: In gitem_t itemlist[] you can check that the name for the regeneration power up is "AutoDoc"; now pick it up and exactly that is displayed.
Some thoughts about rune names and item models:
I only enclose this here just for your consideration.
In case you intend a good measure of runes, including some activated automatically (like the original Q2 ones) and some you need to use (like placing a "trap"), it may be a good idea to add something to identify exactly that: I added "[U]" to the runes' name which tells the owner that he has to press the bound key to take [U]se of this rune.
Also, to make it more fun, you could use the same item model for all of the runes. That way you'll never know which one you'll pick up.
Nick back to the tutorials page and have a look at the next tutorial in the sequence.
-- Credits:
Tutorial by peter
Return to QS Tutorials
-- Important:
If you do use something from QuakeStyle in your mod, please give us credit.
Our code is copyrighted, but we give permission to everyone to use it in any way they see fit, as long as we are recognized.