More tweaks to Tactician Gunner prox aiming.

Added close range safety check/trace to Tactician Gunner prox aiming.
Added check for nightmare mode for Beta-Class Gladiator and dog.
This commit is contained in:
Knightmare66 2021-07-31 21:47:21 -04:00
parent 8401c475f6
commit cedf3628ac
25 changed files with 188 additions and 131 deletions

View file

@ -1315,7 +1315,7 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_
//PGM //PGM
if ((targ->svflags & SVF_MONSTER) if ((targ->svflags & SVF_MONSTER)
//Knightmare- no damage reaction from negative damage lasers and triggers // Knightmare- no damage reaction from negative damage lasers and triggers
&& ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) )) && ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) ))
{ {
M_ReactToDamage (targ, attacker, inflictor); M_ReactToDamage (targ, attacker, inflictor);
@ -1331,7 +1331,7 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_
} }
} }
else if ((client) else if ((client)
//Knightmare- no damage reaction from negative damage lasers and triggers // Knightmare- no damage reaction from negative damage lasers and triggers
&& ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) )) && ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) ))
{ {
if (!(targ->flags & FL_GODMODE) && (take)) { if (!(targ->flags & FL_GODMODE) && (take)) {
@ -1340,7 +1340,7 @@ void T_Damage (edict_t *in_targ, edict_t *inflictor, edict_t *in_attacker, vec3_
} }
} }
else if ((take) else if ((take)
//Knightmare- no damage reaction from negative damage lasers and triggers // Knightmare- no damage reaction from negative damage lasers and triggers
&& ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) )) && ( (damage > 0) || ((mod != MOD_TRIGGER_HURT) && (mod != MOD_TARGET_LASER)) ))
{ {
if (targ->pain) if (targ->pain)

View file

@ -1133,6 +1133,7 @@ extern void GunnerFire ( edict_t * self ) ;
extern void gunner_opengun ( edict_t * self ) ; extern void gunner_opengun ( edict_t * self ) ;
extern void gunner_duck_down ( edict_t * self ) ; extern void gunner_duck_down ( edict_t * self ) ;
extern qboolean gunner_grenade_check ( edict_t * self ) ; extern qboolean gunner_grenade_check ( edict_t * self ) ;
extern qboolean gunner_prox_safety_check ( edict_t * self , vec3_t start , vec3_t target ) ;
extern void gunner_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ; extern void gunner_die ( edict_t * self , edict_t * inflictor , edict_t * attacker , int damage , vec3_t point ) ;
extern void gunner_dead ( edict_t * self ) ; extern void gunner_dead ( edict_t * self ) ;
extern void gunner_pain ( edict_t * self , edict_t * other , float kick , int damage ) ; extern void gunner_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;

View file

@ -1133,6 +1133,7 @@
{"gunner_opengun", (byte *)gunner_opengun}, {"gunner_opengun", (byte *)gunner_opengun},
{"gunner_duck_down", (byte *)gunner_duck_down}, {"gunner_duck_down", (byte *)gunner_duck_down},
{"gunner_grenade_check", (byte *)gunner_grenade_check}, {"gunner_grenade_check", (byte *)gunner_grenade_check},
{"gunner_prox_safety_check", (byte *)gunner_prox_safety_check},
{"gunner_die", (byte *)gunner_die}, {"gunner_die", (byte *)gunner_die},
{"gunner_dead", (byte *)gunner_dead}, {"gunner_dead", (byte *)gunner_dead},
{"gunner_pain", (byte *)gunner_pain}, {"gunner_pain", (byte *)gunner_pain},

View file

@ -1740,8 +1740,6 @@ void kick_attack (edict_t *ent);
// g_newweap.c // g_newweap.c
// //
//extern float nuke_framenum; //extern float nuke_framenum;
extern vec3_t proxMins;
extern vec3_t proxMaxs;
void fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage); void fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage);
//void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed); //void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed);
void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius); void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int damage_multiplier, int speed, int health, float timer, float damage_radius);

View file

@ -151,10 +151,6 @@ void SP_flechette (edict_t *flechette)
#define PROX_HEALTH 20 #define PROX_HEALTH 20
#define PROX_DAMAGE 90 #define PROX_DAMAGE 90
// Knightmare- these are used for aiming traces to avoid collision
vec3_t proxMins = {-8, -8, -8};
vec3_t proxMaxs = {8, 8, 8};
void Prox_Explode (edict_t *ent); void Prox_Explode (edict_t *ent);
//=============== //===============
//=============== //===============
@ -734,7 +730,12 @@ void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int dama
prox = G_Spawn(); prox = G_Spawn();
VectorCopy (start, prox->s.origin); VectorCopy (start, prox->s.origin);
VectorScale (aimdir, speed, prox->velocity); VectorScale (aimdir, speed, prox->velocity);
VectorMA (prox->velocity, 200 + crandom() * 10.0, up, prox->velocity); // Lazarus - keep same vertical boost for players, but monsters do a better job
// of calculating aim direction, so throw that out
if (self->client)
VectorMA (prox->velocity, 200 + crandom() * 10.0, up, prox->velocity);
else
VectorMA (prox->velocity, crandom() * 10.0, up, prox->velocity);
VectorMA (prox->velocity, crandom() * 10.0, right, prox->velocity); VectorMA (prox->velocity, crandom() * 10.0, right, prox->velocity);
// Knightmare- add player's base velocity to prox // Knightmare- add player's base velocity to prox
if (add_velocity_throw->value && self->client) if (add_velocity_throw->value && self->client)

View file

@ -942,6 +942,9 @@ qboolean AimGrenade (edict_t *self, vec3_t start, vec3_t target, vec_t speed, ve
float last_error, v_error; float last_error, v_error;
int i; int i;
vec3_t last_aim; vec3_t last_aim;
// Knightmare- wider bounds to avoid prox collision
vec3_t proxMins = {-8, -8, -8};
vec3_t proxMaxs = {8, 8, 8};
VectorCopy (target, aim_point); VectorCopy (target, aim_point);
VectorSubtract (aim_point, self->s.origin, from_origin); VectorSubtract (aim_point, self->s.origin, from_origin);

View file

@ -452,10 +452,10 @@ void q1_fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, in
VectorScale (aimdir, speed, grenade->velocity); VectorScale (aimdir, speed, grenade->velocity);
// Lazarus - keep same vertical boost for players, but monsters do a better job // Lazarus - keep same vertical boost for players, but monsters do a better job
// of calculating aim direction, so throw that out // of calculating aim direction, so throw that out
if (self->client) // if (self->client)
VectorMA (grenade->velocity, 200 + (random() - 0.5) * 20.0, up, grenade->velocity); VectorMA (grenade->velocity, 200 + (random() - 0.5) * 20.0, up, grenade->velocity);
else // else
VectorMA (grenade->velocity, (random() - 0.5) * 20.0, up, grenade->velocity); // VectorMA (grenade->velocity, (random() - 0.5) * 20.0, up, grenade->velocity);
VectorMA (grenade->velocity, (random() - 0.5) * 20.0, right, grenade->velocity); VectorMA (grenade->velocity, (random() - 0.5) * 20.0, right, grenade->velocity);
VectorSet (grenade->avelocity, 300, 300, 300); VectorSet (grenade->avelocity, 300, 300, 300);

View file

@ -140,12 +140,11 @@ void dog_pain (edict_t *self, edict_t *other, float kick, int damage)
self->pain_debounce_time = level.time + 1; self->pain_debounce_time = level.time + 1;
if (skill->value == 3)
return;
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); //WAS ATTN_IDLE gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); //WAS ATTN_IDLE
if (skill->value == 3)
return; // no pain anims in nightmare
if (random() < 0.5) if (random() < 0.5)
self->monsterinfo.currentmove = &dog_move_pain1; self->monsterinfo.currentmove = &dog_move_pain1;

View file

@ -258,6 +258,9 @@ void gladb_pain (edict_t *self, edict_t *other, float kick, int damage)
else else
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
if (skill->value == 3)
return; // no pain anims in nightmare
if (self->velocity[2] > 100) if (self->velocity[2] > 100)
self->monsterinfo.currentmove = &gladb_move_pain_air; self->monsterinfo.currentmove = &gladb_move_pain_air;
else else

View file

@ -229,7 +229,6 @@ mmove_t gladiator_move_pain_air = {FRAME_painup1, FRAME_painup7, gladiator_frame
void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage) void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
if (self->health < (self->max_health / 2)) if (self->health < (self->max_health / 2))
self->s.skinnum |= 1; self->s.skinnum |= 1;
@ -254,7 +253,6 @@ void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage)
self->monsterinfo.currentmove = &gladiator_move_pain_air; self->monsterinfo.currentmove = &gladiator_move_pain_air;
else else
self->monsterinfo.currentmove = &gladiator_move_pain; self->monsterinfo.currentmove = &gladiator_move_pain;
} }

View file

@ -38,8 +38,11 @@ static int tactician_sound_sight;
// (for the gunner, not for players) since the gunner now shoots // (for the gunner, not for players) since the gunner now shoots
// smarter, and adjusted things so that the initial velocity out // smarter, and adjusted things so that the initial velocity out
// of the barrel is the same. // of the barrel is the same.
#define GRENADE_VELOCITY 632.4555320337 #define GRENADE_VELOCITY 632.4555320337f
#define GRENADE_VELOCITY_SQUARED 400000 #define GRENADE_VELOCITY_SQUARED 400000.0f
// Knightmare- placement spread for Tactician Gunner prox mines
#define GUNNER_PROX_SPREAD 40.0f
#define HALF_GUNNER_PROX_SPREAD (GUNNER_PROX_SPREAD * 0.5f)
void gunner_idlesound (edict_t *self) void gunner_idlesound (edict_t *self)
{ {
@ -296,6 +299,8 @@ mmove_t gunner_move_pain1 = {FRAME_pain101, FRAME_pain118, gunner_frames_pain1,
void gunner_pain (edict_t *self, edict_t *other, float kick, int damage) void gunner_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
int smallDamage, bigDamage;
if (self->health < (self->max_health / 2)) if (self->health < (self->max_health / 2))
self->s.skinnum |= 1; self->s.skinnum |= 1;
@ -303,8 +308,8 @@ void gunner_pain (edict_t *self, edict_t *other, float kick, int damage)
if (!self->groundentity) if (!self->groundentity)
{ {
// if ((g_showlogic) && (g_showlogic->value)) // if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("gunner: pain avoided due to no ground\n"); // gi.dprintf ("gunner: pain avoided due to no ground\n");
return; return;
} }
@ -329,9 +334,20 @@ void gunner_pain (edict_t *self, edict_t *other, float kick, int damage)
if (skill->value == 3) if (skill->value == 3)
return; // no pain anims in nightmare return; // no pain anims in nightmare
if (damage <= 10) if (self->moreflags & FL2_COMMANDER) {
smallDamage = 20;
bigDamage = 50;
}
else {
smallDamage = 10;
bigDamage = 25;
}
// if (damage <= 10)
if (damage <= smallDamage)
self->monsterinfo.currentmove = &gunner_move_pain3; self->monsterinfo.currentmove = &gunner_move_pain3;
else if (damage <= 25) // else if (damage <= 25)
else if (damage <= bigDamage)
self->monsterinfo.currentmove = &gunner_move_pain2; self->monsterinfo.currentmove = &gunner_move_pain2;
else else
self->monsterinfo.currentmove = &gunner_move_pain1; self->monsterinfo.currentmove = &gunner_move_pain1;
@ -340,7 +356,7 @@ void gunner_pain (edict_t *self, edict_t *other, float kick, int damage)
// PMM - clear duck flag // PMM - clear duck flag
if (self->monsterinfo.aiflags & AI_DUCKED) if (self->monsterinfo.aiflags & AI_DUCKED)
monster_duck_up(self); monster_duck_up (self);
} }
void gunner_dead (edict_t *self) void gunner_dead (edict_t *self)
@ -412,6 +428,44 @@ void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag
self->monsterinfo.currentmove = &gunner_move_death; self->monsterinfo.currentmove = &gunner_move_death;
} }
// Knightmare added
// This calcs horizontal spread of prox mines based on distance.
// Then it does a short-range trace at blast radius, to ensure we won't clip a wall.
qboolean gunner_prox_safety_check (edict_t *self, vec3_t start, vec3_t target)
{
trace_t tr;
vec3_t closeCheckMins, closeCheckMaxs, dir, dangerOffset, dangerTarget;
float dist, dangerSpread, dangerRange = 256.0f;
// get dist to target
VectorSubtract (target, start, dir);
dist = VectorLength (dir);
// get spread at damger range
dangerSpread = (HALF_GUNNER_PROX_SPREAD / dist) * dangerRange;
dangerSpread += 8.0f; // add bounds of prox mine + 2
VectorSet (closeCheckMins, -dangerSpread, -dangerSpread, -12.0f);
VectorSet (closeCheckMaxs, dangerSpread, dangerSpread, 12.0f);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("Tactician Gunner: perfoming close-range safety check with radius of %5.2f- ", dangerSpread);
// extrapolate point on path to target at danger range
VectorNormalize (dir);
VectorScale (dir, dangerRange, dangerOffset);
VectorAdd (start, dangerOffset, dangerTarget);
tr = gi.trace(start, closeCheckMins, closeCheckMaxs, dangerTarget, self, MASK_SHOT);
if (tr.fraction < 1.0) {
// if (g_showlogic && g_showlogic->value)
// gi.dprintf ("failed!\n");
return false;
}
// if (g_showlogic && g_showlogic->value)
// gi.dprintf ("succeeded!\n");
return true;
}
qboolean gunner_grenade_check (edict_t *self) qboolean gunner_grenade_check (edict_t *self)
{ {
vec3_t start; vec3_t start;
@ -422,6 +476,11 @@ qboolean gunner_grenade_check (edict_t *self)
vec3_t vhorz; vec3_t vhorz;
float horz, vertmax, dangerClose; float horz, vertmax, dangerClose;
qboolean isProx = (self->moreflags & FL2_COMMANDER); qboolean isProx = (self->moreflags & FL2_COMMANDER);
// Knightmare- Tactician Gunner fires prox mines in a spread,
// so we need a wider safety bounds check
vec3_t checkMins, checkMaxs;
vec3_t proxMins = {-8, -8, -8};
vec3_t proxMaxs = {8, 8, 8};
if (!self->enemy) if (!self->enemy)
return false; return false;
@ -433,6 +492,16 @@ qboolean gunner_grenade_check (edict_t *self)
// Lazarus: We can do better than that... see below // Lazarus: We can do better than that... see below
// Knightmare- use appropriate trace mins/maxs based on projectile
if (isProx) {
VectorCopy (proxMins, checkMins);
VectorCopy (proxMaxs, checkMaxs);
}
else {
VectorCopy (vec3_origin, checkMins);
VectorCopy (vec3_origin, checkMaxs);
}
// check to see that we can trace to the player before we start // check to see that we can trace to the player before we start
// tossing grenades around. // tossing grenades around.
AngleVectors (self->s.angles, forward, right, NULL); AngleVectors (self->s.angles, forward, right, NULL);
@ -462,21 +531,29 @@ qboolean gunner_grenade_check (edict_t *self)
// would almost always hit the platform the target was standing on // would almost always hit the platform the target was standing on
VectorCopy (self->enemy->s.origin, target); VectorCopy (self->enemy->s.origin, target);
target[2] = self->enemy->absmax[2]; target[2] = self->enemy->absmax[2];
if (isProx) tr = gi.trace(start, checkMins, checkMaxs, target, self, MASK_SHOT);
tr = gi.trace(start, proxMins, proxMaxs, target, self, MASK_SHOT);
else
tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1) if (tr.ent == self->enemy || tr.fraction == 1)
return true; { // Knightmare- added close-range prox safety check
if (isProx) {
if (gunner_prox_safety_check(self, start, target))
return true;
}
else
return true;
}
// Repeat for feet... in case we're looking down at a target standing under, // Repeat for feet... in case we're looking down at a target standing under,
// for example, a short doorway // for example, a short doorway
target[2] = self->enemy->absmin[2]; target[2] = self->enemy->absmin[2];
if (isProx) tr = gi.trace(start, checkMins, checkMaxs, target, self, MASK_SHOT);
tr = gi.trace(start, proxMins, proxMaxs, target, self, MASK_SHOT);
else
tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1) if (tr.ent == self->enemy || tr.fraction == 1)
return true; { // Knightmare- added close-range prox safety check
if (isProx) {
if (gunner_prox_safety_check(self, start, target))
return true;
}
else
return true;
}
return false; return false;
} }
@ -493,7 +570,8 @@ void gunner_duck_down (edict_t *self)
self->monsterinfo.aiflags |= AI_DUCKED; self->monsterinfo.aiflags |= AI_DUCKED;
if (skill->value >= 2) if (skill->value >= 2)
{ {
if (random() > 0.5) // Lazarus: Added check for goodness of grenade firing
if (random() > 0.5 && gunner_grenade_check(self))
GunnerGrenade (self); GunnerGrenade (self);
} }
@ -675,17 +753,8 @@ void GunnerGrenade (edict_t *self)
// Knightmare- spread out Tactician Gunner's prox mines so they don't collide // Knightmare- spread out Tactician Gunner's prox mines so they don't collide
if (self->moreflags & FL2_COMMANDER) if (self->moreflags & FL2_COMMANDER)
{ {
if ( blindfire ) target[0] += crandom() * GUNNER_PROX_SPREAD;
{ target[1] += crandom() * GUNNER_PROX_SPREAD;
target[0] += crandom() * 192;
target[1] += crandom() * 192;
target[2] += crandom() * 192;
}
else
{
target[0] += crandom() * 32;
target[1] += crandom() * 32;
}
} }
// Lazarus fog reduction of accuracy // Lazarus fog reduction of accuracy
@ -745,7 +814,7 @@ void GunnerGrenade (edict_t *self)
if (self->moreflags & FL2_COMMANDER) if (self->moreflags & FL2_COMMANDER)
{ {
float prox_timer = (blindfire) ? 60.0f : 30.0f; float prox_timer = (blindfire) ? 60.0f : 30.0f;
monster_fire_prox (self, start, aim, 90, 1, 600, 20, prox_timer, 192, flash_number); monster_fire_prox (self, start, aim, 90, 1, GRENADE_VELOCITY, 20, prox_timer, 192, flash_number);
} }
else else
monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, false); monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, false);
@ -879,7 +948,7 @@ void gunner_attack (edict_t *self)
{ {
// if the check passes, go for the attack // if the check passes, go for the attack
self->monsterinfo.currentmove = &gunner_move_attack_grenade; self->monsterinfo.currentmove = &gunner_move_attack_grenade;
self->monsterinfo.attack_finished = level.time + 2*random(); self->monsterinfo.attack_finished = level.time + 2 * random();
} }
// pmm - should this be active? // pmm - should this be active?
// else // else
@ -1294,7 +1363,7 @@ void SP_monster_gunner (edict_t *self)
if (!self->health) if (!self->health)
self->health = 400; self->health = 400;
if (!self->gib_health) if (!self->gib_health)
self->gib_health = -150; self->gib_health = -250;
if (!self->mass) if (!self->mass)
self->mass = 300; self->mass = 300;

View file

@ -767,13 +767,15 @@ void medic_pain (edict_t *self, edict_t *other, float kick, int damage)
} }
else if (random() < 0.5) else if (random() < 0.5)
{ {
self->monsterinfo.currentmove = &medic_move_pain1;
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &medic_move_pain1;
} }
else else
{ {
self->monsterinfo.currentmove = &medic_move_pain2;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &medic_move_pain2;
} }
// PMM - clear duck flag // PMM - clear duck flag
if (self->monsterinfo.aiflags & AI_DUCKED) if (self->monsterinfo.aiflags & AI_DUCKED)

View file

@ -20,7 +20,7 @@ static int sound_idle;
void q1dog_idle (edict_t *self) void q1dog_idle (edict_t *self)
{ {
if(random() < 0.2) if (random() < 0.2)
gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0); gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
} }
@ -134,18 +134,14 @@ mmove_t q1dog_move_pain2 = {FRAME_painb1, FRAME_painb16, q1dog_frames_pain2, q1d
void q1dog_pain (edict_t *self, edict_t *other, float kick, int damage) void q1dog_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
self->pain_debounce_time = level.time + 1; self->pain_debounce_time = level.time + 1;
if (skill->value == 3)
return;
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); //WAS ATTN_IDLE gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); //WAS ATTN_IDLE
if (random() < 0.5)
if(random() < 0.5)
self->monsterinfo.currentmove = &q1dog_move_pain1; self->monsterinfo.currentmove = &q1dog_move_pain1;
else else
self->monsterinfo.currentmove = &q1dog_move_pain2; self->monsterinfo.currentmove = &q1dog_move_pain2;
@ -418,7 +414,7 @@ void q1dog_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage
self->deadflag = DEAD_DEAD; self->deadflag = DEAD_DEAD;
self->takedamage = DAMAGE_YES; self->takedamage = DAMAGE_YES;
if(random() < 0.5) if (random() < 0.5)
self->monsterinfo.currentmove = &q1dog_move_death1; self->monsterinfo.currentmove = &q1dog_move_death1;
else else
self->monsterinfo.currentmove = &q1dog_move_death2; self->monsterinfo.currentmove = &q1dog_move_death2;

View file

@ -170,9 +170,6 @@ void q1enforcer_pain (edict_t *self, edict_t *other, float kick, int damage)
else else
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
if (skill->value == 3)
return; // no pain anims in nightmare
if (damage <= 10) if (damage <= 10)
self->monsterinfo.currentmove = &q1enforcer_move_pain3; self->monsterinfo.currentmove = &q1enforcer_move_pain3;
else if (damage <= 25) else if (damage <= 25)

View file

@ -367,11 +367,7 @@ void fiend_pain (edict_t *self, edict_t *other, float kick, int damage)
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
if (skill->value == 3)
return; // no pain anims in nightmare
self->monsterinfo.currentmove = &fiend_move_pain; self->monsterinfo.currentmove = &fiend_move_pain;
} }

View file

@ -20,7 +20,7 @@ static int sound_attack;
void q1grunt_idle (edict_t *self) void q1grunt_idle (edict_t *self)
{ {
if(!self->enemy) if (!self->enemy)
if (random() > 0.8) if (random() > 0.8)
{ {
gi.sound (self, CHAN_VOICE, sound_idle, 0.8, ATTN_STATIC, 0); gi.sound (self, CHAN_VOICE, sound_idle, 0.8, ATTN_STATIC, 0);
@ -181,28 +181,28 @@ void q1grunt_pain (edict_t *self, edict_t *other, float kick, int damage)
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
if(self->health <= 0) if (self->health <= 0)
return; return;
r = random(); r = random();
if (r < 0.2) if (r < 0.2)
{ {
self->monsterinfo.currentmove = &q1grunt_move_pain1;
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 0.6; self->pain_debounce_time = level.time + 0.6;
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1grunt_move_pain1;
} }
else if (r < 0.6) else if (r < 0.6)
{ {
self->monsterinfo.currentmove = &q1grunt_move_pain2;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.1; self->pain_debounce_time = level.time + 1.1;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1grunt_move_pain2;
} }
else else
{ {
self->monsterinfo.currentmove = &q1grunt_move_pain3;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.1; self->pain_debounce_time = level.time + 1.1;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1grunt_move_pain3;
} }
} }
@ -220,7 +220,7 @@ void q1grunt_fire (edict_t *self)
vec3_t end; vec3_t end;
float r, u; float r, u;
if(!self->enemy) if (!self->enemy)
return; return;
AngleVectors (self->s.angles, forward, right, NULL); AngleVectors (self->s.angles, forward, right, NULL);

View file

@ -294,16 +294,13 @@ mframe_t hknight_frames_pain1 [] =
mmove_t hknight_move_pain1 = {FRAME_pain1, FRAME_pain5, hknight_frames_pain1, hknight_run}; mmove_t hknight_move_pain1 = {FRAME_pain1, FRAME_pain5, hknight_frames_pain1, hknight_run};
void hknight_pain (edict_t *self, edict_t *other, float kick, int damage) void hknight_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
if (skill->value == 3) self->pain_debounce_time = level.time + 1.1;
return; // no pain anims in nightmare
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.1;
self->monsterinfo.currentmove = &hknight_move_pain1; self->monsterinfo.currentmove = &hknight_move_pain1;
} }

View file

@ -289,21 +289,16 @@ mframe_t knight_frames_pain2 [] =
mmove_t knight_move_pain2 = {FRAME_painb1, FRAME_painb11, knight_frames_pain2, knight_run}; mmove_t knight_move_pain2 = {FRAME_painb1, FRAME_painb11, knight_frames_pain2, knight_run};
void knight_pain (edict_t *self, edict_t *other, float kick, int damage) void knight_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
if (skill->value == 3) self->pain_debounce_time = level.time + 1.1;
return; // no pain anims in nightmare
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
if (random() < 0.85)
self->pain_debounce_time = level.time + 1.1;
if (random() <0.85)
self->monsterinfo.currentmove = &knight_move_pain1; self->monsterinfo.currentmove = &knight_move_pain1;
else else
self->monsterinfo.currentmove = &knight_move_pain2; self->monsterinfo.currentmove = &knight_move_pain2;

View file

@ -211,33 +211,28 @@ void ogre_pain (edict_t *self, edict_t *other, float kick, int damage)
if (r < 0.25) if (r < 0.25)
{ {
self->monsterinfo.currentmove = &ogre_move_pain1;
self->pain_debounce_time = level.time + 1; self->pain_debounce_time = level.time + 1;
self->monsterinfo.currentmove = &ogre_move_pain1;
} }
else if (r < 0.5) else if (r < 0.5)
{ {
self->monsterinfo.currentmove = &ogre_move_pain2;
self->pain_debounce_time = level.time + 1; self->pain_debounce_time = level.time + 1;
self->monsterinfo.currentmove = &ogre_move_pain2;
} }
else if (r < 0.75) else if (r < 0.75)
{ {
self->monsterinfo.currentmove = &ogre_move_pain3;
self->pain_debounce_time = level.time + 1; self->pain_debounce_time = level.time + 1;
self->monsterinfo.currentmove = &ogre_move_pain3;
} }
else if (r < 0.88) else if (r < 0.88)
{ {
self->monsterinfo.currentmove = &ogre_move_pain4;
self->pain_debounce_time = level.time + 2; self->pain_debounce_time = level.time + 2;
self->monsterinfo.currentmove = &ogre_move_pain4;
} }
else else
{ {
self->monsterinfo.currentmove = &ogre_move_pain5;
self->pain_debounce_time = level.time + 2; self->pain_debounce_time = level.time + 2;
self->monsterinfo.currentmove = &ogre_move_pain5;
} }
} }
@ -351,7 +346,7 @@ void ogre_grenade_fire (edict_t *self)
vec3_t start, target; vec3_t start, target;
vec3_t forward, right, aim; vec3_t forward, right, aim;
vec_t monster_speed; // vec_t monster_speed;
AngleVectors (self->s.angles, forward, right, NULL); AngleVectors (self->s.angles, forward, right, NULL);
G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GUNNER_GRENADE_1], forward, right, start); G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GUNNER_GRENADE_1], forward, right, start);
@ -367,9 +362,7 @@ void ogre_grenade_fire (edict_t *self)
else else
target[2] += self->enemy->viewheight*0.8; target[2] += self->enemy->viewheight*0.8;
// VectorSubtract (target, start, aim); #if 0
// VectorNormalize (aim);
if (self->enemy) if (self->enemy)
{ {
float range; float range;
@ -417,6 +410,10 @@ void ogre_grenade_fire (edict_t *self)
VectorMA (aim, delta, v1, aim); VectorMA (aim, delta, v1, aim);
VectorNormalize (aim); VectorNormalize (aim);
} }
#else
VectorSubtract (target, start, aim);
VectorNormalize (aim);
#endif
gi.WriteByte (svc_muzzleflash); gi.WriteByte (svc_muzzleflash);
gi.WriteShort (self-g_edicts); gi.WriteShort (self-g_edicts);
@ -424,8 +421,8 @@ void ogre_grenade_fire (edict_t *self)
gi.multicast (self->s.origin, MULTICAST_PVS); gi.multicast (self->s.origin, MULTICAST_PVS);
gi.sound (self, CHAN_WEAPON|CHAN_RELIABLE, sound_shoot, 1.0, ATTN_NORM, 0); gi.sound (self, CHAN_WEAPON|CHAN_RELIABLE, sound_shoot, 1.0, ATTN_NORM, 0);
// q1_fire_grenade (self, start, aim, 40, 600, 2.5, 80); q1_fire_grenade (self, start, aim, 40, 600, 2.5, 80);
q1_fire_grenade (self, start, aim, 40, GRENADE_VELOCITY, 2.5, 80); // q1_fire_grenade (self, start, aim, 40, GRENADE_VELOCITY, 2.5, 80);
} }

View file

@ -134,6 +134,7 @@ void q1rotfish_bite (edict_t *self)
VectorSet (aim, Q1_FISH_MELEE_DISTANCE, 0, 0); VectorSet (aim, Q1_FISH_MELEE_DISTANCE, 0, 0);
gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0); gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0);
fire_hit (self, aim, (random() + random()) * 3, 0); fire_hit (self, aim, (random() + random()) * 3, 0);
} }
@ -167,6 +168,11 @@ void q1rotfish_melee(edict_t *self)
void q1rotfish_pain (edict_t *self, edict_t *other, float kick, int damage) void q1rotfish_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
if (level.time < self->pain_debounce_time)
return;
self->pain_debounce_time = level.time + 1.1;
self->monsterinfo.currentmove = &q1rotfish_move_pain1; self->monsterinfo.currentmove = &q1rotfish_move_pain1;
} }

View file

@ -152,11 +152,10 @@ void scrag_pain (edict_t *self, edict_t *other, float kick, int damage)
return; return;
self->pain_debounce_time = level.time + 2; self->pain_debounce_time = level.time + 2;
if (skill->value == 3)
return; // no pain anims in nightmare
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &scrag_move_pain; self->monsterinfo.currentmove = &scrag_move_pain;
} }

View file

@ -116,16 +116,18 @@ mmove_t q1shalrath_move_pain1 = {FRAME_pain1, FRAME_pain5, q1shalrath_frames_pai
void q1shalrath_pain (edict_t *self, edict_t *other, float kick, int damage) void q1shalrath_pain (edict_t *self, edict_t *other, float kick, int damage)
{ {
float r; // float r;
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
r = random(); // r = random();
self->pain_debounce_time = level.time + 3;
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1shalrath_move_pain1; self->monsterinfo.currentmove = &q1shalrath_move_pain1;
gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 3;
} }

View file

@ -31,7 +31,7 @@ void shambler_sight (edict_t *self, edict_t *other)
/*static*/ void shambler_idle_sound (edict_t *self) /*static*/ void shambler_idle_sound (edict_t *self)
{ {
if(!self->enemy && random() > 0.8) if (!self->enemy && random() > 0.8)
gi.sound (self, CHAN_VOICE, sound_idle, 0.8, ATTN_IDLE, 0); gi.sound (self, CHAN_VOICE, sound_idle, 0.8, ATTN_IDLE, 0);
} }
@ -154,13 +154,10 @@ void shambler_pain (edict_t *self, edict_t *other, float kick, int damage)
if (self->health <= 0) if (self->health <= 0)
return; return;
if (skill->value == 3)
return; // no pain anims in nightmare
if (self->health > 0) if (self->health > 0)
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0); gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
if(random() * 400 > damage) if (random() * 400 > damage)
return; return;
self->monsterinfo.currentmove = &shambler_move_pain; self->monsterinfo.currentmove = &shambler_move_pain;
@ -266,7 +263,7 @@ void shambler_swing_right (edict_t *self)
{ {
vec3_t aim; vec3_t aim;
if(!self->enemy) if (!self->enemy)
return; return;
VectorSet (aim, MELEE_DISTANCE*1.2, self->maxs[0], 8); VectorSet (aim, MELEE_DISTANCE*1.2, self->maxs[0], 8);
@ -293,7 +290,7 @@ void shambler_smash (edict_t *self)
{ {
vec3_t aim; vec3_t aim;
if(!self->enemy) if (!self->enemy)
return; return;
VectorSet (aim, MELEE_DISTANCE*1.2, self->maxs[0], self->maxs[2]); VectorSet (aim, MELEE_DISTANCE*1.2, self->maxs[0], self->maxs[2]);
@ -472,7 +469,7 @@ void shambler_attack (edict_t *self)
self->monsterinfo.currentmove = &shambler_move_swingR_attack; self->monsterinfo.currentmove = &shambler_move_swingR_attack;
} }
} }
else if((len > 196 && len < 1024) && infront(self,self->enemy)) else if ((len > 196 && len < 1024) && infront(self,self->enemy))
{ {
self->monsterinfo.currentmove = &shambler_move_magic_attack; self->monsterinfo.currentmove = &shambler_move_magic_attack;
} }
@ -486,7 +483,7 @@ void shambler_melee(edict_t *self)
{ {
if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0) if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0)
{ {
// if(random() > 0.5) // if (random() > 0.5)
// self->monsterinfo.currentmove = &shambler_move_walk; // self->monsterinfo.currentmove = &shambler_move_walk;
return; return;
} }
@ -497,7 +494,7 @@ void shambler_melee(edict_t *self)
self->monsterinfo.currentmove = &shambler_move_smash_attack; self->monsterinfo.currentmove = &shambler_move_smash_attack;
else else
{ {
if(random() > 0.5) if (random() > 0.5)
self->monsterinfo.currentmove = &shambler_move_swingL_attack; self->monsterinfo.currentmove = &shambler_move_swingL_attack;
else else
self->monsterinfo.currentmove = &shambler_move_swingR_attack; self->monsterinfo.currentmove = &shambler_move_swingR_attack;

View file

@ -551,32 +551,32 @@ void q1zombie_pain (edict_t *self, edict_t *other, float kick, int damage)
} }
if (self->pain_debounce_time > level.time) if (self->pain_debounce_time > level.time)
return; return;
r = random(); r = random();
if (r < 0.25) if (r < 0.25)
{ {
self->monsterinfo.currentmove = &q1zombie_move_pain1;
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.0; self->pain_debounce_time = level.time + 1.0;
gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1zombie_move_pain1;
} }
else if (r < 0.5) else if (r < 0.5)
{ {
self->monsterinfo.currentmove = &q1zombie_move_pain2;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.5; self->pain_debounce_time = level.time + 1.5;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1zombie_move_pain2;
} }
else if (r < 0.75) else if (r < 0.75)
{ {
self->monsterinfo.currentmove = &q1zombie_move_pain3;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->pain_debounce_time = level.time + 1.1; self->pain_debounce_time = level.time + 1.1;
gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
self->monsterinfo.currentmove = &q1zombie_move_pain3;
} }
else else
{ {
self->monsterinfo.currentmove = &q1zombie_move_pain4;
self->pain_debounce_time = level.time + 1.0; self->pain_debounce_time = level.time + 1.0;
self->monsterinfo.currentmove = &q1zombie_move_pain4;
} }
} }

View file

@ -276,7 +276,7 @@ void tank_pain (edict_t *self, edict_t *other, float kick, int damage)
return; return;
if (level.time < self->pain_debounce_time) if (level.time < self->pain_debounce_time)
return; return;
if (damage <= 30) if (damage <= 30)
if (random() > 0.2) if (random() > 0.2)