[page=Locational Damage for Quake2]
Hello! This is Paril here, with Paril's Mini Tutorials.
Down at Paril's Projects, as you know, AQC is in development, and well.. what's a realistic mod without being able to be hit in the head and dying one hit? Nothing!
Anyways, here's how we're going to do it.. (Also, please ignore the fact about the spacing.. it works fine in C++/Notepad)
Open up G_Combat.c..
find this:
qboolean CheckTeamDamage (edict_t *targ, edict_t *attacker)
{
//FIXME make the next line real and uncomment this block
// if ((ability to damage a teammate == OFF) && (targ's team == attacker's team))
return false;
}
Right after this, copy-paste this entire code after that and before the T_Damage function:
//==============================================================
// AQC Scale damage amount by location of hit on player's body..
//==============================================================
#define VectorEmpty(a) ((a[0]==0)&&(a[1]==0)&&(a[2]==0))
#define IsIn(x,a,b) ((x)>=(a)&&(x)<=(b))
#define LEG_DAMAGE (height/2.0)-abs(targ->mins[2])-3
#define STOMACH_DAMAGE (height/1.6)-abs(targ->mins[2])
#define CHEST_DAMAGE (height/1.4)-abs(targ->mins[2])
#define NECK_DAMAGE (height/1.1)-abs(targ->mins[2])
#define HEAD_DAMAGE (height/0.7)-abs(targ->mins[2])
#define ARM1_DAMAGE (height/1.4)-abs(targ->mins[8]) // Should go about between the chest and stomach, and going over by 8
#define ARM2_DAMAGE (height/1.4)-abs(targ->mins[-8]) // Should go about between the chest and stomach, and going over by -8
//==============================================================
float location_scaling(edict_t *targ, vec3_t point, float damage, int mod) {
float z_rel, height;
edict_t *ent;
if (!(targ->flags&FL_GODMODE))
if (!VectorEmpty(point))
if (IsIn(mod, MOD_BLASTER, MOD_RAILGUN)) {
height = abs(targ->mins[2])+targ->maxs[2];
z_rel = point[2]-targ->s.origin[2];
if (z_rel < LEG_DAMAGE)
return 0.35; // Scale down by 2/3
else
if (z_rel < STOMACH_DAMAGE)
return 0.66; // Scale down by 1/3
else
if (z_rel < CHEST_DAMAGE)
return 1.20; // Scale up by 1/5
if (z_rel < NECK_DAMAGE)
return 3.00; // Scale up by 3X (Come on, a neck shot atleast has to kill;) )
if (z_rel < HEAD_DAMAGE)
return 8.00; // Scale up by 8X (Pretty much dead...)
if (z_rel < ARM1_DAMAGE)
return .66; // Scale down by 1/3
if (z_rel < ARM2_DAMAGE)
return .66; // Scale down by 1/3
else
return 1.0;} // Normal Damage if hit anywhere else
return 1.0; // keep damage the same..
}
//-----------------------------------------------------------
Now go down further, and find this line in your T_Damage function:
// friendly fire avoidance
// if enabled you can't hurt teammates (but you can hurt yourself)
// knockback still occurs
if ((targ != attacker) && ((deathmatch->value && ((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) || coop->value))
{
if (OnSameTeam (targ, attacker))
{
if ((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE)
damage = 0;
else
mod |= MOD_FRIENDLY_FIRE;
}
}
Right above that, add:
//-----------------------------------
//AQC Scale damage by hit location (leg,stomach,chest,head)..
damage *= location_scaling(targ, point, damage, mod);
//------------------------------------
There you go! A simple, yet effective way to implement a very good realistic feature.
Many many things you could do with this. Maybe some text like in Action "You hit %s in the (name of part)!", Kevlar/Armor bullet hitting "%s's Kevlar Vest absorbed most of the shot".. this can be used for every weapon, including melee attacks.
Note, I messed up,
Try this:
#define ARM1_DAMAGE (height/1.4)-abs(targ->mins)+8 // Should go about between the chest and stomach, and going over by 8#define ARM2_DAMAGE (height/1.4)-abs(targ->mins)-8 // Should go about between the chest and stomach, and going over by -8
Oh, sorry, but i think you need folow line:
after (!(targ->flags&FL_GODMODE)):
Code:
if (!(targ->deadflag == DEAD_DEAD))
and before "if (!VectorEmpty(point))" for example.
It prevent an one-shot gibbing of dead enemy.
Moddb.com
Included :-) Thanks :-)