/* * $Header: /H2 Mission Pack/HCode/hydra.hc 7 3/09/98 3:05p Mgummelt $ */ /* ============================================================================== Q:\art\models\monsters\hydra\final\hydra.hc ============================================================================== */ // For building the model $cd Q:\art\models\monsters\hydra\final $origin 0 0 0 $base base 450 200 $skin skin1 $flags 0 // $frame hadie1 hadie2 hadie3 hadie4 hadie5 $frame hadie6 hadie7 hadie8 hadie9 hadie10 $frame hadie11 hadie12 hadie13 hadie14 hadie15 $frame hadie16 hadie17 hadie18 hadie19 hadie20 $frame hadie21 hadie22 hadie23 hadie24 hadie25 $frame hadie26 hadie27 hadie28 hadie29 hadie30 $frame hadie31 hadie32 hadie33 hadie34 hadie35 $frame hadie36 // $frame hapan1 hapan2 hapan3 hapan4 hapan5 $frame hapan6 hapan7 hapan8 hapan9 hapan10 // $frame hlft1 hlft2 hlft3 hlft4 hlft5 $frame hlft6 hlft7 hlft8 hlft9 hlft10 $frame hlft11 hlft12 hlft13 hlft14 hlft15 $frame hlft16 hlft17 hlft18 hlft19 hlft20 $frame hlft21 hlft22 hlft23 hlft24 hlft25 $frame hlft26 hlft27 hlft28 hlft29 hlft30 // $frame hopen1 hopen2 hopen3 hopen4 hopen5 $frame hopen6 hopen7 hopen8 // $frame hrit1 hrit2 hrit3 hrit4 hrit5 $frame hrit6 hrit7 hrit8 hrit9 hrit10 $frame hrit11 hrit12 hrit13 hrit14 hrit15 $frame hrit16 hrit17 hrit18 hrit19 hrit20 $frame hrit21 hrit22 hrit23 hrit24 hrit25 $frame hrit26 hrit27 hrit28 hrit29 hrit30 // $frame hsdie1 hsdie2 hsdie3 hsdie4 hsdie5 $frame hsdie6 hsdie7 hsdie8 hsdie9 hsdie10 $frame hsdie11 hsdie12 hsdie13 hsdie14 hsdie15 $frame hsdie16 hsdie17 hsdie18 hsdie19 hsdie20 $frame hsdie21 hsdie22 hsdie23 hsdie24 hsdie25 $frame hsdie26 hsdie27 hsdie28 hsdie29 hsdie30 $frame hsdie31 hsdie32 hsdie33 hsdie34 hsdie35 $frame hsdie36 // $frame hspan1 hspan2 hspan3 hspan4 hspan5 $frame hspan6 hspan7 hspan8 hspan9 hspan10 // $frame hspit1 hspit2 hspit3 hspit4 hspit5 $frame hspit6 hspit7 hspit8 hspit9 hspit10 $frame hspit11 hspit12 // $frame hswim1 hswim2 hswim3 hswim4 hswim5 $frame hswim6 hswim7 hswim8 hswim9 hswim10 $frame hswim11 hswim12 hswim13 hswim14 hswim15 $frame hswim16 hswim17 hswim18 hswim19 hswim20 // $frame htent1 htent2 htent3 htent4 htent5 $frame htent6 htent7 htent8 htent9 htent10 $frame htent11 htent12 htent13 htent14 htent15 $frame htent16 htent17 htent18 htent19 htent20 $frame htent21 htent22 htent23 htent24 // Monster Stages float HYDRA_STAGE_WAIT = 0; float HYDRA_STAGE_SWIM = 1; float HYDRA_STAGE_FLOAT = 2; float HYDRA_STAGE_STRAIGHT = 3; float HYDRA_STAGE_REVERSE = 4; float HYDRA_STAGE_CHARGE = 5; float HYDRA_STAGE_ATTACK = 10; void hydra_attack(void); void hydra_CloseFrames(void); void hydra_move(float thrust); void hydra_bob(void); void hydra_init(void) { // Set the hydra ready for swim self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); self.think = self.th_run; thinktime self : random(.1,.6); self.count = 0; self.monster_stage = HYDRA_STAGE_SWIM; self.hydra_FloatTo = 0; self.goalentity = self.enemy; self.monster_awake = TRUE; } void hydra_wait(void) { if (LocateTarget()) { // We found a target hydra_init(); } } // Starting frames for making a large turn //void hydra_BigLeft(void); //void hydra_BigRight(void); // Starting frames for making a short turn //void hydra_ShortLeft(void); //void hydra_ShortRight(void); void hydra_OpenFrames(void); void hydra_TentFrames(void); void hydra_SpitFrames(void); float hydra_check_blind_melee(); void hydra_charge_finish() { self.yaw_speed = 5; self.cnt = time + random(5,10); if (CheckMonsterAttack(MA_MELEE, 3.0)) { self.monster_stage += HYDRA_STAGE_ATTACK; self.monster_check = 0; self.think = hydra_attack; thinktime self : 0.05; return; } self.monster_stage = HYDRA_STAGE_SWIM; self.think = self.th_run; thinktime self : 0.1; } void hydra_charge() { float dist; self.yaw_speed = 8; check_pos_enemy(); ai_face(); dist = vlen(self.enemy.origin - self.origin); movetogoal(dist / 8); if (range(self.enemy) == RANGE_MELEE) { self.monster_check = 0; hydra_charge_finish(); return; } if (self.hydra_chargeTime < time) { self.monster_check = 0; hydra_charge_finish(); return; } self.think = hydra_charge; thinktime self : 0.05; } float hydra_check_blind_melee(void) { float dist, c1;//, c2; if (self.enemy.watertype != CONTENT_WATER) return 0; if (self.cnt > time) return 0; dist = vhlen(self.enemy.origin - self.origin); traceline(self.origin, self.enemy.origin, FALSE, self); c1 = fov(self, self.enemy, 80); if ((dist < 256) && c1 && trace_ent == self.enemy) { if (random() < 0.2) return 1; } return 0; } void hydra_blind(void) { stuffcmd (self.enemy, "df\n"); self.hydra_chargeTime = time + 1; self.think = hydra_charge; thinktime self : 0.05; } void hydra_checkForBlind(void) { float r; r = pointcontents(self.enemy.origin); if (r != CONTENT_WATER) { self.think = self.th_run; thinktime self : 0.1; return; } r = vhlen(self.enemy.origin - self.origin); if ((r < 256) && (fov(self, self.enemy, 80)) && (fov(self.enemy, self, 80))) { thinktime self : 0.1; self.think = hydra_blind; } else { self.think = self.th_run; thinktime self : 0.1; } } void hydra_swim(float thrust) { float dist; float temp; if (self.velocity) self.velocity = self.velocity * 0.7; if (!self.enemy.flags2 & FL_ALIVE) { self.goalentity = self.enemy = world; self.monster_stage = HYDRA_STAGE_WAIT; return; } dist = (4.0 + thrust*6); // Movement distance this turn movetogoal(dist); if (self.hydra_FloatTo == 0) { dist = self.enemy.origin_z - self.origin_z; if (dist < -50) self.hydra_FloatTo = dist - random(60); else if (dist > 50) self.hydra_FloatTo = dist + random(60); } if (self.hydra_FloatTo < -10) { temp = random(-3.5,-2.5); // movestep(0,0,temp, FALSE); self.hydra_FloatTo -= temp; } else if (self.hydra_FloatTo > 10) { temp = random(2.5,3.5); // movestep(0,0,temp, FALSE); self.hydra_FloatTo -= temp; } else self.hydra_FloatTo = 0; self.th_save = self.think; //checkenemy(); enemy_range = range (self.enemy); if (hydra_check_blind_melee()) { self.monster_check = 2; hydra_attack(); } dist = vlen(self.enemy.origin - self.origin); if (dist > 350) { if (CheckMonsterAttack(MA_MISSILE,8.0)) return; } else CheckMonsterAttack(MA_MELEE,3.0); } void hydra_float(void) { float Length; if (self.velocity) self.velocity = self.velocity * 0.7; Length = vhlen(self.origin - self.enemy.origin); if (Length < 300.0) { self.monster_stage = HYDRA_STAGE_SWIM; self.hydra_FloatTo = 0; return; } /*self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin); ChangeYaw();*/ ai_face(); self.th_save = self.think; enemy_range = range (self.enemy); if (hydra_check_blind_melee()) { self.monster_check = 2; hydra_attack(); } CheckMonsterAttack(MA_MISSILE,8.0); } /* void hydra_reverse(void) { float retval; float dist; self.monster_duration -= 1; dist = 4.0; // Movement distance this turn retval = walkmove(self.angles_y + 180, dist, FALSE); //self.monster_stage = HYDRA_STAGE_FLOAT; } */ void hydra_move(float thrust) { check_pos_enemy(); if (self.monster_stage == HYDRA_STAGE_SWIM) { hydra_swim(thrust); return; } else if (self.monster_stage == HYDRA_STAGE_FLOAT) { hydra_float(); return; } else if (self.monster_stage == HYDRA_STAGE_WAIT) { hydra_wait(); return; } else if (self.monster_stage == HYDRA_STAGE_REVERSE) { // hydra_reverse(); return; } } void hydra_attack(void) { if (self.monster_check > 0) { hydra_SpitFrames(); } else { hydra_TentFrames(); } } void hydra_fire(void) { sound (self, CHAN_WEAPON, "hydra/spit.wav", 1, ATTN_NORM); do_spit('0 0 0'); do_spit('0 0 0'); do_spit('0 0 0'); } void hydra_tent(float TryHit) { ai_face(); check_pos_enemy(); if (TryHit) { makevectors(self.angles); traceline(self.origin,self.origin+v_forward*128,FALSE,self); if (trace_ent.takedamage) { sound (self, CHAN_WEAPON, "hydra/tent.wav", 1, ATTN_NORM); T_Damage (trace_ent, self, self, random(1,2)); } else movetogoal(15); } } void hydra_open(void) { ai_face(); } void hydra_bob(void) { local float rnd1, rnd2, rnd3; // local vector vtmp1, modi; rnd1 = self.velocity_x + random(-10,10); rnd2 = self.velocity_y + random(-10,10); rnd3 = self.velocity_z + random(10); if (rnd1 > 10) rnd1 = 10; if (rnd1 < -10) rnd1 = -10; if (rnd2 > 10) rnd2 = 10; if (rnd2 < -10) rnd2 = -10; /* if (rnd3 < 10) rnd3 = 15;*/ if (rnd3 > 55) rnd3 = 50; self.velocity_x = rnd1; self.velocity_y = rnd2; self.velocity_z = rnd3; } // Swimming float hydra_Swim[20] = { -0.2, -0.1, 0.0, 0.1, // Top going down 0.2, 0.3, 0.4, 0.5, // middle 0.4, 0.3, 0.2, 0.1, // bottom 0.0, -0.1, -0.2, -0.3, -0.4, -0.5, // middle -0.4, -0.3 }; // Top = 1, tr = 2, br = 3, tl = 4, bl = 5 float hydra_TentAttacks[24] = { 0, 0, 0, 0, 1, 0, 3, 0, 4, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 4, 3, 1, 0, 0 }; // Attacking others void hydra_AttackDieFrames(void) { self.think = hydra_AttackDieFrames; thinktime self : HX_FRAME_TIME; if (self.frame != $hadie36) AdvanceFrame($hadie1,$hadie36); if (self.frame == $hadie35) { self.solid = SOLID_NOT; MakeSolidCorpse(); } if (self.frame >= $hadie13) hydra_bob(); if(self.health<-30) chunk_death(); } void hydra_AttackPainFrames(void) { self.think = hydra_AttackPainFrames; thinktime self : HX_FRAME_TIME; AdvanceFrame($hapan1,$hapan10); } // Swimming others void hydra_SwimDieFrames(void) { self.think = hydra_SwimDieFrames; thinktime self : HX_FRAME_TIME; if (self.frame != $hsdie36) AdvanceFrame($hsdie1,$hsdie36); if (self.frame == $hsdie35) { self.solid = SOLID_NOT; MakeSolidCorpse(); } if (self.frame >= $hsdie8) hydra_bob(); if(self.health<-30) chunk_death(); } void hydra_SwimPainFrames(void) { self.think = hydra_SwimPainFrames; thinktime self : HX_FRAME_TIME; AdvanceFrame($hspan1,$hspan10); } // Attacking void hydra_OpenFrames(void) { self.think = hydra_OpenFrames; thinktime self : HX_FRAME_TIME; if (self.enemy.watertype != CONTENT_WATER) { self.monster_stage = HYDRA_STAGE_FLOAT; self.think = self.th_run; thinktime self : 0.1; return; } hydra_open(); if (AdvanceFrame($hopen1,$hopen8) == AF_END) { hydra_attack(); } } void hydra_CloseFrames(void) { self.think = hydra_CloseFrames; thinktime self : HX_FRAME_TIME; if (RewindFrame($hopen8,$hopen1) == AF_END) { self.monster_stage -= HYDRA_STAGE_ATTACK; self.think = self.th_save; } } void hydra_SpitFrames(void) { vector vecA,vecB; self.think = hydra_SpitFrames; thinktime self : HX_FRAME_TIME; self.angles_y = vectoyaw(self.enemy.origin - self.origin); if (AdvanceFrame($hspit1,$hspit12) == AF_END) { self.think = hydra_CloseFrames; self.monster_check = -1; } else if (self.frame == $hspit7 && self.monster_check == 2) { sound (self, CHAN_WEAPON, "hydra/spit.wav", 1, ATTN_NORM); vecA = self.enemy.origin - self.origin + self.enemy.proj_ofs; vecA = vectoangles(vecA); makevectors(vecA); v_forward_z = 0 - v_forward_z; vecA = v_factor('-40 400 -40'); vecB = v_factor('40 500 40'); particle2(self.origin+v_forward*40,vecA,vecB,256,12,400); self.think = hydra_checkForBlind; thinktime self : 0.1; } else if (self.frame == $hspit8 && self.monster_check == 1) { hydra_fire(); } } void hydra_TentFrames(void) { float r; if (!self.enemy.flags2 & FL_ALIVE) { self.goalentity = self.enemy = world; self.monster_stage = HYDRA_STAGE_WAIT; self.think = self.th_stand; thinktime self : 0.1; return; } self.think = hydra_TentFrames; thinktime self : 0.025; if (AdvanceFrame($htent1,$htent24) == AF_END) { r = range(self.enemy); if ((r == RANGE_MELEE) && (random(0, 1) < 0.3)) { self.frame = $htent1; hydra_tent(hydra_TentAttacks[self.frame - $htent1]); } else self.think = hydra_CloseFrames; } else { hydra_tent(hydra_TentAttacks[self.frame - $htent1]); } } // Regular swimming / movement void hydra_SwimFrames(void) { self.think = hydra_SwimFrames; thinktime self : HX_FRAME_TIME; AdvanceFrame($hswim1,$hswim20); if (self.frame == $hswim1) sound (self, CHAN_WEAPON, "hydra/swim.wav", 1, ATTN_NORM); hydra_move((hydra_Swim[self.frame - $hswim1]) + 0.3); } /*QUAKED misc_fountain (0 1 0.8) (0 0 0) (32 32 32) New item for QuakeEd -------------------------FIELDS------------------------- angles 0 0 0 the direction it should move the particles movedir 1 1 1 the force it should move them color 256 the color cnt 2 the number of particles each time -------------------------------------------------------- */ void misc_fountain(void) { starteffect(CE_FOUNTAIN, self.origin, self.angles,self.movedir,self.color,self.cnt); } void do_hydra_spit(void) { self.monster_check = 1; self.monster_stage += HYDRA_STAGE_ATTACK; sound (self, CHAN_WEAPON, "hydra/open.wav", 1, ATTN_NORM); hydra_OpenFrames(); } void do_hydra_tent(void) { self.monster_check = 0; self.monster_stage += HYDRA_STAGE_ATTACK; sound (self, CHAN_WEAPON, "hydra/open.wav", 1, ATTN_NORM); hydra_OpenFrames(); } void do_hydra_die(void) { self.flags (+) FL_SWIM; sound (self, CHAN_WEAPON, "hydra/die.wav", 1, ATTN_NORM); if (self.monster_stage >= HYDRA_STAGE_ATTACK) hydra_AttackDieFrames(); else hydra_SwimDieFrames(); } /* void hydra_retreat() { self.monster_stage = HYDRA_STAGE_REVERSE; self.think = self.th_run; thinktime self : 0.1; } */ void hydra_pain(entity attacker, float damage) { sound (self, CHAN_WEAPON, "hydra/pain.wav", 1, ATTN_NORM); } void init_hydra(void) { if (deathmatch) { remove(self); return; } self.monster_stage = HYDRA_STAGE_WAIT; if (!self.flags2 & FL_SUMMONED&&!self.flags2&FL2_RESPAWN) { precache_model ("models/hydra.mdl"); precache_model ("models/spit.mdl"); } self.solid = SOLID_SLIDEBOX; self.movetype = MOVETYPE_SWIM; self.thingtype=THINGTYPE_FLESH; self.classname="monster_hydra"; self.mass = 7; setmodel (self, "models/hydra.mdl"); self.skin = 0; setsize (self, '-30 -30 -24', '30 30 24'); self.hull = HULL_SCORPION; //self.hull = HULL_HYDRA; if(!self.health) self.health = 125; if(!self.max_health) self.max_health=self.health; self.experience_value = 50; self.mintel = 4; self.th_stand = hydra_SwimFrames; self.th_walk = hydra_SwimFrames; self.th_run = hydra_SwimFrames; self.th_pain = hydra_pain; self.th_die = do_hydra_die; self.th_missile = do_hydra_spit; self.th_melee = do_hydra_tent; self.takedamage = DAMAGE_YES; self.flags2 (+) FL_ALIVE; self.ideal_yaw = self.angles * '0 1 0'; if (!self.yaw_speed) self.yaw_speed = 5; self.view_ofs = '0 0 0'; self.use = monster_use; self.flags (+) FL_SWIM | FL_MONSTER; self.pausetime = 99999999; total_monsters += 1; self.init_exp_val = self.experience_value; thinktime self : random(0.5); self.think = self.th_stand; } /*QUAKED monster_hydra (1 0.3 0) (-40 -40 -42) (40 40 42) STAND HOVER JUMP x DORMANT New item for QuakeEd -------------------------FIELDS------------------------- NOTE: Normal QuakEd monster spawnflags don't apply here (no_jump, x, no_drop) -------------------------------------------------------- */ void monster_hydra(void) { if(!self.th_init) { self.th_init=monster_hydra; self.init_org=self.origin; } init_hydra(); if (!self.flags2 & FL_SUMMONED&&!self.flags2&FL2_RESPAWN) { precache_sound("hydra/pain.wav"); precache_sound("hydra/die.wav"); precache_sound("hydra/open.wav"); precache_sound("hydra/turn-s.wav"); precache_sound("hydra/turn-b.wav"); precache_sound("hydra/swim.wav"); precache_sound("hydra/tent.wav"); precache_sound("hydra/spit.wav"); } } /* * $Log: /H2 Mission Pack/HCode/hydra.hc $ * * 7 3/09/98 3:05p Mgummelt * * 6 3/03/98 7:31p Mgummelt * * 5 2/12/98 5:55p Jmonroe * remove unreferenced funcs * * 4 2/05/98 12:30p Mgummelt * * 3 2/04/98 4:58p Mgummelt * spawnflags on monsters cleared out * * 62 10/28/97 1:01p Mgummelt * Massive replacement, rewrote entire code... just kidding. Added * support for 5th class. * * 60 9/11/97 9:05a Mgummelt * * 59 9/03/97 2:36a Mgummelt * * 58 9/01/97 12:50a Jweier * * 57 9/01/97 12:20a Jweier * * 56 8/31/97 8:52a Mgummelt * * 55 8/29/97 11:14p Mgummelt * * 54 8/29/97 4:17p Mgummelt * Long night * * 53 8/28/97 2:01a Mgummelt * * 52 8/27/97 6:53p Jweier * * 50 8/25/97 4:06p Mgummelt * * 49 8/24/97 4:02p Jweier * * 48 8/21/97 2:16a Jweier * * 47 8/21/97 2:04a Jweier * * 45 8/20/97 11:56p Jweier * * 44 8/19/97 8:56a Mgummelt * * 43 8/18/97 5:21p Bgokey * * 41 8/15/97 4:02p Rjohnson * Precache update * * 40 8/15/97 12:24p Bgokey * * 39 8/15/97 11:34a Bgokey * * 38 8/14/97 11:11p Bgokey * * 36 8/14/97 7:37p Bgokey * * 32 8/14/97 12:11p Mgummelt * * 31 7/21/97 4:03p Mgummelt * * 30 7/21/97 4:02p Mgummelt * * 29 7/20/97 1:24a Rjohnson * Fix for a missing parameter * * 28 7/15/97 1:25p Rjohnson * Updates * * 27 7/07/97 5:09p Rlove * * 26 7/03/97 8:47a Rlove * * 25 6/19/97 10:18p Rjohnson * Fix for makesolidcorpse() * * 24 6/19/97 3:08p Rjohnson * Code space optimizations * * 23 5/30/97 11:41a Rjohnson * Removed the message field of the starteffect * * 22 5/23/97 3:43p Mgummelt * * 21 5/22/97 3:29p Mgummelt * * 20 5/20/97 11:31a Rjohnson * Revised Effects * * 19 5/19/97 2:54p Rjohnson * New client effects * * 18 5/16/97 2:12p Mgummelt * * 17 5/07/97 3:40p Mgummelt * * 16 5/07/97 11:12a Rjohnson * Added a new field to walkmove and movestep to allow for setting the * traceline info * * 15 5/07/97 10:39a Rjohnson * Minor fixes * * 14 5/06/97 1:29p Mgummelt * * 13 4/21/97 8:47p Mgummelt * * 12 4/21/97 6:15p Mgummelt * * 11 4/17/97 2:50p Mgummelt * * 10 4/07/97 2:56p Mgummelt * * 9 4/07/97 1:39p Rjohnson * Added sounds to the imp, fangel, and hydra * * 8 3/21/97 4:43p Rjohnson * Updates * * 7 3/13/97 9:57a Rlove * Changed constant DAMAGE_AIM to DAMAGE_YES and the old DAMAGE_YES to * DAMAGE_NO_GRENADE * * 6 3/12/97 10:57p Rjohnson * Changed the particle2 parameters to make it less taxing on the network * and more versitile * * 5 1/28/97 10:29a Rjohnson * Added generic experience value * * 4 1/09/97 1:47p Rjohnson * Additional refining * * 3 1/02/97 11:20a Rjohnson * Christmas changes - made him attack and move around * * 2 12/18/96 9:51a Rjohnson * Small Update * * 1 12/17/96 10:38a Rjohnson * Initial Version */