mirror of
https://github.com/yquake2/rogue.git
synced 2025-02-18 10:01:41 +00:00
Cleanup g_turret.c and add sanity checks
This commit is contained in:
parent
695d83441e
commit
2f89dd8382
1 changed files with 442 additions and 237 deletions
421
src/g_turret.c
421
src/g_turret.c
|
@ -1,69 +1,108 @@
|
|||
// g_turret.c
|
||||
|
||||
#include "header/local.h"
|
||||
|
||||
void SpawnTargetingSystem (edict_t *turret); // PGM
|
||||
qboolean FindTarget(edict_t *self);
|
||||
void infantry_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage);
|
||||
void infantry_stand(edict_t *self);
|
||||
void monster_use(edict_t *self, edict_t *other, edict_t *activator);
|
||||
void SpawnTargetingSystem(edict_t *turret);
|
||||
|
||||
void AnglesNormalize(vec3_t vec)
|
||||
void
|
||||
AnglesNormalize(vec3_t vec)
|
||||
{
|
||||
while (vec[0] > 360)
|
||||
{
|
||||
vec[0] -= 360;
|
||||
while(vec[0] < 0)
|
||||
vec[0] += 360;
|
||||
while(vec[1] > 360)
|
||||
vec[1] -= 360;
|
||||
while(vec[1] < 0)
|
||||
vec[1] += 360;
|
||||
}
|
||||
|
||||
float SnapToEights(float x)
|
||||
while (vec[0] < 0)
|
||||
{
|
||||
vec[0] += 360;
|
||||
}
|
||||
|
||||
while (vec[1] > 360)
|
||||
{
|
||||
vec[1] -= 360;
|
||||
}
|
||||
|
||||
while (vec[1] < 0)
|
||||
{
|
||||
vec[1] += 360;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
SnapToEights(float x)
|
||||
{
|
||||
x *= 8.0;
|
||||
|
||||
if (x > 0.0)
|
||||
{
|
||||
x += 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
x -= 0.5;
|
||||
}
|
||||
|
||||
return 0.125 * (int)x;
|
||||
}
|
||||
|
||||
|
||||
void turret_blocked(edict_t *self, edict_t *other)
|
||||
void
|
||||
turret_blocked(edict_t *self, edict_t *other)
|
||||
{
|
||||
if (!self || !other)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
edict_t *attacker;
|
||||
|
||||
if (other->takedamage)
|
||||
{
|
||||
if (self->teammaster->owner)
|
||||
{
|
||||
attacker = self->teammaster->owner;
|
||||
}
|
||||
else
|
||||
{
|
||||
attacker = self->teammaster;
|
||||
T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH);
|
||||
}
|
||||
|
||||
T_Damage(other, self, attacker, vec3_origin, other->s.origin,
|
||||
vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH);
|
||||
}
|
||||
}
|
||||
|
||||
/*QUAKED turret_breach (0 0 0) ?
|
||||
This portion of the turret can change both pitch and yaw.
|
||||
The model should be made with a flat pitch.
|
||||
It (and the associated base) need to be oriented towards 0.
|
||||
Use "angle" to set the starting angle.
|
||||
|
||||
"speed" default 50
|
||||
"dmg" default 10
|
||||
"angle" point this forward
|
||||
"target" point this at an info_notnull at the muzzle tip
|
||||
"minpitch" min acceptable pitch angle : default -30
|
||||
"maxpitch" max acceptable pitch angle : default 30
|
||||
"minyaw" min acceptable yaw angle : default 0
|
||||
"maxyaw" max acceptable yaw angle : default 360
|
||||
/*
|
||||
* QUAKED turret_breach (0 0 0) ?
|
||||
* This portion of the turret can change both pitch and yaw.
|
||||
* The model should be made with a flat pitch.
|
||||
* It (and the associated base) need to be oriented towards 0.
|
||||
* Use "angle" to set the starting angle.
|
||||
*
|
||||
* "speed" default 50
|
||||
* "dmg" default 10
|
||||
* "angle" point this forward
|
||||
* "target" point this at an info_notnull at the muzzle tip
|
||||
* "minpitch" min acceptable pitch angle : default -30
|
||||
* "maxpitch" max acceptable pitch angle : default 30
|
||||
* "minyaw" min acceptable yaw angle : default 0
|
||||
* "maxyaw" max acceptable yaw angle : default 360
|
||||
*/
|
||||
|
||||
void turret_breach_fire (edict_t *self)
|
||||
void
|
||||
turret_breach_fire(edict_t *self)
|
||||
{
|
||||
vec3_t f, r, u;
|
||||
vec3_t start;
|
||||
int damage;
|
||||
int speed;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AngleVectors(self->s.angles, f, r, u);
|
||||
VectorMA(self->s.origin, self->move_origin[0], f, start);
|
||||
VectorMA(start, self->move_origin[1], r, start);
|
||||
|
@ -75,73 +114,127 @@ void turret_breach_fire (edict_t *self)
|
|||
gi.positioned_sound(start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0);
|
||||
}
|
||||
|
||||
void turret_breach_think (edict_t *self)
|
||||
void
|
||||
turret_breach_think(edict_t *self)
|
||||
{
|
||||
edict_t *ent;
|
||||
vec3_t current_angles;
|
||||
vec3_t delta;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy(self->s.angles, current_angles);
|
||||
AnglesNormalize(current_angles);
|
||||
|
||||
AnglesNormalize(self->move_angles);
|
||||
|
||||
if (self->move_angles[PITCH] > 180)
|
||||
{
|
||||
self->move_angles[PITCH] -= 360;
|
||||
}
|
||||
|
||||
// clamp angles to mins & maxs
|
||||
/* clamp angles to mins & maxs */
|
||||
if (self->move_angles[PITCH] > self->pos1[PITCH])
|
||||
{
|
||||
self->move_angles[PITCH] = self->pos1[PITCH];
|
||||
}
|
||||
else if (self->move_angles[PITCH] < self->pos2[PITCH])
|
||||
{
|
||||
self->move_angles[PITCH] = self->pos2[PITCH];
|
||||
}
|
||||
|
||||
if ((self->move_angles[YAW] < self->pos1[YAW]) || (self->move_angles[YAW] > self->pos2[YAW]))
|
||||
if ((self->move_angles[YAW] < self->pos1[YAW]) ||
|
||||
(self->move_angles[YAW] > self->pos2[YAW]))
|
||||
{
|
||||
float dmin, dmax;
|
||||
|
||||
dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]);
|
||||
|
||||
if (dmin < -180)
|
||||
{
|
||||
dmin += 360;
|
||||
}
|
||||
else if (dmin > 180)
|
||||
{
|
||||
dmin -= 360;
|
||||
}
|
||||
|
||||
dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]);
|
||||
|
||||
if (dmax < -180)
|
||||
{
|
||||
dmax += 360;
|
||||
}
|
||||
else if (dmax > 180)
|
||||
{
|
||||
dmax -= 360;
|
||||
}
|
||||
|
||||
if (fabs(dmin) < fabs(dmax))
|
||||
{
|
||||
self->move_angles[YAW] = self->pos1[YAW];
|
||||
}
|
||||
else
|
||||
{
|
||||
self->move_angles[YAW] = self->pos2[YAW];
|
||||
}
|
||||
}
|
||||
|
||||
VectorSubtract(self->move_angles, current_angles, delta);
|
||||
|
||||
if (delta[0] < -180)
|
||||
{
|
||||
delta[0] += 360;
|
||||
}
|
||||
else if (delta[0] > 180)
|
||||
{
|
||||
delta[0] -= 360;
|
||||
}
|
||||
|
||||
if (delta[1] < -180)
|
||||
{
|
||||
delta[1] += 360;
|
||||
}
|
||||
else if (delta[1] > 180)
|
||||
{
|
||||
delta[1] -= 360;
|
||||
}
|
||||
|
||||
delta[2] = 0;
|
||||
|
||||
if (delta[0] > self->speed * FRAMETIME)
|
||||
{
|
||||
delta[0] = self->speed * FRAMETIME;
|
||||
}
|
||||
|
||||
if (delta[0] < -1 * self->speed * FRAMETIME)
|
||||
{
|
||||
delta[0] = -1 * self->speed * FRAMETIME;
|
||||
}
|
||||
|
||||
if (delta[1] > self->speed * FRAMETIME)
|
||||
{
|
||||
delta[1] = self->speed * FRAMETIME;
|
||||
}
|
||||
|
||||
if (delta[1] < -1 * self->speed * FRAMETIME)
|
||||
{
|
||||
delta[1] = -1 * self->speed * FRAMETIME;
|
||||
}
|
||||
|
||||
VectorScale(delta, 1.0 / FRAMETIME, self->avelocity);
|
||||
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
|
||||
for (ent = self->teammaster; ent; ent = ent->teamchain)
|
||||
{
|
||||
ent->avelocity[1] = self->avelocity[1];
|
||||
}
|
||||
|
||||
// if we have adriver, adjust his velocities
|
||||
/* if we have adriver, adjust his velocities */
|
||||
if (self->owner)
|
||||
{
|
||||
float angle;
|
||||
|
@ -150,11 +243,11 @@ void turret_breach_think (edict_t *self)
|
|||
vec3_t target;
|
||||
vec3_t dir;
|
||||
|
||||
// angular is easy, just copy ours
|
||||
/* angular is easy, just copy ours */
|
||||
self->owner->avelocity[0] = self->avelocity[0];
|
||||
self->owner->avelocity[1] = self->avelocity[1];
|
||||
|
||||
// x & y
|
||||
/* x & y */
|
||||
angle = self->s.angles[1] + self->owner->move_origin[1];
|
||||
angle *= (M_PI * 2 / 360);
|
||||
target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]);
|
||||
|
@ -165,7 +258,7 @@ void turret_breach_think (edict_t *self)
|
|||
self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME;
|
||||
self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME;
|
||||
|
||||
// z
|
||||
/* z */
|
||||
angle = self->s.angles[PITCH] * (M_PI * 2 / 360);
|
||||
target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]);
|
||||
|
||||
|
@ -180,9 +273,15 @@ void turret_breach_think (edict_t *self)
|
|||
}
|
||||
}
|
||||
|
||||
void turret_breach_finish_init (edict_t *self)
|
||||
void
|
||||
turret_breach_finish_init(edict_t *self)
|
||||
{
|
||||
// get and save info for muzzle location
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* get and save info for muzzle location */
|
||||
if (!self->target)
|
||||
{
|
||||
gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin));
|
||||
|
@ -190,37 +289,59 @@ void turret_breach_finish_init (edict_t *self)
|
|||
else
|
||||
{
|
||||
self->target_ent = G_PickTarget(self->target);
|
||||
|
||||
if (self->target_ent)
|
||||
{
|
||||
VectorSubtract(self->target_ent->s.origin, self->s.origin, self->move_origin);
|
||||
G_FreeEdict(self->target_ent);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.dprintf("could not find target entity for %s at %s\n", self->classname, vtos(self->s.origin));
|
||||
}
|
||||
}
|
||||
|
||||
self->teammaster->dmg = self->dmg;
|
||||
self->think = turret_breach_think;
|
||||
self->think(self);
|
||||
}
|
||||
|
||||
void SP_turret_breach (edict_t *self)
|
||||
void
|
||||
SP_turret_breach(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->solid = SOLID_BSP;
|
||||
self->movetype = MOVETYPE_PUSH;
|
||||
gi.setmodel(self, self->model);
|
||||
|
||||
if (!self->speed)
|
||||
{
|
||||
self->speed = 50;
|
||||
}
|
||||
|
||||
if (!self->dmg)
|
||||
{
|
||||
self->dmg = 10;
|
||||
}
|
||||
|
||||
if (!st.minpitch)
|
||||
{
|
||||
st.minpitch = -30;
|
||||
}
|
||||
|
||||
if (!st.maxpitch)
|
||||
{
|
||||
st.maxpitch = 30;
|
||||
}
|
||||
|
||||
if (!st.maxyaw)
|
||||
{
|
||||
st.maxyaw = 360;
|
||||
}
|
||||
|
||||
self->pos1[PITCH] = -1 * st.minpitch;
|
||||
self->pos1[YAW] = st.minyaw;
|
||||
|
@ -237,14 +358,20 @@ void SP_turret_breach (edict_t *self)
|
|||
gi.linkentity(self);
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED turret_base (0 0 0) ?
|
||||
This portion of the turret changes yaw only.
|
||||
MUST be teamed with a turret_breach.
|
||||
/*
|
||||
* QUAKED turret_base (0 0 0) ?
|
||||
* This portion of the turret changes yaw only.
|
||||
* MUST be teamed with a turret_breach.
|
||||
*/
|
||||
|
||||
void SP_turret_base (edict_t *self)
|
||||
void
|
||||
SP_turret_base(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->solid = SOLID_BSP;
|
||||
self->movetype = MOVETYPE_PUSH;
|
||||
gi.setmodel(self, self->model);
|
||||
|
@ -252,26 +379,32 @@ void SP_turret_base (edict_t *self)
|
|||
gi.linkentity(self);
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32)
|
||||
Must NOT be on the team with the rest of the turret parts.
|
||||
Instead it must target the turret_breach.
|
||||
/*
|
||||
* QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32)
|
||||
* Must NOT be on the team with the rest of the turret parts.
|
||||
* Instead it must target the turret_breach.
|
||||
*/
|
||||
|
||||
void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage);
|
||||
void infantry_stand (edict_t *self);
|
||||
void monster_use (edict_t *self, edict_t *other, edict_t *activator);
|
||||
|
||||
void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
|
||||
void
|
||||
turret_driver_die(edict_t *self, edict_t *inflictor, edict_t *attacker,
|
||||
int damage, vec3_t point)
|
||||
{
|
||||
edict_t *ent;
|
||||
|
||||
// level the gun
|
||||
if (!self || !inflictor || !attacker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* level the gun */
|
||||
self->target_ent->move_angles[0] = 0;
|
||||
|
||||
// remove the driver from the end of them team chain
|
||||
for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain)
|
||||
;
|
||||
/* remove the driver from the end of them team chain */
|
||||
for (ent = self->target_ent->teammaster;
|
||||
ent->teamchain != self;
|
||||
ent = ent->teamchain)
|
||||
{
|
||||
}
|
||||
|
||||
ent->teamchain = NULL;
|
||||
self->teammaster = NULL;
|
||||
self->flags &= ~FL_TEAMSLAVE;
|
||||
|
@ -282,23 +415,32 @@ void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, in
|
|||
infantry_die(self, inflictor, attacker, damage);
|
||||
}
|
||||
|
||||
qboolean FindTarget (edict_t *self);
|
||||
|
||||
void turret_driver_think (edict_t *self)
|
||||
void
|
||||
turret_driver_think(edict_t *self)
|
||||
{
|
||||
vec3_t target;
|
||||
vec3_t dir;
|
||||
float reaction_time;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
|
||||
if (self->enemy && (!self->enemy->inuse || self->enemy->health <= 0))
|
||||
if (self->enemy && (!self->enemy->inuse || (self->enemy->health <= 0)))
|
||||
{
|
||||
self->enemy = NULL;
|
||||
}
|
||||
|
||||
if (!self->enemy)
|
||||
{
|
||||
if (!FindTarget(self))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.trail_time = level.time;
|
||||
self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
|
||||
}
|
||||
|
@ -319,30 +461,40 @@ void turret_driver_think (edict_t *self)
|
|||
}
|
||||
}
|
||||
|
||||
// let the turret know where we want it to aim
|
||||
/* let the turret know where we want it to aim */
|
||||
VectorCopy(self->enemy->s.origin, target);
|
||||
target[2] += self->enemy->viewheight;
|
||||
VectorSubtract(target, self->target_ent->s.origin, dir);
|
||||
vectoangles(dir, self->target_ent->move_angles);
|
||||
|
||||
// decide if we should shoot
|
||||
/* decide if we should shoot */
|
||||
if (level.time < self->monsterinfo.attack_finished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
reaction_time = (3 - skill->value) * 1.0;
|
||||
|
||||
if ((level.time - self->monsterinfo.trail_time) < reaction_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.attack_finished = level.time + reaction_time + 1.0;
|
||||
//FIXME how do we really want to pass this along?
|
||||
self->target_ent->spawnflags |= 65536;
|
||||
}
|
||||
|
||||
void turret_driver_link (edict_t *self)
|
||||
void
|
||||
turret_driver_link(edict_t *self)
|
||||
{
|
||||
vec3_t vec;
|
||||
edict_t *ent;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->think = turret_driver_think;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
|
||||
|
@ -363,16 +515,24 @@ void turret_driver_link (edict_t *self)
|
|||
|
||||
self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2];
|
||||
|
||||
// add the driver to the end of them team chain
|
||||
/* add the driver to the end of them team chain */
|
||||
for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain)
|
||||
;
|
||||
{
|
||||
}
|
||||
|
||||
ent->teamchain = self;
|
||||
self->teammaster = self->target_ent->teammaster;
|
||||
self->flags |= FL_TEAMSLAVE;
|
||||
}
|
||||
|
||||
void SP_turret_driver (edict_t *self)
|
||||
void
|
||||
SP_turret_driver(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (deathmatch->value)
|
||||
{
|
||||
G_FreeEdict(self);
|
||||
|
@ -408,9 +568,12 @@ void SP_turret_driver (edict_t *self)
|
|||
if (st.item)
|
||||
{
|
||||
self->item = FindItemByClassname(st.item);
|
||||
|
||||
if (!self->item)
|
||||
{
|
||||
gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item);
|
||||
}
|
||||
}
|
||||
|
||||
self->think = turret_driver_link;
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
|
@ -418,15 +581,14 @@ void SP_turret_driver (edict_t *self)
|
|||
gi.linkentity(self);
|
||||
}
|
||||
|
||||
//============
|
||||
// ROGUE
|
||||
/*
|
||||
* invisible turret drivers so we can have unmanned turrets.
|
||||
* originally designed to shoot at func_trains and such, so they
|
||||
* fire at the center of the bounding box, rather than the entity's
|
||||
* origin. */
|
||||
|
||||
// invisible turret drivers so we can have unmanned turrets.
|
||||
// originally designed to shoot at func_trains and such, so they
|
||||
// fire at the center of the bounding box, rather than the entity's
|
||||
// origin.
|
||||
|
||||
void turret_brain_think (edict_t *self)
|
||||
void
|
||||
turret_brain_think(edict_t *self)
|
||||
{
|
||||
vec3_t target;
|
||||
vec3_t dir;
|
||||
|
@ -434,20 +596,32 @@ void turret_brain_think (edict_t *self)
|
|||
float reaction_time;
|
||||
trace_t trace;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->nextthink = level.time + FRAMETIME;
|
||||
|
||||
if (self->enemy)
|
||||
{
|
||||
if (!self->enemy->inuse)
|
||||
{
|
||||
self->enemy = NULL;
|
||||
else if(self->enemy->takedamage && self->enemy->health <= 0)
|
||||
}
|
||||
else if (self->enemy->takedamage && (self->enemy->health <= 0))
|
||||
{
|
||||
self->enemy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->enemy)
|
||||
{
|
||||
if (!FindTarget(self))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.trail_time = level.time;
|
||||
self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
|
||||
}
|
||||
|
@ -456,8 +630,10 @@ void turret_brain_think (edict_t *self)
|
|||
VectorAdd(self->enemy->absmax, self->enemy->absmin, endpos);
|
||||
VectorScale(endpos, 0.5, endpos);
|
||||
|
||||
trace = gi.trace (self->target_ent->s.origin, vec3_origin, vec3_origin, endpos, self->target_ent, MASK_SHOT);
|
||||
if(trace.fraction == 1 || trace.ent == self->enemy)
|
||||
trace = gi.trace(self->target_ent->s.origin, vec3_origin, vec3_origin,
|
||||
endpos, self->target_ent, MASK_SHOT);
|
||||
|
||||
if ((trace.fraction == 1) || (trace.ent == self->enemy))
|
||||
{
|
||||
if (self->monsterinfo.aiflags & AI_LOST_SIGHT)
|
||||
{
|
||||
|
@ -472,33 +648,46 @@ void turret_brain_think (edict_t *self)
|
|||
}
|
||||
}
|
||||
|
||||
// let the turret know where we want it to aim
|
||||
/* let the turret know where we want it to aim */
|
||||
VectorCopy(endpos, target);
|
||||
VectorSubtract(target, self->target_ent->s.origin, dir);
|
||||
vectoangles(dir, self->target_ent->move_angles);
|
||||
|
||||
// decide if we should shoot
|
||||
/* decide if we should shoot */
|
||||
if (level.time < self->monsterinfo.attack_finished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->delay)
|
||||
{
|
||||
reaction_time = self->delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
reaction_time = (3 - skill->value) * 1.0;
|
||||
}
|
||||
|
||||
if ((level.time - self->monsterinfo.trail_time) < reaction_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->monsterinfo.attack_finished = level.time + reaction_time + 1.0;
|
||||
//FIXME how do we really want to pass this along?
|
||||
self->target_ent->spawnflags |= 65536;
|
||||
}
|
||||
|
||||
// =================
|
||||
void turret_brain_link (edict_t *self)
|
||||
void
|
||||
turret_brain_link(edict_t *self)
|
||||
{
|
||||
vec3_t vec;
|
||||
edict_t *ent;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->killtarget)
|
||||
{
|
||||
self->enemy = G_PickTarget(self->killtarget);
|
||||
|
@ -524,30 +713,42 @@ void turret_brain_link (edict_t *self)
|
|||
|
||||
self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2];
|
||||
|
||||
// add the driver to the end of them team chain
|
||||
/* add the driver to the end of them team chain */
|
||||
for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain)
|
||||
;
|
||||
{
|
||||
}
|
||||
|
||||
ent->teamchain = self;
|
||||
self->teammaster = self->target_ent->teammaster;
|
||||
self->flags |= FL_TEAMSLAVE;
|
||||
}
|
||||
|
||||
// =================
|
||||
void turret_brain_deactivate (edict_t *self, edict_t *other, edict_t *activator)
|
||||
void
|
||||
turret_brain_deactivate(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->think = NULL;
|
||||
self->nextthink = 0;
|
||||
}
|
||||
|
||||
// =================
|
||||
void turret_brain_activate (edict_t *self, edict_t *other, edict_t *activator)
|
||||
void
|
||||
turret_brain_activate(edict_t *self, edict_t *other /* unused */, edict_t *activator)
|
||||
{
|
||||
if (!self || !activator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->enemy)
|
||||
{
|
||||
self->enemy = activator;
|
||||
}
|
||||
|
||||
// wait at least 3 seconds to fire.
|
||||
/* wait at least 3 seconds to fire. */
|
||||
self->monsterinfo.attack_finished = level.time + 3;
|
||||
self->use = turret_brain_deactivate;
|
||||
|
||||
|
@ -555,26 +756,34 @@ void turret_brain_activate (edict_t *self, edict_t *other, edict_t *activator)
|
|||
self->nextthink = level.time + FRAMETIME;
|
||||
}
|
||||
|
||||
/*QUAKED turret_invisible_brain (1 .5 0) (-16 -16 -16) (16 16 16)
|
||||
Invisible brain to drive the turret.
|
||||
|
||||
Does not search for targets. If targeted, can only be turned on once
|
||||
and then off once. After that they are completely disabled.
|
||||
|
||||
"delay" the delay between firing (default ramps for skill level)
|
||||
"Target" the turret breach
|
||||
"Killtarget" the item you want it to attack.
|
||||
Target the brain if you want it activated later, instead of immediately. It will wait 3 seconds
|
||||
before firing to acquire the target.
|
||||
/*
|
||||
* QUAKED turret_invisible_brain (1 .5 0) (-16 -16 -16) (16 16 16)
|
||||
* Invisible brain to drive the turret.
|
||||
*
|
||||
* Does not search for targets. If targeted, can only be turned on once
|
||||
* and then off once. After that they are completely disabled.
|
||||
*
|
||||
* "delay" the delay between firing (default ramps for skill level)
|
||||
* "Target" the turret breach
|
||||
* "Killtarget" the item you want it to attack.
|
||||
* Target the brain if you want it activated later, instead of immediately. It will wait 3 seconds
|
||||
* before firing to acquire the target.
|
||||
*/
|
||||
void SP_turret_invisible_brain (edict_t *self)
|
||||
void
|
||||
SP_turret_invisible_brain(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->killtarget)
|
||||
{
|
||||
gi.dprintf("turret_invisible_brain with no killtarget!\n");
|
||||
G_FreeEdict(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
gi.dprintf("turret_invisible_brain with no target!\n");
|
||||
|
@ -595,7 +804,3 @@ void SP_turret_invisible_brain (edict_t *self)
|
|||
self->movetype = MOVETYPE_PUSH;
|
||||
gi.linkentity(self);
|
||||
}
|
||||
|
||||
// ROGUE
|
||||
//============
|
||||
|
||||
|
|
Loading…
Reference in a new issue