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

451 lines
19 KiB
Plaintext

/*==============================================================================
GAUNT (Originally from Quoth - Kell/Necros/Preach)
- Big thank you to necros for the his code base for this monster
==============================================================================*/
// (000) Perched on a ledge (idling)
$frame perch1 perch2 perch3 perch4 perch5 perch6 perch7 perch8
$frame perch9 perch10 perch11 perch12 perch13 perch14 perch15 perch16
// (016) Lift off from perch position
$frame launch1 launch2 launch3 launch4 launch5 launch6 launch7 launch8
// (024) Idling in mid air
$frame hover1 hover2 hover3 hover4 hover5 hover6 hover7 hover8
$frame hover9 hover10 hover11 hover12 hover13 hover14 hover15 hover16
$frame hover17 hover18 hover19 hover20
// (044) range attack (lightning/plasma)
$frame attack1 attack2 attack3 attack4 attack5 attack6 attack7 attack8
$frame attack9 attack10 attack11 attack12 attack13 attack14 attack15 attack16
$frame attack17 attack18 attack19 attack20
// (064) Start of dive attack
$frame swoopStart1 swoopStart2 swoopStart3 swoopStart4
$frame swoopStart5 swoopStart6 swoopStart7 swoopStart8
// (072) Looped version of dive attack
$frame swoop1 swoop2 swoop3 swoop4 swoop5
// (077) Something, not sure what
$frame drop1 drop2 drop3 drop4 drop5
// (082) Swing wing around infront
$frame painA1 painA2 painA3 painA4 painA5 painA6
// (088) Knock head backward
$frame painB1 painB2 painB3 painB4 painB5
// (093) Fall backwards
$frame deathA1 deathA2 deathA3 deathA4 deathA5 deathA6 deathA7 deathA8
// (101) Fall forward
$frame deathB1 deathB2 deathB3 deathB4 deathB5 deathB6 deathB7 deathB8
void() gauntwings =
{ sound(self, CHAN_ITEM, "gaunt/wings1.wav", 1, ATTN_IDLE); };
void() gaunt_elecfinish;
//============================================================================
void() gaunt_idle1 = [ $hover1, gaunt_idle2 ] {monster_idle_sound();ai_stand();};
void() gaunt_idle2 = [ $hover2, gaunt_idle3 ] {ai_stand();};
void() gaunt_idle3 = [ $hover3, gaunt_idle4 ] {ai_stand();};
void() gaunt_idle4 = [ $hover4, gaunt_idle5 ] {ai_stand();};
void() gaunt_idle5 = [ $hover5, gaunt_idle6 ] {gauntwings();ai_stand();};
void() gaunt_idle6 = [ $hover6, gaunt_idle7 ] {ai_stand();};
void() gaunt_idle7 = [ $hover7, gaunt_idle8 ] {ai_stand();};
void() gaunt_idle8 = [ $hover8, gaunt_idle9 ] {ai_stand();};
void() gaunt_idle9 = [ $hover9, gaunt_idle10 ] {ai_stand();};
void() gaunt_idle10 = [ $hover10, gaunt_idle11 ] {ai_stand();};
void() gaunt_idle11 = [ $hover11, gaunt_idle12 ] {ai_stand();};
void() gaunt_idle12 = [ $hover12, gaunt_idle13 ] {ai_stand();};
void() gaunt_idle13 = [ $hover13, gaunt_idle14 ] {ai_stand();};
void() gaunt_idle14 = [ $hover14, gaunt_idle15 ] {ai_stand();};
void() gaunt_idle15 = [ $hover15, gaunt_idle16 ] {gauntwings();ai_stand();};
void() gaunt_idle16 = [ $hover16, gaunt_idle17 ] {ai_stand();};
void() gaunt_idle17 = [ $hover17, gaunt_idle18 ] {ai_stand();};
void() gaunt_idle18 = [ $hover18, gaunt_idle19 ] {ai_stand();};
void() gaunt_idle19 = [ $hover19, gaunt_idle20 ] {ai_stand();};
void() gaunt_idle20 = [ $hover20, gaunt_idle1 ] {ai_stand();};
//============================================================================
void() gaunt_walk1 = [ $hover1, gaunt_walk2 ] {monster_idle_sound();ai_walk(8);};
void() gaunt_walk2 = [ $hover2, gaunt_walk3 ] {ai_walk(8);};
void() gaunt_walk3 = [ $hover3, gaunt_walk4 ] {gauntwings();ai_walk(8);};
void() gaunt_walk4 = [ $hover4, gaunt_walk5 ] {ai_walk(8);};
void() gaunt_walk5 = [ $hover5, gaunt_walk6 ] {ai_walk(8);};
void() gaunt_walk6 = [ $hover6, gaunt_walk7 ] {ai_walk(8);};
void() gaunt_walk7 = [ $hover7, gaunt_walk8 ] {ai_walk(8);};
void() gaunt_walk8 = [ $hover8, gaunt_walk9 ] {ai_walk(8);};
void() gaunt_walk9 = [ $hover9, gaunt_walk10 ] {ai_walk(8);};
void() gaunt_walk10 = [ $hover10, gaunt_walk11 ] {ai_walk(8);};
void() gaunt_walk11 = [ $hover11, gaunt_walk12 ] {ai_walk(8);};
void() gaunt_walk12 = [ $hover12, gaunt_walk13 ] {ai_walk(8);};
void() gaunt_walk13 = [ $hover13, gaunt_walk14 ] {ai_walk(8);};
void() gaunt_walk14 = [ $hover14, gaunt_walk15 ] {ai_walk(8);};
void() gaunt_walk15 = [ $hover15, gaunt_walk16 ] {gauntwings();ai_walk(8);};
void() gaunt_walk16 = [ $hover16, gaunt_walk17 ] {ai_walk(8);};
void() gaunt_walk17 = [ $hover17, gaunt_walk18 ] {ai_walk(8);};
void() gaunt_walk18 = [ $hover18, gaunt_walk19 ] {ai_walk(8);};
void() gaunt_walk19 = [ $hover19, gaunt_walk20 ] {ai_walk(8);};
void() gaunt_walk20 = [ $hover20, gaunt_walk1 ] {ai_walk(8);};
//============================================================================
void() gaunt_run1 = [ $hover1, gaunt_run2 ] {monster_idle_sound();
if (self.attachment && self.attachment.state == STATE_ON) gaunt_elecfinish();
// Switch direction of strafing (random duration)
if (self.meleeattack < time) {
self.meleeattack = time + 4 + (random() + random() + random() * 4);
self.lefty = rint(1 - self.lefty);
}
ai_run(8);
};
void() gaunt_run2 = [ $hover2, gaunt_run3 ] {ai_run(8);};
void() gaunt_run3 = [ $hover3, gaunt_run4 ] {ai_run(8);};
void() gaunt_run4 = [ $hover4, gaunt_run5 ] {ai_run(8);};
void() gaunt_run5 = [ $hover5, gaunt_run6 ] {gauntwings();ai_run(8);};
void() gaunt_run6 = [ $hover6, gaunt_run7 ] {ai_run(8);};
void() gaunt_run7 = [ $hover7, gaunt_run8 ] {ai_run(8);};
void() gaunt_run8 = [ $hover8, gaunt_run9 ] {ai_run(8);};
void() gaunt_run9 = [ $hover9, gaunt_run10 ] {ai_run(8);};
void() gaunt_run10 = [ $hover10, gaunt_run11 ] {ai_run(8);};
void() gaunt_run11 = [ $hover11, gaunt_run12 ] {ai_run(8);};
void() gaunt_run12 = [ $hover12, gaunt_run13 ] {ai_run(8);};
void() gaunt_run13 = [ $hover13, gaunt_run14 ] {ai_run(8);};
void() gaunt_run14 = [ $hover14, gaunt_run15 ] {ai_run(8);};
void() gaunt_run15 = [ $hover15, gaunt_run16 ] {gauntwings();ai_run(8);};
void() gaunt_run16 = [ $hover16, gaunt_run17 ] {ai_run(8);};
void() gaunt_run17 = [ $hover17, gaunt_run18 ] {ai_run(8);};
void() gaunt_run18 = [ $hover18, gaunt_run19 ] {ai_run(8);};
void() gaunt_run19 = [ $hover19, gaunt_run20 ] {ai_run(8);};
void() gaunt_run20 = [ $hover20, gaunt_run1 ] {ai_run(8);};
//============================================================================
// RANGE - Plasma from arc infront
//============================================================================
void() gaunt_plasma =
{
local vector org, dir;
self.effects = self.effects | EF_MUZZLEFLASH;
sound (self, CHAN_WEAPON, "gaunt/plasma_fire.wav", 1, ATTN_NORM);
makevectors (self.angles);
org = self.origin + attack_vector(self.attack_offset);
dir = normalize(SUB_orgEnemyTarget() - self.origin);
self.attack_speed = SPEED_GAUNTBOLT + (skill * SPEED_GAUNTSKILL);
launch_plasma(org, dir, CT_MONGAUNT, self.attack_speed);
};
//----------------------------------------------------------------------
void() gaunt_elecfinish =
{
setmodel(self.attachment, "");
self.attachment.state = STATE_OFF;
};
//----------------------------------------------------------------------
void(float elecframe) gaunt_elecupdate =
{
if (self.health < 1) return;
if (!self.attachment) {
self.attachment = spawn();
self.attachment.owner = self;
self.attachment.classtype = CT_ATTACHMENT;
self.attachment.mdl = self.weaponglow;
if (self.poisonous) self.attachment.skin = 1;
}
if (elecframe == 0) {
self.attachment.state = STATE_ON;
self.pain_finished = time + 1.2; //don't go into pain whilst firing
setorigin(self.attachment, self.origin);
setmodel(self.attachment, self.attachment.mdl);
setsize (self.attachment, VEC_ORIGIN, VEC_ORIGIN);
self.attachment.movetype = MOVETYPE_NONE;
self.attachment.solid = SOLID_NOT;
sound (self, CHAN_WEAPON, "gaunt/plasma_start.wav", 1, ATTN_NORM);
}
ai_face(); // Turn towards enemy
makevectors(self.angles);
setorigin(self.attachment, self.origin);
self.attachment.angles = self.angles;
self.attachment.frame = elecframe;
};
//----------------------------------------------------------------------
void() gaunt_fire1 = [ $attack1, gaunt_fire2 ] {gaunt_elecupdate(0);};
void() gaunt_fire2 = [ $attack2, gaunt_fire3 ] {gaunt_elecupdate(1);};
void() gaunt_fire3 = [ $attack3, gaunt_fire4 ] {gaunt_elecupdate(2);};
void() gaunt_fire4 = [ $attack4, gaunt_fire5 ] {gaunt_elecupdate(3);};
void() gaunt_fire5 = [ $attack5, gaunt_fire6 ] {gaunt_elecupdate(4);gauntwings();};
void() gaunt_fire6 = [ $attack6, gaunt_fire7 ] {gaunt_elecupdate(5);gaunt_plasma();};
void() gaunt_fire7 = [ $attack7, gaunt_fire8 ] {gaunt_elecupdate(6);};
void() gaunt_fire8 = [ $attack8, gaunt_fire9 ] {gaunt_elecupdate(7);gaunt_plasma();};
void() gaunt_fire9 = [ $attack9, gaunt_fire10 ] {gaunt_elecupdate(8);};
void() gaunt_fire10 = [ $attack10, gaunt_fire11 ] {ai_face();
if (skill > SKILL_NORMAL) gaunt_plasma();
gaunt_elecfinish();};
void() gaunt_fire11 = [ $attack11, gaunt_fire12 ] {};
void() gaunt_fire12 = [ $attack12, gaunt_fire13 ] {};
void() gaunt_fire13 = [ $attack13, gaunt_fire14 ] {};
void() gaunt_fire14 = [ $attack14, gaunt_fire15 ] {};
void() gaunt_fire15 = [ $attack15, gaunt_fire16 ] {gauntwings();};
void() gaunt_fire16 = [ $attack16, gaunt_fire17 ] {};
void() gaunt_fire17 = [ $attack17, gaunt_fire18 ] {};
void() gaunt_fire18 = [ $attack18, gaunt_fire19 ] {ai_face();};
void() gaunt_fire19 = [ $attack19, gaunt_fire20 ] {ai_face();};
void() gaunt_fire20 = [ $attack20, gaunt_run1 ] {};
//============================================================================
// PERCH + WAKEUP
//============================================================================
void() gaunt_perch1 = [ $perch1, gaunt_perch2 ] {monster_idle_sound();ai_stand();};
void() gaunt_perch2 = [ $perch2, gaunt_perch3 ] {ai_stand();};
void() gaunt_perch3 = [ $perch3, gaunt_perch4 ] {ai_stand();};
void() gaunt_perch4 = [ $perch4, gaunt_perch5 ] {ai_stand();};
void() gaunt_perch5 = [ $perch5, gaunt_perch6 ] {ai_stand();};
void() gaunt_perch6 = [ $perch6, gaunt_perch7 ] {ai_stand();};
void() gaunt_perch7 = [ $perch7, gaunt_perch8 ] {ai_stand();};
void() gaunt_perch8 = [ $perch8, gaunt_perch9 ] {ai_stand();};
void() gaunt_perch9 = [ $perch9, gaunt_perch10 ] {ai_stand();};
void() gaunt_perch10 = [ $perch10, gaunt_perch11 ] {ai_stand();};
void() gaunt_perch11 = [ $perch11, gaunt_perch12 ] {ai_stand();};
void() gaunt_perch12 = [ $perch12, gaunt_perch13 ] {ai_stand();};
void() gaunt_perch13 = [ $perch13, gaunt_perch14 ] {ai_stand();};
void() gaunt_perch14 = [ $perch14, gaunt_perch15 ] {ai_stand();};
void() gaunt_perch15 = [ $perch15, gaunt_perch16 ] {ai_stand();};
void() gaunt_perch16 = [ $perch16, gaunt_perch1 ] {ai_stand();};
//----------------------------------------------------------------------
// Sightsound and very quick animation while moving forward
void() gaunt_wakeup1 = [ $launch1, gaunt_wakeup2 ] {monster_sightsound();};
void() gaunt_wakeup2 = [ $launch2, gaunt_wakeup3 ] {ai_forward(4);};
void() gaunt_wakeup3 = [ $launch3, gaunt_wakeup4 ] {ai_forward(4);};
void() gaunt_wakeup4 = [ $launch4, gaunt_wakeup5 ] {ai_forward(4);};
void() gaunt_wakeup5 = [ $launch5, gaunt_wakeup6 ] {ai_forward(4);};
void() gaunt_wakeup6 = [ $launch6, gaunt_wakeup7 ] {gauntwings();ai_forward(4);};
void() gaunt_wakeup7 = [ $launch7, gaunt_wakeup8 ] {ai_forward(4);};
void() gaunt_wakeup8 = [ $launch8, gaunt_run1 ] {
FoundHuntTarget(TRUE); // Setup goals and warn other monsters
};
//----------------------------------------------------------------------
void() gaunt_wakeup =
{
// Dead already?
if (self.health < 1) return;
// No longer need perch spawnflag, remove it
self.spawnflags = self.spawnflags - (self.spawnflags & MON_GAUNT_PERCH);
self.spawnstatue = FALSE; // No longer stationary
self.takedamage = DAMAGE_AIM; // Can receive damage
self.use = SUB_Null; // no re-trigger
// Restore all think state functions
self.th_stand = gaunt_idle1;
self.th_walk = gaunt_walk1;
self.th_run = gaunt_run1;
self.th_missile = gaunt_fire1;
// Allow gaunt to fly up, no more ground checks
self.flags = self.flags | FL_FLY;
self.movetype = MOVETYPE_STEP;
self.pain_finished = time + 1.5; // No pain
self.attack_finished = 1.5 + random(); // No skill adjustment
gaunt_wakeup1();
};
//============================================================================
// PAIN
//============================================================================
// Long - Swing wing around infront
void() gaunt_painA1 =[ $painA1, gaunt_painA2 ] {};
void() gaunt_painA2 =[ $painA2, gaunt_painA3 ] {};
void() gaunt_painA3 =[ $painA3, gaunt_painA4 ] {};
void() gaunt_painA4 =[ $painA4, gaunt_painA5 ] {};
void() gaunt_painA5 =[ $painA5, gaunt_painA6 ] {};
void() gaunt_painA6 =[ $painA6, gaunt_run1 ] {};
// Short - Knock head backward
void() gaunt_painB1 =[ $painB1, gaunt_painB2 ] {};
void() gaunt_painB2 =[ $painB2, gaunt_painB3 ] {};
void() gaunt_painB3 =[ $painB3, gaunt_painB4 ] {};
void() gaunt_painB4 =[ $painB4, gaunt_painB5 ] {};
void() gaunt_painB5 =[ $painB5, gaunt_run1 ] {};
//----------------------------------------------------------------------
void(entity inflictor, entity attacker, float damage) gaunt_pain =
{
// Check for perching gaunt, need special wakeup
if (self.spawnflags & MON_GARGOYLE_PERCH) gaunt_wakeup();
else {
// Check all pain conditions and set up what to do next
monster_pain_check(attacker, damage);
// make sure any electricity is hidden
if (self.attachment) gaunt_elecfinish();
// Any pain animation/sound required?
if (self.pain_check > 0) {
sound (self, CHAN_VOICE, self.pain_sound, 1, ATTN_NORM);
if (self.pain_check == 1 || self.pain_check == 2) {
if (self.lip < 0.4) gaunt_painB1(); // Long
else gaunt_painA1(); // Short
}
}
}
};
//============================================================================
void() gaunt_deathA1 = [ $deathA1, gaunt_deathA2 ] {};
void() gaunt_deathA2 = [ $deathA2, gaunt_deathA3 ] {monster_check_gib();};
void() gaunt_deathA3 = [ $deathA3, gaunt_deathA4 ] {monster_check_gib();
self.solid = SOLID_NOT;};
void() gaunt_deathA4 = [ $deathA4, gaunt_deathA5 ] {};
void() gaunt_deathA5 = [ $deathA5, gaunt_deathA6 ] {};
void() gaunt_deathA6 = [ $deathA6, gaunt_deathA7 ] {};
void() gaunt_deathA7 = [ $deathA7, gaunt_deathA8 ] {monster_death_postcheck();};
void() gaunt_deathA8 = [ $deathA8, gaunt_deathA8 ] {monster_deadbody_check();};
//----------------------------------------------------------------------
void() gaunt_deathB1 = [ $deathB1, gaunt_deathB2 ] {};
void() gaunt_deathB2 = [ $deathB2, gaunt_deathB3 ] {monster_check_gib();};
void() gaunt_deathB3 = [ $deathB3, gaunt_deathB4 ] {monster_check_gib();
self.solid = SOLID_NOT;};
void() gaunt_deathB4 = [ $deathB4, gaunt_deathB5 ] {};
void() gaunt_deathB5 = [ $deathB5, gaunt_deathB6 ] {};
void() gaunt_deathB6 = [ $deathB6, gaunt_deathB7 ] {};
void() gaunt_deathB7 = [ $deathB7, gaunt_deathB8 ] {monster_death_postcheck();};
void() gaunt_deathB8 = [ $deathB8, gaunt_deathB8 ] {monster_deadbody_check();};
//----------------------------------------------------------------------
void() gaunt_die =
{
// Check for perching gaunt, need to blow up in gibs
// In an awkward pose that does not go well into death animations
if (self.spawnflags & MON_GAUNT_PERCH) self.gibondeath = TRUE;
// Make sure any wings sound is silenced
sound (self, CHAN_ITEM, SOUND_EMPTY, 1, ATTN_NORM);
// If casting electricity, make it explode!
if (self.attachment) {
if (self.attachment.state == STATE_ON) {
self.gibondeath = TRUE;
SpawnProjectileSmoke(self.origin, 200, 50, 150);
SpawnProjectileSmoke(self.origin, 200, 50, 150);
if (self.poisonous) self.lip = PARTICLE_BURST_GREEN;
else self.lip = PARTICLE_BURST_BLUE;
particle_explode(self.origin-'0 0 16', 50+random()*50, 2, self.lip, PARTICLE_BURST_UPWARD);
makevectors(self.angles);
self.oldorigin = self.origin + v_forward*8;
if (self.poisonous) self.lip = EXPLODE_POISON_BIG;
else self.lip = EXPLODE_PLASMA_BIG;
SpawnExplosion(self.lip, self.oldorigin, SOUND_REXP3);
}
// make sure any electricity is hidden
gaunt_elecfinish();
}
// Pre-check routine to tidy up extra entities
monster_death_precheck();
// regular death
if (!self.gibbed) {
sound (self, CHAN_VOICE, "gaunt/death.wav", 1, ATTN_NORM);
self.flags = FL_MONSTER; // reset all flag conditions
self.movetype = MOVETYPE_TOSS; // Affected by gravity
self.velocity_x = -200 + 400*random();
self.velocity_y = -200 + 400*random();
self.velocity_z = 100 + 100*random();
if (random() < 0.5) gaunt_deathA1();
else gaunt_deathB1();
}
};
/*======================================================================
QUAKED monster_gaunt (1 0.2 0) (-16 -16 -24) (16 16 24)
======================================================================*/
void() monster_gaunt =
{
if (deathmatch) { remove(self); return; }
self.mdl = "progs/mon_gaunt.mdl";
self.headmdl = "progs/h_gaunt.mdl";
self.weaponglow = "progs/mon_gaunt_elec.mdl";
precache_model (self.mdl);
precache_model (self.headmdl);
precache_model (self.weaponglow); // Lightning effect (2 colour)
precache_model (MODEL_PROJ_GAPLASMA); // Plasma spike/bolt
self.idle_sound = "gaunt/idle1.wav";
self.idle_sound2 = "gaunt/idle3.wav";
self.idle_soundcom = "gaunt/idle2.wav";
precache_sound (self.idle_sound);
precache_sound (self.idle_sound2);
precache_sound (self.idle_soundcom);
precache_sound ("gaunt/wings1.wav");
precache_sound ("gaunt/plasma_start.wav");
precache_sound ("gaunt/plasma_fire.wav");
self.pain_sound = "gaunt/pain.wav";
precache_sound (self.pain_sound);
precache_sound ("gaunt/death.wav");
self.sight_sound = "gaunt/sight.wav";
precache_sound (self.sight_sound);
// Check for poisonous entity flag
if (self.poisonous) {
precache_poisongibs(); // precache gibs
self.gibtype = GIBTYPE_POISON; // Poisonous blood trails
precache_model (MODEL_PROJ_GAPLASMAGRN);
}
self.solid = SOLID_NOT; // No interaction with world
self.movetype = MOVETYPE_NONE; // Static item, no movement
if (self.bboxtype < 1) self.bboxtype = BBOX_TALL;
if (self.health < 1) self.health = 120;
self.gibhealth = -70; // Need a powerful weapon to GIB
self.gibbed = FALSE; // no falling apart
self.pain_flinch = 70; // High pain threshold
self.blockudeath = TRUE; // no humanoid death sound
self.height = MONAI_ABOVEDIST; // Enemytarget distance above
self.attack_offset = '8 0 -4'; // Plasma start location
self.deathstring = " was blasted by a Gaunt\n";
self.th_checkattack = GauntCheckAttack;
self.th_pain = gaunt_pain;
self.th_die = gaunt_die;
//----------------------------------------------------------------------
// Perched Gaunt have special idle animation + idle sounds
if (self.spawnflags & MON_GAUNT_PERCH) {
self.th_stand = self.th_walk = gaunt_perch1;
self.th_run = self.th_missile = gaunt_wakeup;
}
//----------------------------------------------------------------------
// Default gaunt setup
else {
self.th_stand = gaunt_idle1;
self.th_walk = gaunt_walk1;
self.th_run = gaunt_run1;
self.th_missile = gaunt_fire1;
}
self.classtype = CT_MONGAUNT;
self.classgroup = CG_WIZARD;
self.classmove = MON_MOVEFLY;
// Always reset Ammo Resistance to be consistent
self.resist_shells = self.resist_nails = 0;
self.resist_rockets = self.resist_cells = 0;
monster_start();
};