mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2025-01-18 06:22:30 +00:00
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:
parent
308e1b13c4
commit
e872299cbd
16 changed files with 230 additions and 65 deletions
|
@ -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;
|
||||
|
|
|
@ -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 ) ;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
141
game/m_gunner.c
141
game/m_gunner.c
|
@ -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 [] =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ) ;
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 [] =
|
||||
|
|
Loading…
Reference in a new issue