m_boss32.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. Makron -- Final Boss
  6. ==============================================================================
  7. */
  8. #include "g_local.h"
  9. #include "m_boss32.h"
  10. qboolean visible (edict_t *self, edict_t *other);
  11. void MakronRailgun (edict_t *self);
  12. void MakronSaveloc (edict_t *self);
  13. void MakronHyperblaster (edict_t *self);
  14. void makron_step_left (edict_t *self);
  15. void makron_step_right (edict_t *self);
  16. void makronBFG (edict_t *self);
  17. void makron_dead (edict_t *self);
  18. static int sound_pain4;
  19. static int sound_pain5;
  20. static int sound_pain6;
  21. static int sound_death;
  22. static int sound_step_left;
  23. static int sound_step_right;
  24. static int sound_attack_bfg;
  25. static int sound_brainsplorch;
  26. static int sound_prerailgun;
  27. static int sound_popup;
  28. static int sound_taunt1;
  29. static int sound_taunt2;
  30. static int sound_taunt3;
  31. static int sound_hit;
  32. void makron_taunt (edict_t *self)
  33. {
  34. float r;
  35. r=random();
  36. if (r <= 0.3)
  37. gi.sound (self, CHAN_AUTO, sound_taunt1, 1, ATTN_NONE, 0);
  38. else if (r <= 0.6)
  39. gi.sound (self, CHAN_AUTO, sound_taunt2, 1, ATTN_NONE, 0);
  40. else
  41. gi.sound (self, CHAN_AUTO, sound_taunt3, 1, ATTN_NONE, 0);
  42. }
  43. //
  44. // stand
  45. //
  46. mframe_t makron_frames_stand []=
  47. {
  48. ai_stand, 0, NULL,
  49. ai_stand, 0, NULL,
  50. ai_stand, 0, NULL,
  51. ai_stand, 0, NULL,
  52. ai_stand, 0, NULL,
  53. ai_stand, 0, NULL,
  54. ai_stand, 0, NULL,
  55. ai_stand, 0, NULL,
  56. ai_stand, 0, NULL,
  57. ai_stand, 0, NULL, // 10
  58. ai_stand, 0, NULL,
  59. ai_stand, 0, NULL,
  60. ai_stand, 0, NULL,
  61. ai_stand, 0, NULL,
  62. ai_stand, 0, NULL,
  63. ai_stand, 0, NULL,
  64. ai_stand, 0, NULL,
  65. ai_stand, 0, NULL,
  66. ai_stand, 0, NULL,
  67. ai_stand, 0, NULL, // 20
  68. ai_stand, 0, NULL,
  69. ai_stand, 0, NULL,
  70. ai_stand, 0, NULL,
  71. ai_stand, 0, NULL,
  72. ai_stand, 0, NULL,
  73. ai_stand, 0, NULL,
  74. ai_stand, 0, NULL,
  75. ai_stand, 0, NULL,
  76. ai_stand, 0, NULL,
  77. ai_stand, 0, NULL, // 30
  78. ai_stand, 0, NULL,
  79. ai_stand, 0, NULL,
  80. ai_stand, 0, NULL,
  81. ai_stand, 0, NULL,
  82. ai_stand, 0, NULL,
  83. ai_stand, 0, NULL,
  84. ai_stand, 0, NULL,
  85. ai_stand, 0, NULL,
  86. ai_stand, 0, NULL,
  87. ai_stand, 0, NULL, // 40
  88. ai_stand, 0, NULL,
  89. ai_stand, 0, NULL,
  90. ai_stand, 0, NULL,
  91. ai_stand, 0, NULL,
  92. ai_stand, 0, NULL,
  93. ai_stand, 0, NULL,
  94. ai_stand, 0, NULL,
  95. ai_stand, 0, NULL,
  96. ai_stand, 0, NULL,
  97. ai_stand, 0, NULL, // 50
  98. ai_stand, 0, NULL,
  99. ai_stand, 0, NULL,
  100. ai_stand, 0, NULL,
  101. ai_stand, 0, NULL,
  102. ai_stand, 0, NULL,
  103. ai_stand, 0, NULL,
  104. ai_stand, 0, NULL,
  105. ai_stand, 0, NULL,
  106. ai_stand, 0, NULL,
  107. ai_stand, 0, NULL // 60
  108. };
  109. mmove_t makron_move_stand = {FRAME_stand201, FRAME_stand260, makron_frames_stand, NULL};
  110. void makron_stand (edict_t *self)
  111. {
  112. self->monsterinfo.currentmove = &makron_move_stand;
  113. }
  114. mframe_t makron_frames_run [] =
  115. {
  116. ai_run, 3, makron_step_left,
  117. ai_run, 12, NULL,
  118. ai_run, 8, NULL,
  119. ai_run, 8, NULL,
  120. ai_run, 8, makron_step_right,
  121. ai_run, 6, NULL,
  122. ai_run, 12, NULL,
  123. ai_run, 9, NULL,
  124. ai_run, 6, NULL,
  125. ai_run, 12, NULL
  126. };
  127. mmove_t makron_move_run = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL};
  128. void makron_hit (edict_t *self)
  129. {
  130. gi.sound (self, CHAN_AUTO, sound_hit, 1, ATTN_NONE,0);
  131. }
  132. void makron_popup (edict_t *self)
  133. {
  134. gi.sound (self, CHAN_BODY, sound_popup, 1, ATTN_NONE,0);
  135. }
  136. void makron_step_left (edict_t *self)
  137. {
  138. gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0);
  139. }
  140. void makron_step_right (edict_t *self)
  141. {
  142. gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0);
  143. }
  144. void makron_brainsplorch (edict_t *self)
  145. {
  146. gi.sound (self, CHAN_VOICE, sound_brainsplorch, 1, ATTN_NORM,0);
  147. }
  148. void makron_prerailgun (edict_t *self)
  149. {
  150. gi.sound (self, CHAN_WEAPON, sound_prerailgun, 1, ATTN_NORM,0);
  151. }
  152. mframe_t makron_frames_walk [] =
  153. {
  154. ai_walk, 3, makron_step_left,
  155. ai_walk, 12, NULL,
  156. ai_walk, 8, NULL,
  157. ai_walk, 8, NULL,
  158. ai_walk, 8, makron_step_right,
  159. ai_walk, 6, NULL,
  160. ai_walk, 12, NULL,
  161. ai_walk, 9, NULL,
  162. ai_walk, 6, NULL,
  163. ai_walk, 12, NULL
  164. };
  165. mmove_t makron_move_walk = {FRAME_walk204, FRAME_walk213, makron_frames_run, NULL};
  166. void makron_walk (edict_t *self)
  167. {
  168. self->monsterinfo.currentmove = &makron_move_walk;
  169. }
  170. void makron_run (edict_t *self)
  171. {
  172. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  173. self->monsterinfo.currentmove = &makron_move_stand;
  174. else
  175. self->monsterinfo.currentmove = &makron_move_run;
  176. }
  177. mframe_t makron_frames_pain6 [] =
  178. {
  179. ai_move, 0, NULL,
  180. ai_move, 0, NULL,
  181. ai_move, 0, NULL,
  182. ai_move, 0, NULL,
  183. ai_move, 0, NULL,
  184. ai_move, 0, NULL,
  185. ai_move, 0, NULL,
  186. ai_move, 0, NULL,
  187. ai_move, 0, NULL,
  188. ai_move, 0, NULL, // 10
  189. ai_move, 0, NULL,
  190. ai_move, 0, NULL,
  191. ai_move, 0, NULL,
  192. ai_move, 0, NULL,
  193. ai_move, 0, NULL,
  194. ai_move, 0, makron_popup,
  195. ai_move, 0, NULL,
  196. ai_move, 0, NULL,
  197. ai_move, 0, NULL,
  198. ai_move, 0, NULL, // 20
  199. ai_move, 0, NULL,
  200. ai_move, 0, NULL,
  201. ai_move, 0, NULL,
  202. ai_move, 0, makron_taunt,
  203. ai_move, 0, NULL,
  204. ai_move, 0, NULL,
  205. ai_move, 0, NULL
  206. };
  207. mmove_t makron_move_pain6 = {FRAME_pain601, FRAME_pain627, makron_frames_pain6, makron_run};
  208. mframe_t makron_frames_pain5 [] =
  209. {
  210. ai_move, 0, NULL,
  211. ai_move, 0, NULL,
  212. ai_move, 0, NULL,
  213. ai_move, 0, NULL
  214. };
  215. mmove_t makron_move_pain5 = {FRAME_pain501, FRAME_pain504, makron_frames_pain5, makron_run};
  216. mframe_t makron_frames_pain4 [] =
  217. {
  218. ai_move, 0, NULL,
  219. ai_move, 0, NULL,
  220. ai_move, 0, NULL,
  221. ai_move, 0, NULL
  222. };
  223. mmove_t makron_move_pain4 = {FRAME_pain401, FRAME_pain404, makron_frames_pain4, makron_run};
  224. mframe_t makron_frames_death2 [] =
  225. {
  226. ai_move, -15, NULL,
  227. ai_move, 3, NULL,
  228. ai_move, -12, NULL,
  229. ai_move, 0, makron_step_left,
  230. ai_move, 0, NULL,
  231. ai_move, 0, NULL,
  232. ai_move, 0, NULL,
  233. ai_move, 0, NULL,
  234. ai_move, 0, NULL,
  235. ai_move, 0, NULL, // 10
  236. ai_move, 0, NULL,
  237. ai_move, 0, NULL,
  238. ai_move, 0, NULL,
  239. ai_move, 0, NULL,
  240. ai_move, 0, NULL,
  241. ai_move, 11, NULL,
  242. ai_move, 12, NULL,
  243. ai_move, 11, makron_step_right,
  244. ai_move, 0, NULL,
  245. ai_move, 0, NULL, // 20
  246. ai_move, 0, NULL,
  247. ai_move, 0, NULL,
  248. ai_move, 0, NULL,
  249. ai_move, 0, NULL,
  250. ai_move, 0, NULL,
  251. ai_move, 0, NULL,
  252. ai_move, 0, NULL,
  253. ai_move, 0, NULL,
  254. ai_move, 0, NULL,
  255. ai_move, 0, NULL, // 30
  256. ai_move, 0, NULL,
  257. ai_move, 0, NULL,
  258. ai_move, 0, NULL,
  259. ai_move, 5, NULL,
  260. ai_move, 7, NULL,
  261. ai_move, 6, makron_step_left,
  262. ai_move, 0, NULL,
  263. ai_move, 0, NULL,
  264. ai_move, -1, NULL,
  265. ai_move, 2, NULL, // 40
  266. ai_move, 0, NULL,
  267. ai_move, 0, NULL,
  268. ai_move, 0, NULL,
  269. ai_move, 0, NULL,
  270. ai_move, 0, NULL,
  271. ai_move, 0, NULL,
  272. ai_move, 0, NULL,
  273. ai_move, 0, NULL,
  274. ai_move, 0, NULL,
  275. ai_move, 0, NULL, // 50
  276. ai_move, 0, NULL,
  277. ai_move, 0, NULL,
  278. ai_move, 0, NULL,
  279. ai_move, -6, NULL,
  280. ai_move, -4, NULL,
  281. ai_move, -6, makron_step_right,
  282. ai_move, -4, NULL,
  283. ai_move, -4, makron_step_left,
  284. ai_move, 0, NULL,
  285. ai_move, 0, NULL, // 60
  286. ai_move, 0, NULL,
  287. ai_move, 0, NULL,
  288. ai_move, -2, NULL,
  289. ai_move, -5, NULL,
  290. ai_move, -3, makron_step_right,
  291. ai_move, -8, NULL,
  292. ai_move, -3, makron_step_left,
  293. ai_move, -7, NULL,
  294. ai_move, -4, NULL,
  295. ai_move, -4, makron_step_right, // 70
  296. ai_move, -6, NULL,
  297. ai_move, -7, NULL,
  298. ai_move, 0, makron_step_left,
  299. ai_move, 0, NULL,
  300. ai_move, 0, NULL,
  301. ai_move, 0, NULL,
  302. ai_move, 0, NULL,
  303. ai_move, 0, NULL,
  304. ai_move, 0, NULL,
  305. ai_move, 0, NULL, // 80
  306. ai_move, 0, NULL,
  307. ai_move, 0, NULL,
  308. ai_move, 0, NULL,
  309. ai_move, 0, NULL,
  310. ai_move, 0, NULL,
  311. ai_move, -2, NULL,
  312. ai_move, 0, NULL,
  313. ai_move, 0, NULL,
  314. ai_move, 2, NULL,
  315. ai_move, 0, NULL, // 90
  316. ai_move, 27, makron_hit,
  317. ai_move, 26, NULL,
  318. ai_move, 0, makron_brainsplorch,
  319. ai_move, 0, NULL,
  320. ai_move, 0, NULL // 95
  321. };
  322. mmove_t makron_move_death2 = {FRAME_death201, FRAME_death295, makron_frames_death2, makron_dead};
  323. mframe_t makron_frames_death3 [] =
  324. {
  325. ai_move, 0, NULL,
  326. ai_move, 0, NULL,
  327. ai_move, 0, NULL,
  328. ai_move, 0, NULL,
  329. ai_move, 0, NULL,
  330. ai_move, 0, NULL,
  331. ai_move, 0, NULL,
  332. ai_move, 0, NULL,
  333. ai_move, 0, NULL,
  334. ai_move, 0, NULL,
  335. ai_move, 0, NULL,
  336. ai_move, 0, NULL,
  337. ai_move, 0, NULL,
  338. ai_move, 0, NULL,
  339. ai_move, 0, NULL,
  340. ai_move, 0, NULL,
  341. ai_move, 0, NULL,
  342. ai_move, 0, NULL,
  343. ai_move, 0, NULL,
  344. ai_move, 0, NULL
  345. };
  346. mmove_t makron_move_death3 = {FRAME_death301, FRAME_death320, makron_frames_death3, NULL};
  347. mframe_t makron_frames_sight [] =
  348. {
  349. ai_move, 0, NULL,
  350. ai_move, 0, NULL,
  351. ai_move, 0, NULL,
  352. ai_move, 0, NULL,
  353. ai_move, 0, NULL,
  354. ai_move, 0, NULL,
  355. ai_move, 0, NULL,
  356. ai_move, 0, NULL,
  357. ai_move, 0, NULL,
  358. ai_move, 0, NULL,
  359. ai_move, 0, NULL,
  360. ai_move, 0, NULL,
  361. ai_move, 0, NULL
  362. };
  363. mmove_t makron_move_sight= {FRAME_active01, FRAME_active13, makron_frames_sight, makron_run};
  364. void makronBFG (edict_t *self)
  365. {
  366. vec3_t forward, right;
  367. vec3_t start;
  368. vec3_t dir;
  369. vec3_t vec;
  370. AngleVectors (self->s.angles, forward, right, NULL);
  371. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_BFG], forward, right, start);
  372. VectorCopy (self->enemy->s.origin, vec);
  373. vec[2] += self->enemy->viewheight;
  374. VectorSubtract (vec, start, dir);
  375. VectorNormalize (dir);
  376. gi.sound (self, CHAN_VOICE, sound_attack_bfg, 1, ATTN_NORM, 0);
  377. monster_fire_bfg (self, start, dir, 50, 300, 100, 300, MZ2_MAKRON_BFG);
  378. }
  379. mframe_t makron_frames_attack3 []=
  380. {
  381. ai_charge, 0, NULL,
  382. ai_charge, 0, NULL,
  383. ai_charge, 0, NULL,
  384. ai_charge, 0, makronBFG, // FIXME: BFG Attack here
  385. ai_move, 0, NULL,
  386. ai_move, 0, NULL,
  387. ai_move, 0, NULL,
  388. ai_move, 0, NULL
  389. };
  390. mmove_t makron_move_attack3 = {FRAME_attak301, FRAME_attak308, makron_frames_attack3, makron_run};
  391. mframe_t makron_frames_attack4[]=
  392. {
  393. ai_charge, 0, NULL,
  394. ai_charge, 0, NULL,
  395. ai_charge, 0, NULL,
  396. ai_charge, 0, NULL,
  397. ai_move, 0, MakronHyperblaster, // fire
  398. ai_move, 0, MakronHyperblaster, // fire
  399. ai_move, 0, MakronHyperblaster, // fire
  400. ai_move, 0, MakronHyperblaster, // fire
  401. ai_move, 0, MakronHyperblaster, // fire
  402. ai_move, 0, MakronHyperblaster, // fire
  403. ai_move, 0, MakronHyperblaster, // fire
  404. ai_move, 0, MakronHyperblaster, // fire
  405. ai_move, 0, MakronHyperblaster, // fire
  406. ai_move, 0, MakronHyperblaster, // fire
  407. ai_move, 0, MakronHyperblaster, // fire
  408. ai_move, 0, MakronHyperblaster, // fire
  409. ai_move, 0, MakronHyperblaster, // fire
  410. ai_move, 0, MakronHyperblaster, // fire
  411. ai_move, 0, MakronHyperblaster, // fire
  412. ai_move, 0, MakronHyperblaster, // fire
  413. ai_move, 0, MakronHyperblaster, // fire
  414. ai_move, 0, NULL,
  415. ai_move, 0, NULL,
  416. ai_move, 0, NULL,
  417. ai_move, 0, NULL,
  418. ai_move, 0, NULL
  419. };
  420. mmove_t makron_move_attack4 = {FRAME_attak401, FRAME_attak426, makron_frames_attack4, makron_run};
  421. mframe_t makron_frames_attack5[]=
  422. {
  423. ai_charge, 0, makron_prerailgun,
  424. ai_charge, 0, NULL,
  425. ai_charge, 0, NULL,
  426. ai_charge, 0, NULL,
  427. ai_charge, 0, NULL,
  428. ai_charge, 0, NULL,
  429. ai_charge, 0, NULL,
  430. ai_charge, 0, MakronSaveloc,
  431. ai_move, 0, MakronRailgun, // Fire railgun
  432. ai_move, 0, NULL,
  433. ai_move, 0, NULL,
  434. ai_move, 0, NULL,
  435. ai_move, 0, NULL,
  436. ai_move, 0, NULL,
  437. ai_move, 0, NULL,
  438. ai_move, 0, NULL
  439. };
  440. mmove_t makron_move_attack5 = {FRAME_attak501, FRAME_attak516, makron_frames_attack5, makron_run};
  441. void MakronSaveloc (edict_t *self)
  442. {
  443. VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot
  444. self->pos1[2] += self->enemy->viewheight;
  445. };
  446. // FIXME: He's not firing from the proper Z
  447. void MakronRailgun (edict_t *self)
  448. {
  449. vec3_t start;
  450. vec3_t dir;
  451. vec3_t forward, right;
  452. AngleVectors (self->s.angles, forward, right, NULL);
  453. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_MAKRON_RAILGUN_1], forward, right, start);
  454. // calc direction to where we targted
  455. VectorSubtract (self->pos1, start, dir);
  456. VectorNormalize (dir);
  457. monster_fire_railgun (self, start, dir, 50, 100, MZ2_MAKRON_RAILGUN_1);
  458. }
  459. // FIXME: This is all wrong. He's not firing at the proper angles.
  460. void MakronHyperblaster (edict_t *self)
  461. {
  462. vec3_t dir;
  463. vec3_t vec;
  464. vec3_t start;
  465. vec3_t forward, right;
  466. int flash_number;
  467. flash_number = MZ2_MAKRON_BLASTER_1 + (self->s.frame - FRAME_attak405);
  468. AngleVectors (self->s.angles, forward, right, NULL);
  469. G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  470. if (self->enemy)
  471. {
  472. VectorCopy (self->enemy->s.origin, vec);
  473. vec[2] += self->enemy->viewheight;
  474. VectorSubtract (vec, start, vec);
  475. vectoangles (vec, vec);
  476. dir[0] = vec[0];
  477. }
  478. else
  479. {
  480. dir[0] = 0;
  481. }
  482. if (self->s.frame <= FRAME_attak413)
  483. dir[1] = self->s.angles[1] - 10 * (self->s.frame - FRAME_attak413);
  484. else
  485. dir[1] = self->s.angles[1] + 10 * (self->s.frame - FRAME_attak421);
  486. dir[2] = 0;
  487. AngleVectors (dir, forward, NULL, NULL);
  488. monster_fire_blaster (self, start, forward, 15, 1000, MZ2_MAKRON_BLASTER_1, EF_BLASTER);
  489. }
  490. void makron_pain (edict_t *self, edict_t *other, float kick, int damage)
  491. {
  492. if (self->health < (self->max_health / 2))
  493. self->s.skinnum = 1;
  494. if (level.time < self->pain_debounce_time)
  495. return;
  496. // Lessen the chance of him going into his pain frames
  497. if (damage <=25)
  498. if (random()<0.2)
  499. return;
  500. self->pain_debounce_time = level.time + 3;
  501. if (skill->value == 3)
  502. return; // no pain anims in nightmare
  503. if (damage <= 40)
  504. {
  505. gi.sound (self, CHAN_VOICE, sound_pain4, 1, ATTN_NONE,0);
  506. self->monsterinfo.currentmove = &makron_move_pain4;
  507. }
  508. else if (damage <= 110)
  509. {
  510. gi.sound (self, CHAN_VOICE, sound_pain5, 1, ATTN_NONE,0);
  511. self->monsterinfo.currentmove = &makron_move_pain5;
  512. }
  513. else
  514. {
  515. if (damage <= 150)
  516. if (random() <= 0.45)
  517. {
  518. gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0);
  519. self->monsterinfo.currentmove = &makron_move_pain6;
  520. }
  521. else
  522. if (random() <= 0.35)
  523. {
  524. gi.sound (self, CHAN_VOICE, sound_pain6, 1, ATTN_NONE,0);
  525. self->monsterinfo.currentmove = &makron_move_pain6;
  526. }
  527. }
  528. };
  529. void makron_sight(edict_t *self, edict_t *other)
  530. {
  531. self->monsterinfo.currentmove = &makron_move_sight;
  532. };
  533. void makron_attack(edict_t *self)
  534. {
  535. vec3_t vec;
  536. float range;
  537. float r;
  538. r = random();
  539. VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  540. range = VectorLength (vec);
  541. if (r <= 0.3)
  542. self->monsterinfo.currentmove = &makron_move_attack3;
  543. else if (r <= 0.6)
  544. self->monsterinfo.currentmove = &makron_move_attack4;
  545. else
  546. self->monsterinfo.currentmove = &makron_move_attack5;
  547. }
  548. /*
  549. ---
  550. Makron Torso. This needs to be spawned in
  551. ---
  552. */
  553. void makron_torso_think (edict_t *self)
  554. {
  555. if (++self->s.frame < 365)
  556. self->nextthink = level.time + FRAMETIME;
  557. else
  558. {
  559. self->s.frame = 346;
  560. self->nextthink = level.time + FRAMETIME;
  561. }
  562. }
  563. void makron_torso (edict_t *ent)
  564. {
  565. ent->movetype = MOVETYPE_NONE;
  566. ent->solid = SOLID_NOT;
  567. VectorSet (ent->mins, -8, -8, 0);
  568. VectorSet (ent->maxs, 8, 8, 8);
  569. ent->s.frame = 346;
  570. ent->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  571. ent->think = makron_torso_think;
  572. ent->nextthink = level.time + 2 * FRAMETIME;
  573. ent->s.sound = gi.soundindex ("makron/spine.wav");
  574. gi.linkentity (ent);
  575. }
  576. //
  577. // death
  578. //
  579. void makron_dead (edict_t *self)
  580. {
  581. VectorSet (self->mins, -60, -60, 0);
  582. VectorSet (self->maxs, 60, 60, 72);
  583. self->movetype = MOVETYPE_TOSS;
  584. self->svflags |= SVF_DEADMONSTER;
  585. self->nextthink = 0;
  586. gi.linkentity (self);
  587. }
  588. void makron_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  589. {
  590. edict_t *tempent;
  591. int n;
  592. self->s.sound = 0;
  593. // check for gib
  594. if (self->health <= self->gib_health)
  595. {
  596. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  597. for (n= 0; n < 1 /*4*/; n++)
  598. ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  599. for (n= 0; n < 4; n++)
  600. ThrowGib (self, "models/objects/gibs/sm_metal/tris.md2", damage, GIB_METALLIC);
  601. ThrowHead (self, "models/objects/gibs/gear/tris.md2", damage, GIB_METALLIC);
  602. self->deadflag = DEAD_DEAD;
  603. return;
  604. }
  605. if (self->deadflag == DEAD_DEAD)
  606. return;
  607. // regular death
  608. gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NONE, 0);
  609. self->deadflag = DEAD_DEAD;
  610. self->takedamage = DAMAGE_YES;
  611. tempent = G_Spawn();
  612. VectorCopy (self->s.origin, tempent->s.origin);
  613. VectorCopy (self->s.angles, tempent->s.angles);
  614. tempent->s.origin[1] -= 84;
  615. makron_torso (tempent);
  616. self->monsterinfo.currentmove = &makron_move_death2;
  617. }
  618. qboolean Makron_CheckAttack (edict_t *self)
  619. {
  620. vec3_t spot1, spot2;
  621. vec3_t temp;
  622. float chance;
  623. trace_t tr;
  624. qboolean enemy_infront;
  625. int enemy_range;
  626. float enemy_yaw;
  627. if (self->enemy->health > 0)
  628. {
  629. // see if any entities are in the way of the shot
  630. VectorCopy (self->s.origin, spot1);
  631. spot1[2] += self->viewheight;
  632. VectorCopy (self->enemy->s.origin, spot2);
  633. spot2[2] += self->enemy->viewheight;
  634. tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
  635. // do we have a clear shot?
  636. if (tr.ent != self->enemy)
  637. return false;
  638. }
  639. enemy_infront = infront(self, self->enemy);
  640. enemy_range = range(self, self->enemy);
  641. VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
  642. enemy_yaw = vectoyaw(temp);
  643. self->ideal_yaw = enemy_yaw;
  644. // melee attack
  645. if (enemy_range == RANGE_MELEE)
  646. {
  647. if (self->monsterinfo.melee)
  648. self->monsterinfo.attack_state = AS_MELEE;
  649. else
  650. self->monsterinfo.attack_state = AS_MISSILE;
  651. return true;
  652. }
  653. // missile attack
  654. if (!self->monsterinfo.attack)
  655. return false;
  656. if (level.time < self->monsterinfo.attack_finished)
  657. return false;
  658. if (enemy_range == RANGE_FAR)
  659. return false;
  660. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  661. {
  662. chance = 0.4;
  663. }
  664. else if (enemy_range == RANGE_MELEE)
  665. {
  666. chance = 0.8;
  667. }
  668. else if (enemy_range == RANGE_NEAR)
  669. {
  670. chance = 0.4;
  671. }
  672. else if (enemy_range == RANGE_MID)
  673. {
  674. chance = 0.2;
  675. }
  676. else
  677. {
  678. return false;
  679. }
  680. if (random () < chance)
  681. {
  682. self->monsterinfo.attack_state = AS_MISSILE;
  683. self->monsterinfo.attack_finished = level.time + 2*random();
  684. return true;
  685. }
  686. if (self->flags & FL_FLY)
  687. {
  688. if (random() < 0.3)
  689. self->monsterinfo.attack_state = AS_SLIDING;
  690. else
  691. self->monsterinfo.attack_state = AS_STRAIGHT;
  692. }
  693. return false;
  694. }
  695. //
  696. // monster_makron
  697. //
  698. void MakronPrecache (void)
  699. {
  700. sound_pain4 = gi.soundindex ("makron/pain3.wav");
  701. sound_pain5 = gi.soundindex ("makron/pain2.wav");
  702. sound_pain6 = gi.soundindex ("makron/pain1.wav");
  703. sound_death = gi.soundindex ("makron/death.wav");
  704. sound_step_left = gi.soundindex ("makron/step1.wav");
  705. sound_step_right = gi.soundindex ("makron/step2.wav");
  706. sound_attack_bfg = gi.soundindex ("makron/bfg_fire.wav");
  707. sound_brainsplorch = gi.soundindex ("makron/brain1.wav");
  708. sound_prerailgun = gi.soundindex ("makron/rail_up.wav");
  709. sound_popup = gi.soundindex ("makron/popup.wav");
  710. sound_taunt1 = gi.soundindex ("makron/voice4.wav");
  711. sound_taunt2 = gi.soundindex ("makron/voice3.wav");
  712. sound_taunt3 = gi.soundindex ("makron/voice.wav");
  713. sound_hit = gi.soundindex ("makron/bhit.wav");
  714. gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  715. }
  716. /*QUAKED monster_makron (1 .5 0) (-30 -30 0) (30 30 90) Ambush Trigger_Spawn Sight
  717. */
  718. void SP_monster_makron (edict_t *self)
  719. {
  720. if (deathmatch->value)
  721. {
  722. G_FreeEdict (self);
  723. return;
  724. }
  725. MakronPrecache ();
  726. self->movetype = MOVETYPE_STEP;
  727. self->solid = SOLID_BBOX;
  728. self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  729. VectorSet (self->mins, -30, -30, 0);
  730. VectorSet (self->maxs, 30, 30, 90);
  731. self->health = 3000;
  732. self->gib_health = -2000;
  733. self->mass = 500;
  734. self->pain = makron_pain;
  735. self->die = makron_die;
  736. self->monsterinfo.stand = makron_stand;
  737. self->monsterinfo.walk = makron_walk;
  738. self->monsterinfo.run = makron_run;
  739. self->monsterinfo.dodge = NULL;
  740. self->monsterinfo.attack = makron_attack;
  741. self->monsterinfo.melee = NULL;
  742. self->monsterinfo.sight = makron_sight;
  743. self->monsterinfo.checkattack = Makron_CheckAttack;
  744. gi.linkentity (self);
  745. // self->monsterinfo.currentmove = &makron_move_stand;
  746. self->monsterinfo.currentmove = &makron_move_sight;
  747. self->monsterinfo.scale = MODEL_SCALE;
  748. walkmonster_start(self);
  749. //PMM
  750. self->monsterinfo.aiflags |= AI_IGNORE_SHOTS;
  751. //pmm
  752. }
  753. /*
  754. =================
  755. MakronSpawn
  756. =================
  757. */
  758. void MakronSpawn (edict_t *self)
  759. {
  760. vec3_t vec;
  761. edict_t *player;
  762. SP_monster_makron (self);
  763. // jump at player
  764. player = level.sight_client;
  765. if (!player)
  766. return;
  767. VectorSubtract (player->s.origin, self->s.origin, vec);
  768. self->s.angles[YAW] = vectoyaw(vec);
  769. VectorNormalize (vec);
  770. VectorMA (vec3_origin, 400, vec, self->velocity);
  771. self->velocity[2] = 200;
  772. self->groundentity = NULL;
  773. }
  774. /*
  775. =================
  776. MakronToss
  777. Jorg is just about dead, so set up to launch Makron out
  778. =================
  779. */
  780. void MakronToss (edict_t *self)
  781. {
  782. edict_t *ent;
  783. ent = G_Spawn ();
  784. ent->nextthink = level.time + 0.8;
  785. ent->think = MakronSpawn;
  786. ent->target = self->target;
  787. VectorCopy (self->s.origin, ent->s.origin);
  788. }