Excluded monsters in death anim from hint_path developer command in default Lazarus and missionpack DLLs.

Added close-range safety check for gunners with contact grenades in default Lazarus and missionpack DLLs.
This commit is contained in:
Knightmare66 2021-08-24 04:50:59 -04:00
parent 308e1b13c4
commit e872299cbd
16 changed files with 230 additions and 65 deletions

View file

@ -2506,7 +2506,7 @@ void ClientCommand (edict_t *ent)
gi.dprintf("Not looking at an entity.\n");
return;
}
if (!(viewing->svflags & SVF_MONSTER) || (viewing->svflags & SVF_DEADMONSTER))
if ( !(viewing->svflags & SVF_MONSTER) || (viewing->svflags & SVF_DEADMONSTER) || (viewing->deadflag != DEAD_NO) )
{
gi.dprintf("hint_test is only valid for live monsters and actors.\n");
return;

View file

@ -443,6 +443,7 @@ extern void gunner_duck_up ( edict_t * self ) ;
extern void gunner_duck_hold ( edict_t * self ) ;
extern void gunner_duck_down ( edict_t * self ) ;
extern qboolean gunner_grenade_check ( edict_t * self ) ;
extern qboolean gunner_ctgrenade_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_dead ( edict_t * self ) ;
extern void gunner_pain ( edict_t * self , edict_t * other , float kick , int damage ) ;

View file

@ -443,6 +443,7 @@
{"gunner_duck_hold", (byte *)gunner_duck_hold},
{"gunner_duck_down", (byte *)gunner_duck_down},
{"gunner_grenade_check", (byte *)gunner_grenade_check},
{"gunner_ctgrenade_safety_check", (byte *)gunner_ctgrenade_safety_check},
{"gunner_die", (byte *)gunner_die},
{"gunner_dead", (byte *)gunner_dead},
{"gunner_pain", (byte *)gunner_pain},

View file

@ -824,7 +824,7 @@ extern cvar_t *vid_ref;
extern cvar_t *zoomrate;
extern cvar_t *zoomsnap;
extern cvar_t *blaster_color; // Knightmare added
extern cvar_t *g_showlogic; // Knightmare added
extern int max_modelindex;
extern int max_soundindex;

View file

@ -136,7 +136,7 @@ cvar_t *zoomsnap;
cvar_t *sv_stopspeed; //PGM (this was a define in g_phys.c)
cvar_t *sv_step_fraction; // Knightmare- this was a define in p_view.c
cvar_t *blaster_color; // Knightmare added
cvar_t *g_showlogic; // Knightmare added
void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
void ClientThink (edict_t *ent, usercmd_t *cmd);

View file

@ -1461,7 +1461,7 @@ void HintTestNext (edict_t *self, edict_t *hint)
self->ideal_yaw = vectoyaw(dir);
self->goalentity = self->movetarget = next;
self->monsterinfo.pausetime = 0;
self->monsterinfo.aiflags = AI_HINT_TEST;
self->monsterinfo.aiflags |= AI_HINT_TEST;
// run for it
self->monsterinfo.run (self);
gi.dprintf("%s (%s): Reached hint_path %s,\nsearching for hint_path %s at %s. %s\n",
@ -1523,7 +1523,7 @@ int HintTestStart (edict_t *self)
self->enemy = self->oldenemy = NULL;
self->goalentity = self->movetarget = hint;
self->monsterinfo.pausetime = 0;
self->monsterinfo.aiflags = AI_HINT_TEST;
self->monsterinfo.aiflags |= AI_HINT_TEST;
// run for it
self->monsterinfo.run (self);
return 1;

View file

@ -476,7 +476,7 @@ void InitGame (void)
crossh = gi.cvar ("crossh", "1", 0);
allow_download = gi.cvar("allow_download", "0", 0);
blaster_color = gi.cvar("blaster_color", "1", 0); // Knightmare added
g_showlogic = gi.cvar("g_showlogic", "0", 0); // Knightmare added
// If this is an SP game and "readout" is not set, force allow_download off
// so we don't get the annoying "Refusing to download path with .." messages

View file

@ -384,6 +384,38 @@ void gunner_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damag
self->monsterinfo.currentmove = &gunner_move_death;
}
// Knightmare added
// This does a short-range trace at blast radius, to ensure we won't clip a wall.
#define GUNNER_CTGRENADE_DANGER_RANGE 128.0f
qboolean gunner_ctgrenade_safety_check (edict_t *self, vec3_t start, vec3_t target)
{
trace_t tr;
vec3_t dir, dangerOffset, dangerTarget;
float dist;
// get dist to target
VectorSubtract (target, start, dir);
dist = VectorLength (dir);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("Gunner: perfoming close-range contactgrenade safety check- ");
// extrapolate point on path to target at danger range
VectorNormalize (dir);
VectorScale (dir, GUNNER_CTGRENADE_DANGER_RANGE, dangerOffset);
VectorAdd (start, dangerOffset, dangerTarget);
tr = gi.trace(start, vec3_origin, vec3_origin, 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)
{
vec3_t start;
@ -392,7 +424,8 @@ qboolean gunner_grenade_check (edict_t *self)
trace_t tr;
vec3_t dir;
vec3_t vhorz;
float horz,vertmax;
float horz, vertmax, dangerClose;
qboolean isContact = (self->spawnflags & SF_MONSTER_SPECIAL);
if (!self->enemy)
return false;
@ -411,8 +444,13 @@ qboolean gunner_grenade_check (edict_t *self)
G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GUNNER_GRENADE_1], forward, right, start);
// see if we're too close
// Knightmare- use longer range for contact grenades
if (isContact)
dangerClose = 128.0f;
else
dangerClose = 100.0f;
VectorSubtract (self->enemy->s.origin, self->s.origin, dir);
if (VectorLength(dir) < 100)
if (VectorLength(dir) < dangerClose)
return false;
// Lazarus: Max vertical distance - this is approximate and conservative
@ -431,13 +469,31 @@ qboolean gunner_grenade_check (edict_t *self)
target[2] = self->enemy->absmax[2];
tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1)
return true;
{
VectorCopy (target, self->pos0); // save this aim location in case later safety check fails
// Knightmare- added close-range contact grenade safety checks
if (isContact) {
if ( gunner_ctgrenade_safety_check(self, start, target) )
return true;
}
else
return true;
}
// Repeat for feet... in case we're looking down at a target standing under,
// for example, a short doorway
target[2] = self->enemy->absmin[2];
tr = gi.trace(start, vec3_origin, vec3_origin, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1)
return true;
{
VectorCopy (target, self->pos0); // save this aim location in case later safety check fails
// Knightmare- added close-range contact grenade safety checks
if (isContact) {
if ( gunner_ctgrenade_safety_check(self, start, target) )
return true;
}
else
return true;
}
return false;
}
@ -538,11 +594,15 @@ void GunnerFire (edict_t *self)
void GunnerGrenade (edict_t *self)
{
vec3_t start,target;
vec3_t forward, right, up;
vec3_t aim;
vec_t monster_speed;
int flash_number;
vec3_t start, target, leadTarget;
vec3_t forward, right, up;
vec3_t aim;
vec_t monster_speed;
int flash_number;
qboolean leadingTarget = false;
qboolean targetSafe = false;
qboolean leadSafe = false;
qboolean isContact = (self->spawnflags & SF_MONSTER_SPECIAL);
if (!self->enemy || !self->enemy->inuse)
return;
@ -573,7 +633,54 @@ void GunnerGrenade (edict_t *self)
// aim at enemy's feet if he's at same elevation or lower. otherwise aim at origin
VectorCopy (self->enemy->s.origin, target);
if (self->enemy->absmin[2] <= self->absmax[2]) target[2] = self->enemy->absmin[2];
if (self->enemy->absmin[2] <= self->absmax[2])
target[2] = self->enemy->absmin[2];
// lead target... 20, 35, 50, 65 chance of leading
if ( random() < (0.2 + skill->value * 0.15) )
{
float dist;
float time;
VectorSubtract (target, start, aim);
dist = VectorLength (aim);
time = dist / GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA (target, time, self->enemy->velocity, leadTarget);
if (!isContact) // delay copying for ctgrenade safety check
VectorCopy (leadTarget, target);
leadingTarget = true;
}
if (isContact)
{
if ( gunner_ctgrenade_safety_check(self, start, target) ) {
VectorCopy (target, self->pos0); // save this target point
targetSafe = true;
}
if ( leadingTarget && gunner_ctgrenade_safety_check(self, start, leadTarget) ) {
VectorCopy (leadTarget, target); // copy lead point over target
leadSafe = true;
}
if ( !targetSafe && !leadSafe ) {
VectorCopy (self->pos0, target); // revert to prev target point
}
/* if ( (g_showlogic) && (g_showlogic->value) )
{
if ( targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at and lead target, saving target point.\n");
else if ( targetSafe && leadingTarget && !leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at but not lead target, saving target point.\n");
else if ( targetSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: safe to fire at target, saving target point.\n");
else if ( !targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to lead target only, not saving target point.\n");
else if ( !targetSafe && !leadSafe && leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at or lead target, reverting to prev target point.\n");
else if ( !targetSafe && !leadSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at target, reverting to prev target point.\n");
} */
}
// Lazarus fog reduction of accuracy
if (self->monsterinfo.visibility < FOG_CANSEEGOOD)
@ -595,18 +702,6 @@ void GunnerGrenade (edict_t *self)
target[1] += crandom() * dist/8 * (2 - skill->value);
} */
// lead target... 20, 35, 50, 65 chance of leading
if ( random() < (0.2 + skill->value * 0.15) )
{
float dist;
float time;
VectorSubtract (target, start, aim);
dist = VectorLength (aim);
time = dist / GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA (target, time, self->enemy->velocity, target);
}
AimGrenade (self, start, target, GRENADE_VELOCITY, aim);
// Lazarus - take into account (sort of) feature of adding shooter's velocity to
// grenade velocity
@ -623,7 +718,7 @@ void GunnerGrenade (edict_t *self)
VectorNormalize (aim);
}
monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, (self->spawnflags & SF_MONSTER_SPECIAL));
monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, isContact);
}
mframe_t gunner_frames_attack_chain [] =

View file

@ -2356,7 +2356,7 @@ void ClientCommand (edict_t *ent)
gi.dprintf("Not looking at an entity.\n");
return;
}
if (!(viewing->svflags & SVF_MONSTER) || (viewing->svflags & SVF_DEADMONSTER))
if ( !(viewing->svflags & SVF_MONSTER) || (viewing->svflags & SVF_DEADMONSTER) || (viewing->deadflag != DEAD_NO) )
{
gi.dprintf("hint_test is only valid for live monsters and actors.\n");
return;

View file

@ -1133,6 +1133,7 @@ extern void GunnerFire ( edict_t * self ) ;
extern void gunner_opengun ( edict_t * self ) ;
extern void gunner_duck_down ( edict_t * self ) ;
extern qboolean gunner_grenade_check ( edict_t * self ) ;
extern qboolean gunner_ctgrenade_safety_check ( edict_t * self , vec3_t start , vec3_t target ) ;
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_dead ( edict_t * self ) ;

View file

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

View file

@ -2487,12 +2487,12 @@ struct edict_s
char *common_name;
char *newtargetname; //used with target_change
char *followtarget; //used with func_door_swinging
char *newtargetname; // used with target_change
char *followtarget; // used with func_door_swinging
char *destroytarget;
char *viewmessage;
char *source; //used with target_bmodel_spawner
char *newteam; //used with target_bmodel_spawner
char *source; // used with target_bmodel_spawner
char *newteam; // used with target_bmodel_spawner
char *musictrack; // Knightmare- for specifying OGG or CD track
@ -2500,7 +2500,7 @@ struct edict_s
// the origin of this entity:
char *move_to;
float distance; //target_playback stuff
float distance; // target_playback stuff
float duration;
float bob;
int lip;
@ -2511,7 +2511,7 @@ struct edict_s
vec3_t color;
float alpha;
float holdtime; //target_fade stuff
float holdtime; // target_fade stuff
float fadein;
float fadeout;

View file

@ -2787,7 +2787,7 @@ int HintTestStart (edict_t *self)
self->enemy = self->oldenemy = NULL;
self->goalentity = self->movetarget = hint;
self->monsterinfo.pausetime = 0;
self->monsterinfo.aiflags2 = AI2_HINT_TEST;
self->monsterinfo.aiflags2 |= AI2_HINT_TEST;
// run for it
self->monsterinfo.run (self);
return 1;

View file

@ -204,8 +204,7 @@ edict_t *CheckForProxField (edict_t *ent)
hit = touch[i];
if (!hit->inuse)
continue;
if (hit->class_id == ENTITY_PROX_FIELD)
{
if (hit->class_id == ENTITY_PROX_FIELD) {
return hit;
}
}

View file

@ -885,8 +885,12 @@ void ED_CallSpawn (edict_t *ent)
&& !(ent->monsterinfo.monsterflags & MFL_DO_NOT_COUNT))
ent->classname = "monster_medic_commander";
// gunner
if ( !strcmp(ent->classname, "monster_gunner") && (random() < ((skill->value + 1.0f) * 0.15f)) )
ent->classname = "monster_gunner_tactician";
if ( !strcmp(ent->classname, "monster_gunner") ) {
if (random() < ((skill->value + 1.0f) * 0.15f))
ent->classname = "monster_gunner_tactician";
else
ent->spawnflags |= SF_MONSTER_SPECIAL;
}
}
// LM Escape monster replacement

View file

@ -467,6 +467,39 @@ qboolean gunner_prox_safety_check (edict_t *self, vec3_t start, vec3_t target)
return true;
}
// Knightmare added
// This does a short-range trace at blast radius, to ensure we won't clip a wall.
#define GUNNER_CTGRENADE_DANGER_RANGE 128.0f
qboolean gunner_ctgrenade_safety_check (edict_t *self, vec3_t start, vec3_t target)
{
trace_t tr;
vec3_t dir, dangerOffset, dangerTarget;
float dist;
// get dist to target
VectorSubtract (target, start, dir);
dist = VectorLength (dir);
// if ((g_showlogic) && (g_showlogic->value))
// gi.dprintf ("Gunner: perfoming close-range contactgrenade safety check- ");
// extrapolate point on path to target at danger range
VectorNormalize (dir);
VectorScale (dir, GUNNER_CTGRENADE_DANGER_RANGE, dangerOffset);
VectorAdd (start, dangerOffset, dangerTarget);
tr = gi.trace(start, vec3_origin, vec3_origin, 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)
{
vec3_t start;
@ -477,6 +510,7 @@ qboolean gunner_grenade_check (edict_t *self)
vec3_t vhorz;
float horz, vertmax, dangerClose;
qboolean isProx = (self->moreflags & FL2_COMMANDER);
qboolean isContact = (self->spawnflags & SF_MONSTER_SPECIAL);
// Knightmare- Tactician Gunner fires prox mines in a spread,
// so we need a wider safety bounds check
vec3_t checkMins, checkMaxs;
@ -510,8 +544,11 @@ qboolean gunner_grenade_check (edict_t *self)
// see if we're too close
// Knightmare- Tactician Gunner's prox mines stick around, so only use at longer range
// Also use longer range for contact grenades
if (isProx)
dangerClose = 320.0f;
else if (isContact)
dangerClose = 128.0f;
else
dangerClose = 100.0f;
VectorSubtract (self->enemy->s.origin, self->s.origin, dir);
@ -534,10 +571,15 @@ qboolean gunner_grenade_check (edict_t *self)
target[2] = self->enemy->absmax[2];
tr = gi.trace(start, checkMins, checkMaxs, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1)
{ // Knightmare- added close-range prox safety check
{
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
// Knightmare- added close-range prox and contact grenade safety checks
if (isProx) {
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
if (gunner_prox_safety_check(self, start, target))
if ( gunner_prox_safety_check(self, start, target) )
return true;
}
else if (isContact) {
if ( gunner_ctgrenade_safety_check(self, start, target) )
return true;
}
else
@ -548,10 +590,15 @@ qboolean gunner_grenade_check (edict_t *self)
target[2] = self->enemy->absmin[2];
tr = gi.trace(start, checkMins, checkMaxs, target, self, MASK_SHOT);
if (tr.ent == self->enemy || tr.fraction == 1)
{ // Knightmare- added close-range prox safety check
{
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
// Knightmare- added close-range prox and contact grenade safety checks
if (isProx) {
VectorCopy (target, self->aim_point); // save this aim location in case later safety check fails
if (gunner_prox_safety_check(self, start, target))
if ( gunner_prox_safety_check(self, start, target) )
return true;
}
else if (isContact) {
if ( gunner_ctgrenade_safety_check(self, start, target) )
return true;
}
else
@ -694,6 +741,7 @@ void GunnerGrenade (edict_t *self)
qboolean targetSafe = false;
qboolean leadSafe = false;
qboolean isProx = (self->moreflags & FL2_COMMANDER);
qboolean isContact = (self->spawnflags & SF_MONSTER_SPECIAL);
//PGM
if (!self->enemy || !self->enemy->inuse)
@ -766,12 +814,13 @@ void GunnerGrenade (edict_t *self)
dist = VectorLength (aim);
time = dist / GRENADE_VELOCITY; // Not correct, but better than nothin'
VectorMA (target, time, self->enemy->velocity, leadTarget);
if (!isProx) // delay copying for prox safety check
if (!isProx && !isContact) // delay copying for prox/ctgrenade safety check
VectorCopy (leadTarget, target);
leadingTarget = true;
}
if (isProx) // Knightmare- run another safety check before firing, so players can't trick us into self-damage
// Knightmare- run another safety check before firing, so players can't trick us into self-damage
if (isProx)
{
if ( gunner_prox_safety_check(self, start, target) ) {
VectorCopy (target, self->aim_point); // save this target point
@ -784,22 +833,36 @@ void GunnerGrenade (edict_t *self)
if ( !targetSafe && !leadSafe ) {
VectorCopy (self->aim_point, target); // revert to prev target point
}
/* if ((g_showlogic) && (g_showlogic->value))
{
if ( targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at and lead target, saving target point.\n");
else if ( targetSafe && leadingTarget && !leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at but not lead target, saving target point.\n");
else if ( targetSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: safe to fire at target, saving target point.\n");
else if ( !targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to lead target only, not saving target point.\n");
else if ( !targetSafe && !leadSafe && leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at or lead target, reverting to prev target point.\n");
else if ( !targetSafe && !leadSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at target, reverting to prev target point.\n");
} */
}
else if (isContact)
{
if ( gunner_ctgrenade_safety_check(self, start, target) ) {
VectorCopy (target, self->aim_point); // save this target point
targetSafe = true;
}
if ( leadingTarget && gunner_ctgrenade_safety_check(self, start, leadTarget) ) {
VectorCopy (leadTarget, target); // copy lead point over target
leadSafe = true;
}
if ( !targetSafe && !leadSafe ) {
VectorCopy (self->aim_point, target); // revert to prev target point
}
}
/* if ( (isProx || isContact) && (g_showlogic) && (g_showlogic->value) )
{
if ( targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at and lead target, saving target point.\n");
else if ( targetSafe && leadingTarget && !leadSafe )
gi.dprintf ("GunnerGrenade: safe to fire at but not lead target, saving target point.\n");
else if ( targetSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: safe to fire at target, saving target point.\n");
else if ( !targetSafe && leadSafe )
gi.dprintf ("GunnerGrenade: safe to lead target only, not saving target point.\n");
else if ( !targetSafe && !leadSafe && leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at or lead target, reverting to prev target point.\n");
else if ( !targetSafe && !leadSafe && !leadingTarget )
gi.dprintf ("GunnerGrenade: NOT safe to fire at target, reverting to prev target point.\n");
} */
// Knightmare- spread out Tactician Gunner's prox mines so they don't collide
if (isProx)
@ -858,7 +921,7 @@ void GunnerGrenade (edict_t *self)
monster_fire_prox (self, start, aim, 90, 1, GRENADE_VELOCITY, 20, prox_timer, 192, flash_number);
}
else
monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, (self->spawnflags & SF_MONSTER_SPECIAL));
monster_fire_grenade (self, start, aim, 50, GRENADE_VELOCITY, flash_number, isContact);
}
mframe_t gunner_frames_attack_chain [] =