TUTORIAL 26 - Weapon Positioning
by Carnage
Ok since most of you people want to change the position of the weapon
in the screen I have made here a small tutorial explaining how to do it.
To introduce, this tutorial wil produce that you can change the weapon
position on the screen in 3 diferent points:
- Normal (Right-handed Q3A normal style)
- Centered (Classic Quake and Doom style)
- Left (For those of you that are left-handed)
Ok this is all client side, in fact you send variables to the server and
you get back the weapon where you want it.
We are going to do changes to the following files. Only cgame will be modified:
- cg_main.c
- cg_weapons.c
- cg_event.c
- cg_local.h
This tutorial has been updated to work with 1.27g source code,
CG_MissileHitWall() now takes an extra argument IMPACTSOUND_DEFAULT.
1. MAKING OUR DEFINITIONS
Ok first of all we need to define our new command and variable
A- Go to cg_local.h, line ~837 and insert below:
extern vmCvar_t cg_deferPlayers;
extern vmCvar_t gen_drawWeapon;
B- Go to cg_main.c line ~117 and insert below:
vmCvar_t cg_teamOverlayUserinfo;
vmCvar_t gen_drawWeapon;
C- Still in cg_main.c, line ~195, add:
{ &cg_stats, "cg_stats", "0", 0 },
// the following variables are created in other parts of the system,
// but we also reference them here
{ &gen_drawWeapon, "gen_drawWeapon", "2", CVAR_ARCHIVE },
Ok, what we have just done is to make the game variable we will soon
use. The client variable gen_drawWeapon is set as centered by default.
2. ADDING THE CODE
Ok now we are going to add the new function, so you can select the weapon position on screen:
A1- At line ~970 of cg_weapons.c in function CG_AddViewWeapon() insert below:
float fovOffset;
vec3_t angles;
weaponInfo_t *weapon;
float gen_gunx, gen_guny, gen_gunz;
A2- Now on line ~999 still in function CG_AddViewWeapon() insert below:
if ( cg.testGun ) {
return;
}
gen_gunx = cg_gun_x.value;
gen_guny = cg_gun_y.value;
gen_gunz = cg_gun_z.value;
if ((gen_drawWeapon.integer > 1) && (gen_drawWeapon.integer < 4))
{
switch (ps->weapon)
{
case WP_GAUNTLET:
gen_guny = cg_gun_y.value + 4*(gen_drawWeapon.integer-1);
break;
case WP_MACHINEGUN:
gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
break;
case WP_SHOTGUN:
gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
break;
case WP_GRENADE_LAUNCHER:
gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
break;
case WP_ROCKET_LAUNCHER:
gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
break;
case WP_LIGHTNING:
gen_guny = cg_gun_y.value + 3*(gen_drawWeapon.integer-1);
break;
case WP_RAILGUN:
gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
break;
case WP_PLASMAGUN:
gen_guny = cg_gun_y.value + 4*(gen_drawWeapon.integer-1);
break;
case WP_BFG:
gen_guny = cg_gun_y.value + 5*(gen_drawWeapon.integer-1);
break;
}
}
A3- Now on line ~1019 still in function CG_AddViewWeapon() replace:
VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[0], hand.origin );
VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[1], hand.origin );
VectorMA( hand.origin, (cg_gun_z.value+fovOffset), cg.refdef.viewaxis[2], hand.origin );
with this:
VectorMA( hand.origin, gen_gunx, cg.refdef.viewaxis[0], hand.origin );
VectorMA( hand.origin, gen_guny, cg.refdef.viewaxis[1], hand.origin );
VectorMA( hand.origin, (gen_gunz+fovOffset), cg.refdef.viewaxis[2], hand.origin );
I'm going to explain what we have just done:
On A1 we define 3 new float values (our new x, y, z position).
On A2 we take the original x,y,z values and assigned them to our new values,
then we search which weapon we are using, it "y" position is added
to the value we type on the console minus 1 (so if we type gen_drawweapon 1
it will remain it's original value), the higher the value the more left
it will be.
On A3 we replace the the VectorMa() so it will take the
new values we already modify.
Ok now compile it, run it, go to the console and type: gen_drawweapon x
(x takes values from 1 to 3).
Hah, how nice, you start remembering the good
old Doom days, you started firing the plasma gun, with the weapon positions
on the center of the screen, you love it, next the good bfg10k, you can see now
how the barrels look, yeah and finally you start firing the Railgun...
Ahem.... what's wrong with the Railgun? It's central but the trail does
not come from the railgun itself, what's the problem?
Ok I will try to explain this, the railgun does not shoot, it makes a
trace from the origin to where it hit and then it makes the trail, but
the origin of the trail is not the weapon itself (like the other weapons are),
but from a position on the screen.
The most difficult thing about this code is in fact the railgun,
but here is the damn fix.
3. FIXING THE DAMN RAILGUN
Now what we are going to do is to fix the railgun, by changing the trail
origin position, we will start making a new rail trail origin.
A- At line ~386 of cg_event.c in function CG_EntityEvent() and insert below:
int clientNum;
clientInfo_t *ci;
vec3_t railtrail_origin;
int pos;
es = ¢->currentState;
B- Now, still on cg_event.c in the same function go to line ~723 and replace:
case EV_RAILTRAIL:
DEBUGNAME("EV_RAILTRAIL");
cent->currentState.weapon = WP_RAILGUN;
// if the end was on a nomark surface, don't make an explosion
if ( es->eventParm != 255 ) {
ByteToDir( es->eventParm, dir );
CG_MissileHitWall( es->weapon, es->clientNum,
position, dir, IMPACTSOUND_DEFAULT );
}
#if 1
CG_RailTrail( ci, es->origin2, es->pos.trBase );
#else
// the railtrail temp entity will be spawned when this player is added
VectorCopy( es->pos.trBase, cg_entities[clientNum].pe.railgunImpact );
cg_entities[clientNum].pe.railgunFlash = qtrue;
#endif
break;
by this:
case EV_RAILTRAIL:
DEBUGNAME("EV_RAILTRAIL");
cent->currentState.weapon = WP_RAILGUN;
// if the end was on a nomark surface, don't make an explosion
if ( es->eventParm != 255 ) {
ByteToDir( es->eventParm, dir );
CG_MissileHitWall( es->weapon, es->clientNum,
position, dir, IMPACTSOUND_DEFAULT );
}
if ( ((gen_drawWeapon.integer == 2) || (gen_drawWeapon.integer == 3))
&& es->clientNum == cg.snap->ps.clientNum
&& !cg.renderingThirdPerson)
{
if (gen_drawWeapon.integer == 2)
pos = -4;
else
pos = -8;
AngleVectors( cg.snap->ps.viewangles, NULL, railtrail_origin, NULL );
VectorMA( es->origin2, pos, railtrail_origin, railtrail_origin );
CG_RailTrail( ci, railtrail_origin, es->pos.trBase );
}
else
{
CG_RailTrail( ci, es->origin2, es->pos.trBase );
}
break;
I will try to explain what this do, in A we define our railtrail_origin
as a vector, like the old origin (origin2).
On B we made a new railtrail event, the server check wich position you
have the weapon, if you have it centered it change the railtrail origin -4
from his original position on "y", if you are lefthanded
it change it -8.
Then it adds the new position to the origin and the railtrail is spawned.
4. WE ARE DONE!
Now Compile it and you will see that every weapon work ok, enjoy it and have fun.
Hope this tutorial help you in your mod. I use "gen_" variable name,
because we are using it in our mod
Generations Arena
Special thanks to Codemonkey for helping me with the railtrail origin,
and to Equim too.
Any comment-> Carnage
|