
I was hacking around in the new 3.14 code, and figured out how to change something that's always annoyed me about Quake2... weapon switch speed. Yeah, I know, it more relistic... but I rather have it faster!.
Here's how to do it:
In p_weapon.c there is a function called "Weapon_Generic". All weapons end up calling this to process generic weapon stuff (fire, change weapon, pick weapon up, et al).
The two areas that cause the delay are the IF's on WEAPON_DROPPING and WEAPON_ACTIVATING. If you look inside of them, you'll notice it checks to see if "ent->client->ps.gunframe" == FRAME_DEACTIVATE_LAST (FRAME_ACTIVATE_LAST for WEAPON_ACTIVATING), and, if it isn't, it will increment the gunframe and return. One of the callers to this function will continue calling this function for the weapon change, until the gunframe is equal to the last frame.
So.. to make weapon switches happen really fast, we'll just ignore this little loop, setting the gunfame to FRAME_DEACTIVATE_LAST (or FRAME_IDLE_FIRST for WEAPON_ACTIVATING), and call change weapon. This will bypass all the weapon change frames. Simple, huh?
(BTW, there may be some other stuff that may make this quicker. I just did a quick scan of the code when I got the new 3.14 source, and found this. I also have not extensibly tested this mod, so the game behavior MIGHT be off a bit :)
Here’s the code, modified. NOTE: I've indicated my changes by "//+@RAT" (start of change) and "//-@RAT" (end of change). As right after my change I do a return, I've left the rest of the code in so you'll be able to see what's happing in the new and old code.
//--------- Start of Example
--------------------------------------------------
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int
FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int
*pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
{
int n;
if (ent->client->weaponstate == WEAPON_DROPPING)
{
//+@RAT
ent->client->ps.gunframe
= FRAME_DEACTIVATE_LAST; //@RAT - may not have to do this... just to make
sure.
ChangeWeapon (ent);
return;
//-@RAT
#if 0
if (ent->client->ps.gunframe ==
FRAME_DEACTIVATE_LAST)
{
ChangeWeapon (ent);
return;
}
ent->client->ps.gunframe++;
return;
#endif
}
if (ent->client->weaponstate == WEAPON_ACTIVATING)
{
//+@RAT
ent->client->weaponstate = WEAPON_READY;
ent->client->ps.gunframe =
FRAME_IDLE_FIRST;
return;
//-@RAT
#if 0
if (ent->client->ps.gunframe ==
FRAME_ACTIVATE_LAST)
{
ent->client->weaponstate =
WEAPON_READY;
ent->client->ps.gunframe = FRAME_IDLE_FIRST;
return;
}
ent->client->ps.gunframe++;
return;
#endif
}
//--------- End of Example ---(Rest of this function should follow! -----------------------------------------------
Here's just the mod:
//--------- Start of Example
--------------------------------------------------
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int
FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int
*pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
{
int n;
if (ent->client->weaponstate ==
WEAPON_DROPPING)
{
ent->client->ps.gunframe =
FRAME_DEACTIVATE_LAST; //@RAT - may not have to do this... just to make
sure.
ChangeWeapon (ent);
return;
}
if (ent->client->weaponstate ==
WEAPON_ACTIVATING)
{
ent->client->weaponstate =
WEAPON_READY;
ent->client->ps.gunframe =
FRAME_IDLE_FIRST;
return;
}
//--------- End of Example ---(Rest of this function should follow!
-----------------------------------------------