Reformat g_combat.c

This commit is contained in:
Yamagi Burmeister 2011-10-13 06:37:06 +00:00
parent 9abb572aff
commit 943e91e300

View file

@ -1,98 +1,126 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// g_combat.c
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Combat code like damage, death and so on.
*
* =======================================================================
*/
#include "header/local.h"
/*
============
CanDamage
Returns true if the inflictor can directly damage the target. Used for
explosions and melee attacks.
============
*/
qboolean CanDamage (edict_t *targ, edict_t *inflictor)
* Returns true if the inflictor can
* directly damage the target. Used for
* explosions and melee attacks.
*/
qboolean
CanDamage(edict_t *targ, edict_t *inflictor)
{
vec3_t dest;
trace_t trace;
vec3_t dest;
trace_t trace;
// bmodels need special checking because their origin is 0,0,0
/* bmodels need special checking because their origin is 0,0,0 */
if (targ->movetype == MOVETYPE_PUSH)
{
VectorAdd (targ->absmin, targ->absmax, dest);
VectorScale (dest, 0.5, dest);
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
VectorAdd(targ->absmin, targ->absmax, dest);
VectorScale(dest, 0.5, dest);
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
{
return true;
}
if (trace.ent == targ)
{
return true;
}
return false;
}
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, targ->s.origin, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
return true;
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
targ->s.origin, inflictor, MASK_SOLID);
VectorCopy (targ->s.origin, dest);
if (trace.fraction == 1.0)
{
return true;
}
VectorCopy(targ->s.origin, dest);
dest[0] += 15.0;
dest[1] += 15.0;
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
return true;
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
dest, inflictor, MASK_SOLID);
VectorCopy (targ->s.origin, dest);
if (trace.fraction == 1.0)
{
return true;
}
VectorCopy(targ->s.origin, dest);
dest[0] += 15.0;
dest[1] -= 15.0;
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
return true;
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
dest, inflictor, MASK_SOLID);
VectorCopy (targ->s.origin, dest);
if (trace.fraction == 1.0)
{
return true;
}
VectorCopy(targ->s.origin, dest);
dest[0] -= 15.0;
dest[1] += 15.0;
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
return true;
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
dest, inflictor, MASK_SOLID);
VectorCopy (targ->s.origin, dest);
if (trace.fraction == 1.0)
{
return true;
}
VectorCopy(targ->s.origin, dest);
dest[0] -= 15.0;
dest[1] -= 15.0;
trace = gi.trace (inflictor->s.origin, vec3_origin, vec3_origin, dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
return true;
trace = gi.trace(inflictor->s.origin, vec3_origin, vec3_origin,
dest, inflictor, MASK_SOLID);
if (trace.fraction == 1.0)
{
return true;
}
return false;
}
/*
============
Killed
============
*/
void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
void
Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
int damage, vec3_t point)
{
if (targ->health < -999)
{
targ->health = -999;
}
targ->enemy = attacker;
@ -101,93 +129,101 @@ void Killed (edict_t *targ, edict_t *inflictor, edict_t *attacker, int damage, v
if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY))
{
level.killed_monsters++;
if (coop->value && attacker->client)
{
attacker->client->resp.score++;
// medics won't heal monsters that they kill themselves
}
/* medics won't heal monsters that they kill themselves */
if (strcmp(attacker->classname, "monster_medic") == 0)
{
targ->owner = attacker;
}
}
}
if (targ->movetype == MOVETYPE_PUSH || targ->movetype == MOVETYPE_STOP || targ->movetype == MOVETYPE_NONE)
{ // doors, triggers, etc
targ->die (targ, inflictor, attacker, damage, point);
if ((targ->movetype == MOVETYPE_PUSH) ||
(targ->movetype == MOVETYPE_STOP) || (targ->movetype == MOVETYPE_NONE))
{
/* doors, triggers, etc */
targ->die(targ, inflictor, attacker, damage, point);
return;
}
if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD))
{
targ->touch = NULL;
monster_death_use (targ);
monster_death_use(targ);
}
targ->die (targ, inflictor, attacker, damage, point);
targ->die(targ, inflictor, attacker, damage, point);
}
/*
================
SpawnDamage
================
*/
void SpawnDamage (int type, vec3_t origin, vec3_t normal, int damage)
void
SpawnDamage(int type, vec3_t origin, vec3_t normal, int damage)
{
if (damage > 255)
{
damage = 255;
gi.WriteByte (svc_temp_entity);
gi.WriteByte (type);
gi.WritePosition (origin);
gi.WriteDir (normal);
gi.multicast (origin, MULTICAST_PVS);
}
gi.WriteByte(svc_temp_entity);
gi.WriteByte(type);
gi.WritePosition(origin);
gi.WriteDir(normal);
gi.multicast(origin, MULTICAST_PVS);
}
/*
============
T_Damage
targ entity that is being damaged
inflictor entity that is causing the damage
attacker entity that caused the inflictor to damage targ
example: targ=monster, inflictor=rocket, attacker=player
dir direction of the attack
point point at which the damage is being inflicted
normal normal vector from that point
damage amount of damage being inflicted
knockback force to be applied against targ as a result of the damage
dflags these flags are used to control how T_Damage works
DAMAGE_RADIUS damage was indirect (from a nearby explosion)
DAMAGE_NO_ARMOR armor does not protect from this damage
DAMAGE_ENERGY damage is from an energy based weapon
DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles
DAMAGE_BULLET damage is from a bullet (used for ricochets)
DAMAGE_NO_PROTECTION kills godmode, armor, everything
============
*/
static int CheckPowerArmor (edict_t *ent, vec3_t point, vec3_t normal, int damage, int dflags)
* targ entity that is being damaged
* inflictor entity that is causing the damage
* attacker entity that caused the inflictor to damage targ
*
* dir direction of the attack
* point point at which the damage is being inflicted
* normal normal vector from that point
* damage amount of damage being inflicted
* knockback force to be applied against targ as a result of the damage
*
* dflags these flags are used to control how T_Damage works
* DAMAGE_RADIUS damage was indirect (from a nearby explosion)
* DAMAGE_NO_ARMOR armor does not protect from this damage
* DAMAGE_ENERGY damage is from an energy based weapon
* DAMAGE_NO_KNOCKBACK do not affect velocity, just view angles
* DAMAGE_BULLET damage is from a bullet (used for ricochets)
* DAMAGE_NO_PROTECTION kills godmode, armor, everything
* ============
*/
static int
CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal,
int damage, int dflags)
{
gclient_t *client;
int save;
int power_armor_type;
int index = 0;
int damagePerCell;
int pa_te_type;
int power = 0;
int power_used;
gclient_t *client;
int save;
int power_armor_type;
int index = 0;
int damagePerCell;
int pa_te_type;
int power = 0;
int power_used;
if (!damage)
{
return 0;
}
client = ent->client;
if (dflags & DAMAGE_NO_ARMOR)
{
return 0;
}
if (client)
{
power_armor_type = PowerArmorType (ent);
power_armor_type = PowerArmorType(ent);
if (power_armor_type != POWER_ARMOR_NONE)
{
index = ITEM_INDEX(FindItem("Cells"));
@ -201,26 +237,36 @@ static int CheckPowerArmor (edict_t *ent, vec3_t point, vec3_t normal, int damag
index = 0;
}
else
{
return 0;
}
if (power_armor_type == POWER_ARMOR_NONE)
{
return 0;
}
if (!power)
{
return 0;
}
if (power_armor_type == POWER_ARMOR_SCREEN)
{
vec3_t vec;
float dot;
vec3_t forward;
vec3_t vec;
float dot;
vec3_t forward;
/* only works if damage point is in front */
AngleVectors(ent->s.angles, forward, NULL, NULL);
VectorSubtract(point, ent->s.origin, vec);
VectorNormalize(vec);
dot = DotProduct(vec, forward);
// only works if damage point is in front
AngleVectors (ent->s.angles, forward, NULL, NULL);
VectorSubtract (point, ent->s.origin, vec);
VectorNormalize (vec);
dot = DotProduct (vec, forward);
if (dot <= 0.3)
{
return 0;
}
damagePerCell = 1;
pa_te_type = TE_SCREEN_SPARKS;
@ -228,92 +274,132 @@ static int CheckPowerArmor (edict_t *ent, vec3_t point, vec3_t normal, int damag
}
else
{
damagePerCell = 1; // power armor is weaker in CTF
damagePerCell = 1; /* power armor is weaker in CTF */
pa_te_type = TE_SHIELD_SPARKS;
damage = (2 * damage) / 3;
}
save = power * damagePerCell;
if (!save)
return 0;
if (save > damage)
save = damage;
SpawnDamage (pa_te_type, point, normal, save);
if (!save)
{
return 0;
}
if (save > damage)
{
save = damage;
}
SpawnDamage(pa_te_type, point, normal, save);
ent->powerarmor_time = level.time + 0.2;
power_used = save / damagePerCell;
if (client)
{
client->pers.inventory[index] -= power_used;
}
else
{
ent->monsterinfo.power_armor_power -= power_used;
}
return save;
}
static int CheckArmor (edict_t *ent, vec3_t point, vec3_t normal, int damage, int te_sparks, int dflags)
static int
CheckArmor(edict_t *ent, vec3_t point, vec3_t normal,
int damage, int te_sparks, int dflags)
{
gclient_t *client;
int save;
int index;
gitem_t *armor;
gclient_t *client;
int save;
int index;
gitem_t *armor;
if (!damage)
{
return 0;
}
client = ent->client;
if (!client)
{
return 0;
}
if (dflags & DAMAGE_NO_ARMOR)
{
return 0;
}
index = ArmorIndex(ent);
index = ArmorIndex (ent);
if (!index)
{
return 0;
}
armor = GetItemByIndex (index);
armor = GetItemByIndex(index);
if (dflags & DAMAGE_ENERGY)
save = ceil(((gitem_armor_t *)armor->info)->energy_protection*damage);
{
save = ceil(((gitem_armor_t *)armor->info)->energy_protection * damage);
}
else
save = ceil(((gitem_armor_t *)armor->info)->normal_protection*damage);
{
save = ceil(((gitem_armor_t *)armor->info)->normal_protection * damage);
}
if (save >= client->pers.inventory[index])
{
save = client->pers.inventory[index];
}
if (!save)
{
return 0;
}
client->pers.inventory[index] -= save;
SpawnDamage (te_sparks, point, normal, save);
SpawnDamage(te_sparks, point, normal, save);
return save;
}
void M_ReactToDamage (edict_t *targ, edict_t *attacker)
void
M_ReactToDamage(edict_t *targ, edict_t *attacker)
{
if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER))
{
return;
}
if (attacker == targ || attacker == targ->enemy)
if ((attacker == targ) || (attacker == targ->enemy))
{
return;
}
// if we are a good guy monster and our attacker is a player
// or another good guy, do not get mad at them
/* if we are a good guy monster and our
attacker is a player or another good
guy, do not get mad at them */
if (targ->monsterinfo.aiflags & AI_GOOD_GUY)
{
if (attacker->client || (attacker->monsterinfo.aiflags & AI_GOOD_GUY))
{
return;
}
}
// we now know that we are not both good guys
// if attacker is a client, get mad at them because he's good and we're not
/* if attacker is a client, get mad at
them because he's good and we're not */
if (attacker->client)
{
// this can only happen in coop (both new and old enemies are clients)
// only switch if can't see the current enemy
/* this can only happen in coop (both
new and old enemies are clients)
only switch if can't see the
current enemy */
if (targ->enemy && targ->enemy->client)
{
if (visible(targ, targ->enemy))
@ -321,273 +407,358 @@ void M_ReactToDamage (edict_t *targ, edict_t *attacker)
targ->oldenemy = attacker;
return;
}
targ->oldenemy = targ->enemy;
}
targ->enemy = attacker;
if (!(targ->monsterinfo.aiflags & AI_DUCKED))
FoundTarget (targ);
{
FoundTarget(targ);
}
return;
}
// it's the same base (walk/swim/fly) type and a different classname and it's not a tank
// (they spray too much), get mad at them
if (((targ->flags & (FL_FLY|FL_SWIM)) == (attacker->flags & (FL_FLY|FL_SWIM))) &&
(strcmp (targ->classname, attacker->classname) != 0) &&
(strcmp(attacker->classname, "monster_tank") != 0) &&
(strcmp(attacker->classname, "monster_supertank") != 0) &&
(strcmp(attacker->classname, "monster_makron") != 0) &&
(strcmp(attacker->classname, "monster_jorg") != 0) )
/* it's the same base (walk/swim/fly) type
and a different classname and it's not a tank
(they spray too much), get mad at them */
if (((targ->flags & (FL_FLY | FL_SWIM)) ==
(attacker->flags & (FL_FLY | FL_SWIM))) &&
(strcmp(targ->classname, attacker->classname) != 0) &&
(strcmp(attacker->classname, "monster_tank") != 0) &&
(strcmp(attacker->classname, "monster_supertank") != 0) &&
(strcmp(attacker->classname, "monster_makron") != 0) &&
(strcmp(attacker->classname, "monster_jorg") != 0))
{
if (targ->enemy)
{
if (targ->enemy->client)
{
targ->oldenemy = targ->enemy;
}
}
targ->enemy = attacker;
if (!(targ->monsterinfo.aiflags & AI_DUCKED))
FoundTarget (targ);
{
FoundTarget(targ);
}
}
else
// otherwise get mad at whoever they are mad at (help our buddy)
else /* otherwise get mad at whoever they are mad at (help our buddy) */
{
if (targ->enemy)
{
if (targ->enemy->client)
{
targ->oldenemy = targ->enemy;
}
}
targ->enemy = attacker->enemy;
FoundTarget (targ);
FoundTarget(targ);
}
}
qboolean CheckTeamDamage (edict_t *targ, edict_t *attacker)
qboolean
CheckTeamDamage(edict_t *targ, edict_t *attacker)
{
//ZOID
if (ctf->value && targ->client && attacker->client)
if (targ->client->resp.ctf_team == attacker->client->resp.ctf_team &&
targ != attacker)
{
if ((targ->client->resp.ctf_team == attacker->client->resp.ctf_team) &&
(targ != attacker))
{
return true;
//ZOID
}
}
//FIXME make the next line real and uncomment this block
return false;
}
void T_Damage (edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir, vec3_t point, vec3_t normal, int damage, int knockback, int dflags, int mod)
void
T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
vec3_t dir, vec3_t point, vec3_t normal, int damage,
int knockback, int dflags, int mod)
{
gclient_t *client;
int take;
int save;
int asave;
int psave;
int te_sparks;
gclient_t *client;
int take;
int save;
int asave;
int psave;
int te_sparks;
if (!targ->takedamage)
return;
// 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))
return;
}
/* 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;
}
}
}
meansOfDeath = mod;
// easy mode takes half damage
if (skill->value == 0 && deathmatch->value == 0 && targ->client)
/* easy mode takes half damage */
if ((skill->value == 0) && (deathmatch->value == 0) && targ->client)
{
damage *= 0.5;
if (!damage)
{
damage = 1;
}
}
client = targ->client;
if (dflags & DAMAGE_BULLET)
{
te_sparks = TE_BULLET_SPARKS;
}
else
{
te_sparks = TE_SPARKS;
}
VectorNormalize(dir);
// bonus damage for suprising a monster
if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) && (attacker->client) && (!targ->enemy) && (targ->health > 0))
/* bonus damage for suprising a monster */
if (!(dflags & DAMAGE_RADIUS) && (targ->svflags & SVF_MONSTER) &&
(attacker->client) && (!targ->enemy) && (targ->health > 0))
{
damage *= 2;
}
//ZOID
//strength tech
/* strength tech */
damage = CTFApplyStrength(attacker, damage);
//ZOID
if (targ->flags & FL_NO_KNOCKBACK)
{
knockback = 0;
}
// figure momentum add
/* figure momentum add */
if (!(dflags & DAMAGE_NO_KNOCKBACK))
{
if ((knockback) && (targ->movetype != MOVETYPE_NONE) && (targ->movetype != MOVETYPE_BOUNCE) && (targ->movetype != MOVETYPE_PUSH) && (targ->movetype != MOVETYPE_STOP))
if ((knockback) && (targ->movetype != MOVETYPE_NONE) &&
(targ->movetype != MOVETYPE_BOUNCE) &&
(targ->movetype != MOVETYPE_PUSH) &&
(targ->movetype != MOVETYPE_STOP))
{
vec3_t kvel;
float mass;
vec3_t kvel;
float mass;
if (targ->mass < 50)
{
mass = 50;
}
else
{
mass = targ->mass;
}
if (targ->client && attacker == targ)
VectorScale (dir, 1600.0 * (float)knockback / mass, kvel); // the rocket jump hack...
if (targ->client && (attacker == targ))
{
VectorScale(dir, 1600.0 * (float)knockback / mass, kvel); /* the rocket jump hack... */
}
else
VectorScale (dir, 500.0 * (float)knockback / mass, kvel);
{
VectorScale(dir, 500.0 * (float)knockback / mass, kvel);
}
VectorAdd (targ->velocity, kvel, targ->velocity);
VectorAdd(targ->velocity, kvel, targ->velocity);
}
}
take = damage;
save = 0;
// check for godmode
if ( (targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION) )
/* check for godmode */
if ((targ->flags & FL_GODMODE) && !(dflags & DAMAGE_NO_PROTECTION))
{
take = 0;
save = damage;
SpawnDamage (te_sparks, point, normal, save);
SpawnDamage(te_sparks, point, normal, save);
}
// check for invincibility
if ((client && client->invincible_framenum > level.framenum ) && !(dflags & DAMAGE_NO_PROTECTION))
/* check for invincibility */
if ((client &&
(client->invincible_framenum > level.framenum)) &&
!(dflags & DAMAGE_NO_PROTECTION))
{
if (targ->pain_debounce_time < level.time)
{
gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0);
targ->pain_debounce_time = level.time + 2;
}
take = 0;
save = damage;
}
//ZOID
//team armor protect
/* team armor protect */
if (ctf->value && targ->client && attacker->client &&
targ->client->resp.ctf_team == attacker->client->resp.ctf_team &&
targ != attacker && ((int)dmflags->value & DF_ARMOR_PROTECT)) {
(targ->client->resp.ctf_team == attacker->client->resp.ctf_team) &&
(targ != attacker) && ((int)dmflags->value & DF_ARMOR_PROTECT))
{
psave = asave = 0;
} else {
//ZOID
psave = CheckPowerArmor (targ, point, normal, take, dflags);
}
else
{
psave = CheckPowerArmor(targ, point, normal, take, dflags);
take -= psave;
asave = CheckArmor (targ, point, normal, take, te_sparks, dflags);
asave = CheckArmor(targ, point, normal, take, te_sparks, dflags);
take -= asave;
}
//treat cheat/powerup savings the same as armor
/* treat cheat/powerup savings the same as armor */
asave += save;
//ZOID
//resistance tech
/* resistance tech */
take = CTFApplyResistance(targ, take);
//ZOID
// team damage avoidance
if (!(dflags & DAMAGE_NO_PROTECTION) && CheckTeamDamage (targ, attacker))
/* team damage avoidance */
if (!(dflags & DAMAGE_NO_PROTECTION) && CheckTeamDamage(targ, attacker))
{
return;
}
//ZOID
CTFCheckHurtCarrier(targ, attacker);
//ZOID
// do the damage
/* do the damage */
if (take)
{
if ((targ->svflags & SVF_MONSTER) || (client))
SpawnDamage (TE_BLOOD, point, normal, take);
{
SpawnDamage(TE_BLOOD, point, normal, take);
}
else
SpawnDamage (te_sparks, point, normal, take);
{
SpawnDamage(te_sparks, point, normal, take);
}
if (!CTFMatchSetup())
{
targ->health = targ->health - take;
}
if (targ->health <= 0)
{
if ((targ->svflags & SVF_MONSTER) || (client))
{
targ->flags |= FL_NO_KNOCKBACK;
Killed (targ, inflictor, attacker, take, point);
}
Killed(targ, inflictor, attacker, take, point);
return;
}
}
if (targ->svflags & SVF_MONSTER)
{
M_ReactToDamage (targ, attacker);
M_ReactToDamage(targ, attacker);
if (!(targ->monsterinfo.aiflags & AI_DUCKED) && (take))
{
targ->pain (targ, attacker, knockback, take);
// nightmare mode monsters don't go into pain frames often
targ->pain(targ, attacker, knockback, take);
/* nightmare mode monsters don't go into pain frames often */
if (skill->value == 3)
{
targ->pain_debounce_time = level.time + 5;
}
}
}
else if (client)
{
if (!(targ->flags & FL_GODMODE) && (take) && !CTFMatchSetup())
targ->pain (targ, attacker, knockback, take);
{
targ->pain(targ, attacker, knockback, take);
}
}
else if (take)
{
if (targ->pain)
targ->pain (targ, attacker, knockback, take);
{
targ->pain(targ, attacker, knockback, take);
}
}
// add to the damage inflicted on a player this frame
// the total will be turned into screen blends and view angle kicks
// at the end of the frame
/* add to the damage inflicted on a
player this frame the total will
be turned into screen blends and
view angle kicks at the end of
the frame */
if (client)
{
client->damage_parmor += psave;
client->damage_armor += asave;
client->damage_blood += take;
client->damage_knockback += knockback;
VectorCopy (point, client->damage_from);
VectorCopy(point, client->damage_from);
}
}
/*
============
T_RadiusDamage
============
*/
void T_RadiusDamage (edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, int mod)
void
T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage,
edict_t *ignore, float radius, int mod)
{
float points;
edict_t *ent = NULL;
vec3_t v;
vec3_t dir;
float points;
edict_t *ent = NULL;
vec3_t v;
vec3_t dir;
while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL)
{
if (ent == ignore)
{
continue;
if (!ent->takedamage)
continue;
}
if (!ent->takedamage)
{
continue;
}
VectorAdd(ent->mins, ent->maxs, v);
VectorMA(ent->s.origin, 0.5, v, v);
VectorSubtract(inflictor->s.origin, v, v);
points = damage - 0.5 * VectorLength(v);
VectorAdd (ent->mins, ent->maxs, v);
VectorMA (ent->s.origin, 0.5, v, v);
VectorSubtract (inflictor->s.origin, v, v);
points = damage - 0.5 * VectorLength (v);
if (ent == attacker)
{
points = points * 0.5;
}
if (points > 0)
{
if (CanDamage (ent, inflictor))
if (CanDamage(ent, inflictor))
{
VectorSubtract (ent->s.origin, inflictor->s.origin, dir);
T_Damage (ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int)points, (int)points, DAMAGE_RADIUS, mod);
VectorSubtract(ent->s.origin, inflictor->s.origin, dir);
T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin,
vec3_origin, (int)points, (int)points, DAMAGE_RADIUS,
mod);
}
}
}