quake2-rerelease-dll/rerelease/rogue/g_rogue_combat.cpp
2023-08-07 14:48:30 -05:00

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
// ********************