|
qwFix:
Tutorials:
|
|
|
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
|
|
|