Files
quakemapping/mod_xj18/my_progs/mon_dfury.qc
2020-01-07 11:54:38 +01:00

830 lines
38 KiB
Plaintext

/*==============================================================================
FURY KNIGHT (one more night)
==============================================================================*/
$cd id1/models/dfury
$origin 0 0 24
$base base
$skin skin
// (001 - 012) Default Stand - LEFT Sword forward
$frame standL1 standL2 standL3 standL4 standL5 standL6 standL7 standL8
$frame standL9 standL10 standL11 standL12
// (013 - 019) Switch dual swords LEFT -> RIGHT
$frame standLR1 standLR2 standLR3 standLR4 standLR5 standLR6 standLR7
// (020 - 031) Default Stand - RIGHT Sword forward
$frame standR1 standR2 standR3 standR4 standR5 standR6 standR7 standR8
$frame standR9 standR10 standR11 standR12
// (032 - 038) Switch dual swords RIGHT -> LEFT
$frame standRL1 standRL2 standRL3 standRL4 standRL5 standRL6 standRL7
// (039 - 050) Stand idle - Quick look around (MUST following left sword idle)
$frame standB1 standB2 standB3 standB4 standB5 standB6 standB7 standB8
$frame standB9 standB10 standB11 standB12
// (051 - 070) Stand idle - checking sword (MUST following left sword idle)
$frame standC1 standC2 standC3 standC4 standC5 standC6 standC7 standC8
$frame standC9 standC10 standC11 standC12 standC13 standC14 standC15 standC16
$frame standC17 standC18 standC19 standC20
// (071 - 084) Default walk - typical hell knight stride
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9
$frame walk10 walk11 walk12 walk13 walk14
// (085 - 090) Default run
$frame run1 run2 run3 run4 run5 run6
// Pain animations A = Slow D = Stagger
// (091 - 095) (096 - 111)
$frame painA1 painA2 painA3 painA4 painA5
$frame painD1 painD2 painD3 painD4 painD5 painD6 painD7 painD8
$frame painD9 painD10 painD11 painD12 painD13 painD14 painD15 painD16
// (112 - 125) Forward dual sword Slice
$frame slice1 slice2 slice3 slice4 slice5 slice6 slice7 slice8
$frame slice9 slice10 slice11 slice12 slice13 slice14
// (126 - 140) Forward dual sword Lunge
$frame lunge1 lunge2 lunge3 lunge4 lunge5 lunge6 lunge7 lunge8
$frame lunge9 lunge10 lunge11 lunge12 lunge13 lunge14 lunge15
// (141 - 164) Charging attack A - swinging swords left to right infront
$frame w_attack1 w_attack2 w_attack3 w_attack4 w_attack5 w_attack6 w_attack7 w_attack8
$frame w_attack9 w_attack10 w_attack11 w_attack12 w_attack13 w_attack14 w_attack15 w_attack16
$frame w_attack17 w_attack18 w_attack19 w_attack20 w_attack21 w_attack22 w_attack23 w_attack24
// (165 - 172) Right Swing
$frame rswing1 rswing2 rswing3 rswing4 rswing5 rswing6 rswing7 rswing8
// (173 - 180) Left Swing
$frame lswing1 lswing2 lswing3 lswing4 lswing5 lswing6 lswing7 lswing8
// (181 - 195) Smash (chop overhead to ground)
$frame smash1 smash2 smash3 smash4 smash5 smash6 smash7 smash8
$frame smash9 smash10 smash11 smash12 smash13 smash14 smash15
// (196 - 211) MagicA - Swords lock together infront (missile attack)
$frame magica1 magica2 magica3 magica4 magica5 magica6 magica7 magica8
$frame magica9 magica10 magica11 magica12 magica13 magica14 magica15 magica16
// (212 - 224) MagicB - Swords Swipe downwards infront (enable bullet shield)
$frame magicb1 magicb2 magicb3 magicb4 magicb5 magicb6 magicb7 magicb8
$frame magicb9 magicb10 magicb11 magicb12 magicb13
// (225 - 241) Death forward
$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14 death15 death16 death17
// (242 - 255) Death back
$frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
$frame deathb9 deathb10 deathb11 deathb12 deathb13 deathb14
void() dfury_standL1;
void() dfury_magic;
void() dfury_sword_sound; // Sword swipe sounds
void(float soundtype) dfury_grunt_sound; // Grunting while attacking
// Different types of grunting sounds
float DFURY_SOUND_PULLAPART = 1;
float DFURY_SOUND_OVERSMASH = 2;
float DFURY_SOUND_JUMP = 3;
float DFURY_SOUND_LRFURY = 4;
float DFURY_SOUND_RUNSWING = 5;
float DFURY_SOUND_OPTIONAL = 6;
//----------------------------------------------------------------------
void() dfury_standB1 =[ $standB1, dfury_standB2 ] {ai_stand();};
void() dfury_standB2 =[ $standB2, dfury_standB3 ] {ai_stand();};
void() dfury_standB3 =[ $standB3, dfury_standB4 ] {ai_stand();};
void() dfury_standB4 =[ $standB4, dfury_standB5 ] {ai_stand();};
void() dfury_standB5 =[ $standB5, dfury_standB6 ] {ai_stand();};
void() dfury_standB6 =[ $standB6, dfury_standB7 ] {ai_stand();};
void() dfury_standB7 =[ $standB7, dfury_standB8 ] {ai_stand();};
void() dfury_standB8 =[ $standB8, dfury_standB9 ] {ai_stand();self.nextthink = self.nextthink + random()*0.2;};
void() dfury_standB9 =[ $standB9, dfury_standB10 ] {ai_stand();self.nextthink = self.nextthink + random()*0.2;};
void() dfury_standB10 =[ $standB10, dfury_standB11 ] {ai_stand();self.nextthink = self.nextthink + random()*0.2;};
void() dfury_standB11 =[ $standB11, dfury_standB12 ] {ai_stand();};
void() dfury_standB12 =[ $standB12, dfury_standL1 ] {ai_stand();};
//----------------------------------------------------------------------
void() dfury_standC1 =[ $standC1, dfury_standC2 ] {ai_stand();};
void() dfury_standC2 =[ $standC2, dfury_standC3 ] {ai_stand();};
void() dfury_standC3 =[ $standC3, dfury_standC4 ] {ai_stand();};
void() dfury_standC4 =[ $standC4, dfury_standC5 ] {ai_stand();};
void() dfury_standC5 =[ $standC5, dfury_standC6 ] {ai_stand();};
void() dfury_standC6 =[ $standC6, dfury_standC7 ] {ai_stand();};
void() dfury_standC7 =[ $standC7, dfury_standC8 ] {ai_stand();};
void() dfury_standC8 =[ $standC8, dfury_standC9 ] {ai_stand();};
void() dfury_standC9 =[ $standC9, dfury_standC10 ] {ai_stand();};
void() dfury_standC10 =[ $standC10, dfury_standC11 ] {ai_stand();};
void() dfury_standC11 =[ $standC11, dfury_standC12 ] {ai_stand();};
void() dfury_standC12 =[ $standC12, dfury_standC13 ] {ai_stand();};
void() dfury_standC13 =[ $standC13, dfury_standC14 ] {ai_stand();};
void() dfury_standC14 =[ $standC14, dfury_standC15 ] {ai_stand();};
void() dfury_standC15 =[ $standC15, dfury_standC16 ] {ai_stand();};
void() dfury_standC16 =[ $standC16, dfury_standC17 ] {ai_stand();};
void() dfury_standC17 =[ $standC17, dfury_standC18 ] {ai_stand();};
void() dfury_standC18 =[ $standC18, dfury_standC19 ] {ai_stand();};
void() dfury_standC19 =[ $standC19, dfury_standC20 ] {ai_stand();};
void() dfury_standC20 =[ $standC20, dfury_standL1 ] {ai_stand();};
//----------------------------------------------------------------------
void() dfury_standRL1 =[ $standRL1, dfury_standRL2 ] {ai_stand();};
void() dfury_standRL2 =[ $standRL2, dfury_standRL3 ] {ai_stand();};
void() dfury_standRL3 =[ $standRL3, dfury_standRL4 ] {ai_stand();};
void() dfury_standRL4 =[ $standRL4, dfury_standRL5 ] {ai_stand();};
void() dfury_standRL5 =[ $standRL5, dfury_standRL6 ] {ai_stand();};
void() dfury_standRL6 =[ $standRL6, dfury_standRL7 ] {ai_stand();};
void() dfury_standRL7 =[ $standRL7, dfury_standL1 ] {ai_stand();};
//----------------------------------------------------------------------
void() dfury_standR1 =[ $standR1, dfury_standR2 ] {monster_idle_sound();
if (random() < MON_IDLE_ANIMATION && self.weaponswitch < time)
self.think = dfury_standRL1; // Switch weapon stance
ai_stand();
};
void() dfury_standR2 =[ $standR2, dfury_standR3 ] {ai_stand();};
void() dfury_standR3 =[ $standR3, dfury_standR4 ] {ai_stand();};
void() dfury_standR4 =[ $standR4, dfury_standR5 ] {ai_stand();};
void() dfury_standR5 =[ $standR5, dfury_standR6 ] {ai_stand();};
void() dfury_standR6 =[ $standR6, dfury_standR7 ] {monster_idle_sound(); ai_stand();};
void() dfury_standR7 =[ $standR7, dfury_standR8 ] {ai_stand();};
void() dfury_standR8 =[ $standR8, dfury_standR9 ] {ai_stand();};
void() dfury_standR9 =[ $standR9, dfury_standR10 ] {ai_stand();};
void() dfury_standR10=[ $standR10, dfury_standR11 ] {ai_stand();};
void() dfury_standR11=[ $standR11, dfury_standR12 ] {ai_stand();};
void() dfury_standR12=[ $standR12, dfury_standR1 ] {ai_stand();};
//----------------------------------------------------------------------
void() dfury_standLR1 =[ $standLR1, dfury_standLR2 ] {ai_stand();};
void() dfury_standLR2 =[ $standLR2, dfury_standLR3 ] {ai_stand();};
void() dfury_standLR3 =[ $standLR3, dfury_standLR4 ] {ai_stand();};
void() dfury_standLR4 =[ $standLR4, dfury_standLR5 ] {ai_stand();};
void() dfury_standLR5 =[ $standLR5, dfury_standLR6 ] {ai_stand();};
void() dfury_standLR6 =[ $standLR6, dfury_standLR7 ] {ai_stand();};
void() dfury_standLR7 =[ $standLR7, dfury_standR1 ] {ai_stand();};
//----------------------------------------------------------------------
void() dfury_standL1 =[ $standL1, dfury_standL2 ] {monster_idle_sound();
self.idlebusy = FALSE;
if (random() < MON_IDLE_ANIMATION && self.weaponswitch < time) {
// Slow down the repeating of idle animations
self.weaponswitch = time + 1 + random()*3;
self.idlebusy = TRUE;
// Make sure the idle animations don't repeat in a row
self.lefty = self.lip;
while (self.lefty == self.lip) { self.lefty = rint(random()*4);}
self.lip = self.lefty;
if (self.lip < 2) self.think = dfury_standC1; // Look at weapon
else if (self.lip == 2) self.think = dfury_standB1; // Look around
else self.think = dfury_standLR1; // Switch weapon stance
}
ai_stand();
};
void() dfury_standL2 =[ $standL2, dfury_standL3 ] {ai_stand();};
void() dfury_standL3 =[ $standL3, dfury_standL4 ] {ai_stand();};
void() dfury_standL4 =[ $standL4, dfury_standL5 ] {ai_stand();};
void() dfury_standL5 =[ $standL5, dfury_standL6 ] {ai_stand();};
void() dfury_standL6 =[ $standL6, dfury_standL7 ] {ai_stand();};
void() dfury_standL7 =[ $standL7, dfury_standL8 ] {ai_stand();};
void() dfury_standL8 =[ $standL8, dfury_standL9 ] {ai_stand();};
void() dfury_standL9 =[ $standL9, dfury_standL10 ] {ai_stand();};
void() dfury_standL10=[ $standL10, dfury_standL11 ] {ai_stand();};
void() dfury_standL11=[ $standL11, dfury_standL12 ] {ai_stand();};
void() dfury_standL12=[ $standL12, dfury_standL1 ] {ai_stand();};
//===========================================================================
void() dfury_walk1 =[ $walk1, dfury_walk2 ] { monster_idle_sound();
self.idlebusy = FALSE; ai_walk(2);};
void() dfury_walk2 =[ $walk2, dfury_walk3 ] {monster_footstep(FALSE);ai_walk(5);};
void() dfury_walk3 =[ $walk3, dfury_walk4 ] {ai_walk(5);};
void() dfury_walk4 =[ $walk4, dfury_walk5 ] {ai_walk(4);};
void() dfury_walk5 =[ $walk5, dfury_walk6 ] {ai_walk(4);};
void() dfury_walk6 =[ $walk6, dfury_walk7 ] {ai_walk(2);};
void() dfury_walk7 =[ $walk7, dfury_walk8 ] {ai_walk(2);};
void() dfury_walk8 =[ $walk8, dfury_walk9 ] {monster_footstep(FALSE); ai_walk(3);};
void() dfury_walk9 =[ $walk9, dfury_walk10] {ai_walk(3);};
void() dfury_walk10=[ $walk10, dfury_walk11] {ai_walk(4);};
void() dfury_walk11=[ $walk11, dfury_walk12] {ai_walk(3);};
void() dfury_walk12=[ $walk12, dfury_walk13] {ai_walk(4);};
void() dfury_walk13=[ $walk13, dfury_walk14] {ai_walk(6);};
void() dfury_walk14=[ $walk14, dfury_walk1 ] {ai_walk(2);};
//===========================================================================
// 6 frames instead of 8 frames (skipping 3rd/7th timing of original)
void() dfury_run1 =[ $run1, dfury_run2 ] {monster_idle_sound();
self.idlebusy = FALSE;ai_run (22); };
void() dfury_run2 =[ $run2, dfury_run3 ] {monster_footstep(FALSE); ai_run(27);};
void() dfury_run3 =[ $run3, dfury_run4 ] {ai_run(18);};
void() dfury_run4 =[ $run4, dfury_run5 ] {ai_run(16);};
void() dfury_run5 =[ $run5, dfury_run6 ] {monster_footstep(FALSE); ai_run(27);};
void() dfury_run6 =[ $run6, dfury_run1 ] {ai_run(15);};
//===========================================================================
// Melee Attack 1 - Slice (bring swords together and pull apart)
void() dfury_slice1 =[ $slice2, dfury_slice2 ] {dfury_grunt_sound(DFURY_SOUND_PULLAPART);ai_charge(9);};
void() dfury_slice2 =[ $slice3, dfury_slice3 ] {ai_charge(10); dfury_sword_sound();};
void() dfury_slice3 =[ $slice4, dfury_slice4 ] {ai_charge(17);};
void() dfury_slice4 =[ $slice5, dfury_slice5 ] {monster_footstep(FALSE); ai_charge(4);};
void() dfury_slice5 =[ $slice6, dfury_slice6 ] {ai_charge(11); dfury_sword_sound(); ai_melee();};
void() dfury_slice6 =[ $slice7, dfury_slice7 ] {ai_charge(19); ai_melee();};
void() dfury_slice7 =[ $slice8, dfury_slice8 ] {ai_charge(12); ai_melee();};
void() dfury_slice8 =[ $slice9, dfury_slice9 ] {ai_charge(6); ai_melee();};
void() dfury_slice9 =[ $slice11, dfury_slice10 ] {monster_footstep(FALSE); ai_melee();};
void() dfury_slice10 =[ $slice13, dfury_slice11 ] {ai_charge(0);};
void() dfury_slice11 =[ $slice14, dfury_run1 ] {monster_footstep(FALSE); ai_charge(7);};
//----------------------------------------------------------------------
// Melee Attack 2 - Smash (both swords chop overhead to ground)
void() dfury_smash1 =[ $smash2, dfury_smash2 ] {ai_charge(1);};
void() dfury_smash2 =[ $smash3, dfury_smash3 ] {ai_charge(13);};
void() dfury_smash3 =[ $smash4, dfury_smash4 ] {ai_charge(9); monster_footstep(FALSE);};
void() dfury_smash4 =[ $smash5, dfury_smash5 ] {ai_charge(11);};
void() dfury_smash5 =[ $smash6, dfury_smash6 ] {dfury_grunt_sound(DFURY_SOUND_OVERSMASH);ai_charge(10);};
void() dfury_smash6 =[ $smash7, dfury_smash7 ] {ai_charge(7); dfury_sword_sound();};
void() dfury_smash7 =[ $smash8, dfury_smash8 ] {ai_charge(12); monster_footstep(FALSE);};
void() dfury_smash8 =[ $smash9, dfury_smash9 ] {ai_charge(2);self.meleecontact = TRUE; ai_meleesmash(40);};
void() dfury_smash9 =[ $smash10, dfury_smash10 ] {ai_charge(3); ai_melee();self.meleecontact = FALSE;};
void() dfury_smash10 =[ $smash12, dfury_smash11 ] {ai_charge(0);};
void() dfury_smash11 =[ $smash13, dfury_run1 ] {ai_charge(0);};
//----------------------------------------------------------------------
// Melee Attack 4a - Single Right Swing (fast attack)
void() dfury_lswing3;
void() dfury_rswing1 =[ $rswing2, dfury_rswing3 ] {ai_charge(2);};
void() dfury_rswing3 =[ $rswing3, dfury_rswing4 ] {dfury_grunt_sound(DFURY_SOUND_LRFURY);ai_charge(5);};
void() dfury_rswing4 =[ $rswing4, dfury_rswing5 ] {ai_charge(8);ai_melee();monster_footstep(FALSE);};
void() dfury_rswing5 =[ $rswing5, dfury_rswing6 ] {ai_charge(7);ai_melee();};
void() dfury_rswing6 =[ $rswing6, dfury_rswing7 ] {ai_charge(5);ai_melee(); dfury_sword_sound();};
void() dfury_rswing7 =[ $rswing7, dfury_rswing8 ] {ai_charge(2);monster_footstep(FALSE);};
void() dfury_rswing8 =[ $rswing8, dfury_run1 ] {ai_charge(1);
if (ai_checkmelee(MONAI_MELEEFRONT) && self.enemy.health > 0) self.think = dfury_lswing3;
};
//----------------------------------------------------------------------
// Melee Attack 4a - Single Right Swing (fast attack)
void() dfury_lswing1 =[ $lswing2, dfury_lswing3 ] {ai_charge(2);};
void() dfury_lswing3 =[ $lswing3, dfury_lswing4 ] {dfury_grunt_sound(DFURY_SOUND_OPTIONAL);ai_charge(5);};
void() dfury_lswing4 =[ $lswing4, dfury_lswing5 ] {ai_charge(8);ai_melee();monster_footstep(FALSE);};
void() dfury_lswing5 =[ $lswing5, dfury_lswing6 ] {ai_charge(7);ai_melee();};
void() dfury_lswing6 =[ $lswing6, dfury_lswing7 ] {ai_charge(5);ai_melee(); dfury_sword_sound();};
void() dfury_lswing7 =[ $lswing7, dfury_lswing8 ] {ai_charge(2);monster_footstep(FALSE);};
void() dfury_lswing8 =[ $lswing8, dfury_run1 ] {ai_charge(1);
if (ai_checkmelee(MONAI_MELEEFRONT) && self.enemy.health > 0) self.think = dfury_rswing3;
};
//----------------------------------------------------------------------
// Melee Attack 3 - Lunge forward (leaving ground) and do heavy damage
void() dfury_JumpTouch =
{
local float ldmg;
if (self.health < 1) return;
ai_jumpbreakable(30); // Damage any breakables
self.touch = SUB_Null; // No more touching
self.think = self.th_jumpexit; // Exit frame
self.jumptouch = other; // Keep track of touch target
if ( CanDamage(other, self) ) {
if ( vlen(self.velocity) > 300 ) {
ldmg = 20 + 10*random();
T_Damage (other, self, self, ldmg, DAMARMOR);
spawn_touchblood (self, self.enemy, ldmg*3);
}
}
// Is the fury knight floating in the air?
if (!checkbottom(self)) {
// Is the fury knight standing on something?
if (self.flags & FL_ONGROUND) {
// Do an extra jump if got the count
if (self.count < 2) self.think = self.th_jump;
}
}
// Next timer
self.nextthink = time + 0.1;
};
//----------------------------------------------------------------------
void() dfury_lunge1 =[ $lunge1, dfury_lunge2 ] {ai_face();
self.jump_flag = time + MONAI_JUMPFURYTIME;
dfury_grunt_sound(DFURY_SOUND_JUMP);
};
void() dfury_lunge2 =[ $lunge2, dfury_lunge3 ] {ai_face();};
void() dfury_lunge3 =[ $lunge3, dfury_lunge4 ] {ai_face();};
void() dfury_lunge4 =[ $lunge4, dfury_lunge5 ] {
ai_face();
self.jump_flag = time + MONAI_JUMPFURYTIME;
self.touch = dfury_JumpTouch;
makevectors (self.angles);
self.velocity = v_forward * 500 + '0 0 250';
self.flags = self.flags - (self.flags & FL_ONGROUND);
self.oldorigin = self.origin;
};
void() dfury_lunge5 =[ $lunge5, dfury_lunge6 ] {};
void() dfury_lunge6 =[ $lunge6, dfury_lunge7 ] {};
void() dfury_lunge7 =[ $lunge7, dfury_lunge8 ] {};
void() dfury_lunge8 =[ $lunge8, dfury_lunge8 ] {
// Double check monster is still falling?
if (CheckZeroVector(self.velocity) || self.oldorigin == self.origin) {
self.ideal_yaw = random() * 360; //random jump angle
self.think = dfury_lunge4; // Keep jumping
}
self.oldorigin = self.origin;
};
//----------------------------------------------------------------------
// Landed with thrush attack
void() dfury_lunge9 =[ $lunge9, dfury_lunge10 ] {ai_melee();};
void() dfury_lunge10 =[ $lunge10, dfury_lunge11 ] {ai_charge(5);ai_melee();};
void() dfury_lunge11 =[ $lunge11, dfury_lunge12 ] {ai_charge(4);ai_melee();dfury_sword_sound();};
void() dfury_lunge12 =[ $lunge12, dfury_lunge13 ] {ai_charge(1);ai_melee();};
void() dfury_lunge13 =[ $lunge13, dfury_lunge14 ] {ai_charge(1);ai_melee();monster_footstep(FALSE);};
void() dfury_lunge14 =[ $lunge14, dfury_lunge15 ] {ai_charge(1);};
void() dfury_lunge15 =[ $lunge15, dfury_run1 ] {ai_resetangles();
// If close enough starting swinging left+right ELSE return to run cycle
if (ai_checkmelee(MONAI_MELEEFRONT) && self.enemy.health > 0) self.think = dfury_rswing3;
};
//----------------------------------------------------------------------
// Melee Attack 5 - W_Attack (two handed slashing attack)
// Identical frame set (Hell Knight / Death Knight)
// Speed boost (+16 charge) to all frames, fast charging attack!
void() dfury_watk1 =[ $w_attack2, dfury_watk3 ] {ai_charge(18);monster_footstep(FALSE);};
void() dfury_watk3 =[ $w_attack3, dfury_watk4 ] {ai_charge(18);};
void() dfury_watk4 =[ $w_attack4, dfury_watk5 ] {ai_charge(18);};
void() dfury_watk5 =[ $w_attack5, dfury_watk6 ] {ai_charge(18);dfury_grunt_sound(DFURY_SOUND_RUNSWING);};
void() dfury_watk6 =[ $w_attack6, dfury_watk7 ] {ai_charge(18);};
void() dfury_watk7 =[ $w_attack7, dfury_watk8 ] {ai_charge(19);monster_footstep(FALSE);};
void() dfury_watk8 =[ $w_attack8, dfury_watk9 ] {ai_charge(22);dfury_sword_sound();ai_melee();};
void() dfury_watk9 =[ $w_attack9, dfury_watk10] {ai_charge(23);ai_melee(); };
void() dfury_watk10=[ $w_attack10,dfury_watk11] {ai_charge(21); ai_melee();};
void() dfury_watk11=[ $w_attack11,dfury_watk12] {ai_charge(19);};
void() dfury_watk12=[ $w_attack12,dfury_watk13] {ai_charge(19);};
void() dfury_watk13=[ $w_attack13,dfury_watk14] {ai_charge(18);};
void() dfury_watk14=[ $w_attack14,dfury_watk15] {ai_charge(18);dfury_grunt_sound(DFURY_SOUND_OPTIONAL);};
void() dfury_watk15=[ $w_attack15,dfury_watk16] {ai_charge(18);};
void() dfury_watk16=[ $w_attack16,dfury_watk17] {ai_charge(19);dfury_sword_sound();ai_melee();};
void() dfury_watk17=[ $w_attack17,dfury_watk18] {ai_charge(19); monster_footstep(FALSE); ai_melee();};
void() dfury_watk18=[ $w_attack18,dfury_watk19] {ai_charge(21); ai_melee();};
void() dfury_watk19=[ $w_attack19,dfury_watk20] {ai_charge(22);};
void() dfury_watk20=[ $w_attack20,dfury_watk21] {ai_charge(24);};
void() dfury_watk21=[ $w_attack21,dfury_watk22] {ai_charge(25);};
void() dfury_watk22=[ $w_attack22,dfury_run1 ] {ai_charge(21);
// this is a long animations set for chasing the player
// Quick check if within melee range, close melee range or random magic attack!
if (self.enemy.health > 0) {
if (ai_checkmelee(MONAI_MELEEFRONT)) self.think = dfury_rswing3;
else if (ai_checkmelee(MONAI_JUMPFURYNEAR)) self.think = dfury_slice1;
else if (random() < 0.3) self.think = dfury_magic;
}
};
//----------------------------------------------------------------------
void() dfury_melee =
{
// Use heavy overhead smash for monsters
if (self.enemy.flags & FL_MONSTER) dfury_smash1();
else {
// Make sure next attack is different to previous (randomly while loop)
self.lip = self.meleeattack;
while (self.lip == self.meleeattack) { self.lip = rint(random()*2); }
self.meleeattack = self.lip;
if (self.meleeattack == 0) dfury_lswing1(); // Quick left
else if (self.meleeattack == 1) dfury_rswing1(); // Quick right
else dfury_smash1(); // Overhead smash
}
};
//===========================================================================
// Magic attacks (glowing swords)
//===========================================================================
// Magic Attack A - Spray of spikes from raised up swords
//----------------------------------------------------------------------
void(float offset) dfury_magica_shot =
{
local float shotcount;
local vector soffset, dir, offang;
if (!self.enemy) return;
if (self.health < 1) return;
// Single sound per volley of bullets
sound (self, CHAN_WEAPON, "hknight/attack1.wav", 1, ATTN_NORM);
// Randomize quantity each time called
if (random() < 0.5) shotcount = 2;
else shotcount = 3;
// based angle of projectiles on straight line between source and target
offang = vectoangles (self.enemy.origin - self.origin);
offang_y = offang_y + offset * 6; // Arc offset
makevectors (offang);
while (shotcount > 0) {
// Randomly spawn projectiles up and down sword length
soffset = v_forward * 20 + v_up * random() * 20;
// Double check that missile is not blocked by any world geo
if (!visxray(self.enemy, soffset, '0 0 0', TRUE)) soffset = soffset + '0 0 24';
soffset = self.origin + soffset;
// Straight line velocity from source to target
dir = normalize (v_forward);
dir_z = 0 - dir_z + (random() - 0.5)*0.1; // Slight wiggle up/down
// Variable speed based on skill level with extra random spice
self.attack_speed = SPEED_DFURYSPIKE + (skill * SPEED_DFURYSKILL) + random()*10;
launch_projectile (soffset, dir, CT_PROJ_FURY2, self.attack_speed);
shotcount = shotcount - 1;
}
};
//----------------------------------------------------------------------
// Magic Attack B - 3 x rockets launched in an arc
//----------------------------------------------------------------------
void() dfury_magicb_shot =
{
local float offset, shotcount;
local vector soffset, dir, offang, avel;
if (!self.enemy) return;
if (self.health < 1) return;
// Single sound for all rockets fired
sound (self, CHAN_WEAPON, "hknight/attack1.wav", 1, ATTN_NORM);
// create an arc of rockets fanning outwards from source
offset = -4; shotcount = 3;
while (shotcount > 0) {
// based angle of projectiles on straight line between source and target
offang = vectoangles (self.enemy.origin - self.origin);
offang_y = offang_y + offset;
makevectors (offang);
// Randomly spawn projectiles around central point
soffset = v_forward * 20 + v_up * (5 + random() * 10);
// Double check that missile is not blocked by any world geo
if (!visxray(self.enemy, soffset, '0 0 0', TRUE)) soffset = soffset + '0 0 24';
soffset = self.origin + soffset;
// Straight line velocity from source to target
dir = normalize (v_forward);
dir_z = 0 - dir_z + (random() - 0.5)*0.1; // Slight wiggle up/down
avel = vecrand(100,200,FALSE);
// Variable speed based on skill level with extra random spice
self.attack_speed = SPEED_DFURYSPIKE + (skill * SPEED_DFURYSKILL) + random()*10;
Launch_Missile (soffset, dir, avel, CT_PROJ_FURY1, self.attack_speed );
offset = offset + 4;
shotcount = shotcount - 1;
}
};
//----------------------------------------------------------------------
void() dfury_attachment_finish =
{
if (self.state) {
self.state = FALSE;
self.alpha = 0.1;
setmodel(self, "");
}
};
//----------------------------------------------------------------------
void(float skincolor) dfury_attachment_setup =
{
if (self.attachment && !self.attachment.state) {
self.attachment.state = TRUE;
setmodel(self.attachment, self.weaponglow);
self.attachment.alpha = 0.1;
self.attachment.skin = skincolor;
setorigin(self.attachment, self.origin);
self.attachment.angles = self.angles;
self.attachment.nextthink = time + 0.15;
self.attachment.think = dfury_attachment_finish;
}
};
//----------------------------------------------------------------------
void() dfury_attachment_update =
{
if (self.attachment && self.attachment.state) {
setorigin(self.attachment, self.origin);
self.attachment.angles = self.angles;
self.attachment.frame = self.frame;
self.attachment.alpha = 0.3 + random()*0.7;
self.attachment.nextthink = time + 0.15;
self.attachment.think = dfury_attachment_finish;
}
};
//----------------------------------------------------------------------
// Magic Attack A - Spray of spikes from raised up swords
// Block pain function from interrupting magic attack
void() dfury_magica1 =[ $magica2, dfury_magica2 ] {ai_face();self.pain_finished = time + 2;};
void() dfury_magica2 =[ $magica3, dfury_magica3 ] {ai_face();};
void() dfury_magica3 =[ $magica4, dfury_magica4 ] {ai_face();};
void() dfury_magica4 =[ $magica5, dfury_magica5 ] {ai_face();};
void() dfury_magica5 =[ $magica6, dfury_magica6 ] {ai_charge(2);dfury_attachment_setup(0);};
void() dfury_magica6 =[ $magica7, dfury_magica7 ] {ai_charge(2);dfury_attachment_update();};
void() dfury_magica7 =[ $magica8, dfury_magica8 ] {ai_charge(2);dfury_attachment_update();};
void() dfury_magica8 =[ $magica9, dfury_magica9 ] {ai_charge(2);dfury_attachment_update();};
void() dfury_magica9 =[ $magica10, dfury_magica10] {ai_charge(2);dfury_attachment_update();};
void() dfury_magica10 =[ $magica11, dfury_magica11] {dfury_attachment_update();dfury_magica_shot(-3);};
void() dfury_magica11 =[ $magica12, dfury_magica12] {dfury_attachment_update();dfury_magica_shot(-1);};
void() dfury_magica12 =[ $magica13, dfury_magica13] {dfury_attachment_update();dfury_magica_shot(0);};
void() dfury_magica13 =[ $magica14, dfury_magica14] {dfury_attachment_update();dfury_magica_shot(1);};
void() dfury_magica14 =[ $magica15, dfury_magica15] {dfury_attachment_update();dfury_magica_shot(2);};
void() dfury_magica15 =[ $magica16, dfury_run1] {};
//----------------------------------------------------------------------
// Magic Attack B - 3 x rockets launched in an arc
// Block pain function from interrupting magic attack
void() dfury_magicb1 =[ $magicb1, dfury_magicb2 ] {self.pain_finished = time + 2;};
void() dfury_magicb2 =[ $magicb2, dfury_magicb3 ] {ai_face();dfury_attachment_setup(1);};
void() dfury_magicb3 =[ $magicb3, dfury_magicb4 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb4 =[ $magicb4, dfury_magicb5 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb5 =[ $magicb5, dfury_magicb6 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb6 =[ $magicb6, dfury_magicb7 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb7 =[ $magicb7, dfury_magicb8 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb8 =[ $magicb8, dfury_magicb9 ] {ai_face();dfury_attachment_update();};
void() dfury_magicb9 =[ $magicb9, dfury_magicb10] {ai_face();dfury_attachment_update();dfury_magicb_shot();};
void() dfury_magicb10 =[ $magicb10, dfury_magicb11] {dfury_attachment_update();};
void() dfury_magicb11 =[ $magicb11, dfury_magicb12] {};
void() dfury_magicb12 =[ $magicb12, dfury_magicb13] {};
void() dfury_magicb13 =[ $magica13, dfury_run1] {};
//----------------------------------------------------------------------
// MagicB is explosive so only use if there is range available
// Otherwise randomly pick between the two types (spikes/rockets)
//----------------------------------------------------------------------
void() dfury_magic =
{
SUB_AttackFinished (2 + random());
self.enemydist = range_distance(self.enemy, FALSE);
if (self.enemydist < MONAI_JUMPFURYNEAR) dfury_magica1();
else {
if (random() < 0.2) dfury_magica1();
else dfury_magicb1();
}
};
//============================================================================
void() dfury_painA1 =[ $painA1, dfury_painA2 ] {};
void() dfury_painA2 =[ $painA2, dfury_painA3 ] {};
void() dfury_painA3 =[ $painA3, dfury_painA4 ] {};
void() dfury_painA4 =[ $painA4, dfury_painA5 ] {};
void() dfury_painA5 =[ $painA5, dfury_run1 ] {};
//----------------------------------------------------------------------
void() dfury_painD1 =[ $painD1, dfury_painD2 ] {};
void() dfury_painD2 =[ $painD2, dfury_painD3 ] {};
void() dfury_painD3 =[ $painD3, dfury_painD4 ] {};
void() dfury_painD4 =[ $painD4, dfury_painD5 ] {monster_footstep(FALSE); };
void() dfury_painD5 =[ $painD5, dfury_painD6 ] {};
void() dfury_painD6 =[ $painD6, dfury_painD7 ] {};
void() dfury_painD7 =[ $painD7, dfury_painD8 ] {};
void() dfury_painD8 =[ $painD8, dfury_painD9 ] {monster_footstep(FALSE); };
void() dfury_painD9 =[ $painD9, dfury_painD10 ] {};
void() dfury_painD10 =[ $painD10, dfury_painD11 ] {};
void() dfury_painD11 =[ $painD11, dfury_run1 ] {};
//----------------------------------------------------------------------
void(entity inflictor, entity attacker, float damage) dfury_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) {
sound (self, CHAN_VOICE, self.pain_sound, 1, ATTN_NORM);
if (self.pain_check == 1) {
// Randomly pick which pain animation to play
if (random() < 0.9) dfury_painA1 (); // classic, body recoil
else {
dfury_painD1 (); // Cool stumble
self.pain_finished = time + 2; // long animation
}
}
else if (self.pain_check == 2) {
// reset axe hit and setup short pain recovery
self.pain_finished = time + 1.1;
self.axhitme = 0;
dfury_painD1 ();
}
}
};
//============================================================================
void() dfury_die1 =[ $death2, dfury_die2 ] {ai_forward(10);};
void() dfury_die2 =[ $death3, dfury_die3 ] {monster_check_gib();ai_forward(8);};
void() dfury_die3 =[ $death4, dfury_die4 ] {monster_check_gib();
self.solid = SOLID_NOT; ai_forward(7);};
void() dfury_die4 =[ $death5, dfury_die5 ] {};
void() dfury_die5 =[ $death6, dfury_die6 ] {};
void() dfury_die6 =[ $death7, dfury_die7 ] {
sound (self, CHAN_WEAPON, GIB_SOUND_METALA, 1, ATTN_NORM);};
void() dfury_die7 =[ $death8, dfury_die8 ] {};
void() dfury_die8 =[ $death9, dfury_die9 ] {ai_forward(10);};
void() dfury_die9 =[ $death10, dfury_die10 ] {ai_forward(11);};
void() dfury_die10 =[ $death11, dfury_die11 ] {};
void() dfury_die11 =[ $death12, dfury_die12 ] {};
void() dfury_die12 =[ $death13, dfury_die13 ] {};
void() dfury_die13 =[ $death14, dfury_die14 ] {};
void() dfury_die14 =[ $death15, dfury_die15 ] {
sound (self, CHAN_WEAPON, GIB_SOUND_METALA, 1, ATTN_NORM);};
void() dfury_die15 =[ $death16, dfury_die16 ] {monster_death_postcheck();};
void() dfury_die16 =[ $death17, dfury_die16 ] {monster_deadbody_check();};
//----------------------------------------------------------------------
void() dfury_dieb1 =[ $deathb1, dfury_dieb2 ] {};
void() dfury_dieb2 =[ $deathb2, dfury_dieb3 ] {monster_check_gib();};
void() dfury_dieb3 =[ $deathb3, dfury_dieb4 ] {monster_check_gib();
self.solid = SOLID_NOT;};
void() dfury_dieb4 =[ $deathb4, dfury_dieb5 ] {};
void() dfury_dieb5 =[ $deathb5, dfury_dieb6 ] {};
void() dfury_dieb6 =[ $deathb6, dfury_dieb7 ] {
sound (self, CHAN_WEAPON, GIB_SOUND_METALB, 1, ATTN_NORM);};
void() dfury_dieb7 =[ $deathb7, dfury_dieb8 ] {};
void() dfury_dieb8 =[ $deathb8, dfury_dieb9 ] {};
void() dfury_dieb9 =[ $deathb9, dfury_dieb10] {};
void() dfury_dieb10=[ $deathb10, dfury_dieb11] {};
void() dfury_dieb11=[ $deathb11, dfury_dieb12] {};
void() dfury_dieb12=[ $deathb12, dfury_dieb13] {};
void() dfury_dieb13=[ $deathb13, dfury_dieb14] {monster_death_postcheck();};
void() dfury_dieb14=[ $deathb14, dfury_dieb14] {monster_deadbody_check();};
//----------------------------------------------------------------------
void() dfury_die =
{
// Pre-check routine to tidy up extra entities
monster_death_precheck();
// regular death
if (!self.gibbed) {
sound (self, CHAN_VOICE, "hknight/death1.wav", 1, ATTN_NORM);
if (random() > 0.5) dfury_die1 ();
else dfury_dieb1 ();
}
};
//============================================================================
void() dfury_sword_sound =
{
self.weaponstate = random();
if (self.weaponstate < 0.25) sound (self, CHAN_WEAPON, "weapons/sword1a.wav", 1, ATTN_NORM);
else if (self.weaponstate < 0.5) sound (self, CHAN_WEAPON, "weapons/sword2a.wav", 1, ATTN_NORM);
else if (self.weaponstate < 0.75) sound (self, CHAN_WEAPON, "weapons/sword1b.wav", 1, ATTN_NORM);
else sound (self, CHAN_WEAPON, "weapons/sword2b.wav", 1, ATTN_NORM);
};
//============================================================================
void(float soundtype) dfury_grunt_sound =
{
if (soundtype == DFURY_SOUND_PULLAPART)
sound (self, CHAN_WEAPON, "dknight/dfury_grunt3.wav", 1, ATTN_NORM);
else if (soundtype == DFURY_SOUND_OVERSMASH)
sound (self, CHAN_WEAPON, "dknight/dfury_grunt4.wav", 1, ATTN_NORM);
else if (soundtype == DFURY_SOUND_JUMP)
sound (self, CHAN_WEAPON, "dknight/dfury_leap.wav", 1, ATTN_NORM);
else {
if (soundtype == DFURY_SOUND_OPTIONAL && random() < 0.8) return;
self.weaponstate = random();
self.weaponswitch = 0.6 + random()*0.4;
if (self.weaponstate < 0.25) sound (self, CHAN_WEAPON, "dknight/dfury_grunt1.wav", self.weaponswitch, ATTN_NORM);
else if (self.weaponstate < 0.5) sound (self, CHAN_WEAPON, "dknight/dfury_grunt2.wav", self.weaponswitch, ATTN_NORM);
else if (self.weaponstate < 0.75) sound (self, CHAN_WEAPON, "dknight/dfury_grunt3.wav", self.weaponswitch, ATTN_NORM);
else sound (self, CHAN_WEAPON, "dknight/dfury_grunt4.wav", self.weaponswitch, ATTN_NORM);
}
};
/*======================================================================
QUAKED monster_dfury (1 0 0) (-16 -16 -24) (16 16 40) Ambush
======================================================================*/
void() monster_dfury =
{
if (deathmatch) { remove(self); return; }
self.mdl = "progs/mon_dfury.mdl";
self.headmdl = "progs/h_dfury.mdl";
self.weaponglow = "progs/mon_dfury_glow.mdl";
self.gib1mdl = "progs/w_dfurysword1.mdl"; // Unique sword L
self.gib2mdl = "progs/w_dfurysword2.mdl"; // Unique sword R
self.gib3mdl = "progs/gib_knfoot_r.mdl"; // right foot
precache_model (self.mdl);
precache_model (self.headmdl);
precache_model (self.weaponglow); // Glowing magical swords
precache_model (MODEL_PROJ_FURY1); // Vore spike ball with smoke trail
precache_model (MODEL_PROJ_FURY2); // Wizard spit with smoke trail
precache_model (self.gib1mdl);
precache_model (self.gib2mdl);
precache_model (self.gib3mdl);
self.gib3skin = 2;
self.gib1sound = self.gib2sound = GIB_IMPACT_METALA;
self.idle_sound = "hknight/idle.wav";
precache_sound (self.idle_sound);
// Firing of magic spikes (first 0.1s must loop)
precache_sound ("hknight/attack1.wav");
precache_sound ("hknight/death1.wav");
self.pain_sound = "hknight/pain1.wav";
precache_sound (self.pain_sound);
// TE_KNIGHTSPIKE = Magic spike hitting the wall
// Has got to be in this location because the filename is hardcoded (engine.exe)
precache_sound ("hknight/hit.wav");
// Double sword swipe (like death knight++)
self.sight_sound = "dknight/dfury_sight.wav";
precache_sound (self.sight_sound);
// Heavy thud sound
self.meleehitsound = GIB_SOUND_HEAVY2;
precache_sound (self.meleehitsound);
// New sword sweep/slash sounds
precache_sound ("weapons/sword1a.wav");
precache_sound ("weapons/sword1b.wav");
precache_sound ("weapons/sword2a.wav");
precache_sound ("weapons/sword2b.wav");
// New grunt sounds during combat
precache_sound ("dknight/dfury_grunt1.wav");
precache_sound ("dknight/dfury_grunt2.wav");
precache_sound ("dknight/dfury_grunt3.wav");
precache_sound ("dknight/dfury_grunt4.wav");
precache_sound ("dknight/dfury_leap.wav");
// Check for poisonous entity flag
if (self.poisonous) {
precache_poisongibs(); // precache gibs
self.gibtype = GIBTYPE_POISON; // Poisonous blood trails
precache_model (MODEL_PROJ_SHALGRN); // Green voreball
}
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 = 400;
self.gibhealth = -50;
self.gibbed = FALSE;
self.pain_flinch = 80;
self.pain_longanim = TRUE; // can be chopped with shadow axe
self.pain_timeout = 2; // High pain level
if (!self.infightextra) self.infightextra = 2; // 2x infighting dmg
self.steptype = FS_TYPEMEDIUM;
self.meleecontact = FALSE; // Smash contact
self.meleerange = MONAI_MELEEFRONT; // Smash attack
self.meleeoffset = '24 0 16'; // Jump attack offset
self.attack_offset = '20 0 10'; // Average of both attacks
self.deathstring = " was sliced by a Fury Knight\n";
// Always reset Ammo Resistance to be consistent
self.resist_shells = self.resist_nails = 0;
self.resist_rockets = self.resist_cells = 0;
self.th_checkattack = DFuryCheckAttack;
self.th_stand = dfury_standL1;
self.th_walk = dfury_walk1;
self.th_run = dfury_run1;
self.th_melee = dfury_melee;
self.th_missile = dfury_magic;
self.th_pain = dfury_pain;
self.th_die = dfury_die;
self.th_jump = dfury_lunge1;
self.th_jumpexit = dfury_lunge9;
self.th_charge = dfury_watk1;
self.th_slide = dfury_slice1;
self.meleeattack = rint(random()*5);
self.weaponswitch = time + 5;
self.classtype = CT_MONDFURY;
self.classgroup = CG_DCAPTAIN;
self.classmove = MON_MOVEWALK;
// Setup magic glowing sword effect
self.attachment = spawn();
self.attachment.owner = self;
self.attachment.classtype = CT_ATTACHMENT;
setsize (self.attachment, VEC_ORIGIN, VEC_ORIGIN);
self.attachment.movetype = MOVETYPE_NONE;
self.attachment.solid = SOLID_NOT;
setorigin(self.attachment, self.origin);
monster_start();
};