shambler.qc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /* Copyright (C) 1996-2022 id Software LLC
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  13. See file, 'COPYING', for details.
  14. */
  15. /*
  16. ==============================================================================
  17. SHAMBLER
  18. ==============================================================================
  19. */
  20. $cd /raid/quake/id1/models/shams
  21. $origin 0 0 24
  22. $base base
  23. $skin base
  24. $frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8 stand9
  25. $frame stand10 stand11 stand12 stand13 stand14 stand15 stand16 stand17
  26. $frame walk1 walk2 walk3 walk4 walk5 walk6 walk7
  27. $frame walk8 walk9 walk10 walk11 walk12
  28. $frame run1 run2 run3 run4 run5 run6
  29. $frame smash1 smash2 smash3 smash4 smash5 smash6 smash7
  30. $frame smash8 smash9 smash10 smash11 smash12
  31. $frame swingr1 swingr2 swingr3 swingr4 swingr5
  32. $frame swingr6 swingr7 swingr8 swingr9
  33. $frame swingl1 swingl2 swingl3 swingl4 swingl5
  34. $frame swingl6 swingl7 swingl8 swingl9
  35. $frame magic1 magic2 magic3 magic4 magic5
  36. $frame magic6 magic7 magic8 magic9 magic10 magic11 magic12
  37. $frame pain1 pain2 pain3 pain4 pain5 pain6
  38. $frame death1 death2 death3 death4 death5 death6
  39. $frame death7 death8 death9 death10 death11
  40. void() sham_stand1 =[ $stand1, sham_stand2 ] {ai_stand();};
  41. void() sham_stand2 =[ $stand2, sham_stand3 ] {ai_stand();};
  42. void() sham_stand3 =[ $stand3, sham_stand4 ] {ai_stand();};
  43. void() sham_stand4 =[ $stand4, sham_stand5 ] {ai_stand();};
  44. void() sham_stand5 =[ $stand5, sham_stand6 ] {ai_stand();};
  45. void() sham_stand6 =[ $stand6, sham_stand7 ] {ai_stand();};
  46. void() sham_stand7 =[ $stand7, sham_stand8 ] {ai_stand();};
  47. void() sham_stand8 =[ $stand8, sham_stand9 ] {ai_stand();};
  48. void() sham_stand9 =[ $stand9, sham_stand10] {ai_stand();};
  49. void() sham_stand10 =[ $stand10, sham_stand11] {ai_stand();};
  50. void() sham_stand11 =[ $stand11, sham_stand12] {ai_stand();};
  51. void() sham_stand12 =[ $stand12, sham_stand13] {ai_stand();};
  52. void() sham_stand13 =[ $stand13, sham_stand14] {ai_stand();};
  53. void() sham_stand14 =[ $stand14, sham_stand15] {ai_stand();};
  54. void() sham_stand15 =[ $stand15, sham_stand16] {ai_stand();};
  55. void() sham_stand16 =[ $stand16, sham_stand17] {ai_stand();};
  56. void() sham_stand17 =[ $stand17, sham_stand1 ] {ai_stand();};
  57. void() sham_walk1 =[ $walk1, sham_walk2 ] {ai_walk(10);};
  58. void() sham_walk2 =[ $walk2, sham_walk3 ] {ai_walk(9);};
  59. void() sham_walk3 =[ $walk3, sham_walk4 ] {ai_walk(9);};
  60. void() sham_walk4 =[ $walk4, sham_walk5 ] {ai_walk(5);};
  61. void() sham_walk5 =[ $walk5, sham_walk6 ] {ai_walk(6);};
  62. void() sham_walk6 =[ $walk6, sham_walk7 ] {ai_walk(12);};
  63. void() sham_walk7 =[ $walk7, sham_walk8 ] {ai_walk(8);};
  64. void() sham_walk8 =[ $walk8, sham_walk9 ] {ai_walk(3);};
  65. void() sham_walk9 =[ $walk9, sham_walk10] {ai_walk(13);};
  66. void() sham_walk10 =[ $walk10, sham_walk11] {ai_walk(9);};
  67. void() sham_walk11 =[ $walk11, sham_walk12] {ai_walk(7);};
  68. void() sham_walk12 =[ $walk12, sham_walk1 ] {ai_walk(7);
  69. if (random() > 0.8)
  70. sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE);};
  71. void() sham_run1 =[ $run1, sham_run2 ] {ai_run(20);};
  72. void() sham_run2 =[ $run2, sham_run3 ] {ai_run(24);};
  73. void() sham_run3 =[ $run3, sham_run4 ] {ai_run(20);};
  74. void() sham_run4 =[ $run4, sham_run5 ] {ai_run(20);};
  75. void() sham_run5 =[ $run5, sham_run6 ] {ai_run(24);};
  76. void() sham_run6 =[ $run6, sham_run1 ] {ai_run(20);
  77. if (random() > 0.8)
  78. sound (self, CHAN_VOICE, "shambler/sidle.wav", 1, ATTN_IDLE);
  79. };
  80. void() sham_smash1 =[ $smash1, sham_smash2 ] {
  81. sound (self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM);
  82. ai_charge(2);};
  83. void() sham_smash2 =[ $smash2, sham_smash3 ] {ai_charge(6);};
  84. void() sham_smash3 =[ $smash3, sham_smash4 ] {ai_charge(6);};
  85. void() sham_smash4 =[ $smash4, sham_smash5 ] {ai_charge(5);};
  86. void() sham_smash5 =[ $smash5, sham_smash6 ] {ai_charge(4);};
  87. void() sham_smash6 =[ $smash6, sham_smash7 ] {ai_charge(1);};
  88. void() sham_smash7 =[ $smash7, sham_smash8 ] {ai_charge(0);};
  89. void() sham_smash8 =[ $smash8, sham_smash9 ] {ai_charge(0);};
  90. void() sham_smash9 =[ $smash9, sham_smash10 ] {ai_charge(0);};
  91. void() sham_smash10 =[ $smash10, sham_smash11 ] {
  92. local vector delta;
  93. local float ldmg;
  94. if (!self.enemy)
  95. return;
  96. ai_charge(0);
  97. delta = self.enemy.origin - self.origin;
  98. if (vlen(delta) > 100)
  99. return;
  100. if (!CanDamage (self.enemy, self))
  101. return;
  102. ldmg = (random() + random() + random()) * 40;
  103. T_Damage (self.enemy, self, self, ldmg);
  104. sound (self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM);
  105. SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right);
  106. SpawnMeatSpray (self.origin + v_forward*16, crandom() * 100 * v_right);
  107. };
  108. void() sham_smash11 =[ $smash11, sham_smash12 ] {ai_charge(5);};
  109. void() sham_smash12 =[ $smash12, sham_run1 ] {ai_charge(4);};
  110. void() sham_swingr1;
  111. void(float side) ShamClaw =
  112. {
  113. local vector delta;
  114. local float ldmg;
  115. if (!self.enemy)
  116. return;
  117. ai_charge(10);
  118. delta = self.enemy.origin - self.origin;
  119. if (vlen(delta) > 100)
  120. return;
  121. ldmg = (random() + random() + random()) * 20;
  122. T_Damage (self.enemy, self, self, ldmg);
  123. sound (self, CHAN_VOICE, "shambler/smack.wav", 1, ATTN_NORM);
  124. if (side)
  125. {
  126. makevectors (self.angles);
  127. SpawnMeatSpray (self.origin + v_forward*16, side * v_right);
  128. }
  129. };
  130. void() sham_swingl1 =[ $swingl1, sham_swingl2 ] {
  131. sound (self, CHAN_VOICE, "shambler/melee2.wav", 1, ATTN_NORM);
  132. ai_charge(5);};
  133. void() sham_swingl2 =[ $swingl2, sham_swingl3 ] {ai_charge(3);};
  134. void() sham_swingl3 =[ $swingl3, sham_swingl4 ] {ai_charge(7);};
  135. void() sham_swingl4 =[ $swingl4, sham_swingl5 ] {ai_charge(3);};
  136. void() sham_swingl5 =[ $swingl5, sham_swingl6 ] {ai_charge(7);};
  137. void() sham_swingl6 =[ $swingl6, sham_swingl7 ] {ai_charge(9);};
  138. void() sham_swingl7 =[ $swingl7, sham_swingl8 ] {ai_charge(5); ShamClaw(250);};
  139. void() sham_swingl8 =[ $swingl8, sham_swingl9 ] {ai_charge(4);};
  140. void() sham_swingl9 =[ $swingl9, sham_run1 ] {
  141. ai_charge(8);
  142. if (random()<0.5)
  143. self.think = sham_swingr1;
  144. };
  145. void() sham_swingr1 =[ $swingr1, sham_swingr2 ] {
  146. sound (self, CHAN_VOICE, "shambler/melee1.wav", 1, ATTN_NORM);
  147. ai_charge(1);};
  148. void() sham_swingr2 =[ $swingr2, sham_swingr3 ] {ai_charge(8);};
  149. void() sham_swingr3 =[ $swingr3, sham_swingr4 ] {ai_charge(14);};
  150. void() sham_swingr4 =[ $swingr4, sham_swingr5 ] {ai_charge(7);};
  151. void() sham_swingr5 =[ $swingr5, sham_swingr6 ] {ai_charge(3);};
  152. void() sham_swingr6 =[ $swingr6, sham_swingr7 ] {ai_charge(6);};
  153. void() sham_swingr7 =[ $swingr7, sham_swingr8 ] {ai_charge(6); ShamClaw(-250);};
  154. void() sham_swingr8 =[ $swingr8, sham_swingr9 ] {ai_charge(3);};
  155. void() sham_swingr9 =[ $swingr9, sham_run1 ] {ai_charge(1);
  156. ai_charge(10);
  157. if (random()<0.5)
  158. self.think = sham_swingl1;
  159. };
  160. void() sham_melee =
  161. {
  162. local float chance;
  163. chance = random();
  164. if (chance > 0.6 || self.health == 600)
  165. sham_smash1 ();
  166. else if (chance > 0.3)
  167. sham_swingr1 ();
  168. else
  169. sham_swingl1 ();
  170. };
  171. //============================================================================
  172. void() CastLightning =
  173. {
  174. local vector org, dir;
  175. self.effects = self.effects | EF_MUZZLEFLASH;
  176. ai_face ();
  177. org = self.origin + '0 0 40';
  178. dir = self.enemy.origin + '0 0 16' - org;
  179. dir = normalize (dir);
  180. traceline (org, self.origin + dir*600, TRUE, self);
  181. WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  182. WriteByte (MSG_BROADCAST, TE_LIGHTNING1);
  183. WriteEntity (MSG_BROADCAST, self);
  184. WriteCoord (MSG_BROADCAST, org_x);
  185. WriteCoord (MSG_BROADCAST, org_y);
  186. WriteCoord (MSG_BROADCAST, org_z);
  187. WriteCoord (MSG_BROADCAST, trace_endpos_x);
  188. WriteCoord (MSG_BROADCAST, trace_endpos_y);
  189. WriteCoord (MSG_BROADCAST, trace_endpos_z);
  190. // overload the frags field which is unused on enemies
  191. self.frags += 1;
  192. LightningDamage (org, trace_endpos, self, 10);
  193. };
  194. void() sham_magic1 =[ $magic1, sham_magic2 ] {ai_face();
  195. sound (self, CHAN_WEAPON, "shambler/sattck1.wav", 1, ATTN_NORM);
  196. };
  197. void() sham_magic2 =[ $magic2, sham_magic3 ] {ai_face();};
  198. void() sham_magic3 =[ $magic3, sham_magic4 ] {ai_face();self.nextthink = self.nextthink + 0.2;
  199. local entity o;
  200. self.effects = self.effects | EF_MUZZLEFLASH;
  201. ai_face();
  202. self.owner = spawn();
  203. o = self.owner;
  204. setmodel (o, "progs/s_light.mdl");
  205. setorigin (o, self.origin);
  206. o.angles = self.angles;
  207. o.nextthink = time + 0.7;
  208. o.think = SUB_Remove;
  209. };
  210. void() sham_magic4 =[ $magic4, sham_magic5 ]
  211. {
  212. self.effects = self.effects | EF_MUZZLEFLASH;
  213. self.owner.frame = 1;
  214. };
  215. void() sham_magic5 =[ $magic5, sham_magic6 ]
  216. {
  217. self.effects = self.effects | EF_MUZZLEFLASH;
  218. self.owner.frame = 2;
  219. };
  220. void() sham_magic6 =[ $magic6, sham_magic9 ]
  221. {
  222. remove (self.owner);
  223. CastLightning();
  224. sound (self, CHAN_WEAPON, "shambler/sboom.wav", 1, ATTN_NORM);
  225. };
  226. void() sham_magic9 =[ $magic9, sham_magic10 ]
  227. {CastLightning();};
  228. void() sham_magic10 =[ $magic10, sham_magic11 ]
  229. {CastLightning();};
  230. void() sham_magic11 =[ $magic11, sham_magic12 ] {};
  231. void() sham_magic12 =[ $magic12, sham_run1 ] {};
  232. void() sham_pain1 =[ $pain1, sham_pain2 ] {};
  233. void() sham_pain2 =[ $pain2, sham_pain3 ] {};
  234. void() sham_pain3 =[ $pain3, sham_pain4 ] {};
  235. void() sham_pain4 =[ $pain4, sham_pain5 ] {};
  236. void() sham_pain5 =[ $pain5, sham_pain6 ] {};
  237. void() sham_pain6 =[ $pain6, sham_run1 ] {};
  238. void(entity attacker, float damage) sham_pain =
  239. {
  240. sound (self, CHAN_VOICE, "shambler/shurt2.wav", 1, ATTN_NORM);
  241. if (damage >= self.health && attacker.classname == "player" && attacker.weapon == IT_AXE)
  242. {
  243. msg_entity = attacker;
  244. WriteByte (MSG_ONE, SVC_ACHIEVEMENT);
  245. WriteString(MSG_ONE, "ACH_CLOSE_SHAVE");
  246. }
  247. // overload frags field for shambler dance achievement
  248. if (damage >= self.health && attacker.classname == "player" && self.frags == 0)
  249. {
  250. msg_entity = attacker;
  251. WriteByte (MSG_ONE, SVC_ACHIEVEMENT);
  252. WriteString(MSG_ONE, "ACH_SHAMBLER_DANCE");
  253. }
  254. if (self.health <= 0)
  255. return; // allready dying, don't go into pain frame
  256. if (random()*400 > damage)
  257. return; // didn't flinch
  258. if (self.pain_finished > time)
  259. return;
  260. self.pain_finished = time + 2;
  261. sham_pain1 ();
  262. };
  263. //============================================================================
  264. void() sham_death1 =[ $death1, sham_death2 ] {};
  265. void() sham_death2 =[ $death2, sham_death3 ] {};
  266. void() sham_death3 =[ $death3, sham_death4 ] {self.solid = SOLID_NOT;};
  267. void() sham_death4 =[ $death4, sham_death5 ] {};
  268. void() sham_death5 =[ $death5, sham_death6 ] {};
  269. void() sham_death6 =[ $death6, sham_death7 ] {};
  270. void() sham_death7 =[ $death7, sham_death8 ] {};
  271. void() sham_death8 =[ $death8, sham_death9 ] {};
  272. void() sham_death9 =[ $death9, sham_death10 ] {};
  273. void() sham_death10 =[ $death10, sham_death11 ] {};
  274. void() sham_death11 =[ $death11, sham_death11 ] {};
  275. void() sham_die =
  276. {
  277. // check for gib
  278. if (self.health < -60)
  279. {
  280. sound (self, CHAN_VOICE, "player/udeath.wav", 1, ATTN_NORM);
  281. ThrowHead ("progs/h_shams.mdl", self.health);
  282. ThrowGib ("progs/gib1.mdl", self.health);
  283. ThrowGib ("progs/gib2.mdl", self.health);
  284. ThrowGib ("progs/gib3.mdl", self.health);
  285. return;
  286. }
  287. // regular death
  288. sound (self, CHAN_VOICE, "shambler/sdeath.wav", 1, ATTN_NORM);
  289. sham_death1 ();
  290. };
  291. //============================================================================
  292. /*QUAKED monster_shambler (1 0 0) (-32 -32 -24) (32 32 64) Ambush
  293. */
  294. void() monster_shambler =
  295. {
  296. if (deathmatch)
  297. {
  298. remove(self);
  299. return;
  300. }
  301. precache_model ("progs/shambler.mdl");
  302. precache_model ("progs/s_light.mdl");
  303. precache_model ("progs/h_shams.mdl");
  304. precache_model ("progs/bolt.mdl");
  305. precache_sound ("shambler/sattck1.wav");
  306. precache_sound ("shambler/sboom.wav");
  307. precache_sound ("shambler/sdeath.wav");
  308. precache_sound ("shambler/shurt2.wav");
  309. precache_sound ("shambler/sidle.wav");
  310. precache_sound ("shambler/ssight.wav");
  311. precache_sound ("shambler/melee1.wav");
  312. precache_sound ("shambler/melee2.wav");
  313. precache_sound ("shambler/smack.wav");
  314. self.solid = SOLID_SLIDEBOX;
  315. self.movetype = MOVETYPE_STEP;
  316. setmodel (self, "progs/shambler.mdl");
  317. setsize (self, VEC_HULL2_MIN, VEC_HULL2_MAX);
  318. self.health = 600;
  319. self.th_stand = sham_stand1;
  320. self.th_walk = sham_walk1;
  321. self.th_run = sham_run1;
  322. self.th_die = sham_die;
  323. self.th_melee = sham_melee;
  324. self.th_missile = sham_magic1;
  325. self.th_pain = sham_pain;
  326. // overload frags for lightning attack counts
  327. self.frags = 0;
  328. walkmonster_start();
  329. };