484 lines
18 KiB
Plaintext
484 lines
18 KiB
Plaintext
/*=============================================================================
|
|
PYRO - Originally from Rubicon2 by John Fitzgibbons
|
|
FUMIGATOR - Green/Poison version of the Pyro
|
|
==============================================================================*/
|
|
$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
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_soundreset =
|
|
{
|
|
//turn off flame sound
|
|
if (self.attack_finished > time)
|
|
sound (self, CHAN_WEAPON, self.noise4, 1, ATTN_NORM);
|
|
//play sound anyway to be sure the channel is silent
|
|
else sound (self, CHAN_WEAPON, SOUND_EMPTY, 0, ATTN_NORM);
|
|
};
|
|
|
|
//============================================================================
|
|
void() pyro_stand1 =[ $stand1, pyro_stand2 ] {monster_idle_sound(); ai_stand();};
|
|
void() pyro_stand2 =[ $stand2, pyro_stand3 ] {ai_stand();};
|
|
void() pyro_stand3 =[ $stand3, pyro_stand4 ] {ai_stand();};
|
|
void() pyro_stand4 =[ $stand4, pyro_stand5 ] {ai_stand();};
|
|
void() pyro_stand5 =[ $stand5, pyro_stand6 ] {ai_stand();};
|
|
void() pyro_stand6 =[ $stand6, pyro_stand7 ] {ai_stand();};
|
|
void() pyro_stand7 =[ $stand7, pyro_stand1 ] {ai_stand();};
|
|
|
|
//============================================================================
|
|
void() pyro_walk1 =[ $walk1, pyro_walk2 ] {monster_idle_sound();ai_walk(2);};
|
|
void() pyro_walk2 =[ $walk2, pyro_walk3 ] {monster_footstep(FALSE); ai_walk(4);};
|
|
void() pyro_walk3 =[ $walk3, pyro_walk4 ] {ai_walk(4);};
|
|
void() pyro_walk4 =[ $walk4, pyro_walk5 ] {ai_walk(3);};
|
|
void() pyro_walk5 =[ $walk5, pyro_walk6 ] {ai_walk(1);};
|
|
void() pyro_walk6 =[ $walk6, pyro_walk7 ] {ai_walk(2);};
|
|
void() pyro_walk7 =[ $walk7, pyro_walk8 ] {ai_walk(2);};
|
|
void() pyro_walk8 =[ $walk8, pyro_walk9 ] {ai_walk(1);};
|
|
void() pyro_walk9 =[ $walk9, pyro_walk10 ] {ai_walk(2);};
|
|
void() pyro_walk10 =[ $walk10, pyro_walk11 ] {monster_footstep(FALSE); ai_walk(4);};
|
|
void() pyro_walk11 =[ $walk11, pyro_walk12 ] {ai_walk(4);};
|
|
void() pyro_walk12 =[ $walk12, pyro_walk13 ] {ai_walk(1);};
|
|
void() pyro_walk13 =[ $walk13, pyro_walk14 ] {ai_walk(2);};
|
|
void() pyro_walk14 =[ $walk14, pyro_walk15 ] {ai_walk(3);};
|
|
void() pyro_walk15 =[ $walk15, pyro_walk16 ] {ai_walk(4);};
|
|
void() pyro_walk16 =[ $walk16, pyro_walk1 ] {ai_walk(2);};
|
|
|
|
//============================================================================
|
|
float pyro_RUN_SPEED = 1.5;
|
|
void() pyro_run1 =[ $run1, pyro_run2 ] {monster_idle_sound(); ai_run(18 * pyro_RUN_SPEED);};
|
|
void() pyro_run2 =[ $run2, pyro_run3 ] {ai_run(14 * pyro_RUN_SPEED);};
|
|
void() pyro_run3 =[ $run3, pyro_run4 ] {ai_run(7 * pyro_RUN_SPEED);};
|
|
void() pyro_run4 =[ $run4, pyro_run5 ] {ai_run(12 * pyro_RUN_SPEED);};
|
|
void() pyro_run5 =[ $run5, pyro_run6 ] {ai_run(14 * pyro_RUN_SPEED);};
|
|
void() pyro_run6 =[ $run6, pyro_run7 ] {ai_run(14 * pyro_RUN_SPEED);};
|
|
void() pyro_run7 =[ $run7, pyro_run8 ] {ai_run(7 * pyro_RUN_SPEED);};
|
|
void() pyro_run8 =[ $run8, pyro_run1 ] {ai_run(11 * pyro_RUN_SPEED);};
|
|
|
|
//============================================================================
|
|
// - Pyro enforcer (FIRE FIRE FIRE!)
|
|
//----------------------------------------------------------------------
|
|
void() pyroflame_touch =
|
|
{
|
|
if (other == self.owner) return;
|
|
if (other.solid == SOLID_TRIGGER) return;
|
|
if (other.health < 1) return;
|
|
if (other.takedamage == DAMAGE_NO) return;
|
|
if (self.attack_finished > time) return;
|
|
if (other.classtype == self.owner.classtype) return; // Pyro proof!
|
|
|
|
// Stop still if hit world, carry on if burning something
|
|
if (other != world) self.velocity = self.movedir;
|
|
else self.velocity = '0 0 0';
|
|
|
|
// Block sprite burst from damage again
|
|
self.attack_finished = time + 1;
|
|
|
|
// Check owner is a Pyro?
|
|
if (self.owner.classtype == CT_MONPYRO) {
|
|
// damage and debuff are same function
|
|
ApplyFireDmg(other, DAMAGE_PYROFLAME, DAMAGE_MONFLAME);
|
|
}
|
|
else {
|
|
// Can only poison the player
|
|
if (other.flags & FL_CLIENT) {
|
|
// Check if player is posioned already?
|
|
if (other.poisoned) T_Damage (other, self, self, DAMAGE_FUMPOISON, DAMARMOR);
|
|
// Make sure player is posioned
|
|
else PoisonDeBuff(other);
|
|
}
|
|
// Poison anything else (very quick death, high damage)
|
|
else T_Damage (other, self, self, DAMAGE_MONFLAME, DAMARMOR);
|
|
}
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyroflame_think =
|
|
{
|
|
self.cnt = self.cnt + 1;
|
|
if (self.cnt > 6) remove(self);
|
|
else {
|
|
self.frame = self.cnt;
|
|
// Randomly drift upwards and slow down forward movement
|
|
self.velocity_z = self.velocity_z + 10 + (random() * 20);
|
|
self.velocity = self.velocity - (self.movedir * 0.125);
|
|
self.nextthink = time + 0.1;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void(vector org, vector dir) pyroflame_spawn =
|
|
{
|
|
local vector variance;
|
|
local float roll, pointc;
|
|
|
|
newmis = spawn();
|
|
newmis.classtype = CT_TEMPSTREAM;
|
|
newmis.classname = "PBurst";
|
|
newmis.owner = self;
|
|
newmis.frame = newmis.cnt = 0;
|
|
|
|
// Extra wide flame contact if fighting a monster
|
|
if (self.enemy.flags & FL_MONSTER) newmis.movetype = MOVETYPE_FLYMISSILE;
|
|
else newmis.movetype = MOVETYPE_FLY; // Standard flame size
|
|
newmis.solid = SOLID_TRIGGER; // collision, touch required
|
|
|
|
// The Pyro and Fumigator have different flame types
|
|
// Pyro = fire, Fum = Poison
|
|
//-----------------------------------------------
|
|
if (self.classtype == CT_MONPYRO) {
|
|
// Switch particles between fire and smoke based on contents
|
|
pointc = pointcontents(self.origin);
|
|
if (pointc <= CONTENT_WATER) {
|
|
if (ext_dppart) {
|
|
// Use special DP smoke and empty sprite for collision
|
|
pointparticles(particleeffectnum(DPP_PYROFLAME2), org, dir, 1);
|
|
setmodel (newmis, SBURST_FLAMEDP);
|
|
}
|
|
else setmodel (newmis, SBURST_SMOKE);
|
|
}
|
|
else {
|
|
if (ext_dppart) {
|
|
// Use special DP flames and empty sprite for collision
|
|
pointparticles(particleeffectnum(DPP_PYROFLAME1), org, dir, 1);
|
|
setmodel (newmis, SBURST_FLAMEDP);
|
|
}
|
|
else setmodel (newmis, SBURST_FLAME);
|
|
}
|
|
}
|
|
else {
|
|
if (ext_dppart) {
|
|
// Use special DP flames and empty sprite for collision
|
|
pointparticles(particleeffectnum(DPP_PYROFLAME3), org, dir, 1);
|
|
setmodel (newmis, SBURST_POISONDP);
|
|
}
|
|
else setmodel (newmis, SBURST_POISON);
|
|
}
|
|
|
|
setorigin (newmis, org);
|
|
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
|
|
|
|
// Work out forward speed (tweak based on skill level)
|
|
variance = vecrand(0,10,TRUE); // +/- 10 on all axis
|
|
newmis.attack_speed = SPEED_PYROFLAME + skill * SPEED_PYROSKILL;
|
|
newmis.movedir = (dir * newmis.attack_speed) + '0 0 -50' + variance;
|
|
newmis.velocity = newmis.movedir;
|
|
|
|
// Roll the flames from side to side towards the target
|
|
roll = 350 + random() * 20;
|
|
newmis.angles_z = anglemod(roll);
|
|
|
|
// If DP engine active remove particle shadow
|
|
if (engine == ENG_DPEXT) newmis.effects = newmis.effects + EF_NOSHADOW;
|
|
|
|
newmis.nextthink = time + 0.1;
|
|
newmis.think = pyroflame_think;
|
|
newmis.touch = pyroflame_touch;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_fire =
|
|
{
|
|
local vector org, dir, targ_org;
|
|
|
|
if (self.health < 1) return;
|
|
|
|
makevectors (self.angles);
|
|
org = self.origin + attack_vector(self.attack_offset);
|
|
// point the flames at the feet of the player
|
|
if (self.enemy.flags & FL_CLIENT) targ_org = self.enemy.origin - '0 0 20';
|
|
else targ_org = self.enemy.origin - self.enemy.view_ofs;
|
|
dir = normalize(targ_org - self.origin);
|
|
pyroflame_spawn(org, dir);
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_atk1 =[ $attack1, pyro_atk2 ] {ai_face();};
|
|
void() pyro_atk2 =[ $attack3, pyro_atk3 ] {ai_face();};
|
|
void() pyro_atk3 =[ $attack5, pyro_atk4 ] {ai_face();
|
|
sound (self, CHAN_WEAPON, self.noise3, 1, ATTN_NORM); // ON
|
|
pyro_fire();
|
|
self.attack_finished = time + 0.3;
|
|
};
|
|
void() pyro_atk4 =[ $attack5, pyro_atk5 ] {ai_face();
|
|
pyro_fire();
|
|
if (self.attack_finished > time ||
|
|
(range(self.enemy) == RANGE_MELEE && self.enemy.health > 0) )
|
|
self.think = pyro_atk4;
|
|
};
|
|
void() pyro_atk5 =[ $attack10, pyro_run1 ] {ai_face();
|
|
sound (self, CHAN_WEAPON, self.noise4, 1, ATTN_NORM); // OFF
|
|
SUB_CheckRefire (pyro_atk1);
|
|
};
|
|
|
|
//============================================================================
|
|
void() pyro_paina1 =[ $paina1, pyro_paina2 ] {};
|
|
void() pyro_paina2 =[ $paina2, pyro_paina3 ] {};
|
|
void() pyro_paina3 =[ $paina3, pyro_paina4 ] {};
|
|
void() pyro_paina4 =[ $paina4, pyro_run1 ] {};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_painb1 =[ $painb1, pyro_painb2 ] {};
|
|
void() pyro_painb2 =[ $painb2, pyro_painb3 ] {};
|
|
void() pyro_painb3 =[ $painb3, pyro_painb4 ] {};
|
|
void() pyro_painb4 =[ $painb4, pyro_painb5 ] {};
|
|
void() pyro_painb5 =[ $painb5, pyro_run1 ] {};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_painc1 =[ $painc1, pyro_painc2 ] {};
|
|
void() pyro_painc2 =[ $painc2, pyro_painc3 ] {};
|
|
void() pyro_painc3 =[ $painc3, pyro_painc4 ] {};
|
|
void() pyro_painc4 =[ $painc4, pyro_painc5 ] {};
|
|
void() pyro_painc5 =[ $painc5, pyro_painc6 ] {};
|
|
void() pyro_painc6 =[ $painc6, pyro_painc7 ] {};
|
|
void() pyro_painc7 =[ $painc7, pyro_painc8 ] {};
|
|
void() pyro_painc8 =[ $painc8, pyro_run1 ] {};
|
|
|
|
//----------------------------------------------------------------------
|
|
void(entity inflictor, entity attacker, float damage) pyro_pain =
|
|
{
|
|
// Check all pain conditions and set up what to do next
|
|
monster_pain_check(attacker, damage);
|
|
pyro_soundreset();
|
|
|
|
// Any pain animation/sound required?
|
|
if (self.pain_check > 0) {
|
|
self.lip = random ();
|
|
if (self.lip < 0.5) sound (self, CHAN_VOICE, self.pain_sound, 1, ATTN_NORM);
|
|
else sound (self, CHAN_VOICE, self.pain_sound2, 1, ATTN_NORM);
|
|
|
|
// Not using long pain animation (need to be agile)
|
|
if (self.pain_check == 1) {
|
|
// Randomly pick which pain animation to play
|
|
if (self.lip < 0.3) pyro_paina1 ();
|
|
else if (self.lip < 0.6) pyro_painb1 ();
|
|
else pyro_painc1 ();
|
|
}
|
|
else if (self.pain_check == 2) {
|
|
// reset axe hit and setup short pain recovery
|
|
self.pain_finished = time + 0.8;
|
|
self.axhitme = 0;
|
|
pyro_painc1 ();
|
|
}
|
|
}
|
|
};
|
|
|
|
//============================================================================
|
|
void() pyro_die1 =[ $death1, pyro_die2 ] {};
|
|
void() pyro_die2 =[ $death2, pyro_die3 ] {monster_check_gib();};
|
|
void() pyro_die3 =[ $death3, pyro_die4 ] {monster_check_gib();
|
|
self.solid = SOLID_NOT; if (!self.gibbed) DropBackpack();};
|
|
void() pyro_die4 =[ $death4, pyro_die5 ] {ai_forward(14);};
|
|
void() pyro_die5 =[ $death5, pyro_die6 ] {ai_forward(2);};
|
|
void() pyro_die6 =[ $death6, pyro_die7 ] {};
|
|
void() pyro_die7 =[ $death7, pyro_die8 ] {};
|
|
void() pyro_die8 =[ $death8, pyro_die9 ] {};
|
|
void() pyro_die9 =[ $death9, pyro_die10 ] {ai_forward(3);};
|
|
void() pyro_die10 =[ $death10, pyro_die11 ] {ai_forward(5);};
|
|
void() pyro_die11 =[ $death11, pyro_die12 ] {ai_forward(5);};
|
|
void() pyro_die12 =[ $death12, pyro_die13 ] {ai_forward(5);};
|
|
void() pyro_die13 =[ $death13, pyro_die14 ] {monster_death_postcheck();};
|
|
void() pyro_die14 =[ $death14, pyro_die14 ] {monster_deadbody_check();};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_fdie1 =[ $fdeath1, pyro_fdie2 ] {};
|
|
void() pyro_fdie2 =[ $fdeath2, pyro_fdie3 ] {monster_check_gib();};
|
|
void() pyro_fdie3 =[ $fdeath3, pyro_fdie4 ] {monster_check_gib();
|
|
self.solid = SOLID_NOT; if (!self.gibbed) DropBackpack();};
|
|
void() pyro_fdie4 =[ $fdeath4, pyro_fdie5 ] {};
|
|
void() pyro_fdie5 =[ $fdeath5, pyro_fdie6 ] {};
|
|
void() pyro_fdie6 =[ $fdeath6, pyro_fdie7 ] {};
|
|
void() pyro_fdie7 =[ $fdeath7, pyro_fdie8 ] {};
|
|
void() pyro_fdie8 =[ $fdeath8, pyro_fdie9 ] {};
|
|
void() pyro_fdie9 =[ $fdeath9, pyro_fdie10 ] {};
|
|
void() pyro_fdie10 =[ $fdeath10, pyro_fdie11 ] {monster_death_postcheck();};
|
|
void() pyro_fdie11 =[ $fdeath11, pyro_fdie11 ] {monster_deadbody_check();};
|
|
|
|
//----------------------------------------------------------------------
|
|
void() pyro_die =
|
|
{
|
|
// Pre-check routine to tidy up extra entities
|
|
monster_death_precheck();
|
|
pyro_soundreset();
|
|
|
|
// regular death
|
|
if (!self.gibbed) {
|
|
sound (self, CHAN_VOICE, "enforcer/death1.wav", 1, ATTN_NORM);
|
|
if (random() > 0.5) pyro_die1 ();
|
|
else pyro_fdie1 ();
|
|
}
|
|
};
|
|
|
|
/*======================================================================
|
|
QUAKED monster_pyro (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
|
======================================================================*/
|
|
void() monster_pyro =
|
|
{
|
|
if (deathmatch) { remove(self); return; }
|
|
|
|
self.mdl = "progs/mon_pyro.mdl";
|
|
self.headmdl = "progs/h_pyro.mdl";
|
|
self.gib1mdl = "progs/w_enforcergun.mdl"; // Unique weapon
|
|
precache_model (self.mdl);
|
|
precache_model (self.headmdl);
|
|
precache_model (self.gib1mdl);
|
|
self.gib1skin = 3;
|
|
|
|
precache_sound ("enforcer/death1.wav");
|
|
self.pain_sound = "enforcer/pain1.wav";
|
|
self.pain_sound2 = "enforcer/pain2.wav";
|
|
precache_sound (self.pain_sound);
|
|
precache_sound (self.pain_sound2);
|
|
|
|
self.idle_sound = "enforcer/idle1.wav";
|
|
precache_sound (self.idle_sound);
|
|
self.sight_sound = "enforcer/sight1.wav";
|
|
precache_sound (self.sight_sound);
|
|
precache_sound ("enforcer/sight2.wav");
|
|
precache_sound ("enforcer/sight3.wav");
|
|
precache_sound ("enforcer/sight4.wav");
|
|
|
|
// Extra sound/sprite assets (from Rubicon2 MOD)
|
|
self.noise3 = "enforcer/pyro_flameon.wav";
|
|
self.noise4 = "enforcer/pyro_flameoff.wav";
|
|
precache_sound (self.noise3);
|
|
precache_sound (self.noise4);
|
|
precache_model (SBURST_FLAME); // Flame on
|
|
precache_model (SBURST_SMOKE); // Underwater
|
|
precache_model (SBURST_FLAMEDP); // DP Collision
|
|
|
|
self.solid = SOLID_NOT;
|
|
self.movetype = MOVETYPE_NONE;
|
|
if (self.bboxtype < 1) self.bboxtype = BBOX_TALL;
|
|
if (self.health < 1) self.health = 100;
|
|
self.gibhealth = -35;
|
|
self.gibbed = FALSE;
|
|
self.yaw_speed = 35; // Can turn really fast
|
|
self.pain_flinch = 100; // extremely high pain tolerance
|
|
self.pain_longanim = TRUE; // can be chopped with shadow axe
|
|
self.steptype = FS_TYPEHEAVY; // heavy feet
|
|
self.attack_offset = '24 8.5 16'; // End of Gun
|
|
self.ammo_shells = 4; // drops armor shards instead
|
|
if (!self.exactskin) self.randomskin = 4;
|
|
self.poisonous = FALSE; // Use Fumigator instead
|
|
self.deathstring = " was toasted by a Pyro\n";
|
|
|
|
// Always reset Ammo Resistance to be consistent
|
|
self.resist_shells = 0; self.resist_nails = 0.5;
|
|
self.resist_rockets = self.resist_cells = 0;
|
|
|
|
self.th_checkattack = PyroCheckAttack;
|
|
self.th_stand = pyro_stand1;
|
|
self.th_walk = pyro_walk1;
|
|
self.th_run = pyro_run1;
|
|
self.th_pain = pyro_pain;
|
|
self.th_die = pyro_die;
|
|
self.th_melee = pyro_atk1;
|
|
self.th_missile = pyro_atk1; // For monster_turret function
|
|
|
|
self.classtype = CT_MONPYRO;
|
|
self.classgroup = CG_ENFORCER;
|
|
self.classmove = MON_MOVEWALK;
|
|
monster_start();
|
|
};
|
|
|
|
/*======================================================================
|
|
QUAKED monster_fumigator (1 0 0) (-16 -16 -24) (16 16 40) Ambush
|
|
======================================================================*/
|
|
void() monster_fumigator =
|
|
{
|
|
if (deathmatch) { remove(self); return; }
|
|
|
|
self.mdl = "progs/mon_fumigator.mdl";
|
|
self.headmdl = "progs/h_pyro.mdl";
|
|
self.gib1mdl = "progs/w_enforcergun.mdl"; // Unique weapon
|
|
precache_model (self.mdl);
|
|
precache_model (self.headmdl);
|
|
precache_model (self.gib1mdl);
|
|
self.gib1sound = GIB_IMPACT_WOOD;
|
|
self.gib1skin = 4;
|
|
|
|
precache_sound ("enforcer/death1.wav");
|
|
self.pain_sound = "enforcer/pain1.wav";
|
|
self.pain_sound2 = "enforcer/pain2.wav";
|
|
precache_sound (self.pain_sound);
|
|
precache_sound (self.pain_sound2);
|
|
|
|
self.idle_sound = "enforcer/idle1.wav";
|
|
precache_sound (self.idle_sound);
|
|
self.sight_sound = "enforcer/sight1.wav";
|
|
precache_sound (self.sight_sound);
|
|
precache_sound ("enforcer/sight2.wav");
|
|
precache_sound ("enforcer/sight3.wav");
|
|
precache_sound ("enforcer/sight4.wav");
|
|
|
|
// Extra sound/sprite assets (from Rubicon2 MOD)
|
|
self.noise3 = "enforcer/fum_poisonon.wav";
|
|
self.noise4 = "enforcer/fum_poisonoff.wav";
|
|
precache_sound (self.noise3);
|
|
precache_sound (self.noise4);
|
|
precache_model (SBURST_POISON); // Poison on
|
|
precache_model (SBURST_POISONDP); // DP Collision
|
|
|
|
precache_poisongibs(); // precache gibs
|
|
self.gibtype = GIBTYPE_POISON; // Poison gibs!
|
|
self.poisonous = TRUE; // Oh yeah! Always!
|
|
|
|
self.solid = SOLID_NOT;
|
|
self.movetype = MOVETYPE_NONE;
|
|
if (self.bboxtype < 1) self.bboxtype = BBOX_TALL;
|
|
if (self.health < 1) self.health = 100;
|
|
self.gibhealth = -35;
|
|
self.gibbed = FALSE;
|
|
self.yaw_speed = 35; // Can turn really fast
|
|
self.pain_flinch = 100; // extremely high pain tolerance
|
|
self.pain_longanim = TRUE; // can be chopped with shadow axe
|
|
self.steptype = FS_TYPEHEAVY; // heavy feet
|
|
self.attack_offset = '24 8.5 16'; // End of Gun
|
|
self.ammo_shells = 4; // drops armor shards instead
|
|
self.no_liquiddmg = TRUE; // Immune to slime/lava
|
|
if (!self.exactskin) self.randomskin = 4;
|
|
self.deathstring = " was choked by a Fumigator\n";
|
|
|
|
// Always reset Ammo Resistance to be consistent
|
|
self.resist_shells = 0; self.resist_nails = 0.5;
|
|
self.resist_rockets = self.resist_cells = 0;
|
|
self.reflectnails = TRUE; // Reflect nail projectiles
|
|
|
|
self.th_checkattack = PyroCheckAttack;
|
|
self.th_stand = pyro_stand1;
|
|
self.th_walk = pyro_walk1;
|
|
self.th_run = pyro_run1;
|
|
self.th_pain = pyro_pain;
|
|
self.th_die = pyro_die;
|
|
self.th_melee = pyro_atk1;
|
|
self.th_missile = pyro_atk1; // For monster_turret function
|
|
|
|
self.classtype = CT_MONFUMIGATOR;
|
|
self.classgroup = CG_ENFORCER;
|
|
self.classmove = MON_MOVEWALK;
|
|
monster_start();
|
|
};
|