Weapon Knocking - Enhancement (Rebuilt & Fixed)


Here is the complete tutorial on Weapon Knocking, with the changes that I've made..

Have Fun!

Maj.Bitch

==================================================================

Title: Weapon Knocking - Enhancement
By: Maj.Bitch
Difficulty: Moderate
Email: peblair@frontiernet.com
Date: 05-07-99
Note: Please give credit where credit is due.
============================================================

Because I just put together the Backpack Drop tutorial, I was
thinking... if the player gets shot in the area where they are
holding their weapon, then why doesn't the weapon get blown out
of their hands? Previously, this feature was not enabled and
the only way the player ever let go of their weapon is upon
death (or if they purposefully tossed it away).. Well.. with
this simple enhancement, you can now shoot the player's weapon
out of their hands!!

How it works..

Simple.. The server admin sets the sv_knockweap config variable
in their config file to ON so that the knocking weapons out of
the player's hand feature is enabled..

After that, when you shoot a player and they get damaged and your
shot doesn't kill them (because they automatically toss their weapon
when killed) and the region of the point of impact is in a very
narrowly defined area where they hold their weapon (around their gut!)
then their weapon gets blown out of their hand and they don't take any
damage (because the weapon took the impact and saved them this time around)!!

Also, This new feature relies on the standard issue Q2 TossClientWeapon()
function which, btw, forces them to drop their quad too! So, not only can
you shoot their weapon out of their hand but you can shoot their quad out
of their hand too! This doesn't work for the Blaster.. They must be holding
some other weapon, else the normal damage occurs.. Cool!

Okay! Let's get started!

============================================================
We need to set up the server config variable so add this new
variable to your g_locals.h file where your other cvar_t's
are defined..



extern cvar_t *sv_knockweap;   // 1=ON  - Enable Knocking weapons out of players hand..


And let's formally declare this new variable at the top of g_main.c like so:



cvar_t *sv_knockweap;


And, let's intitalize this variable in InitGame() like so:



  sv_knockweap=gi.cvar("sv_knockweap","1", CVAR_SERVERINFO);


This will set the default state to ON. If you want to change it
to OFF then change the '1' to a '0'..

============================================================
Open you g_combat.c file and find your T_Damage() function.
Make the addition as indicated AT A POINT BELOW THE KILLED()
function call.



  // Was the damage directly on the weapon?

  if (HitTheWeapon(targ, attacker, point)) {

    TossClientWeapon(targ); // Make them toss weapon..

    return; }


============================================================

Okay, now at a point just above the T_Damage function past in this
new function:



//==============================================================

// TRUE if impact point hit target's weapon from in front?

//==============================================================

qboolean HitTheWeapon(edict_t *targ, edict_t *attacker, vec3_t point) {

float regionsize, height, mid_hi, mid_lo;

vec3_t v1, v2, forward;

  // Make sure targ is a player..
  if (!G_EntExists(targ) || !deathmatch->value)
    return false;

  // If Weapon Knocking is Enabled then..
  if (sv_knockweap->value != 1.0)
    return false;

  // Don't shoot the blaster out of their hand!
  if (targ->client->pers.weapon == item_blaster)
    return false;

  //-----------------------------------
  // Find out if the impact came from an
  // angle +/- 30 from front dead-center.
  //-----------------------------------

  // Get v1 from player to point directly forward
  AngleVectors(targ->s.angles, forward, NULL, NULL);
  VectorMA(targ->s.origin, 10, forward, v1);
  VectorNormalize(v1);
  // Get v2 from impact out to attacker's origin.
  // NOTE: dir parameter is not always valid!
  VectorSubtract(point, attacker->s.origin, v2);
  VectorNormalize(v2);
 
if (acos(DotProduct(v1,v2)) <= M_PI/6.0)
    return false;

  //------------------------------------
  // Check if the projectile hit in the
  // narrow frontal region of the player.
  //------------------------------------

  // What is height of target's BBOX?
  height = targ->maxs[2]-targ->mins[2];

  // Determine size of region (10% if ctanding, 30% if crouched)
  regionsize=(BitCmp(targ->client->ps.pmove.pm_flags,PMF_DUCKED))?0.30f:0.10f;

  // Determine a region around origin which is +/- (10% or 30%) of height
  mid_hi = targ->s.origin[2]+(height*regionsize);
  mid_lo = targ->s.origin[2]-(height*regionsize);

  // Is impact in narrow frontal region?
  if (point[2]>=mid_lo && point[2]<=mid_hi)
    return true;

  return false;
}


The comments will explain this new functionality.

Note: you can also make it so that only certain weapons can
be knocked out of their hands!

============================================================

That's it! You're done!

Now, get out there and BLAST THE BASTARD'S WEAPON OUT OF THEIR HANDS!!


Have Fun!!

Maj.Bitch