djcev.com

//

Git Repos / fte_dogmode / qc / monsters / enforcer.qc

Last update to this file was on 2024-06-26 at 03:47.

Show enforcer.qc

//==============================================================================
// ENFORCER
//==============================================================================

//======================================================================
// constants
//======================================================================

const float ENFORCER_HEALTH = 80; // id1 80
const float ENFORCER_HEALTH_CORPSE = 40;

const vector ENFORCER_HEAD_MINS = '-10.63 -10.23 -0.05';
const vector ENFORCER_HEAD_MAXS = '9.27 8.25 30';
const vector ENFORCER_CORPSE_MINS = '-39.85 -29.35 -49.07';
const vector ENFORCER_CORPSE_MAXS = '20.52 33.17 30';
const vector ENFORCER_CORPSE_F_MINS = '-41.16 -45.65 -51.95';
const vector ENFORCER_CORPSE_F_MAXS = '21.45 25.49 30';
const vector ENFORCER_CORPSE_Z_MINS = '-16 -16 -24'; // thin 32sq box on ground
const vector ENFORCER_CORPSE_Z_MAXS = '16 16 -8';

//======================================================================
// forward declarations
//======================================================================

// monster_enforcer
void() monster_enforcer_sightsound; // AI & attacks
void() monster_enforcer_attack_lightning;
void() monster_enforcer_attack; // animation & thinking below
void() enf_stand1; void() enf_stand2; void() enf_stand3; void() enf_stand4;
void() enf_stand5; void() enf_stand6; void() enf_stand7;
void() enf_walk1; void() enf_walk2; void() enf_walk3; void() enf_walk4;
void() enf_walk5; void() enf_walk6; void() enf_walk7; void() enf_walk8;
void() enf_walk9; void() enf_walk10; void() enf_walk11; void() enf_walk12;
void() enf_walk13; void() enf_walk14; void() enf_walk15; void() enf_walk16;
void() enf_run1; void() enf_run2; void() enf_run3; void() enf_run4;
void() enf_run5; void() enf_run6; void() enf_run7; void() enf_run8;
void() enf_atk1; void() enf_atk2; void() enf_atk3; void() enf_atk4;
void() enf_atk5; void() enf_atk6; void() enf_atk7; void() enf_atk8;
void() enf_atk9; void() enf_atk10; void() enf_atk11; void() enf_atk12;
void() enf_atk13; void() enf_atk14;
void() enf_atkb1; void() enf_atkb2; void() enf_atkb3; void() enf_atkb4;
void() enf_atkb5; void() enf_atkb6; void() enf_atkb7; void() enf_atkb8;
void() enf_atkb9; void() enf_atkb10;
void() enf_atkc1; void() enf_atkc2; void() enf_atkc3; void() enf_atkc4;
void() enf_atkc5; void() enf_atkc6; void() enf_atkc7; void() enf_atkc8;
void() enf_atkc9; void() enf_atkc10; void() enf_atkc11; void() enf_atkc12;
void() enf_tur_atk1; void() enf_tur_atk2; void() enf_tur_atk3;
void() enf_tur_atk4; void() enf_tur_atk5; void() enf_tur_atk6;
void() enf_tur_atk7; void() enf_tur_atk8; void() enf_tur_atk9;
void() enf_tur_atk10; void() enf_tur_atk11; void() enf_tur_atk12;
void() enf_tur_atk13; void() enf_tur_atk14;
void() enf_seek_stand1; void() enf_seek_stand2; void() enf_seek_stand3;
void() enf_seek_stand4; void() enf_seek_stand5; void() enf_seek_stand6;
void() enf_seek_stand7;
void() enf_tur_atkb1; void() enf_tur_atkb2; void() enf_tur_atkb3;
void() enf_tur_atkb4; void() enf_tur_atkb5; void() enf_tur_atkb6;
void() enf_tur_atkb7; void() enf_tur_atkb8; void() enf_tur_atkb9;
void() enf_tur_atkb10;
void() enf_tur_atkc1; void() enf_tur_atkc2; void() enf_tur_atkc3;
void() enf_tur_atkc4; void() enf_tur_atkc5; void() enf_tur_atkc6;
void() enf_tur_atkc7; void() enf_tur_atkc8; void() enf_tur_atkc9;
void() enf_tur_atkc10; void() enf_tur_atkc11; void() enf_tur_atkc12;
void() enf_standb1; void() enf_standb2; void() enf_standb3; void() enf_standb4;
void() enf_standb5; void() enf_standb6; void() enf_standb7;
void() enf_paina1; void() enf_paina2; void() enf_paina3; void() enf_paina4;
void() enf_painb1; void() enf_painb2; void() enf_painb3; void() enf_painb4;
void() enf_painb5;
void() enf_painc1; void() enf_painc2; void() enf_painc3; void() enf_painc4;
void() enf_painc5; void() enf_painc6; void() enf_painc7; void() enf_painc8;
void() enf_paind1; void() enf_paind2; void() enf_paind3; void() enf_paind4;
void() enf_paind5; void() enf_paind6; void() enf_paind7; void() enf_paind8;
void() enf_paind9; void() enf_paind10; void() enf_paind11; void() enf_paind12;
void() enf_paind13; void() enf_paind14; void() enf_paind15; void() enf_paind16;
void() enf_paind17; void() enf_paind18; void() enf_paind19;
void() enf_die1; void() enf_die2; void() enf_die3; void() enf_die4;
void() enf_die5; void() enf_die6; void() enf_die7; void() enf_die8;
void() enf_die9; void() enf_die10; void() enf_die11; void() enf_die12;
void() enf_die13; void() enf_die14;
void() enf_dief1; void() enf_dief2; void() enf_dief3; void() enf_dief4;
void() enf_dief5; void() enf_dief6; void() enf_dief7; void() enf_dief8;
void() enf_dief9; void() enf_dief10; void() enf_dief11;
void(entity attacker, float damage) monster_enforcer_pain; // interaction
void(vector dir) monster_enforcer_destroy;
entity(vector org, vector ang, float sflags, float yaw, float angry)
spawn_monster_enforcer; // initialization
void(entity e) monster_enforcer_init;
void() monster_enforcer;

// gib_head_enforcer
void(entity act, vector dir, float dmg) throw_gib_head_enforcer;
void(entity e) gib_head_enforcer_init;
void() gib_head_enforcer;

// monster_dead_enforcer
void(entity e) monster_dead_enforcer_init;
void() monster_dead_enforcer;

//======================================================================
// frame macros
//======================================================================
$cd id1/models/enforcer
$origin 0 -6 24
$base base
$skin skin

$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7

$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15 walk16

$frame run1 run2 run3 run4 run5 run6 run7 run8

$frame attack1 attack2 attack3 attack4 attack5 attack6
$frame attack7 attack8 attack9 attack10

$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14

$frame fdeath1 fdeath2 fdeath3 fdeath4 fdeath5 fdeath6 fdeath7 fdeath8
$frame fdeath9 fdeath10 fdeath11

$frame paina1 paina2 paina3 paina4

$frame painb1 painb2 painb3 painb4 painb5

$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8

$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8
$frame paind9 paind10 paind11 paind12 paind13 paind14 paind15 paind16
$frame paind17 paind18 paind19

//------------------------------------------------------------------------------

/*QUAKED monster_enforcer (1 0 0) (-16 -16 -24) (16 16 40) AMBUSH X X TRIGGER_SPAWNED X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/enforcer.mdl");
}
Enforcer.

Default health = 80

keep_ammo(integer) : "1 = Don't drop backpack upon death"

style(Choices) : "Attack type"
0 : "Default (lasers)"
1 : "rockets"
2 : "grenades"
3 : "nails"

snd_death(string) : Path to custom death sound"
snd_pain(string) : "Path to 1st custom pain sound"
snd_sight(string) : "Path to custom sight sound for STOP!"
snd_attack(string) : Path to custom attack sound e.g laser firing"
snd_hit(string) : "Path to custom hit sound e.g. laser hits wall"
snd_idle(string) : "Path to custom idle sound"
snd_misc(string) : "Path to custom sight sound for FREEZE!"
snd_misc1(string) : "Path to custom sight sound for YOU THERE!"
snd_misc2(string) : "Path to custom sight sound for HALT!"
snd_misc3(string) : "Path to 2nd custom pain sound"

mdl_head(string) : "Path to custom head model"
mdl_body(string) : "Path to custom body model"
mdl_proj(string) : "Path to custom projectile model"
skin_head(float) : "Skin index of custom head model"
skin_proj(float) : "Skin index of custom projectile model"
mdl_gib1(string) : "Path to custom 1st gib model"
mdl_gib2(string) : "Path to custom 2nd gib model"
mdl_gib3(string) : "Path to custom 3rd gib model"

effects(choices) : "Add a visual effect to an entity"
0 : "None (Default)"
1 : "Brightfield (yellow particles)"
4 : "Bright light"
8 : "Dim light"

berserk(choices) "Skips certain pain animations similar to skill 3 (Makes a semi-nightmare monster!)"
0 : "Off (Default)"
1 : "Berserk (skip pain animations)"

delay(float) : "Delay spawn in for this amount of time"

wait(choices) : "Play an effect when trigger spawned?"
0 : "Teleport Effects (Default)"
1 : "Spawn Silently"

spawn_angry(Choices)
0 : "Only when trigger spawned, default behavior - not angry"
1 : "Only when trigger spawned, set to 1 to spawn angry at player"

infight_mode(Choices)
0 : "Default behavior, only with different classnames"
1 : "Infight with monsters with the same classname but a different mdl_body"
2 : "Infight with monsters with the same classname and model but a different skin"
3 : "Infight no matter what"

health(integer) : "Set this to a custom health amount"
pain_target(string) : "Fire this target when pain_threshold is reached"
pain_threshold(integer) : "Fire pain_target when health drops below this amount"
sight_trigger(integer) : "1 = Fire target upon seeing the player instead of death"
skin(integer) : "Skin index (default 0) Use this when your custom model has more than one skin to select"
obit_method(string) : "When used with obit_name, will set part of the text for a custom obituary. e.g. eviscerated - If empty, defaults to killed."
obit_name(string) : "When used with obit_method, this will set part of the text for a custom obituary. e.g. a Super Soldier! Using the examples here, the obituary would read: Player was eviscerated by a Super Solider!"
damage_mod(float) : "USE WITH CAUTION! Multiply all damage from this monster by this number (e.g. 4 = Quad damage)"

*/
//----------------------------------------------------------------------
// class monster_enforcer: base_walkmonster
// {
//--------------------------------------------------------------
void() monster_enforcer_sightsound =
{
local float rsnd;

rsnd = rint (random() * 3);
if (rsnd == 1)
// dumptruck_ds
sound_sight (self, CHAN_VOICE, "enforcer/sight1.wav",
VOL_HIGH, ATTN_NORM);
else if (rsnd == 2)
sound_misc (self, CHAN_VOICE, "enforcer/sight2.wav",
VOL_HIGH, ATTN_NORM);
else if (rsnd == 0)
sound_misc1 (self, CHAN_VOICE, "enforcer/sight3.wav",
VOL_HIGH, ATTN_NORM);
else
sound_misc2 (self, CHAN_VOICE, "enforcer/sight4.wav",
VOL_HIGH, ATTN_NORM);
};

//--------------------------------------------------------------
// enf_lightning -- TODO CEV
//--------------------------------------------------------------
void() monster_enforcer_attack_lightning =
{
local vector org, dir;

self.effects = self.effects | EF_MUZZLEFLASH;
sound_attack (self, CHAN_WEAPON, "weapons/lstart.wav",
VOL_HIGH, ATTN_NORM);
ai_face ();
makevectors (self.angles);
org = self.origin + v_forward * 30 + v_right * 8.5 + '0 0 16';

dir = self.enemy.origin - self.enemy.velocity * 0.075;
dir = normalize (dir - org + '0 0 16');

if (self.spawnflags & I_AM_TURRET)
traceline (org, self.origin + dir * 900, TRUE, self);
else
traceline (org, self.origin + dir * 600, TRUE, self);

WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
WriteCoord (MSG_BROADCAST, trace_endpos_x);
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);

fire_lightning (org, trace_endpos, self, 4);
};

//--------------------------------------------------------------
void() monster_enforcer_attack =
{
// style stuff -- dumptruck_ds
if (self.style == 1)
{
self.effects = self.effects | EF_MUZZLEFLASH;
ai_face ();
sound_attack (self, CHAN_WEAPON, "enforcer/enfire.wav",
VOL_HIGH, ATTN_NORM);

makevectors (self.angles);
// last number was 16 - dumptruck_ds
local vector org = self.origin + v_forward * 30 +
v_right * 8.5 + '0 0 12';

// org, dir, direct_damage, splash_damage, speed
base_monster_fire_rocket (org,
self.enemy.origin - self.origin,
30, 40, 900);
return;
}
else if (self.style == 2)
{
ai_face ();
// TODO CEV calling makevectors here & then again in
// fire_grenade below is not ideal
makevectors (self.angles);
// enforcer grenade offset -- CEV
local vector org1 = self.origin +
(v_forward * 30 + v_right * 8.5 + '0 0 16');
if (self.spawnflags & I_AM_TURRET)
base_monster_fire_grenade (org1,
40, 40, self.attack_elevation);
else
base_monster_fire_grenade (org1, 40, 40, 0);
return;
}
else if (self.style == 3 || self.style == 5)
{
sound_attack (self, CHAN_WEAPON, "weapons/spike2.wav",
VOL_HIGH, ATTN_NORM);
self.effects = self.effects | EF_MUZZLEFLASH;
makevectors (self.angles);

// this is changed from pd3, speed there was 600; I've
// set it to standard SPIKE_SPEED (1000) here -- CEV
base_monster_fire_spike (self.origin +
(v_forward * 30 + v_right * 8.5 + '0 0 16'),
self.enemy.origin - self.origin,
SPIKE_SUPER_DAMAGE, SPIKE_SPEED);
return;
}
else
{
makevectors (self.angles);

local vector org2 = self.origin +
(v_forward * 30 + v_right * 8.5 + '0 0 16');

base_monster_fire_laser (org2,
self.enemy.origin - self.origin);
}
};

//--------------------------------------------------------------
// Enforcer stand functions
//--------------------------------------------------------------
void() enf_stand1 = [$stand1, enf_stand2] { ai_stand (); };
void() enf_stand2 = [$stand2, enf_stand3] { ai_stand (); };
void() enf_stand3 = [$stand3, enf_stand4] { ai_stand (); };
void() enf_stand4 = [$stand4, enf_stand5] { ai_stand (); };
void() enf_stand5 = [$stand5, enf_stand6] { ai_stand (); };
void() enf_stand6 = [$stand6, enf_stand7] { ai_stand (); };
void() enf_stand7 = [$stand7, enf_stand1] { ai_stand (); };

//--------------------------------------------------------------
// Enforcer walk functions
//--------------------------------------------------------------
void() enf_walk1 = [$walk1, enf_walk2]
{
if (random() < 0.2)
// dumptruck_ds
sound_idle (self, CHAN_VOICE, "enforcer/idle1.wav",
VOL_HIGH, ATTN_IDLE);
ai_walk (2);
};
void() enf_walk2 = [$walk2, enf_walk3] { ai_walk (4); };
void() enf_walk3 = [$walk3, enf_walk4] { ai_walk (4); };
void() enf_walk4 = [$walk4, enf_walk5] { ai_walk (3); };
void() enf_walk5 = [$walk5, enf_walk6] { ai_walk (1); };
void() enf_walk6 = [$walk6, enf_walk7] { ai_walk (2); };
void() enf_walk7 = [$walk7, enf_walk8] { ai_walk (2); };
void() enf_walk8 = [$walk8, enf_walk9] { ai_walk (1); };
void() enf_walk9 = [$walk9, enf_walk10] { ai_walk (2); };
void() enf_walk10 = [$walk10, enf_walk11] { ai_walk (4); };
void() enf_walk11 = [$walk11, enf_walk12] { ai_walk (4); };
void() enf_walk12 = [$walk12, enf_walk13] { ai_walk (1); };
void() enf_walk13 = [$walk13, enf_walk14] { ai_walk (2); };
void() enf_walk14 = [$walk14, enf_walk15] { ai_walk (3); };
void() enf_walk15 = [$walk15, enf_walk16] { ai_walk (4); };
void() enf_walk16 = [$walk16, enf_walk1] { ai_walk (2); };

//--------------------------------------------------------------
// Enforcer run functions
//--------------------------------------------------------------
void() enf_run1 = [$run1, enf_run2]
{
if (random() < 0.2)
// dumptruck_ds
sound_idle (self, CHAN_VOICE, "enforcer/idle1.wav",
VOL_HIGH, ATTN_IDLE);
ai_run (18);
};
void() enf_run2 = [$run2, enf_run3] { ai_run (14); };
void() enf_run3 = [$run3, enf_run4] { ai_run (7); };
void() enf_run4 = [$run4, enf_run5] { ai_run (12); };
void() enf_run5 = [$run5, enf_run6] { ai_run (14); };
void() enf_run6 = [$run6, enf_run7] { ai_run (14); };
void() enf_run7 = [$run7, enf_run8] { ai_run (7); };
void() enf_run8 = [$run8, enf_run1] { ai_run (11); };

//--------------------------------------------------------------
// Enforcer attack functions
//--------------------------------------------------------------
void() enf_atk1 = [$attack1, enf_atk2] { ai_face (); };
void() enf_atk2 = [$attack2, enf_atk3] { ai_face (); };
void() enf_atk3 = [$attack3, enf_atk4] { ai_face (); };
void() enf_atk4 = [$attack4, enf_atk5] { ai_face (); };
void() enf_atk5 = [$attack5, enf_atk6] { ai_face (); };
void() enf_atk6 = [$attack6, enf_atk7] { monster_enforcer_attack (); };
void() enf_atk7 = [$attack7, enf_atk8] { ai_face (); };
void() enf_atk8 = [$attack8, enf_atk9] { ai_face (); };
void() enf_atk9 = [$attack5, enf_atk10] { ai_face (); };
void() enf_atk10 = [$attack6, enf_atk11] { monster_enforcer_attack ();};
void() enf_atk11 = [$attack7, enf_atk12] { ai_face (); };
void() enf_atk12 = [$attack8, enf_atk13] { ai_face (); };
void() enf_atk13 = [$attack9, enf_atk14] { ai_face (); };
void() enf_atk14 = [$attack10, enf_run1]
{
ai_face ();
sub_checkrefire (enf_atk1);
};

//--------------------------------------------------------------
// Enforcer attack functions 2
// modified animation frames for style Enforcers -- dumptruck_ds
//--------------------------------------------------------------
void() enf_atkb1 = [$attack1, enf_atkb2]
{
ai_face ();
self.count = 0;
self.t_length = 8 + floor (random() * 6);
};
void() enf_atkb2 = [$attack2, enf_atkb3] { ai_face (); };
void() enf_atkb3 = [$attack3, enf_atkb4] { ai_face (); };
void() enf_atkb4 = [$attack4, enf_atkb5] { ai_face (); };
void() enf_atkb5 = [$attack5, enf_atkb6] { ai_face (); };
void() enf_atkb6 =
{
self.frame = $attack6;
self.nextthink = time + 0.1;
if (self.style == 5 && self.count < self.t_length)
{
self.count += 1;
}
else
{
self.think = enf_atkb7;
}
ai_face ();
monster_enforcer_attack ();
};
void() enf_atkb7 = [$attack7, enf_atkb8] { ai_face (); };
void() enf_atkb8 = [$attack8, enf_atkb9] { ai_face (); };
void() enf_atkb9 = [$attack9, enf_atkb10] { ai_face (); };
void() enf_atkb10 = [$attack10, enf_run1]
{
ai_face ();
sub_checkrefire (enf_atkb1);
};

//--------------------------------------------------------------
// Enforcer attack functions 4
//--------------------------------------------------------------
void() enf_atkc1 = [$attack1, enf_atkc2] { ai_face (); };
void() enf_atkc2 = [$attack2, enf_atkc3] { ai_face (); };
void() enf_atkc3 = [$attack3, enf_atkc4] { ai_face (); };
void() enf_atkc4 = [$attack4, enf_atkc5] { ai_face (); };
void() enf_atkc5 = [$attack5, enf_atkc6] { ai_face (); };
void() enf_atkc6 = [$attack6, enf_atkc7]
{
monster_enforcer_attack_lightning ();
};
void() enf_atkc7 = [$attack6, enf_atkc8]
{
monster_enforcer_attack_lightning ();
};
void() enf_atkc8 = [$attack6, enf_atkc9]
{
monster_enforcer_attack_lightning ();
};
void() enf_atkc9 = [$attack7, enf_atkc10] { ai_face (); };
void() enf_atkc10 = [$attack8, enf_atkc11] { ai_face (); };
void() enf_atkc11 = [$attack9, enf_atkc12] { ai_face (); };
void() enf_atkc12 = [$attack10, enf_run1]
{
ai_face ();
sub_checkrefire (enf_atkc1);
};

//////////////////////////////////////
// new frames for turret mode START //
//////////////////////////////////////

//--------------------------------------------------------------
// Enforcer turret attack 1
//--------------------------------------------------------------
void() enf_tur_atk1 = [$attack1, enf_tur_atk2] { ai_face (); };
void() enf_tur_atk2 = [$attack2, enf_tur_atk3] { ai_face (); };
void() enf_tur_atk3 = [$attack3, enf_tur_atk4]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
OGRE_DEFAULT_ELEVATION, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk4 = [$attack4, enf_tur_atk5]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
self.attack_elevation, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk5 = [$attack5, enf_tur_atk6]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
self.attack_elevation, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk6 = [$attack6, enf_tur_atk7]
{
monster_enforcer_attack ();
};
void() enf_tur_atk7 = [$attack7, enf_tur_atk8]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
self.attack_elevation, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk8 = [$attack8, enf_tur_atk9]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
self.attack_elevation, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk9 = [$attack5, enf_tur_atk10]
{
ai_face ();
self.attack_elevation = preach_iterate_elevation (
self.attack_elevation, GRENADE_SPEED,
self.origin, self.enemy.origin);
};
void() enf_tur_atk10 = [$attack6, enf_tur_atk11]
{
monster_enforcer_attack ();
};
void() enf_tur_atk11 = [$attack7, enf_tur_atk12] { ai_face (); };
void() enf_tur_atk12 = [$attack8, enf_tur_atk13] { ai_face (); };
void() enf_tur_atk13 = [$attack9, enf_tur_atk14] { ai_face (); };
void() enf_tur_atk14 = [$attack10, enf_seek_stand1]
{
ai_face ();
sub_checkrefire (enf_tur_atk1);
};

//--------------------------------------------------------------
// Enforcer turret seek
//--------------------------------------------------------------
void() enf_seek_stand1 = [$stand1, enf_seek_stand2] { ai_run (0); };
void() enf_seek_stand2 = [$stand2, enf_seek_stand3] { ai_run (0); };
void() enf_seek_stand3 = [$stand3, enf_seek_stand4] { ai_run (0); };
void() enf_seek_stand4 = [$stand4, enf_seek_stand5] { ai_run (0); };
void() enf_seek_stand5 = [$stand5, enf_seek_stand6] { ai_run (0); };
void() enf_seek_stand6 = [$stand6, enf_seek_stand7] { ai_run (0); };
void() enf_seek_stand7 = [$stand7, enf_seek_stand1] { ai_run (0); };

//--------------------------------------------------------------
// Enforcer turret attack 2 (?)
//--------------------------------------------------------------
void() enf_tur_atkb1 = [$attack1, enf_tur_atkb2]
{
ai_face ();
self.count = 0;
self.t_length = 4 + floor (random() * 4);
};
void() enf_tur_atkb2 = [$attack2, enf_tur_atkb3] { ai_face (); };
void() enf_tur_atkb3 = [$attack3, enf_tur_atkb4] { ai_face (); };
void() enf_tur_atkb4 = [$attack4, enf_tur_atkb5] { ai_face (); };
void() enf_tur_atkb5 = [$attack5, enf_tur_atkb6] { ai_face (); };
void() enf_tur_atkb6 =
{
self.frame = $attack6;
self.nextthink = time + 0.1;

if (self.style == 5 && self.count < self.t_length)
self.count += 1;
else
self.think = enf_tur_atkb7;

ai_face ();
monster_enforcer_attack ();
};
void() enf_tur_atkb7 = [$attack7, enf_tur_atkb8] { ai_face (); };
void() enf_tur_atkb8 = [$attack8, enf_tur_atkb9] { ai_face (); };
void() enf_tur_atkb9 = [$attack9, enf_tur_atkb10] { ai_face (); };
void() enf_tur_atkb10 = [$attack10, enf_standb1]
{
ai_face ();
sub_checkrefire (enf_tur_atkb1);
};

//--------------------------------------------------------------
// Enforcer turret attack 4 (?)
//--------------------------------------------------------------
void() enf_tur_atkc1 = [$attack1, enf_tur_atkc2] { ai_face (); };
void() enf_tur_atkc2 = [$attack2, enf_tur_atkc3] { ai_face (); };
void() enf_tur_atkc3 = [$attack3, enf_tur_atkc4] { ai_face (); };
void() enf_tur_atkc4 = [$attack4, enf_tur_atkc5] { ai_face (); };
void() enf_tur_atkc5 = [$attack5, enf_tur_atkc6] { ai_face (); };
void() enf_tur_atkc6 = [$attack6, enf_tur_atkc7]
{
monster_enforcer_attack_lightning ();
};
void() enf_tur_atkc7 = [$attack6, enf_tur_atkc8]
{
monster_enforcer_attack_lightning ();
};
void() enf_tur_atkc8 = [$attack6, enf_tur_atkc9]
{
monster_enforcer_attack_lightning ();
};
void() enf_tur_atkc9 = [$attack7, enf_tur_atkc10] { ai_face (); };
void() enf_tur_atkc10 = [$attack8, enf_tur_atkc11] { ai_face (); };
void() enf_tur_atkc11 = [$attack9, enf_tur_atkc12] { ai_face (); };
void() enf_tur_atkc12 = [$attack10, enf_standb1]
{
ai_face ();
sub_checkrefire (enf_tur_atkb1);
};

//--------------------------------------------------------------
// Enforcer turret stand 2 (?)
//--------------------------------------------------------------
void() enf_standb1 = [$stand1, enf_standb2] { ai_run (0); };
void() enf_standb2 = [$stand2, enf_standb3] { ai_run (0); };
void() enf_standb3 = [$stand3, enf_standb4] { ai_run (0); };
void() enf_standb4 = [$stand4, enf_standb5] { ai_run (0); };
void() enf_standb5 = [$stand5, enf_standb6] { ai_run (0); };
void() enf_standb6 = [$stand6, enf_standb7] { ai_run (0); };
void() enf_standb7 = [$stand7, enf_standb1] { ai_run (0); };

//////////////////////////////////////
// new frames for turret mode END //
//////////////////////////////////////

//--------------------------------------------------------------
// Enforcer pain state A
//--------------------------------------------------------------
void() enf_paina1 = [$paina1, enf_paina2] { };
void() enf_paina2 = [$paina2, enf_paina3] { };
void() enf_paina3 = [$paina3, enf_paina4] { };
void() enf_paina4 = [$paina4, enf_run1] { };

//--------------------------------------------------------------
// Enforcer pain state B
//--------------------------------------------------------------
void() enf_painb1 = [$painb1, enf_painb2] { };
void() enf_painb2 = [$painb2, enf_painb3] { };
void() enf_painb3 = [$painb3, enf_painb4] { };
void() enf_painb4 = [$painb4, enf_painb5] { };
void() enf_painb5 = [$painb5, enf_run1] { };

//--------------------------------------------------------------
// Enforcer pain state C
//--------------------------------------------------------------
void() enf_painc1 = [$painc1, enf_painc2] { };
void() enf_painc2 = [$painc2, enf_painc3] { };
void() enf_painc3 = [$painc3, enf_painc4] { };
void() enf_painc4 = [$painc4, enf_painc5] { };
void() enf_painc5 = [$painc5, enf_painc6] { };
void() enf_painc6 = [$painc6, enf_painc7] { };
void() enf_painc7 = [$painc7, enf_painc8] { };
void() enf_painc8 = [$painc8, enf_run1] { };

//--------------------------------------------------------------
// Enforcer pain state D
//--------------------------------------------------------------
void() enf_paind1 = [$paind1, enf_paind2] { };
void() enf_paind2 = [$paind2, enf_paind3] { };
void() enf_paind3 = [$paind3, enf_paind4] { };
void() enf_paind4 = [$paind4, enf_paind5] { ai_painforward (2); };
void() enf_paind5 = [$paind5, enf_paind6] { ai_painforward (1); };
void() enf_paind6 = [$paind6, enf_paind7] { };
void() enf_paind7 = [$paind7, enf_paind8] { };
void() enf_paind8 = [$paind8, enf_paind9] { };
void() enf_paind9 = [$paind9, enf_paind10] { };
void() enf_paind10 = [$paind10, enf_paind11] { };
void() enf_paind11 = [$paind11, enf_paind12] { ai_painforward (1); };
void() enf_paind12 = [$paind12, enf_paind13] { ai_painforward (1); };
void() enf_paind13 = [$paind13, enf_paind14] { ai_painforward (1); };
void() enf_paind14 = [$paind14, enf_paind15] { };
void() enf_paind15 = [$paind15, enf_paind16] { };
void() enf_paind16 = [$paind16, enf_paind17] { ai_pain (1); };
void() enf_paind17 = [$paind17, enf_paind18] { ai_pain (1); };
void() enf_paind18 = [$paind18, enf_paind19] { };
void() enf_paind19 = [$paind19, enf_run1] { };

//--------------------------------------------------------------
// Enforcer death state A
//--------------------------------------------------------------
void() enf_die1 = [$death1, enf_die2]
{
base_entity_aligntoground (self);
};
void() enf_die2 = [$death2, enf_die3] { };
void() enf_die3 = [$death3, enf_die4]
{
self.solid = SOLID_NOT;

// style ammotype check -- dumptruck_ds
if (self.style == 1)
self.ammo_rockets = 2;

// style ammotype check -- dumptruck_ds
if (self.style == 2)
self.ammo_rockets = 2;

// style ammotype check -- dumptruck_ds
if (self.style == 3 || self.style == 5)
self.ammo_nails = 5;

// style ammotype check -- dumptruck_ds
if (self.style == 0 || self.style == 4)
self.ammo_cells = 5;

if (!self.keep_ammo)
item_backpack_drop (self);
};
void() enf_die4 = [$death4, enf_die5] { ai_forward (14); };
void() enf_die5 = [$death5, enf_die6] { ai_forward (2); };
void() enf_die6 = [$death6, enf_die7] { };
void() enf_die7 = [$death7, enf_die8] { };
void() enf_die8 = [$death8, enf_die9] { };
void() enf_die9 = [$death9, enf_die10] { ai_forward (3); };
void() enf_die10 = [$death10, enf_die11] { ai_forward (5); };
void() enf_die11 = [$death11, enf_die12] { ai_forward (5); };
void() enf_die12 = [$death12, enf_die13] { ai_forward (5); };
void() enf_die13 = [$death13, enf_die14]
{
become_base_corpse (self, ENFORCER_HEALTH_CORPSE);
setsize (self, ENFORCER_CORPSE_Z_MINS, ENFORCER_CORPSE_Z_MAXS);
};
void() enf_die14 = [$death14, enf_die14] { };

//--------------------------------------------------------------
// Enforcer death state F
//--------------------------------------------------------------
void() enf_dief1 = [$fdeath1, enf_dief2]
{
base_entity_aligntoground (self);
};
void() enf_dief2 = [$fdeath2, enf_dief3] { };
void() enf_dief3 = [$fdeath3, enf_dief4]
{
self.solid = SOLID_NOT;

// style ammotype check -- dumptruck_ds
if (self.style == 1)
self.ammo_rockets = 2;

// style ammotype check -- dumptruck_ds
if (self.style == 2)
self.ammo_rockets = 2;

// style ammotype check -- dumptruck_ds
if (self.style == 3 || self.style == 5)
self.ammo_nails = 5;

// style ammotype check -- dumptruck_ds
if (self.style == 0 || self.style == 4)
self.ammo_cells = 5;

if (!self.keep_ammo)
item_backpack_drop (self);
};
void() enf_dief4 = [$fdeath4, enf_dief5] { };
void() enf_dief5 = [$fdeath5, enf_dief6] { };
void() enf_dief6 = [$fdeath6, enf_dief7] { };
void() enf_dief7 = [$fdeath7, enf_dief8] { };
void() enf_dief8 = [$fdeath8, enf_dief9] { };
void() enf_dief9 = [$fdeath9, enf_dief10] { };
void() enf_dief10 = [$fdeath10, enf_dief11]
{
become_base_corpse (self, ENFORCER_HEALTH_CORPSE);
setsize (self, ENFORCER_CORPSE_Z_MINS, ENFORCER_CORPSE_Z_MAXS);
};
void() enf_dief11 = [$fdeath11, enf_dief11] { };

//==============================================================
// Interaction
//==============================================================

//--------------------------------------------------------------
// enf_pain
//--------------------------------------------------------------
void(entity attacker, float damage) monster_enforcer_pain =
{
local float r;

r = random ();

if (self.pain_finished > time)
return;

if (r < 0.5)
// dumptruck_ds
sound_pain (self, CHAN_VOICE, "enforcer/pain1.wav",
VOL_HIGH, ATTN_NORM);
else
// dumptruck_ds
sound_misc3 (self, CHAN_VOICE, "enforcer/pain2.wav",
VOL_HIGH, ATTN_NORM);

if (r < 0.2)
{
self.pain_finished = time + 1;
// moved these here to avoid spamming pain sounds
// -- dumptruck_ds
if (self.spawnflags & I_AM_TURRET)
return;
else
enf_paina1 ();
}
else if (r < 0.4)
{
self.pain_finished = time + 1;
if (self.spawnflags & I_AM_TURRET)
return;
else
enf_painb1 ();
}
else if (r < 0.7)
{
self.pain_finished = time + 1;
if (self.spawnflags & I_AM_TURRET)
return;
else
enf_painc1 ();
}
else
{
self.pain_finished = time + 2;
if (self.spawnflags & I_AM_TURRET)
return;
else
enf_paind1 ();
}
};

//--------------------------------------------------------------
// enf_die
//--------------------------------------------------------------
void(vector dir) monster_enforcer_destroy =
{
// check if we're dead already
if (self.classgroup & CG_CORPSE)
{
sound (self, CHAN_VOICE, "player/udeath.wav",
VOL_HIGH, ATTN_NORM);

throw_gib_head_enforcer (self, dir, self.health);
throw_gib_1 (self, dir, self.health);
throw_gib_2 (self, dir, self.health);
throw_gib_3 (self, dir, self.health);

return;
}

// check for gib
if (self.health < -35)
{
sound (self, CHAN_VOICE, "player/udeath.wav",
VOL_HIGH, ATTN_NORM);

throw_gib_head_enforcer (self, dir, self.health);
throw_gib_1 (self, dir, self.health);
throw_gib_2 (self, dir, self.health);
throw_gib_3 (self, dir, self.health);

base_item_drop_stuff (self);
return;
}

// regular death
// dumptruck_ds
sound_death (self, CHAN_VOICE, "enforcer/death1.wav",
VOL_HIGH, ATTN_NORM);
base_item_drop_stuff (self);
if (random() > 0.5)
enf_die1 ();
else
enf_dief1 ();
};

//==============================================================
// Initialization
//==============================================================

//--------------------------------------------------------------
entity(vector org, vector ang, float sflags, float yaw, float angry)
spawn_monster_enforcer =
{
return spawn_base_monster (org, ang, sflags, yaw, angry,
monster_enforcer_init);
};

//--------------------------------------------------------------
void(entity e) monster_enforcer_init =
{
if (deathmatch)
{
remove (e);
return;
}

if (e.style >= 6)
objerror ("style key set too high\n");

e.classname = "monster_enforcer";
e.classtype = CT_MONSTER_ENFORCER;

// custom_mdls function -- dumptruck_ds
precache_body_model2 (e, "progs/enforcer.mdl");
precache_head_model2 (e, "progs/h_mega.mdl");
precache_proj_model2 (e, "progs/laser.mdl");
precache_proj_model2 (e, "progs/s_spike.mdl");
precache_proj_model2 (e, "progs/missile.mdl");
// dumptruck_ds
precache_sound2_death (e, "enforcer/death1.wav");
precache_sound2_attack (e, "enforcer/enfire.wav");
precache_sound2_hit (e, "enforcer/enfstop.wav");
precache_sound2_idle (e, "enforcer/idle1.wav");
precache_sound2_pain (e, "enforcer/pain1.wav");
precache_sound2_misc3 (e, "enforcer/pain2.wav");
precache_sound2_sight (e, "enforcer/sight1.wav");
// these will be replaced with custom noise fields eventually
// -- dumptruck_ds
precache_sound2_misc (e, "enforcer/sight2.wav");
precache_sound2_misc1 (e, "enforcer/sight3.wav");
precache_sound2_misc2 (e, "enforcer/sight4.wav");

precache_gib1 (e, "progs/gib1.mdl");
precache_gib2 (e, "progs/gib2.mdl");
precache_gib3 (e, "progs/gib3.mdl");

e.solid = SOLID_SLIDEBOX;
e.movetype = MOVETYPE_STEP;

// SPIKE to the RESCUE!!!! - got this fixed. -- dumptruck_ds
body_model (e, "progs/enforcer.mdl");
// orginal dumptruck_ds
// setmodel (e, "progs/enforcer.mdl");

setsize (e, '-16 -16 -24', '16 16 40');

if (!e.proj_speed_mod)
e.proj_speed_mod = 1;

if (!e.health)
// thanks RennyC -- dumptruck_ds
e.health = ENFORCER_HEALTH;

e.sightsound = monster_enforcer_sightsound;
e.th_stand = enf_stand1;
e.th_walk = enf_walk1;

if (e.spawnflags & I_AM_TURRET)
e.th_run = enf_standb1;
else
e.th_run = enf_run1;
// Berserk test from
// http://celephais.net/board/view_thread.php?id=4&start=3465
// -- dumptruck_ds
if !(e.berserk)
e.th_pain = monster_enforcer_pain;
else
e.th_pain = sub_nullpain;
e.destroy = monster_enforcer_destroy;
// new animation frame check -- dumptruck_ds
if (e.style == 1 || e.style == 2 || e.style == 5)
{
if (e.spawnflags & I_AM_TURRET)
e.th_turret = enf_tur_atkb1;
e.th_missile = enf_atkb1;
}
else if (e.style == 0 || e.style == 3 )
{
if (e.spawnflags & I_AM_TURRET)
e.th_turret = enf_tur_atk1;
e.th_missile = enf_atk1;
}
else if (e.style == 4)
{
if (e.spawnflags & I_AM_TURRET)
e.th_turret = enf_tur_atkc1;
e.th_missile = enf_atkc1;
}

// walkmonster_start
base_walkmonster_init (e);
};

//--------------------------------------------------------------
void() monster_enforcer =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

monster_enforcer_init (self);
};
// };

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Scenic Dead Monster Patch stuff here from DeadStuff mod -- dumptruck_ds
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

/*QUAKED gib_head_enforcer (0 0.5 0.8) (-16 -16 0) (16 16 56) SOLID X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ("progs/h_mega.mdl");
}
*/
//----------------------------------------------------------------------
// class gib_head_enforcer: base_gib_head
// {
//--------------------------------------------------------------
// ThrowHead
//--------------------------------------------------------------
void(entity act, vector dir, float dmg) throw_gib_head_enforcer =
{
base_gib_head_throw (act, dir, dmg, gib_head_enforcer_init);
};

//--------------------------------------------------------------
void(entity e) gib_head_enforcer_init =
{
e.classname = "gib_head_enforcer";
e.classtype = CT_GORE_HEAD_ENFORCER;

// gib_init interprets spawnflags and will set .solid -- CEV
base_gib_head_init (e);

if (e.mdl_head != "")
{
precache_model (e.mdl_head);
setmodel (e, e.mdl_head);
}
else
{
precache_model ("progs/h_mega.mdl");
setmodel (e, "progs/h_mega.mdl");
if (e.solid == SOLID_BBOX)
setsize (e, ENFORCER_HEAD_MINS,
ENFORCER_HEAD_MAXS);
else if (e.solid == SOLID_TRIGGER)
setsize (e, '-16 -16 0', '16 16 56');
}

e.frame = 0;
};

//--------------------------------------------------------------
void() gib_head_enforcer =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

gib_head_enforcer_init (self);
};
// };

/*QUAKED monster_dead_enforcer (0 0.5 0.8) (-16 -16 -24) (16 16 32) SOLID FACE_UP X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path":"progs/enforcer.mdl","frame":54});
}
*/
//----------------------------------------------------------------------
// class monster_dead_enforcer: base_corpse
// {
//--------------------------------------------------------------
void(entity e) monster_dead_enforcer_init =
{
base_corpse_init (e);

precache_model ("progs/enforcer.mdl");
setmodel (e, "progs/enforcer.mdl");

if (e.spawnflags & 2)
{
e.frame = $fdeath11;

if (e.solid == SOLID_BBOX)
setsize (e, ENFORCER_CORPSE_F_MINS,
ENFORCER_CORPSE_F_MAXS);
}
else
{
e.frame = $death14;

if (e.solid == SOLID_BBOX)
setsize (e, ENFORCER_CORPSE_MINS,
ENFORCER_CORPSE_MAXS);
}
};

//--------------------------------------------------------------
void() monster_dead_enforcer =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

monster_dead_enforcer_init (self);
};
// };

Return to the top of this page or return to the overview of this repo.

Log enforcer.qc

Date Commit Message Author + -
2024-06-26 pmove fixes, GL now a faux tribolt, wall climbing cev +12 -6
2024-06-15 Major update, committing as-is, will have bugs cev +106 -59
2024-04-12 Moveable gibs, heads, some bugfixes cev +78 -29
2024-04-08 Registered monsters, projectile bugfixes cev +498 -440
2024-02-18 Client/player, projectiles, entrypoints refactor cev +81 -424
2024-01-31 Class based monster refactor & start projectiles cev +997 -756
2024-01-13 Refactored items into classes, fix teleporttrain cev +6 -4
2024-01-09 Continue OO / Class-based refactor cev +4 -4
2023-10-13 New movement code based on SV_RunClientCommand cev +1044 -1044
2023-10-13 Rename "qc-server" dir to "qc" cev +1044  

Return to the top of this page or return to the overview of this repo.