mirror of
https://github.com/id-Software/quake2-rerelease-dll.git
synced 2025-02-22 11:21:22 +00:00
146 lines
No EOL
3.4 KiB
C++
146 lines
No EOL
3.4 KiB
C++
// Copyright (c) ZeniMax Media Inc.
|
|
// Licensed under the GNU General Public License 2.0.
|
|
// g_combat.c
|
|
|
|
#include "../g_local.h"
|
|
|
|
void M_SetEffects(edict_t *self);
|
|
|
|
/*
|
|
ROGUE
|
|
clean up heal targets for medic
|
|
*/
|
|
void cleanupHealTarget(edict_t *ent)
|
|
{
|
|
ent->monsterinfo.healer = nullptr;
|
|
ent->takedamage = true;
|
|
ent->monsterinfo.aiflags &= ~AI_RESURRECTING;
|
|
M_SetEffects(ent);
|
|
}
|
|
|
|
// **********************
|
|
// ROGUE
|
|
|
|
/*
|
|
============
|
|
T_RadiusNukeDamage
|
|
|
|
Like T_RadiusDamage, but ignores walls (skips CanDamage check, among others)
|
|
// up to KILLZONE radius, do 10,000 points
|
|
// after that, do damage linearly out to KILLZONE2 radius
|
|
============
|
|
*/
|
|
|
|
void T_RadiusNukeDamage(edict_t *inflictor, edict_t *attacker, float damage, edict_t *ignore, float radius, mod_t mod)
|
|
{
|
|
float points;
|
|
edict_t *ent = nullptr;
|
|
vec3_t v;
|
|
vec3_t dir;
|
|
float len;
|
|
float killzone, killzone2;
|
|
trace_t tr;
|
|
float dist;
|
|
|
|
killzone = radius;
|
|
killzone2 = radius * 2.0f;
|
|
|
|
while ((ent = findradius(ent, inflictor->s.origin, killzone2)) != nullptr)
|
|
{
|
|
// ignore nobody
|
|
if (ent == ignore)
|
|
continue;
|
|
if (!ent->takedamage)
|
|
continue;
|
|
if (!ent->inuse)
|
|
continue;
|
|
if (!(ent->client || (ent->svflags & SVF_MONSTER) || (ent->flags & FL_DAMAGEABLE)))
|
|
continue;
|
|
|
|
v = ent->mins + ent->maxs;
|
|
v = ent->s.origin + (v * 0.5f);
|
|
v = inflictor->s.origin - v;
|
|
len = v.length();
|
|
if (len <= killzone)
|
|
{
|
|
if (ent->client)
|
|
ent->flags |= FL_NOGIB;
|
|
points = 10000;
|
|
}
|
|
else if (len <= killzone2)
|
|
points = (damage / killzone) * (killzone2 - len);
|
|
else
|
|
points = 0;
|
|
|
|
if (points > 0)
|
|
{
|
|
if (ent->client)
|
|
ent->client->nuke_time = level.time + 2_sec;
|
|
dir = ent->s.origin - inflictor->s.origin;
|
|
T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int) points, (int) points, DAMAGE_RADIUS, mod);
|
|
}
|
|
}
|
|
ent = g_edicts + 1; // skip the worldspawn
|
|
// cycle through players
|
|
while (ent)
|
|
{
|
|
if ((ent->client) && (ent->client->nuke_time != level.time + 2_sec) && (ent->inuse))
|
|
{
|
|
tr = gi.traceline(inflictor->s.origin, ent->s.origin, inflictor, MASK_SOLID);
|
|
if (tr.fraction == 1.0f)
|
|
ent->client->nuke_time = level.time + 2_sec;
|
|
else
|
|
{
|
|
dist = realrange(ent, inflictor);
|
|
if (dist < 2048)
|
|
ent->client->nuke_time = max(ent->client->nuke_time, level.time + 1.5_sec);
|
|
else
|
|
ent->client->nuke_time = max(ent->client->nuke_time, level.time + 1_sec);
|
|
}
|
|
ent++;
|
|
}
|
|
else
|
|
ent = nullptr;
|
|
}
|
|
}
|
|
|
|
/*
|
|
============
|
|
T_RadiusClassDamage
|
|
|
|
Like T_RadiusDamage, but ignores anything with classname=ignoreClass
|
|
============
|
|
*/
|
|
void T_RadiusClassDamage(edict_t *inflictor, edict_t *attacker, float damage, char *ignoreClass, float radius, mod_t mod)
|
|
{
|
|
float points;
|
|
edict_t *ent = nullptr;
|
|
vec3_t v;
|
|
vec3_t dir;
|
|
|
|
while ((ent = findradius(ent, inflictor->s.origin, radius)) != nullptr)
|
|
{
|
|
if (ent->classname && !strcmp(ent->classname, ignoreClass))
|
|
continue;
|
|
if (!ent->takedamage)
|
|
continue;
|
|
|
|
v = ent->mins + ent->maxs;
|
|
v = ent->s.origin + (v * 0.5f);
|
|
v = inflictor->s.origin - v;
|
|
points = damage - 0.5f * v.length();
|
|
if (ent == attacker)
|
|
points = points * 0.5f;
|
|
if (points > 0)
|
|
{
|
|
if (CanDamage(ent, inflictor))
|
|
{
|
|
dir = ent->s.origin - inflictor->s.origin;
|
|
T_Damage(ent, inflictor, attacker, dir, inflictor->s.origin, vec3_origin, (int) points, (int) points, DAMAGE_RADIUS, mod);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ROGUE
|
|
// ********************
|