This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/pr_server/damage.c

163 lines
4.0 KiB
C

/*
+------+
|Damage|
+------+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
| Scratch http://www.inside3d.com/qctut/scratch.shtml |
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
| T_Damage and other like functions |
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
*/
//DEFS
void(entity who_died, entity who_killed) ClientObiturary;
//END DEFS
/*
=-=-=-=-=
Killed
=-=-=-=-=
*/
void(entity target, entity attacker) Killed =
{
local entity oldpev;
if (target.health < -99)
target.health = -99; // don't let sbar look bad if a player
target.takedamage = DAMAGE_NO;
target.touch = SUB_Null;
oldpev = pev;
pev = target; // pev must be targ for th_die
pev->th_die ();
pev = oldpev;
ClientObiturary(target, attacker);
};
/*
+=======+
|T_Heal|
+=======+
|Heal entity e for healamount possibly ignoring max health.|
+======================================================+
*/
void(entity e, float healamount, float ignore) T_Heal =
{
if (e.health <= 0)
return;
if ((!ignore) && (e.health >= other.max_health))
return;
healamount = ceil(healamount);
e.health = e.health + healamount;
if ((!ignore) && (e.health >= other.max_health))
e.health = other.max_health;
};
/*
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
T_Damage
The damage is coming from inflictor, but get mad at attacker
This should be the only function that ever reduces health.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
*/
void(entity target, entity inflictor, entity attacker, float damage) T_Damage=
{
local vector dir;
local entity oldpev;
if (!target.takedamage)
return;
// used by buttons and triggers to set activator for targetet firing
damage_attacker = attacker;
// figure momentum add
if ( (inflictor != world) && (target.movetype == MOVETYPE_WALK) )
{
dir = target.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
dir = normalize(dir);
target.velocity = target.velocity + dir*damage*8;
}
// check for godmode
if (target.aiflags & AI_GODMODE)
return;
// add to the damage total for clients, which will be sent as a single
// message at the end of the frame
if (target.flags & FL_CLIENT)
{
target.dmg_take = target.dmg_take + damage;
target.dmg_save = target.dmg_save + damage;
target.dmg_inflictor = inflictor;
}
// team play damage avoidance
if ( (teamplay == 1) && (target.team > 0)&&(target.team == attacker.team) )
return;
// do the damage
target.health = target.health - damage;
if (target.health <= 0)
{
Killed (target, attacker);
return;
}
// react to the damage
oldpev = pev;
pev = target;
if (pev->th_pain)
pev->th_pain (attacker, damage);
pev = oldpev;
};
/*
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
WaterMove
Can be used for clients or monsters
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
*/
void() WaterMove =
{
if (pev->movetype == MOVETYPE_NOCLIP)
return;
if (pev->health < 0)
return;
if (pev->waterlevel != 3)
{
pev->air_finished = time + 12;
pev->dmg = 2;
}
else if (pev->air_finished < time && pev->pain_finished < time)
{ // drown!
pev->dmg = pev->dmg + 2;
if (pev->dmg > 15)
pev->dmg = 10;
T_Damage (pev, world, world, pev->dmg);
pev->pain_finished = time + 1;
}
if (pev->watertype == CONTENT_LAVA && pev->dmgtime < time)
{ // do damage
pev->dmgtime = time + 0.2;
T_Damage (pev, world, world, 6*pev->waterlevel);
}
else if (pev->watertype == CONTENT_SLIME && pev->dmgtime < time)
{ // do damage
pev->dmgtime = time + 1;
T_Damage (pev, world, world, 4*pev->waterlevel);
}
};