Files
quakemapping/mod_ad_dev/my_progs/mon_freddie.qc
2019-12-30 22:24:44 +01:00

565 lines
24 KiB
Plaintext

/*==============================================================================
FREDDIE (Edie from Quoth - Kell/Necros/Preach)
==============================================================================*/
// Run/Walk same animation
$frame run1 run2 run3 run4 run5 run6 run7 run8
$frame run9 run10 run11 run12 run13 run14 run15 run16
// Run and fire nail/laser gun at same time
$frame rfire1 rfire2 rfire3 rfire4 rfire5 rfire6 rfire7 rfire8
$frame rfire9 rfire10 rfire11 rfire12 rfire13 rfire14 rfire15 rfire16
// Stand and fire nail/laser gun
$frame sfire1 sfire2 sfire3 sfire4 sfire5 sfire6 sfire7 sfire8
$frame sfire9 sfire10 sfire11 sfire12 sfire13 sfire14 sfire15 sfire16
$frame sfire17 sfire18 sfire19 sfire20 sfire21 sfire22 sfire23 sfire24
$frame sfire25 sfire26 sfire27 sfire28
// Pain forward
$frame pain1 pain2 pain3 pain4 pain5 pain6 pain7 pain8
$frame pain9 pain10 pain11 pain12
// Pain Backward (short)
$frame painb1 painb2 painb3 painb4 painb5
// Quick forward swing of chainsaw arm
$frame fswing1 fswing2 fswing3 fswing4 fswing5 fswing6 fswing7 fswing8
$frame fswing9 fswing10 fswing11
// Quick smack with elbow of chainsaw arm
$frame fswinge1 fswinge2 fswinge3 fswinge4 fswinge5 fswinge6 fswinge7
$frame fswinge8 fswinge9 fswinge10
// Slow back swing of chainsaw arm (left to right)
$frame bswing1 bswing2 bswing3 bswing4 bswing5 bswing6 bswing7 bswing8
$frame bswing9 bswing10 bswing11 bswing12 bswing13 bswing14
// Extremely long death animation!
$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14 death15 death16
$frame death17 death18 death19 death20 death21 death22 death23 death24
$frame death25 death26 death27 death28 death29 death30 death31 death32
$frame death33 death34 death35
// Export frames (ignored)
$frame base1 base2
// Standing / idle animation
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8
//============================================================================
void() fred_stand1 =[ $stand1, fred_stand2 ] {monster_idle_sound(); ai_stand();};
void() fred_stand2 =[ $stand2, fred_stand3 ] {ai_stand();};
void() fred_stand3 =[ $stand3, fred_stand4 ] {ai_stand();};
void() fred_stand4 =[ $stand4, fred_stand5 ] {ai_stand();};
void() fred_stand5 =[ $stand5, fred_stand6 ] {ai_stand();};
void() fred_stand6 =[ $stand6, fred_stand7 ] {ai_stand();};
void() fred_stand7 =[ $stand7, fred_stand8 ] {ai_stand();};
void() fred_stand8 =[ $stand8, fred_stand1 ] {ai_stand();};
//============================================================================
void() fred_walk1 = [ $run1, fred_walk2 ] {monster_idle_sound(); ai_walk(20);};
void() fred_walk2 = [ $run2, fred_walk3 ] {monster_footstep(FALSE);ai_walk(16);};
void() fred_walk3 = [ $run3, fred_walk4 ] {ai_walk(1);};
void() fred_walk4 = [ $run4, fred_walk5 ] {ai_walk(2);};
void() fred_walk5 = [ $run5, fred_walk6 ] {ai_walk(4);};
void() fred_walk6 = [ $run6, fred_walk7 ] {ai_walk(8);};
void() fred_walk7 = [ $run7, fred_walk8 ] {ai_walk(4);};
void() fred_walk8 = [ $run8, fred_walk9 ] {ai_walk(16);};
void() fred_walk9 = [ $run9, fred_walk10 ] {ai_walk(20);};
void() fred_walk10 = [ $run10, fred_walk11 ] {monster_footstep(FALSE);ai_walk(16);};
void() fred_walk11 = [ $run11, fred_walk12 ] {ai_walk(1);};
void() fred_walk12 = [ $run12, fred_walk13 ] {ai_walk(2);};
void() fred_walk13 = [ $run13, fred_walk14 ] {ai_walk(4);};
void() fred_walk14 = [ $run14, fred_walk15 ] {ai_walk(8);};
void() fred_walk15 = [ $run15, fred_walk16 ] {ai_walk(4);};
void() fred_walk16 = [ $run16, fred_walk1 ] {ai_walk(16);};
//===========================================================================
// RANGE ATTACK - Fires spikes or laser bolts
//===========================================================================
void(vector weapofs) fred_fireweapon =
{
local vector org, dir, vec;
// Check for death?
if (self.health < 1) return;
// Lit up that barrel
self.effects = self.effects | EF_MUZZLEFLASH;
// Nail and laser use the same firing speed
self.attack_speed = SPEED_FREDDIEPROJ + (skill * SPEED_FREDDIESKILL);
// turn and face your enemy!
makevectors (self.angles);
org = self.origin + attack_vector(weapofs);
// The mini burst mode (run+fire) can do tracking
if (self.attack_timer && skill > SKILL_NORMAL) {
// More precise fire, track player velocity
// Reset the tracking on first shot, get better over time
if (self.cnt == 1)
self.attack_track = SUB_Tracking(self.enemy.origin, weapofs, self.enemy, self.attack_speed);
else self.attack_track = SUB_Tracking(self.attack_track, weapofs, self.enemy, self.attack_speed);
dir = normalize(self.attack_track - org);
}
else {
// Standard mode spray bullets at player
vec = v_right*(crandom()*(20+random()*50));
dir = normalize((self.enemy.origin + vec) - org);
}
// Switch projectile type based on spawnflag
if (self.spawnflags & MON_FREDDIE_LASER) {
sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
launch_projectile(org, dir, CT_PROJ_LASER, self.attack_speed);
}
else {
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
launch_projectile(org, dir, CT_PROJ_MONNG, self.attack_speed);
}
};
// Start the initial wind up of the weapon first
//----------------------------------------------------------------------
void() fred_sfire1 = [ $sfire1, fred_sfire2 ] {ai_face();
self.pain_finished = time + 0.5 + (skill*0.5);
sound (self, CHAN_WEAPON, "freddie/stfire.wav", 1, ATTN_NORM);};
void() fred_sfire2 = [ $sfire2, fred_sfire3 ] {ai_face();};
void() fred_sfire3 = [ $sfire3, fred_sfire4 ] {ai_face();};
void() fred_sfire4 = [ $sfire4, fred_sfire5 ] {ai_face();};
void() fred_sfire5 = [ $sfire5, fred_sfire6 ] {ai_face();monster_footstep(FALSE);};
void() fred_sfire6 = [ $sfire6, fred_sfire7 ] {ai_face();};
void() fred_sfire7 = [ $sfire7, fred_sfire8 ] {ai_face();};
void() fred_sfire8 = [ $sfire8, fred_sfire9 ] {ai_face();
self.cnt = 0;
// Vary bullet burst based on skill
self.attack_chance = 4 + skill*2;
};
// Fire the weapon in bursts
//----------------------------------------------------------------------
void(vector weapofs) fred_standfire =
{
// Always check AI health before locking in function
if (self.health < 1) return;
// Turn before offset check
ai_face();
// If no enemy or enemy dead then stop attack
if (!self.enemy || self.enemy.health < 1) self.cnt = 10;
// Check if can see enemy? (use weapon offset)
else if (visxray(self.enemy, weapofs, '0 0 0', FALSE))
self.cnt = self.cnt + 1;
// Reset counter and keep firing
else self.cnt = 0;
// If fired a burst of bullets at enemy, stop loop
if (self.cnt > self.attack_chance) self.think = self.th_charge;
else fred_fireweapon(weapofs);
};
// Cycle through barrel firing
// Easy = 7 shots, Normal = 11 shots, Hard/NM = 15 shots
//----------------------------------------------------------------------
void() fred_sfire9 = [ $sfire9, fred_sfire10 ] {fred_standfire('45 -10 20');};
void() fred_sfire10 = [ $sfire10, fred_sfire11 ] {fred_standfire('45 -10 20');};
void() fred_sfire11 = [ $sfire11, fred_sfire12 ] {fred_standfire('45 -10 22');};
void() fred_sfire12 = [ $sfire12, fred_sfire13 ] {fred_standfire('45 -10 22');};
void() fred_sfire13 = [ $sfire13, fred_sfire14 ] {fred_standfire('45 -12 23');};
void() fred_sfire14 = [ $sfire14, fred_sfire15 ] {fred_standfire('42 -12 25');};
void() fred_sfire15 = [ $sfire15, fred_sfire16 ] {fred_standfire('42 -14 23');
// Always double check health before changing think
if (self.health > 0 && skill == SKILL_EASY) self.think = self.th_charge;};
void() fred_sfire16 = [ $sfire16, fred_sfire17 ] {fred_standfire('38 -14 27');};
void() fred_sfire17 = [ $sfire17, fred_sfire18 ] {fred_standfire('38 -17 26');};
void() fred_sfire18 = [ $sfire18, fred_sfire19 ] {fred_standfire('36 -17 28');};
void() fred_sfire19 = [ $sfire19, fred_sfire20 ] {fred_standfire('36 -17 26');
// Always double check health before changing think
if (self.health > 0 && skill == SKILL_NORMAL) self.think = self.th_charge;};
void() fred_sfire20 = [ $sfire20, fred_sfire21 ] {fred_standfire('30 -17 28');};
void() fred_sfire21 = [ $sfire21, fred_sfire22 ] {fred_standfire('30 -18 25');};
void() fred_sfire22 = [ $sfire22, fred_sfire23 ] {fred_standfire('25 -18 27');};
void() fred_sfire23 = [ $sfire23, fred_sfire24 ] {fred_standfire('25 -18 27');};
// Finish the wind down of weapon
void() fred_sfire24 = [ $sfire24, fred_sfire25 ] {};
void() fred_sfire25 = [ $sfire25, fred_sfire26 ] {};
void() fred_sfire26 = [ $sfire26, fred_sfire27 ] {};
void() fred_sfire27 = [ $sfire27, fred_run ] {};
//============================================================================
// freddie has a run while firing and can switch seamless
// between the two if the player is within sight
//============================================================================
void() fred_runframe =
{
// If dead, no more updates
if (self.health < 1) return;
// If enemy is dead or missing no firing
if (!self.enemy || self.enemy.health < 1) self.attack_timer = FALSE;
if (self.attack_timer) self.frame = $rfire1 + self.walkframe;
else self.frame = $run1 + self.walkframe;
// Beginning of animation block
if (self.walkframe == 0) monster_idle_sound();
else if (self.walkframe == 1) monster_footstep(FALSE);
else if (self.walkframe == 10) monster_footstep(FALSE);
if (self.walkframe == 0) {self.distance = 24;self.attack_offset = '50 -20 32';}
else if (self.walkframe == 1) {self.distance = 19;self.attack_offset = '43 -18 33';}
else if (self.walkframe == 2) {self.distance = 1;self.attack_offset = '53 -20 27';}
else if (self.walkframe == 3) {self.distance = 2;self.attack_offset = '47 -19 31';}
else if (self.walkframe == 4) {self.distance = 5;self.attack_offset = '54 -17 29';}
else if (self.walkframe == 5) {self.distance = 10;self.attack_offset = '47 -17 35';}
else if (self.walkframe == 6) {self.distance = 5;self.attack_offset = '53 -15 32';}
else if (self.walkframe == 7) {self.distance = 5;self.attack_offset = '47 -15 36';}
else if (self.walkframe == 8) {self.distance = 24;self.attack_offset = '50 -13 32';}
else if (self.walkframe == 9) {self.distance = 19;self.attack_offset = '46 -15 33';}
else if (self.walkframe == 10) {self.distance = 1;self.attack_offset = '51 -14 33';}
else if (self.walkframe == 11) {self.distance = 2;self.attack_offset = '47 -14 32';}
else if (self.walkframe == 12) {self.distance = 5;self.attack_offset = '52 -14 33';}
else if (self.walkframe == 13) {self.distance = 10;self.attack_offset = '47 -14 36';}
else if (self.walkframe == 14) {self.distance = 5;self.attack_offset = '49 -14 35';}
else if (self.walkframe == 15) {self.distance = 5;self.attack_offset = '45 -15 34';}
// Run + Fire time?
if (self.attack_timer) {
// Keep turning towards the enemy
ai_face();
// Fire a small burst at the enemy
self.cnt = self.cnt + 1;
if (self.cnt > 2) self.attack_timer = FALSE;
else fred_fireweapon(self.attack_offset);
}
// Move frame forward, check for conditions
self.walkframe = self.walkframe + 1;
if (self.walkframe > 15) self.walkframe = 0;
self.nextthink = time + 0.1;
self.think = fred_runframe;
ai_run(self.distance);
};
//----------------------------------------------------------------------
void() fred_run = { self.walkframe = 0; fred_runframe(); };
//===========================================================================
// MELEE ATTACK - Various back and forth blade arm attacks
//===========================================================================
void(float side) fred_blade =
{
local float ldmg;
if (!self.enemy) return;
if (self.health < 1) return;
ai_damagebreakable(20); // Damage any breakables
if (!ai_checkmelee(self.meleerange)) return; // Too far away
// Can the target bleed? - generate blood
if (!CanDamage (self.enemy, self)) return;
// Check for poisonous attribute (new poison version)
if (self.poisonous) PoisonDeBuff(self.enemy);
sound (self, CHAN_WEAPON, "freddie/mangle.wav", 1, ATTN_NORM);
// 1-45 (3x15) damage
ldmg = (random() + random() + random()) * 15;
if (ldmg < 1) ldmg = 1;
T_Damage (self.enemy, self, self, ldmg, DAMARMOR);
SpawnMeatSpray (self, self.enemy, side);
SpawnMeatSpray (self, self.enemy, side);
};
// Alternative ending of melee attack (chance of extra damage)
//----------------------------------------------------------------------
void() fred_bswing1 = [ $bswing1, fred_bswing2 ] {ai_faceforward(20);
sound (self, CHAN_WEAPON, "freddie/sawstart.wav", 1, ATTN_NORM);};
void() fred_bswing2 = [ $bswing2, fred_bswing3 ] {ai_faceforward(12);};
void() fred_bswing3 = [ $bswing3, fred_bswing4 ] {ai_faceforward(4);};
void() fred_bswing4 = [ $bswing4, fred_bswing5 ] {ai_faceforward(2);monster_footstep(FALSE);};
void() fred_bswing5 = [ $bswing5, fred_bswing6 ] {ai_faceforward(6);fred_blade(200);};
void() fred_bswing6 = [ $bswing6, fred_bswing7 ] {ai_faceforward(4);};
void() fred_bswing7 = [ $bswing7, fred_bswing8 ] {ai_faceforward(4);};
void() fred_bswing8 = [ $bswing8, fred_bswing9 ] {ai_faceforward(8);};
void() fred_bswing9 = [ $bswing9, fred_bswing10 ] {ai_faceforward(8);monster_footstep(FALSE);};
void() fred_bswing10 = [ $bswing10, fred_bswing11 ] {ai_faceforward(8);};
void() fred_bswing11 = [ $bswing11, fred_bswing12 ] {ai_faceforward(8);};
void() fred_bswing12 = [ $bswing12, fred_bswing13 ] {ai_faceforward(12);};
void() fred_bswing13 = [ $bswing13, fred_bswing14 ] {ai_faceforward(10);};
void() fred_bswing14 = [ $bswing14, fred_run ] {ai_faceforward(10);};
// Start of melee attack
//----------------------------------------------------------------------
void() fred_fswing1 = [ $fswing1, fred_fswing2 ] {ai_faceforward(8);
sound (self, CHAN_WEAPON, "freddie/sawstart.wav", 1, ATTN_NORM);};
void() fred_fswing2 = [ $fswing2, fred_fswing3 ] {ai_faceforward(16); monster_footstep(FALSE);};
void() fred_fswing3 = [ $fswing3, fred_fswing4 ] {ai_faceforward(10);
self.nextthink = time + 0.09;};
void() fred_fswing4 = [ $fswing4, fred_fswing5 ] {ai_faceforward(4);
self.nextthink = time + 0.08; monster_footstep(FALSE);};
void() fred_fswing5 = [ $fswing5, fred_fswing6 ] {ai_faceforward(2);
self.nextthink = time + 0.07;};
void() fred_fswing6 = [ $fswing6, fred_fswing7 ] {ai_faceforward(1);
self.nextthink = time + 0.07;};
void() fred_fswing7 = [ $fswing7, fred_fswing8 ] {ai_faceforward(1);
self.nextthink = time + 0.06;};
void() fred_fswing8 = [ $fswing8, fred_fswing9 ] {ai_faceforward(2);fred_blade(-200);
self.nextthink = time + 0.05;};
void() fred_fswing9 = [ $fswing9, fred_fswing10 ] {ai_faceforward(2);};
void() fred_fswing10 = [ $fswing10, fred_fswing11 ] {ai_faceforward(2);};
void() fred_fswing11 = [ $fswing11, fred_fswinge1 ] {
// Always check for enemy and health before changing think
if (self.enemy && self.enemy.health > 1 && self.health > 0) {
// Check if within range to do a second (back) swing attack
if (ai_checkmelee(self.meleerange)) self.think = fred_bswing1;
}
};
// End of melee attack
//----------------------------------------------------------------------
void() fred_fswinge1 = [ $fswinge1, fred_fswinge2 ] {ai_faceforward(2);};
void() fred_fswinge2 = [ $fswinge2, fred_fswinge3 ] {ai_faceforward(2);};
void() fred_fswinge3 = [ $fswinge3, fred_fswinge4 ] {ai_faceforward(3);};
void() fred_fswinge4 = [ $fswinge4, fred_fswinge5 ] {ai_faceforward(4);};
void() fred_fswinge5 = [ $fswinge5, fred_fswinge6 ] {ai_faceforward(8);};
void() fred_fswinge6 = [ $fswinge6, fred_fswinge7 ] {ai_faceforward(12);};
void() fred_fswinge7 = [ $fswinge7, fred_fswinge8 ] {ai_faceforward(16);};
void() fred_fswinge8 = [ $fswinge8, fred_fswinge9 ] {ai_faceforward(12);};
void() fred_fswinge9 = [ $fswinge9, fred_fswinge10 ] {ai_faceforward(16);};
void() fred_fswinge10 = [ $fswinge10, fred_run ] {
ai_faceforward(16);monster_footstep(FALSE);};
//============================================================================
void() fred_pain1 = [ $pain1, fred_pain2 ] {};
void() fred_pain2 = [ $pain2, fred_pain3 ] {ai_pain(10);};
void() fred_pain3 = [ $pain3, fred_pain4 ] {ai_pain(9);};
void() fred_pain4 = [ $pain4, fred_pain5 ] {ai_pain(4);};
void() fred_pain5 = [ $pain5, fred_pain6 ] {};
void() fred_pain6 = [ $pain6, fred_pain7 ] {};
void() fred_pain7 = [ $pain7, fred_pain8 ] {};
void() fred_pain8 = [ $pain8, fred_pain9 ] {};
void() fred_pain9 = [ $pain9, fred_pain10 ] {};
void() fred_pain10 = [ $pain10, fred_pain11 ] {};
void() fred_pain11 = [ $pain11, fred_pain12 ] {};
void() fred_pain12 = [ $pain12, fred_run ] {};
//----------------------------------------------------------------------
void() fred_painb1 = [ $painb1, fred_painb2 ] {};
void() fred_painb2 = [ $painb2, fred_painb3 ] {};
void() fred_painb3 = [ $painb3, fred_painb4 ] {};
void() fred_painb4 = [ $painb4, fred_painb5 ] {};
void() fred_painb5 = [ $painb5, fred_run ] {};
//----------------------------------------------------------------------
void(entity inflictor, entity attacker, float damage) fred_pain =
{
// Check all pain conditions and set up what to do next
monster_pain_check(attacker, damage);
// Any pain animation/sound required?
if (self.pain_check > 0) {
if (random() < 0.2) {
sound (self, CHAN_VOICE, self.pain_sound, 1, ATTN_NORM);
self.pain_finished = time + 3 + random()*2;
fred_pain1();
}
else {
sound (self, CHAN_VOICE, self.pain_sound2, 1, ATTN_NORM);
self.pain_finished = time + 2 + random()*2;
fred_painb1();
}
}
};
//============================================================================
void() fred_death1 = [ $death1, fred_death2 ] {};
void() fred_death2 = [ $death2, fred_death3 ] {monster_check_gib();};
void() fred_death3 = [ $death3, fred_death4 ] {monster_check_gib();
self.solid = SOLID_NOT;};
void() fred_death4 = [ $death4, fred_death5 ] {};
void() fred_death5 = [ $death5, fred_death6 ] {};
void() fred_death6 = [ $death6, fred_death7 ] {};
void() fred_death7 = [ $death7, fred_death8 ] {};
void() fred_death8 = [ $death8, fred_death9 ] {};
void() fred_death9 = [ $death9, fred_death10 ] {};
void() fred_death10 = [ $death10, fred_death11 ] {};
void() fred_death11 = [ $death11, fred_death12 ] {};
void() fred_death12 = [ $death12, fred_death13 ] {};
void() fred_death13 = [ $death13, fred_death14 ] {};
void() fred_death14 = [ $death14, fred_death15 ] {};
void() fred_death15 = [ $death15, fred_death16 ] {};
void() fred_death16 = [ $death16, fred_death17 ] {};
void() fred_death17 = [ $death17, fred_death18 ] {};
void() fred_death18 = [ $death18, fred_death19 ] {};
void() fred_death19 = [ $death19, fred_death20 ] {};
void() fred_death20 = [ $death20, fred_death21 ] {};
void() fred_death21 = [ $death21, fred_death22 ] {};
void() fred_death22 = [ $death22, fred_death23 ] {};
void() fred_death23 = [ $death23, fred_death24 ] {};
void() fred_death24 = [ $death24, fred_death25 ] {};
void() fred_death25 = [ $death25, fred_death26 ] {};
void() fred_death26 = [ $death26, fred_death27 ] {};
void() fred_death27 = [ $death27, fred_death28 ] {};
void() fred_death28 = [ $death28, fred_death29 ] {};
void() fred_death29 = [ $death29, fred_death30 ] {};
void() fred_death30 = [ $death30, fred_death31 ] {};
void() fred_death31 = [ $death31, fred_death32 ] {};
void() fred_death32 = [ $death32, fred_death33 ] {};
void() fred_death33 = [ $death33, fred_death34 ] {};
void() fred_death34 = [ $death34, fred_death35 ] {monster_death_postcheck();};
void() fred_death35 = [ $death35, fred_death35 ] {monster_deadbody_check();};
//----------------------------------------------------------------------
void() fred_explode =
{
// no more FREDDIE!
entity_hide (self);
// Make sure gibs go flying up
self.max_health = MON_GIBFOUNTAIN;
self.health = -100;
// ID style explosion
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
T_RadiusDamage (self, self, self.death_dmg, world, DAMAGEALL);
// Sprite + Dust
SpawnExplosion(EXPLODE_BIG, self.origin, self.death_sound);
SpawnProjectileSmoke(self.origin, 200, 250, 100);
SpawnProjectileSmoke(self.origin, 200, 250, 100);
// Regular blood like gibs
ThrowGib(4, 2 + rint(random()*4));
ThrowGib(5, 2 + rint(random()*4));
ThrowGib(25, 1);
// Metal and custom body parts
self.gibtype = GIBTYPE_METAL;
ThrowGib(11, 1 + rint(random()*2));
ThrowGib(12, 2 + rint(random()*2));
ThrowGib(13, 2 + rint(random()*2));
};
//----------------------------------------------------------------------
void() fred_die =
{
// Pre-check routine to tidy up extra entities
monster_death_precheck();
// regular death
if (!self.gibbed) {
sound (self, CHAN_VOICE, "freddie/death.wav", 1, ATTN_NORM);
fred_death1 ();
}
};
/*======================================================================
QUAKED monster_freddie (1 0 0) (-32 -32 -24) (32 32 64) Ambush
======================================================================*/
void() monster_freddie =
{
if (deathmatch) { remove(self); return; }
self.mdl = "progs/mon_freddie.mdl"; // was edie.mdl
self.headmdl = "progs/h_ogre.mdl"; // ID ogre
self.gib1mdl = "progs/gib_freddiejunk.mdl"; // wreckage.mdl
self.gib2mdl = "progs/gib_metal1.mdl"; // Breakable metal
self.gib3mdl = "progs/gib_metal3.mdl"; // Breakable metal
precache_model (self.mdl);
precache_model (self.headmdl); // ID Ogre head
// Gib Junk - 0=Axle, 1=bolt, 2=chip, 3=wing
precache_model (self.gib1mdl); // Multiple chunks of junk
self.gib1frame = 3; // 4 frames choose from
precache_model (self.gib2mdl); // Generic metal1_2
precache_model (self.gib3mdl); // Generic metal1_2
self.idle_sound = "freddie/idle1.wav";
precache_sound (self.idle_sound);
// Melee sounds, swing and impact
precache_sound("freddie/sawstart.wav");
precache_sound("freddie/mangle.wav");
// Default attack - red glowing nails
precache_model (MODEL_PROJ_NGRED);
precache_sound("freddie/stfire.wav");
// Alternative attack - lasers!?!
if (self.spawnflags & MON_FREDDIE_LASER) {
precache_model (MODEL_PROJ_LASER);
precache_sound("seeker/range_laser.wav");
precache_sound ("enforcer/enfire.wav");
precache_sound ("enforcer/enfstop.wav");
}
precache_sound ("freddie/death.wav");
self.death_sound = "seeker/explode_major.wav";
precache_sound (self.death_sound);
self.pain_sound = "freddie/pain.wav";
self.pain_sound2 = "freddie/painshrt.wav";
precache_sound (self.pain_sound);
precache_sound (self.pain_sound2);
self.sight_sound = "freddie/sight.wav";
precache_sound (self.sight_sound);
self.solid = SOLID_NOT; // No interaction with world
self.movetype = MOVETYPE_NONE; // Static item, no movement
if (self.bboxtype < 1) self.bboxtype = BBOX_GIANT;
if (self.health < 1) self.health = 500;
self.gibhealth = -80; // Hard to gib
self.gibbed = FALSE;
self.pain_flinch = 200; // takes alot to pain
self.pain_longanim = FALSE; // cannot be chopped with shadow axe
if (!self.infightextra) self.infightextra = 2; // 2x infighting dmg
self.meleerange = MONAI_MELEEFREDDIE; // Blade range
if (self.death_dmg < 1) self.death_dmg = DAMAGE_FREDDIE;
self.pain_timeout = 2; // High pain threshold
self.blockudeath = TRUE; // no humanoid death sound
self.attack_offset = '0 0 0'; // Run + Gun vector
self.poisonous = FALSE; // Robots are not poisonous
self.deathstring = " was exterminated by Freddie\n";
// Always reset Ammo Resistance to be consistent
self.resist_shells = self.resist_nails = 0;
self.resist_rockets = self.resist_cells = 0;
// Custom feet sounds (specific order)
self.stepc1 = "freddie/step.wav";
self.stepc2 = "freddie/step2.wav";
self.stepc3 = "freddie/step.wav";
self.stepc4 = "freddie/step2.wav";
self.stepc5 = "freddie/step3.wav";
precache_sound (self.stepc1);
precache_sound (self.stepc2);
precache_sound (self.stepc5);
self.steptype = FS_TYPECUSTOM;
self.th_checkattack = FreddieCheckAttack;
self.th_stand = fred_stand1;
self.th_walk = fred_walk1;
self.th_run = fred_run;
self.th_melee = fred_fswing1; // Blade arm
self.th_missile = fred_sfire1; // Spike/Laser bolts
self.th_charge = fred_sfire24; // End of barrel weapon
self.th_pain = fred_pain;
self.th_die = fred_die;
self.th_gibdie = fred_explode;
self.classtype = CT_MONFREDDIE;
self.classgroup = CG_OGRE;
self.classmove = MON_MOVEWALK;
monster_start();
};
// Re-direct all Quoth Edie requests to Freddie!
void() monster_edie = { monster_freddie(); }