/* ============================================================================== Dweller coded by Michael Rogers a.k.a Xsniper http://xsniper.virtualave.net/ some code done by iD software ============================================================================== */ $cd /models/enemies $origin 0 0 32 $base base $skin base $frame idle101 idle102 idle103 idle104 idle105 idle106 idle107 idle108 idle109 idle110 $frame idle111 idle112 idle113 idle114 idle115 idle116 $frame idle201 idle202 idle203 idle204 idle205 idle206 idle207 idle208 idle209 idle210 $frame idle211 idle212 idle213 idle214 idle215 idle216 $frame run01 run02 run03 run04 run05 run06 run07 run08 $frame walk01 walk02 walk03 walk04 walk05 walk06 walk07 walk08 walk09 walk10 $frame walk11 walk12 walk13 $frame attack101 attack102 attack103 attack104 attack105 attack106 attack107 attack108 attack109 attack110 $frame attack111 $frame attack201 attack202 attack203 attack204 attack205 attack206 attack207 attack208 $frame pain101 pain102 pain103 pain104 pain105 $frame pain201 pain202 pain203 pain204 pain205 pain206 pain207 $frame pain301 pain302 pain303 pain304 pain305 pain306 pain307 pain308 pain309 pain310 $frame pain311 $frame death101 death102 death103 death104 death105 death106 death107 death108 death109 $frame death201 death202 death203 death204 death205 death206 death207 death208 death209 death210 $frame death211 death212 death213 death214 death215 death216 death217 death218 death219 death220 $frame death221 death222 death223 death224 death225 death226 $frame death301 death302 death303 death304 death305 death306 death307 death308 death309 death310 $frame death311 death312 death313 death314 death315 death316 death317 death318 death319 death320 $frame death321 float SPAWN_CRUCIFIED = 1; .float inpain; void() dweller_charge1; void() dweller_die; void() dweller_idlesound; //============================================================================= void() DwellerCheckForCharge = { // check for mad charge if (!enemy_vis) return; if (time < self.attack_finished) return; if ( fabs(self.origin_z - self.enemy.origin_z) > 20) return; // too much height change if ( vlen (self.origin - self.enemy.origin) < 80) return; // use regular attack // play rage sound and charge in sound (self, CHAN_VOICE, "enemy/dweller/rage.wav", 1, ATTN_NORM); SUB_AttackFinished (2); dweller_charge1 (); }; //============================================================================= void() dweller_stand1 =[ $idle101, dweller_stand2 ] {ai_stand();}; void() dweller_stand2 =[ $idle102, dweller_stand3 ] {ai_stand();}; void() dweller_stand3 =[ $idle103, dweller_stand4 ] {ai_stand();}; void() dweller_stand4 =[ $idle104, dweller_stand5 ] {ai_stand();}; void() dweller_stand5 =[ $idle105, dweller_stand6 ] {ai_stand();}; void() dweller_stand6 =[ $idle106, dweller_stand7 ] {ai_stand();}; void() dweller_stand7 =[ $idle107, dweller_stand8 ] {ai_stand();}; void() dweller_stand8 =[ $idle108, dweller_stand9 ] {ai_stand();}; void() dweller_stand9 =[ $idle109, dweller_stand10 ] {ai_stand();}; void() dweller_stand10 =[ $idle110, dweller_stand11 ] {ai_stand();}; void() dweller_stand11 =[ $idle111, dweller_stand12 ] {ai_stand();}; void() dweller_stand12 =[ $idle112, dweller_stand13 ] {ai_stand();}; void() dweller_stand13 =[ $idle113, dweller_stand14 ] {ai_stand();}; void() dweller_stand14 =[ $idle114, dweller_stand15 ] {ai_stand();}; void() dweller_stand15 =[ $idle115, dweller_stand16 ] {ai_stand();}; void() dweller_stand16 =[ $idle116, dweller_stand1 ] {ai_stand();}; //============================================================================= void() dweller_walk1 =[ $walk01, dweller_walk2 ] {ai_walk(3);}; void() dweller_walk2 =[ $walk02, dweller_walk3 ] {ai_walk(2);}; void() dweller_walk3 =[ $walk03, dweller_walk4 ] {ai_walk(3);}; void() dweller_walk4 =[ $walk04, dweller_walk5 ] {ai_walk(2);}; void() dweller_walk5 =[ $walk05, dweller_walk6 ] {ai_walk(2);}; void() dweller_walk6 =[ $walk06, dweller_walk7 ] {ai_walk(3);}; void() dweller_walk7 =[ $walk07, dweller_walk8 ] {ai_walk(3);}; void() dweller_walk8 =[ $walk08, dweller_walk9 ] {ai_walk(2);}; void() dweller_walk9 =[ $walk09, dweller_walk10 ] {ai_walk(2);}; void() dweller_walk10 =[ $walk10, dweller_walk11 ] {ai_walk(1);}; void() dweller_walk11 =[ $walk11, dweller_walk12 ] {ai_walk(2);}; void() dweller_walk12 =[ $walk12, dweller_walk13 ] {ai_walk(3);}; void() dweller_walk13 =[ $walk13, dweller_walk1 ] {ai_walk(2);dweller_idlesound();}; //============================================================================= void() dweller_run1 =[ $run01, dweller_run2 ] { ai_run(15); self.inpain = 0; DwellerCheckForCharge(); }; void() dweller_run2 =[ $run02, dweller_run3 ] {ai_run(10);}; void() dweller_run3 =[ $run03, dweller_run4 ] {ai_run(12);}; void() dweller_run4 =[ $run04, dweller_run5 ] {ai_run(14);}; void() dweller_run5 =[ $run05, dweller_run6 ] {ai_run(15);}; void() dweller_run6 =[ $run06, dweller_run7 ] {ai_run(14);}; void() dweller_run7 =[ $run07, dweller_run8 ] {ai_run(11);}; void() dweller_run8 =[ $run08, dweller_run1 ] {ai_run(16);dweller_idlesound();}; //============================================================================= void() dweller_charge1 =[ $run01, dweller_charge2 ] {ai_charge(20);}; void() dweller_charge2 =[ $run02, dweller_charge3 ] {ai_charge(18);}; void() dweller_charge3 =[ $run03, dweller_charge4 ] {ai_charge(15);}; void() dweller_charge4 =[ $run04, dweller_charge5 ] {ai_charge(22);}; void() dweller_charge5 =[ $run05, dweller_charge6 ] {ai_charge(13);}; void() dweller_charge6 =[ $run06, dweller_charge7 ] {ai_charge(20);}; void() dweller_charge7 =[ $run07, dweller_charge8 ] {ai_charge(19);}; void() dweller_charge8 =[ $run08, dweller_run1 ] {ai_charge(21);}; //============================================================================= void() dweller_atta1 =[ $attack101, dweller_atta2 ] {ai_charge(20);}; void() dweller_atta2 =[ $attack102, dweller_atta3 ] {ai_charge(22);}; void() dweller_atta3 =[ $attack103, dweller_atta4 ] {ai_charge(26);}; void() dweller_atta4 =[ $attack104, dweller_atta5 ] {ai_charge(20);ai_melee();}; void() dweller_atta5 =[ $attack105, dweller_atta6 ] {ai_charge(21);ai_melee();}; void() dweller_atta6 =[ $attack106, dweller_atta7 ] {ai_charge(24);ai_melee();}; void() dweller_atta7 =[ $attack107, dweller_atta8 ] {ai_charge(23);ai_melee();}; void() dweller_atta8 =[ $attack108, dweller_atta9 ] {ai_charge(22);ai_melee();}; void() dweller_atta9 =[ $attack109, dweller_atta10 ] {ai_face();}; void() dweller_atta10 =[ $attack110, dweller_atta11 ] {ai_face();}; void() dweller_atta11 =[ $attack111, dweller_run1 ] {ai_face();}; //============================================================================= void() dweller_attb1 =[ $attack201, dweller_attb2 ] {ai_charge(29);}; void() dweller_attb2 =[ $attack202, dweller_attb3 ] {ai_charge(22);}; void() dweller_attb3 =[ $attack203, dweller_attb4 ] {ai_charge(21);ai_melee();}; void() dweller_attb4 =[ $attack204, dweller_attb5 ] {ai_charge(26);ai_melee();}; void() dweller_attb5 =[ $attack205, dweller_attb6 ] {ai_charge(24);ai_melee();}; void() dweller_attb6 =[ $attack206, dweller_attb7 ] {ai_charge(25);ai_melee();}; void() dweller_attb7 =[ $attack207, dweller_attb8 ] {ai_face();}; void() dweller_attb8 =[ $attack208, dweller_run1 ] {ai_face();}; //============================================================================= /* ============================================================================= PAIN ============================================================================= */ void() dweller_paina1 =[ $pain101, dweller_paina2 ] {}; void() dweller_paina2 =[ $pain102, dweller_paina3 ] {ai_painforward(3);}; void() dweller_paina3 =[ $pain103, dweller_paina4 ] {ai_painforward(1);}; void() dweller_paina4 =[ $pain104, dweller_paina5 ] {ai_pain(1);}; void() dweller_paina5 =[ $pain105, dweller_run1 ] {ai_pain(3);}; //============================================================================= void() dweller_painb1 =[ $pain201, dweller_painb2 ] {}; void() dweller_painb2 =[ $pain202, dweller_painb3 ] {ai_pain(2);}; void() dweller_painb3 =[ $pain203, dweller_painb4 ] {ai_pain(8);}; void() dweller_painb4 =[ $pain204, dweller_painb5 ] {ai_pain(6);}; void() dweller_painb5 =[ $pain205, dweller_painb6 ] {ai_pain(2);}; void() dweller_painb6 =[ $pain206, dweller_painb7 ] {ai_pain(2);}; void() dweller_painb7 =[ $pain207, dweller_run1 ] {}; //============================================================================= void() dweller_painc1 =[ $pain301, dweller_painc2 ] {}; void() dweller_painc2 =[ $pain302, dweller_painc3 ] {}; void() dweller_painc3 =[ $pain303, dweller_painc4 ] {ai_pain(3);}; void() dweller_painc4 =[ $pain304, dweller_painc5 ] {ai_pain(1);}; void() dweller_painc5 =[ $pain305, dweller_painc6 ] {}; void() dweller_painc6 =[ $pain306, dweller_painc7 ] {}; void() dweller_painc7 =[ $pain307, dweller_painc8 ] {}; void() dweller_painc8 =[ $pain308, dweller_painc9 ] {}; void() dweller_painc9 =[ $pain309, dweller_painc10 ] {}; void() dweller_painc10 =[ $pain310, dweller_painc11 ] {}; void() dweller_painc11 =[ $pain311, dweller_run1 ] {}; //============================================================================= void() dweller_paine1 =[ $death101, dweller_paine2 ] {self.health = 60;}; void() dweller_paine2 =[ $death102, dweller_paine3 ] {ai_pain(8);}; void() dweller_paine3 =[ $death103, dweller_paine4 ] {ai_pain(5);}; void() dweller_paine4 =[ $death104, dweller_paine5 ] {ai_pain(3);}; void() dweller_paine5 =[ $death105, dweller_paine6 ] {ai_pain(1);}; void() dweller_paine6 =[ $death106, dweller_paine7 ] {ai_pain(2);}; void() dweller_paine7 =[ $death107, dweller_paine8 ] {ai_pain(1);}; void() dweller_paine8 =[ $death108, dweller_paine9 ] {ai_pain(1);}; void() dweller_paine9 =[ $death109, dweller_paine10 ] {self.solid = SOLID_NOT;}; void() dweller_paine10 =[ $death109, dweller_paine11 ] { self.nextthink = self.nextthink + 5; self.health = 60; }; void() dweller_paine11 =[ $death109, dweller_paine12 ] { // see if ok to stand up self.health = 60; self.solid = SOLID_SLIDEBOX; if (!walkmove (0, 0)) { self.health = -60; return; } else if (random() <= 0.5) { //random chance of dieing anyway //self.think = dweller_die; //self.solid = SOLID_NOT; self.health = -60; return; } }; void() dweller_paine12 =[ $death108, dweller_paine13 ] {}; void() dweller_paine13 =[ $death107, dweller_paine14 ] {}; void() dweller_paine14 =[ $death106, dweller_paine15 ] {}; void() dweller_paine15 =[ $death105, dweller_paine16 ] {}; void() dweller_paine16 =[ $death104, dweller_paine17 ] {}; void() dweller_paine17 =[ $death103, dweller_paine18 ] {}; void() dweller_paine18 =[ $death102, dweller_paine19 ] {}; void() dweller_paine19 =[ $death101, dweller_run1 ] {}; /* ================= dweller_pain Dwellers can only be killed (gibbed) by doing 60 hit points of damage in a single frame (rockets, grenades, quad shotgun, quad nailgun). A hit of 25 points or more (super shotgun, quad nailgun) will allways put it down to the ground. A hit of from 10 to 40 points in one frame will cause it to go down if it has been twice in two seconds, otherwise it goes into one of the four fast pain frames. A hit of less than 10 points of damage (winged by a shotgun) will be ignored. FIXME: don't use pain_finished because of nightmare hack ================= */ void(entity attacker, float take) dweller_pain = { local float r; self.health = set_health(60); // allways reset health if (take < 9) return; // totally ignore if (self.inpain == 2) return; // down on ground, so don't reset any counters //pick a pain sound at random r = random(); if (r <= 0.3) sound (self, CHAN_VOICE, "enemy/dweller/pain1.wav", 1, ATTN_NORM); else if(r <= 0.6) sound (self, CHAN_VOICE, "enemy/dweller/pain2.wav", 1, ATTN_NORM); else sound (self, CHAN_VOICE, "enemy/dweller/pain3.wav", 1, ATTN_NORM); // go down immediately if a big enough hit if (take >= 25) { self.inpain = 2; dweller_paine1 (); return; } if (self.inpain) { // if hit again in next gre seconds while not in pain frames, definately drop self.pain_finished = time + 3; return; // currently going through an animation, don't change } if (self.pain_finished > time) { // hit again, so drop down self.inpain = 2; dweller_paine1 (); return; } // go into one of the fast pain animations self.inpain = 1; r = random(); if (r < 0.35) dweller_paina1 (); else if (r < 0.65) dweller_painb1 (); else dweller_painc1 (); }; //============================================================================= void() dweller_die = { //this seems important self.solid = SOLID_NOT; //lets do some damage here T_RadiusDamage (self, self, 65, world); self.origin = self.origin - 8*normalize(self.velocity); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_TAREXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); }; //============================================================================= void() dweller_idlesound = { if (random() <= 0.2) { if (random() <= 0.5) sound (self, CHAN_VOICE, "enemy/dweller/alert1.wav", 1, ATTN_NORM); else sound (self, CHAN_VOICE, "enemy/dweller/attack1.wav", 1, ATTN_NORM); } }; void() dweller_melee = { local float r; r = random(); //play attack sound sound (self, CHAN_VOICE, "enemy/dweller/miss.wav", 1, ATTN_NORM); if (r > 0.5) dweller_atta1 (); else if (r < 0.5) dweller_attb1 (); }; //============================================================================ /*QUAKED monster_dweller (1 0 0) (-16 -16 -24) (16 16 32) Crucified ambush If crucified, stick the bounding box 12 pixels back into a wall to look right. */ void() monster_dweller = { local float r; if (deathmatch) { remove(self); return; } if (self.spawnflags & SPAWN_CRUCIFIED) { remove(self); return; } precache_model ("models/enemies/dweller.md2"); precache_sound ("enemy/dweller/alert1.wav"); precache_sound ("enemy/dweller/attack1.wav"); precache_sound ("enemy/dweller/miss.wav"); precache_sound ("enemy/dweller/pain1.wav"); precache_sound ("enemy/dweller/pain2.wav"); precache_sound ("enemy/dweller/pain3.wav"); precache_sound ("enemy/dweller/rage.wav"); self.solid = SOLID_SLIDEBOX; self.movetype = MOVETYPE_STEP; setmodel (self, "models/enemies/dweller.md2"); setsize (self, '-16 -16 -24', '16 16 32'); // setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX); self.health = set_health(60); self.speed = set_speed(600); self.dtype = 4; //dodge type do nothing self.th_stand = dweller_stand1; self.th_walk = dweller_walk1; self.th_run = dweller_run1; self.th_pain = dweller_pain; self.th_die = dweller_die; self.th_melee = dweller_melee; //pick a random skin r = random(); if (r <= 0.25) self.skin = 0; else if (r <= 0.5) self.skin = 1; else if (r <= 0.75) self.skin = 2; else self.skin = 3; //my new classname is? self.classname = "monster_dweller"; //set up our monflag self.monflag = "TRUE"; walkmonster_start(); }; /* ================= create_dwellerbot Creates a Dweller at the specified 'spot'. This is mostly used for the Necromancer's summoning ability. ================= */ void(vector spot) create_dwellerbot = { local entity bot; local float r; // start entity and place it in world bot = spawn(); bot.angles = self.angles; setorigin (bot, spot); bot.fixangle = TRUE; spawn_tfog (bot.origin); spawn_tdeath (bot.origin, bot); // set size and shape bot.solid = SOLID_SLIDEBOX; bot.movetype = MOVETYPE_STEP; setmodel (bot, "models/enemies/dweller.md2"); setsize (bot, '-16 -16 -24', '16 16 32'); bot.flags = bot.flags | FL_MONSTER; bot.takedamage = DAMAGE_AIM; // define his animation bot.th_stand = dweller_stand1; bot.th_walk = dweller_walk1; bot.th_run = dweller_run1; bot.th_die = dweller_die; bot.th_melee = dweller_melee; bot.th_pain = dweller_pain; bot.health = set_health(60); bot.speed = set_speed(600); bot.dtype = 4; //dodge type do nothing // polish him up bot.classname = "monster_dweller"; bot.ideal_yaw = bot.angles * '0 1 0'; bot.yaw_speed = 120; bot.view_ofs = '0 0 22'; //set up our monflag bot.monflag = "TRUE"; //pick a random skin r = random(); if (r <= 0.25) bot.skin = 0; else if (r <= 0.5) bot.skin = 1; else if (r <= 0.75) bot.skin = 2; else bot.skin = 3; // begin his thinking bot.nextthink = time + 0.1 + random(); bot.think = th_stuck; };