Click Here!
 

   qwFix:

   News

   Mods
   Maps
   Demos

   Board
   Contact
   FAQ
   Notes

   Tutorials:

   Backpacks
   Rail Color

   Other

     BACKPACK TUTORIAL - READ THIS FIRST

"Copyright" notice
You are allowed to use the code in this tutorial in any way you like, as long you give me at least some credit for the work I've done.

Disclaimer
I am not responsible for any direct or indirect damage caused by this tutorial. Use it at your own risk.

I DO NOT GET PAID TO DO THIS!

 
     STEP 1: Creating the necessary resources
First, you'll need a backpack model and a backpack icon. The backpack model in qwFix is, indirectly, a copyright of Jason 'Fireball' Verkaart, so don't use it without asking. The backpack icon in qwFix may be used and altered freely, though.

When you've created the model and the icon, place the resources in the following directories:
The model: yourQ3modpath\models
The icon: yourQ3modpath\icons

Now you'll need a shader for the backpack icon, or else it will show "through walls". Create a file named "backpack.shader" and place it in "yourQ3modpath\scripts". The shader should include the following lines:

icons/icon_backpack
{
   nopicmip
   {
      map icons/icon_backpack.tga
      blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
   }
}

I'm not a shader expert, but that will get the job done. Of course, you should "map" the correct icon, if you've named it anything else than "icon_backpack.tga".

 
     STEP 2: Adding the backpack item to the itemlist
Now we'll dig into the code. To get the new item working correctly, we need to add it to the Big List of Items. But before we can do that, we'll have to define how q3 is going to define a backpack.

There's lots of possibilites, but I chose to make the backpack a "weapon". If you like, you could make the backpack a powerup instead (or a completely new type, for that matter), but this tutorial assumes the "weapon" solution is used.

Now open the file "bg_public.h" and search for "WP_NUM_WEAPONS". You should find a enum structure with all the WP_ definitions. Then, just above the WP_NUM_WEAPONS (but below WP_GRAPPLING_HOOK), add this line:

WP_BACKPACK,

Save and close "bg_public.h" and open "bg_misc.c" instead. Search for "team_CTF_redflag" and you'll find a structure defining what model/icon the red flag should use. Now add these lines above the flag structure (below the flight powerup structure):

{
   "weapon_backpack",
   "sound/misc/w_pkup.wav",
   { "models/backpack.md3", 0, 0, 0},
   "icons/icon_backpack",
   "Backpack",
   0,
   IT_WEAPON,
   WP_BACKPACK,
   "",
   ""
},

Now it is added. Now there are one of thing to remember... If a player who doesn't have your client-side code installed connects to your server, he will be kicked out if the gametype is CTF. Why? Because the flags will be located in item index positions that he won't have.

 
     STEP 3: Dropping the backpack when a player dies
Now you want people to drop the damn backpacks, right? This requires some hacking because we don't want to change the entity structure (it is already large enough). So how are we going to save all ammo information in an entity that hasn't got enough data fields?

Well this can be solved with some bit operations. As you know, each weapon has a maximum ammo count of 200 rounds. 200 in hex is C8 and 11001000 binary. If you count the bits, you'll notice their eight of them. Almost every field in the entity structure are integers (int). An integer can hold 16 bits (actually, I believe the ANSI C code defines "int" as 32 bit, email me if you know for sure), which is enough to hold two ammo types.

Now, to put two ammo types into the same field, you must use bitwise shift operations. Basically, it looks like this:

[Data Field] = (([Ammo1] & 0x00FF) << 8) + ([Ammo2] & 0x00FF);

But first, we must drop the backpack... Open "g_combat.c" and search for "toss". You will find a function named "TossClientItems". This function is called when the player has died and it's time to drop the items he was carrying. Find the large if-statement block, starting with this line:

if ( weapon > WP_MACHINEGUN && weapon != WP_GRAPPLING_HOOK &&

Remove the complete if-block (or just place it in a comment). Then add the new backpack code:

// find the item type for the backpack
item = BG_FindItemForWeapon(WP_BACKPACK);
// spawn the backpack
drop = Drop_Item( self, item, 0 );
// fill the backpack with the player's weapon information:
// count is used for weapon info, damage for MG-ammo and SG-ammo,
// health for GL-ammo and RL-ammo, splashdamage for LG-ammo and
// RAIL-ammo, and splashradius for PLASMA and BFG-ammo
drop->count = weapon;
drop->damage =
   ((self->client->ps.ammo[WP_MACHINEGUN] & 0x00FF) << 8) +
   (self->client->ps.ammo[WP_SHOTGUN] & 0x00FF);
drop->health =
   ((self->client->ps.ammo[WP_GRENADE_LAUNCHER] & 0x00FF) << 8) +
   (self->client->ps.ammo[WP_ROCKET_LAUNCHER] & 0x00FF);
drop->splashDamage =
   ((self->client->ps.ammo[WP_LIGHTNING] & 0x00FF) << 8) +
   (self->client->ps.ammo[WP_RAILGUN] & 0x00FF);
drop->splashRadius =
   ((self->client->ps.ammo[WP_PLASMAGUN] & 0x00FF) << 8) +
   (self->client->ps.ammo[WP_BFG] & 0x00FF);

As you can see, I use the damage, health, splashdamage and splashradius data fields to keep the ammo information. This is all it takes to drop the backpack. Now we must be able to pick it up, too.

 
     STEP 4: Making it possible to pick up the backpacks
As a final step you must open "g_items.c" and change the Pickup_Weapon function. Look for the first if statement:

if ( ent->count < 0 ) {

BEFORE that line, add this code:

// if it is a backpack that has been picked up...
if (ent->item->giTag == WP_BACKPACK)
{
   
// give the player the backpack's weapon, if it isn't an gauntlet or a machinegun
   if ( ent->count > WP_MACHINEGUN && ent->count != WP_GRAPPLING_HOOK)
   {
      other->client->ps.stats[STAT_WEAPONS] |= ( 1 << ent->count );
   }
   
// give the player lots of ammo (sort of...)
   Add_Ammo( other, WP_MACHINEGUN, (ent->damage >> 8) );
   Add_Ammo( other, WP_SHOTGUN, (ent->damage & 0x00FF) );
   Add_Ammo( other, WP_GRENADE_LAUNCHER, (ent->health >> 8) );
   Add_Ammo( other, WP_ROCKET_LAUNCHER, (ent->health & 0x00FF) );
   Add_Ammo( other, WP_LIGHTNING, (ent->splashDamage >> 8) );
   Add_Ammo( other, WP_RAILGUN, (ent->splashDamage & 0x00FF) );
   Add_Ammo( other, WP_PLASMAGUN, (ent->splashRadius >> 8) );
   Add_Ammo( other, WP_BFG, (ent->splashRadius & 0x00FF) );
}
else
// a normal weapon (ie not a backpack)
{

And as a final touch, add a single bracket ( } ) AFTER this line to maintain correct code:

quantity = 1; // only add a single shot

 
     STEP 5: Registering the backpack
Before the backpack can be used, it must be registered (so it can be precached). Find the "ClearRegisteredItems" function in "g_items.c". And add the following line in the end of the function:

RegisterItem( BG_FindItemForWeapon(WP_BACKPACK));


That's it! Contact me for suggestions and comments, I check the board every day

// KHAILE
 
  Backpack tutorial info

   Last modified: 11 feb

   General:
 Requires a client download: YES
 Requires new gfx/mdl's: YES
 Modifies cgame: YES
 Modifies game: YES
 Modifies ui: NO

   Modified files:
 bg_misc.c
 g_combat.c
 g_items.c
 bg_public.h