mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
game: sync ctf g_cmds
This commit is contained in:
parent
2b69f3774f
commit
802a874f64
6 changed files with 520 additions and 1518 deletions
2
Makefile
2
Makefile
|
@ -1482,7 +1482,7 @@ CTF_OBJS_ = \
|
||||||
src/common/shared/shared.o \
|
src/common/shared/shared.o \
|
||||||
src/ctf/g_ai.o \
|
src/ctf/g_ai.o \
|
||||||
src/game/g_chase.o \
|
src/game/g_chase.o \
|
||||||
src/ctf/g_cmds.o \
|
src/game/g_cmds.o \
|
||||||
src/ctf/g_combat.o \
|
src/ctf/g_combat.o \
|
||||||
src/game/g_ctf.o \
|
src/game/g_ctf.o \
|
||||||
src/game/g_func.o \
|
src/game/g_func.o \
|
||||||
|
|
1460
src/ctf/g_cmds.c
1460
src/ctf/g_cmds.c
File diff suppressed because it is too large
Load diff
|
@ -142,16 +142,82 @@ void
|
||||||
Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
int damage, vec3_t point)
|
int damage, vec3_t point)
|
||||||
{
|
{
|
||||||
|
if (!targ || !inflictor || !attacker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (targ->health < -999)
|
if (targ->health < -999)
|
||||||
{
|
{
|
||||||
targ->health = -999;
|
targ->health = -999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset AI flag for being ducked. This fixes a corner case
|
||||||
|
were the monster is ressurected by a medic and get's stuck
|
||||||
|
in the next frame for mmove_t not matching the AI state. */
|
||||||
|
if (targ->monsterinfo.aiflags & AI_DUCKED)
|
||||||
|
{
|
||||||
|
targ->monsterinfo.aiflags &= ~AI_DUCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targ->monsterinfo.aiflags & AI_MEDIC)
|
||||||
|
{
|
||||||
|
if (targ->enemy)
|
||||||
|
{
|
||||||
|
cleanupHealTarget(targ->enemy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean up self */
|
||||||
|
targ->monsterinfo.aiflags &= ~AI_MEDIC;
|
||||||
targ->enemy = attacker;
|
targ->enemy = attacker;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targ->enemy = attacker;
|
||||||
|
}
|
||||||
|
|
||||||
if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD))
|
if ((targ->svflags & SVF_MONSTER) && (targ->deadflag != DEAD_DEAD))
|
||||||
{
|
{
|
||||||
if (!(targ->monsterinfo.aiflags & AI_GOOD_GUY))
|
/* free up slot for spawned monster if it's spawned */
|
||||||
|
if (targ->monsterinfo.aiflags & AI_SPAWNED_CARRIER)
|
||||||
|
{
|
||||||
|
if (targ->monsterinfo.commander &&
|
||||||
|
targ->monsterinfo.commander->inuse &&
|
||||||
|
!strcmp(targ->monsterinfo.commander->classname, "monster_carrier"))
|
||||||
|
{
|
||||||
|
targ->monsterinfo.commander->monsterinfo.monster_slots++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targ->monsterinfo.aiflags & AI_SPAWNED_MEDIC_C)
|
||||||
|
{
|
||||||
|
if (targ->monsterinfo.commander)
|
||||||
|
{
|
||||||
|
if (targ->monsterinfo.commander->inuse &&
|
||||||
|
!strcmp(targ->monsterinfo.commander->classname, "monster_medic_commander"))
|
||||||
|
{
|
||||||
|
targ->monsterinfo.commander->monsterinfo.monster_slots++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targ->monsterinfo.aiflags & AI_SPAWNED_WIDOW)
|
||||||
|
{
|
||||||
|
/* need to check this because we can
|
||||||
|
have variable numbers of coop players */
|
||||||
|
if (targ->monsterinfo.commander &&
|
||||||
|
targ->monsterinfo.commander->inuse &&
|
||||||
|
!strncmp(targ->monsterinfo.commander->classname, "monster_widow", 13))
|
||||||
|
{
|
||||||
|
if (targ->monsterinfo.commander->monsterinfo.monster_used > 0)
|
||||||
|
{
|
||||||
|
targ->monsterinfo.commander->monsterinfo.monster_used--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!(targ->monsterinfo.aiflags & AI_GOOD_GUY)) &&
|
||||||
|
(!(targ->monsterinfo.aiflags & AI_DO_NOT_COUNT)))
|
||||||
{
|
{
|
||||||
level.killed_monsters++;
|
level.killed_monsters++;
|
||||||
|
|
||||||
|
@ -161,7 +227,7 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
if (attacker->classname && strcmp(attacker->classname, "monster_medic") == 0)
|
||||||
{
|
{
|
||||||
targ->owner = attacker;
|
targ->owner = attacker;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +235,8 @@ Killed(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((targ->movetype == MOVETYPE_PUSH) ||
|
if ((targ->movetype == MOVETYPE_PUSH) ||
|
||||||
(targ->movetype == MOVETYPE_STOP) || (targ->movetype == MOVETYPE_NONE))
|
(targ->movetype == MOVETYPE_STOP) ||
|
||||||
|
(targ->movetype == MOVETYPE_NONE))
|
||||||
{
|
{
|
||||||
/* doors, triggers, etc */
|
/* doors, triggers, etc */
|
||||||
targ->die(targ, inflictor, attacker, damage, point);
|
targ->die(targ, inflictor, attacker, damage, point);
|
||||||
|
@ -301,7 +368,15 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
damagePerCell = 1; /* power armor is weaker in CTF */
|
if (ctf->value)
|
||||||
|
{
|
||||||
|
/* power armor is weaker in CTF */
|
||||||
|
damagePerCell = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
damagePerCell = 2;
|
||||||
|
}
|
||||||
pa_te_type = TE_SHIELD_SPARKS;
|
pa_te_type = TE_SHIELD_SPARKS;
|
||||||
damage = (2 * damage) / 3;
|
damage = (2 * damage) / 3;
|
||||||
}
|
}
|
||||||
|
@ -418,19 +493,47 @@ CheckArmor(edict_t *ent, vec3_t point, vec3_t normal, int damage,
|
||||||
void
|
void
|
||||||
M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
||||||
{
|
{
|
||||||
|
qboolean new_tesla;
|
||||||
|
|
||||||
|
if (!targ || !attacker || !inflictor)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targ->health <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER))
|
if (!(attacker->client) && !(attacker->svflags & SVF_MONSTER))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* logic for tesla - if you are hit by a tesla,
|
||||||
|
and can't see who you should be mad at (attacker)
|
||||||
|
attack the tesla also, target the tesla if it's
|
||||||
|
a "new" tesla */
|
||||||
|
if (!strcmp(inflictor->classname, "tesla"))
|
||||||
|
{
|
||||||
|
new_tesla = MarkTeslaArea(targ, inflictor);
|
||||||
|
|
||||||
|
if (new_tesla || !targ->enemy)
|
||||||
|
{
|
||||||
|
TargetTesla(targ, inflictor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((attacker == targ) || (attacker == targ->enemy))
|
if ((attacker == targ) || (attacker == targ->enemy))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we are a good guy monster and our
|
/* if we are a good guy monster and
|
||||||
attacker is a player or another good
|
our attacker is a player or another
|
||||||
guy, do not get mad at them */
|
good guy, do not get mad at them */
|
||||||
if (targ->monsterinfo.aiflags & AI_GOOD_GUY)
|
if (targ->monsterinfo.aiflags & AI_GOOD_GUY)
|
||||||
{
|
{
|
||||||
if (attacker->client || (attacker->monsterinfo.aiflags & AI_GOOD_GUY))
|
if (attacker->client || (attacker->monsterinfo.aiflags & AI_GOOD_GUY))
|
||||||
|
@ -439,14 +542,55 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if we're currently mad at something
|
||||||
|
a target_anger made us mad at, ignore
|
||||||
|
damage */
|
||||||
|
if (targ->enemy && targ->monsterinfo.aiflags & AI_TARGET_ANGER)
|
||||||
|
{
|
||||||
|
float percentHealth;
|
||||||
|
|
||||||
|
/* make sure whatever we were pissed at is still around. */
|
||||||
|
if (targ->enemy->inuse)
|
||||||
|
{
|
||||||
|
percentHealth = (float)(targ->health) / (float)(targ->max_health);
|
||||||
|
|
||||||
|
if (percentHealth > 0.33)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the target anger flag */
|
||||||
|
targ->monsterinfo.aiflags &= ~AI_TARGET_ANGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we're healing someone, do like above and try to stay with them */
|
||||||
|
if ((targ->enemy) && (targ->monsterinfo.aiflags & AI_MEDIC))
|
||||||
|
{
|
||||||
|
float percentHealth;
|
||||||
|
|
||||||
|
percentHealth = (float)(targ->health) / (float)(targ->max_health);
|
||||||
|
|
||||||
|
/* ignore it some of the time */
|
||||||
|
if (targ->enemy->inuse && (percentHealth > 0.25))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the medic flag */
|
||||||
|
targ->monsterinfo.aiflags &= ~AI_MEDIC;
|
||||||
|
cleanupHealTarget(targ->enemy);
|
||||||
|
}
|
||||||
|
|
||||||
/* if attacker is a client, get mad at
|
/* if attacker is a client, get mad at
|
||||||
them because he's good and we're not */
|
them because he's good and we're not */
|
||||||
if (attacker->client)
|
if (attacker->client)
|
||||||
{
|
{
|
||||||
/* this can only happen in coop (both
|
targ->monsterinfo.aiflags &= ~AI_SOUND_TARGET;
|
||||||
new and old enemies are clients)
|
|
||||||
only switch if can't see the
|
/* this can only happen in coop (both new and
|
||||||
current enemy */
|
old enemies are clients) only switch if can't
|
||||||
|
see the current enemy */
|
||||||
if (targ->enemy && targ->enemy->client)
|
if (targ->enemy && targ->enemy->client)
|
||||||
{
|
{
|
||||||
if (visible(targ, targ->enemy))
|
if (visible(targ, targ->enemy))
|
||||||
|
@ -468,8 +612,8 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* it's the same base (walk/swim/fly) type
|
/* it's the same base (walk/swim/fly) type and a
|
||||||
and a different classname and it's not a tank
|
different classname and it's not a tank
|
||||||
(they spray too much), get mad at them */
|
(they spray too much), get mad at them */
|
||||||
if (((targ->flags & (FL_FLY | FL_SWIM)) ==
|
if (((targ->flags & (FL_FLY | FL_SWIM)) ==
|
||||||
(attacker->flags & (FL_FLY | FL_SWIM))) &&
|
(attacker->flags & (FL_FLY | FL_SWIM))) &&
|
||||||
|
@ -477,15 +621,14 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
||||||
(strcmp(attacker->classname, "monster_tank") != 0) &&
|
(strcmp(attacker->classname, "monster_tank") != 0) &&
|
||||||
(strcmp(attacker->classname, "monster_supertank") != 0) &&
|
(strcmp(attacker->classname, "monster_supertank") != 0) &&
|
||||||
(strcmp(attacker->classname, "monster_makron") != 0) &&
|
(strcmp(attacker->classname, "monster_makron") != 0) &&
|
||||||
(strcmp(attacker->classname, "monster_jorg") != 0))
|
(strcmp(attacker->classname, "monster_jorg") != 0) &&
|
||||||
|
!(attacker->monsterinfo.aiflags & AI_IGNORE_SHOTS) &&
|
||||||
|
!(targ->monsterinfo.aiflags & AI_IGNORE_SHOTS))
|
||||||
{
|
{
|
||||||
if (targ->enemy)
|
if (targ->enemy && targ->enemy->client)
|
||||||
{
|
|
||||||
if (targ->enemy->client)
|
|
||||||
{
|
{
|
||||||
targ->oldenemy = targ->enemy;
|
targ->oldenemy = targ->enemy;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
targ->enemy = attacker;
|
targ->enemy = attacker;
|
||||||
|
|
||||||
|
@ -494,19 +637,37 @@ M_ReactToDamage(edict_t *targ, edict_t *attacker, edict_t *inflictor)
|
||||||
FoundTarget(targ);
|
FoundTarget(targ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* otherwise get mad at whoever they are mad at (help our buddy) */
|
/* if they *meant* to shoot us, then shoot back */
|
||||||
|
else if (attacker->enemy == targ)
|
||||||
{
|
{
|
||||||
if (targ->enemy)
|
if (targ->enemy && targ->enemy->client)
|
||||||
{
|
|
||||||
if (targ->enemy->client)
|
|
||||||
{
|
{
|
||||||
targ->oldenemy = targ->enemy;
|
targ->oldenemy = targ->enemy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targ->enemy = attacker;
|
||||||
|
|
||||||
|
if (!(targ->monsterinfo.aiflags & AI_DUCKED))
|
||||||
|
{
|
||||||
|
FoundTarget(targ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* otherwise get mad at whoever they are mad
|
||||||
|
at (help our buddy) unless it is us! */
|
||||||
|
else if (attacker->enemy)
|
||||||
|
{
|
||||||
|
if (targ->enemy && targ->enemy->client)
|
||||||
|
{
|
||||||
|
targ->oldenemy = targ->enemy;
|
||||||
}
|
}
|
||||||
|
|
||||||
targ->enemy = attacker->enemy;
|
targ->enemy = attacker->enemy;
|
||||||
|
|
||||||
|
if (!(targ->monsterinfo.aiflags & AI_DUCKED))
|
||||||
|
{
|
||||||
FoundTarget(targ);
|
FoundTarget(targ);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean
|
qboolean
|
||||||
|
@ -524,10 +685,28 @@ CheckTeamDamage(edict_t *targ, edict_t *attacker)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_knockback(edict_t *targ, vec3_t dir, float knockback, float scale)
|
||||||
|
{
|
||||||
|
vec3_t kvel;
|
||||||
|
float mass;
|
||||||
|
|
||||||
|
if (!knockback)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mass = (targ->mass < 50) ? 50.0f : (float)targ->mass;
|
||||||
|
|
||||||
|
VectorNormalize2(dir, kvel);
|
||||||
|
VectorScale(kvel, scale * (knockback / mass), kvel);
|
||||||
|
VectorAdd(targ->velocity, kvel, targ->velocity);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
||||||
vec3_t dir, vec3_t point, vec3_t normal, int damage,
|
vec3_t point, vec3_t normal, int damage, int knockback, int dflags,
|
||||||
int knockback, int dflags, int mod)
|
int mod)
|
||||||
{
|
{
|
||||||
gclient_t *client;
|
gclient_t *client;
|
||||||
int take;
|
int take;
|
||||||
|
@ -535,24 +714,32 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
int asave;
|
int asave;
|
||||||
int psave;
|
int psave;
|
||||||
int te_sparks;
|
int te_sparks;
|
||||||
|
int sphere_notified;
|
||||||
|
|
||||||
|
if (!targ || !inflictor || !attacker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!targ->takedamage)
|
if (!targ->takedamage)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* friendly fire avoidance
|
sphere_notified = false;
|
||||||
if enabled you can't hurt
|
|
||||||
teammates (but you can hurt
|
/* friendly fire avoidance. If enabled you can't
|
||||||
yourself) knockback still occurs */
|
hurt teammates (but you can hurt yourself)
|
||||||
if ((targ != attacker) &&
|
knockback still occurs */
|
||||||
((deathmatch->value &&
|
if ((targ != attacker) && ((deathmatch->value &&
|
||||||
((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) ||
|
((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS))) ||
|
||||||
coop->value))
|
coop->value))
|
||||||
{
|
{
|
||||||
if (OnSameTeam(targ, attacker))
|
if (OnSameTeam(targ, attacker))
|
||||||
{
|
{
|
||||||
if ((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE)
|
/* nukes kill everyone */
|
||||||
|
if (((int)(dmflags->value) & DF_NO_FRIENDLY_FIRE) &&
|
||||||
|
(mod != MOD_NUKE))
|
||||||
{
|
{
|
||||||
damage = 0;
|
damage = 0;
|
||||||
}
|
}
|
||||||
|
@ -565,6 +752,25 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
|
|
||||||
meansOfDeath = mod;
|
meansOfDeath = mod;
|
||||||
|
|
||||||
|
/* allow the deathmatch game to change values */
|
||||||
|
if (deathmatch->value && gamerules && gamerules->value)
|
||||||
|
{
|
||||||
|
if (DMGame.ChangeDamage)
|
||||||
|
{
|
||||||
|
damage = DMGame.ChangeDamage(targ, attacker, damage, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DMGame.ChangeKnockback)
|
||||||
|
{
|
||||||
|
knockback = DMGame.ChangeKnockback(targ, attacker, knockback, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!damage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* easy mode takes half damage */
|
/* easy mode takes half damage */
|
||||||
if ((skill->value == SKILL_EASY) && (deathmatch->value == 0) && targ->client)
|
if ((skill->value == SKILL_EASY) && (deathmatch->value == 0) && targ->client)
|
||||||
{
|
{
|
||||||
|
@ -578,6 +784,18 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
|
|
||||||
client = targ->client;
|
client = targ->client;
|
||||||
|
|
||||||
|
/* defender sphere takes half damage */
|
||||||
|
if ((client) && (client->owned_sphere) &&
|
||||||
|
(client->owned_sphere->spawnflags == 1))
|
||||||
|
{
|
||||||
|
damage *= 0.5;
|
||||||
|
|
||||||
|
if (!damage)
|
||||||
|
{
|
||||||
|
damage = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dflags & DAMAGE_BULLET)
|
if (dflags & DAMAGE_BULLET)
|
||||||
{
|
{
|
||||||
te_sparks = TE_BULLET_SPARKS;
|
te_sparks = TE_BULLET_SPARKS;
|
||||||
|
@ -651,11 +869,28 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
/* check for invincibility */
|
/* check for invincibility */
|
||||||
if ((client &&
|
if ((client &&
|
||||||
(client->invincible_framenum > level.framenum)) &&
|
(client->invincible_framenum > level.framenum)) &&
|
||||||
|
!(dflags & DAMAGE_NO_PROTECTION) && (mod != MOD_TRAP))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for monster invincibility */
|
||||||
|
if (((targ->svflags & SVF_MONSTER) &&
|
||||||
|
(targ->monsterinfo.invincible_framenum > level.framenum)) &&
|
||||||
!(dflags & DAMAGE_NO_PROTECTION))
|
!(dflags & DAMAGE_NO_PROTECTION))
|
||||||
{
|
{
|
||||||
if (targ->pain_debounce_time < level.time)
|
if (targ->pain_debounce_time < level.time)
|
||||||
{
|
{
|
||||||
gi.sound(targ, CHAN_ITEM, gi.soundindex("items/protect4.wav"), 1, ATTN_NORM, 0);
|
gi.sound(targ, CHAN_ITEM, gi.soundindex(
|
||||||
|
"items/protect4.wav"), 1, ATTN_NORM, 0);
|
||||||
targ->pain_debounce_time = level.time + 2;
|
targ->pain_debounce_time = level.time + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,10 +931,26 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
/* do the damage */
|
/* do the damage */
|
||||||
if (take)
|
if (take)
|
||||||
{
|
{
|
||||||
if ((targ->svflags & SVF_MONSTER) || (client))
|
/* need more blood for chainfist. */
|
||||||
|
if (targ->flags & FL_MECHANICAL)
|
||||||
|
{
|
||||||
|
SpawnDamage(TE_ELECTRIC_SPARKS, point, normal);
|
||||||
|
}
|
||||||
|
else if ((targ->svflags & SVF_MONSTER) || (client))
|
||||||
|
{
|
||||||
|
if (strcmp(targ->classname, "monster_gekk") == 0)
|
||||||
|
{
|
||||||
|
SpawnDamage(TE_GREENBLOOD, point, normal);
|
||||||
|
}
|
||||||
|
else if (mod == MOD_CHAINFIST)
|
||||||
|
{
|
||||||
|
SpawnDamage(TE_MOREBLOOD, point, normal);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
SpawnDamage(TE_BLOOD, point, normal);
|
SpawnDamage(TE_BLOOD, point, normal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SpawnDamage(te_sparks, point, normal);
|
SpawnDamage(te_sparks, point, normal);
|
||||||
|
@ -710,6 +961,17 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
targ->health = targ->health - take;
|
targ->health = targ->health - take;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* spheres need to know who to shoot at */
|
||||||
|
if (client && client->owned_sphere)
|
||||||
|
{
|
||||||
|
sphere_notified = true;
|
||||||
|
|
||||||
|
if (client->owned_sphere->pain)
|
||||||
|
{
|
||||||
|
client->owned_sphere->pain(client->owned_sphere, attacker, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (targ->health <= 0)
|
if (targ->health <= 0)
|
||||||
{
|
{
|
||||||
if ((targ->svflags & SVF_MONSTER) || (client))
|
if ((targ->svflags & SVF_MONSTER) || (client))
|
||||||
|
@ -722,6 +984,19 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* spheres need to know who to shoot at */
|
||||||
|
if (!sphere_notified)
|
||||||
|
{
|
||||||
|
if (client && client->owned_sphere)
|
||||||
|
{
|
||||||
|
if (client->owned_sphere->pain)
|
||||||
|
{
|
||||||
|
client->owned_sphere->pain(client->owned_sphere, attacker, 0,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (targ->svflags & SVF_MONSTER)
|
if (targ->svflags & SVF_MONSTER)
|
||||||
{
|
{
|
||||||
M_ReactToDamage(targ, attacker, inflictor);
|
M_ReactToDamage(targ, attacker, inflictor);
|
||||||
|
@ -776,6 +1051,11 @@ T_RadiusDamage(edict_t *inflictor, edict_t *attacker, float damage,
|
||||||
vec3_t v;
|
vec3_t v;
|
||||||
vec3_t dir;
|
vec3_t dir;
|
||||||
|
|
||||||
|
if (!inflictor || !attacker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL)
|
while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL)
|
||||||
{
|
{
|
||||||
if (ent == ignore)
|
if (ent == ignore)
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
#include "../header/local.h"
|
#include "../header/local.h"
|
||||||
#include "../monster/misc/player.h"
|
#include "../monster/misc/player.h"
|
||||||
|
|
||||||
|
edict_t *pm_passent;
|
||||||
|
|
||||||
|
void ClientUserinfoChanged(edict_t *ent, char *userinfo);
|
||||||
void SP_misc_teleporter_dest(edict_t *ent);
|
void SP_misc_teleporter_dest(edict_t *ent);
|
||||||
void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
|
void Touch_Item(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
|
||||||
|
|
||||||
|
@ -2370,3 +2373,34 @@ ClientBeginServerFrame(edict_t *ent)
|
||||||
client->latched_buttons = 0;
|
client->latched_buttons = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is called to clean up the pain daemons that
|
||||||
|
* the disruptor attaches to clients to damage them.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RemoveAttackingPainDaemons(edict_t *self)
|
||||||
|
{
|
||||||
|
edict_t *tracker;
|
||||||
|
|
||||||
|
if (!self)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker = G_Find(NULL, FOFS(classname), "pain daemon");
|
||||||
|
|
||||||
|
while (tracker)
|
||||||
|
{
|
||||||
|
if (tracker->enemy == self)
|
||||||
|
{
|
||||||
|
G_FreeEdict(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker = G_Find(tracker, FOFS(classname), "pain daemon");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->client)
|
||||||
|
{
|
||||||
|
self->client->tracker_pain_framenum = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "header/local.h"
|
#include "header/local.h"
|
||||||
#include "monster/misc/player.h"
|
#include "monster/misc/player.h"
|
||||||
|
|
||||||
|
gitem_t *CTFWhat_Tech(edict_t *ent);
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ClientTeam(edict_t *ent, char* value)
|
ClientTeam(edict_t *ent, char* value)
|
||||||
{
|
{
|
||||||
|
@ -103,7 +105,12 @@ SelectNextItem(edict_t *ent, int itflags)
|
||||||
|
|
||||||
cl = ent->client;
|
cl = ent->client;
|
||||||
|
|
||||||
if (cl->chase_target)
|
if (cl->menu)
|
||||||
|
{
|
||||||
|
PMenu_Next(ent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cl->chase_target)
|
||||||
{
|
{
|
||||||
ChaseNext(ent);
|
ChaseNext(ent);
|
||||||
return;
|
return;
|
||||||
|
@ -152,7 +159,12 @@ SelectPrevItem(edict_t *ent, int itflags)
|
||||||
|
|
||||||
cl = ent->client;
|
cl = ent->client;
|
||||||
|
|
||||||
if (cl->chase_target)
|
if (cl->menu)
|
||||||
|
{
|
||||||
|
PMenu_Prev(ent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cl->chase_target)
|
||||||
{
|
{
|
||||||
ChasePrev(ent);
|
ChasePrev(ent);
|
||||||
return;
|
return;
|
||||||
|
@ -622,6 +634,12 @@ Cmd_Drop_f(edict_t *ent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((Q_stricmp(gi.args(), "tech") == 0) && ((it = CTFWhat_Tech(ent)) != NULL))
|
||||||
|
{
|
||||||
|
it->drop(ent, it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
s = gi.args();
|
s = gi.args();
|
||||||
it = FindItem(s);
|
it = FindItem(s);
|
||||||
|
|
||||||
|
@ -700,6 +718,7 @@ Cmd_Score_f(edict_t *ent)
|
||||||
if (ent->client->showscores)
|
if (ent->client->showscores)
|
||||||
{
|
{
|
||||||
ent->client->showscores = false;
|
ent->client->showscores = false;
|
||||||
|
ent->client->update_chase = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,6 +727,9 @@ Cmd_Score_f(edict_t *ent)
|
||||||
gi.unicast(ent, true);
|
gi.unicast(ent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display the current help message
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
Cmd_Help_f(edict_t *ent)
|
Cmd_Help_f(edict_t *ent)
|
||||||
{
|
{
|
||||||
|
@ -726,7 +748,8 @@ Cmd_Help_f(edict_t *ent)
|
||||||
ent->client->showinventory = false;
|
ent->client->showinventory = false;
|
||||||
ent->client->showscores = false;
|
ent->client->showscores = false;
|
||||||
|
|
||||||
if (ent->client->showhelp)
|
if (ent->client->showhelp &&
|
||||||
|
(ent->client->resp.game_helpchanged == game.helpchanged))
|
||||||
{
|
{
|
||||||
ent->client->showhelp = false;
|
ent->client->showhelp = false;
|
||||||
return;
|
return;
|
||||||
|
@ -753,12 +776,25 @@ Cmd_Inven_f(edict_t *ent)
|
||||||
cl->showscores = false;
|
cl->showscores = false;
|
||||||
cl->showhelp = false;
|
cl->showhelp = false;
|
||||||
|
|
||||||
|
if (ent->client->menu)
|
||||||
|
{
|
||||||
|
PMenu_Close(ent);
|
||||||
|
ent->client->update_chase = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cl->showinventory)
|
if (cl->showinventory)
|
||||||
{
|
{
|
||||||
cl->showinventory = false;
|
cl->showinventory = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctf->value && (cl->resp.ctf_team == CTF_NOTEAM))
|
||||||
|
{
|
||||||
|
CTFOpenJoinMenu(ent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cl->showinventory = true;
|
cl->showinventory = true;
|
||||||
|
|
||||||
InventoryMessage(ent);
|
InventoryMessage(ent);
|
||||||
|
@ -775,6 +811,12 @@ Cmd_InvUse_f(edict_t *ent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ent->client->menu)
|
||||||
|
{
|
||||||
|
PMenu_Select(ent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ValidateSelectedItem(ent);
|
ValidateSelectedItem(ent);
|
||||||
|
|
||||||
if (ent->client->pers.selected_item == -1)
|
if (ent->client->pers.selected_item == -1)
|
||||||
|
@ -794,6 +836,21 @@ Cmd_InvUse_f(edict_t *ent)
|
||||||
it->use(ent, it);
|
it->use(ent, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cmd_LastWeap_f(edict_t *ent)
|
||||||
|
{
|
||||||
|
gclient_t *cl;
|
||||||
|
|
||||||
|
cl = ent->client;
|
||||||
|
|
||||||
|
if (!cl->pers.weapon || !cl->pers.lastweapon)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->pers.lastweapon->use(ent, cl->pers.lastweapon);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cmd_WeapPrev_f(edict_t *ent)
|
Cmd_WeapPrev_f(edict_t *ent)
|
||||||
{
|
{
|
||||||
|
@ -982,6 +1039,11 @@ Cmd_Kill_f(edict_t *ent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ent->solid == SOLID_NOT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (((level.time - ent->client->respawn_time) < 5) ||
|
if (((level.time - ent->client->respawn_time) < 5) ||
|
||||||
(ent->client->resp.spectator))
|
(ent->client->resp.spectator))
|
||||||
{
|
{
|
||||||
|
@ -1018,6 +1080,13 @@ Cmd_PutAway_f(edict_t *ent)
|
||||||
ent->client->showscores = false;
|
ent->client->showscores = false;
|
||||||
ent->client->showhelp = false;
|
ent->client->showhelp = false;
|
||||||
ent->client->showinventory = false;
|
ent->client->showinventory = false;
|
||||||
|
|
||||||
|
if (ent->client->menu)
|
||||||
|
{
|
||||||
|
PMenu_Close(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
ent->client->update_chase = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1973,9 +2042,9 @@ ClientCommand(edict_t *ent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Q_stricmp(cmd, "say_team") == 0)
|
if ((Q_stricmp(cmd, "say_team") == 0) || (Q_stricmp(cmd, "steam") == 0))
|
||||||
{
|
{
|
||||||
Cmd_Say_f(ent, true, false);
|
CTFSay_Team(ent, gi.args());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2080,10 +2149,62 @@ ClientCommand(edict_t *ent)
|
||||||
{
|
{
|
||||||
Cmd_Wave_f(ent);
|
Cmd_Wave_f(ent);
|
||||||
}
|
}
|
||||||
|
/* ZOID */
|
||||||
|
else if (Q_stricmp(cmd, "team") == 0)
|
||||||
|
{
|
||||||
|
CTFTeam_f(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "id") == 0)
|
||||||
|
{
|
||||||
|
CTFID_f(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "yes") == 0)
|
||||||
|
{
|
||||||
|
CTFVoteYes(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "no") == 0)
|
||||||
|
{
|
||||||
|
CTFVoteNo(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "ready") == 0)
|
||||||
|
{
|
||||||
|
CTFReady(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "notready") == 0)
|
||||||
|
{
|
||||||
|
CTFNotReady(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "ghost") == 0)
|
||||||
|
{
|
||||||
|
CTFGhost(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "admin") == 0)
|
||||||
|
{
|
||||||
|
CTFAdmin(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "stats") == 0)
|
||||||
|
{
|
||||||
|
CTFStats(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "warp") == 0)
|
||||||
|
{
|
||||||
|
CTFWarp(ent);
|
||||||
|
}
|
||||||
|
else if (Q_stricmp(cmd, "boot") == 0)
|
||||||
|
{
|
||||||
|
CTFBoot(ent);
|
||||||
|
}
|
||||||
else if (Q_stricmp(cmd, "playerlist") == 0)
|
else if (Q_stricmp(cmd, "playerlist") == 0)
|
||||||
|
{
|
||||||
|
if (ctf->value)
|
||||||
|
{
|
||||||
|
CTFPlayerList(ent);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Cmd_PlayerList_f(ent);
|
Cmd_PlayerList_f(ent);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (Q_stricmp(cmd, "entcount") == 0)
|
else if (Q_stricmp(cmd, "entcount") == 0)
|
||||||
{
|
{
|
||||||
Cmd_Ent_Count_f(ent);
|
Cmd_Ent_Count_f(ent);
|
||||||
|
@ -2116,6 +2237,10 @@ ClientCommand(edict_t *ent)
|
||||||
{
|
{
|
||||||
Cmd_PrefWeap_f(ent);
|
Cmd_PrefWeap_f(ent);
|
||||||
}
|
}
|
||||||
|
else if (Q_stricmp(cmd, "observer") == 0)
|
||||||
|
{
|
||||||
|
CTFObserver(ent);
|
||||||
|
}
|
||||||
else /* anything that doesn't match a command will be a chat */
|
else /* anything that doesn't match a command will be a chat */
|
||||||
{
|
{
|
||||||
Cmd_Say_f(ent, false, true);
|
Cmd_Say_f(ent, false, true);
|
||||||
|
|
|
@ -367,8 +367,16 @@ CheckPowerArmor(edict_t *ent, vec3_t point, vec3_t normal,
|
||||||
damage = damage / 3;
|
damage = damage / 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (ctf->value)
|
||||||
|
{
|
||||||
|
/* power armor is weaker in CTF */
|
||||||
|
damagePerCell = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
damagePerCell = 2;
|
damagePerCell = 2;
|
||||||
|
}
|
||||||
pa_te_type = TE_SHIELD_SPARKS;
|
pa_te_type = TE_SHIELD_SPARKS;
|
||||||
damage = (2 * damage) / 3;
|
damage = (2 * damage) / 3;
|
||||||
}
|
}
|
||||||
|
@ -863,11 +871,21 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
||||||
save = damage;
|
save = damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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))
|
||||||
|
{
|
||||||
|
psave = asave = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
psave = CheckPowerArmor(targ, point, normal, take, dflags);
|
psave = CheckPowerArmor(targ, point, normal, take, dflags);
|
||||||
take -= psave;
|
take -= psave;
|
||||||
|
|
||||||
asave = CheckArmor(targ, point, normal, take, te_sparks, dflags);
|
asave = CheckArmor(targ, point, normal, take, te_sparks, dflags);
|
||||||
take -= asave;
|
take -= asave;
|
||||||
|
}
|
||||||
|
|
||||||
/* treat cheat/powerup savings the same as armor */
|
/* treat cheat/powerup savings the same as armor */
|
||||||
asave += save;
|
asave += save;
|
||||||
|
@ -911,7 +929,10 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
||||||
SpawnDamage(te_sparks, point, normal);
|
SpawnDamage(te_sparks, point, normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CTFMatchSetup())
|
||||||
|
{
|
||||||
targ->health = targ->health - take;
|
targ->health = targ->health - take;
|
||||||
|
}
|
||||||
|
|
||||||
/* spheres need to know who to shoot at */
|
/* spheres need to know who to shoot at */
|
||||||
if (client && client->owned_sphere)
|
if (client && client->owned_sphere)
|
||||||
|
@ -966,7 +987,7 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
||||||
}
|
}
|
||||||
else if (client)
|
else if (client)
|
||||||
{
|
{
|
||||||
if (!(targ->flags & FL_GODMODE) && (take))
|
if (!(targ->flags & FL_GODMODE) && (take) && !CTFMatchSetup())
|
||||||
{
|
{
|
||||||
targ->pain(targ, attacker, knockback, take);
|
targ->pain(targ, attacker, knockback, take);
|
||||||
}
|
}
|
||||||
|
@ -979,9 +1000,11 @@ T_Damage(edict_t *targ, edict_t *inflictor, edict_t *attacker, vec3_t dir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add to the damage inflicted on a player this frame
|
/* add to the damage inflicted on a
|
||||||
the total will be turned into screen blends and view
|
player this frame the total will
|
||||||
angle kicks at the end of the frame */
|
be turned into screen blends and
|
||||||
|
view angle kicks at the end of
|
||||||
|
the frame */
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
client->damage_parmor += psave;
|
client->damage_parmor += psave;
|
||||||
|
|
Loading…
Reference in a new issue