|
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
|
| |