m_boss31.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. jorg
  6. ==============================================================================
  7. */
  8. #include "g_local.h"
  9. #include "m_boss31.h"
  10. extern SP_monster_makron (edict_t *self);
  11. qboolean visible (edict_t *self, edict_t *other);
  12. static int sound_pain1;
  13. static int sound_pain2;
  14. static int sound_pain3;
  15. static int sound_idle;
  16. static int sound_death;
  17. static int sound_search1;
  18. static int sound_search2;
  19. static int sound_search3;
  20. static int sound_attack1;
  21. static int sound_attack2;
  22. static int sound_firegun;
  23. static int sound_step_left;
  24. static int sound_step_right;
  25. static int sound_death_hit;
  26. void BossExplode (edict_t *self);
  27. void MakronToss (edict_t *self);
  28. void jorg_search (edict_t *self)
  29. {
  30. float r;
  31. r = random();
  32. if (r <= 0.3)
  33. gi.sound (self, CHAN_VOICE, sound_search1, 1, ATTN_NORM, 0);
  34. else if (r <= 0.6)
  35. gi.sound (self, CHAN_VOICE, sound_search2, 1, ATTN_NORM, 0);
  36. else
  37. gi.sound (self, CHAN_VOICE, sound_search3, 1, ATTN_NORM, 0);
  38. }
  39. void jorg_dead (edict_t *self);
  40. void jorgBFG (edict_t *self);
  41. void jorgMachineGun (edict_t *self);
  42. void jorg_firebullet (edict_t *self);
  43. void jorg_reattack1(edict_t *self);
  44. void jorg_attack1(edict_t *self);
  45. void jorg_idle(edict_t *self);
  46. void jorg_step_left(edict_t *self);
  47. void jorg_step_right(edict_t *self);
  48. void jorg_death_hit(edict_t *self);
  49. //
  50. // stand
  51. //
  52. mframe_t jorg_frames_stand []=
  53. {
  54. ai_stand, 0, jorg_idle,
  55. ai_stand, 0, NULL,
  56. ai_stand, 0, NULL,
  57. ai_stand, 0, NULL,
  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, // 10
  64. ai_stand, 0, NULL,
  65. ai_stand, 0, NULL,
  66. ai_stand, 0, NULL,
  67. ai_stand, 0, NULL,
  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, // 20
  74. ai_stand, 0, NULL,
  75. ai_stand, 0, NULL,
  76. ai_stand, 0, NULL,
  77. ai_stand, 0, NULL,
  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, // 30
  84. ai_stand, 0, NULL,
  85. ai_stand, 0, NULL,
  86. ai_stand, 0, NULL,
  87. ai_stand, 19, NULL,
  88. ai_stand, 11, jorg_step_left,
  89. ai_stand, 0, NULL,
  90. ai_stand, 0, NULL,
  91. ai_stand, 6, NULL,
  92. ai_stand, 9, jorg_step_right,
  93. ai_stand, 0, NULL, // 40
  94. ai_stand, 0, NULL,
  95. ai_stand, 0, NULL,
  96. ai_stand, 0, NULL,
  97. ai_stand, 0, NULL,
  98. ai_stand, 0, NULL,
  99. ai_stand, 0, NULL,
  100. ai_stand, -2, NULL,
  101. ai_stand, -17, jorg_step_left,
  102. ai_stand, 0, NULL,
  103. ai_stand, -12, NULL, // 50
  104. ai_stand, -14, jorg_step_right // 51
  105. };
  106. mmove_t jorg_move_stand = {FRAME_stand01, FRAME_stand51, jorg_frames_stand, NULL};
  107. void jorg_idle (edict_t *self)
  108. {
  109. gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_NORM,0);
  110. }
  111. void jorg_death_hit (edict_t *self)
  112. {
  113. gi.sound (self, CHAN_BODY, sound_death_hit, 1, ATTN_NORM,0);
  114. }
  115. void jorg_step_left (edict_t *self)
  116. {
  117. gi.sound (self, CHAN_BODY, sound_step_left, 1, ATTN_NORM,0);
  118. }
  119. void jorg_step_right (edict_t *self)
  120. {
  121. gi.sound (self, CHAN_BODY, sound_step_right, 1, ATTN_NORM,0);
  122. }
  123. void jorg_stand (edict_t *self)
  124. {
  125. self->monsterinfo.currentmove = &jorg_move_stand;
  126. }
  127. mframe_t jorg_frames_run [] =
  128. {
  129. ai_run, 17, jorg_step_left,
  130. ai_run, 0, NULL,
  131. ai_run, 0, NULL,
  132. ai_run, 0, NULL,
  133. ai_run, 12, NULL,
  134. ai_run, 8, NULL,
  135. ai_run, 10, NULL,
  136. ai_run, 33, jorg_step_right,
  137. ai_run, 0, NULL,
  138. ai_run, 0, NULL,
  139. ai_run, 0, NULL,
  140. ai_run, 9, NULL,
  141. ai_run, 9, NULL,
  142. ai_run, 9, NULL
  143. };
  144. mmove_t jorg_move_run = {FRAME_walk06, FRAME_walk19, jorg_frames_run, NULL};
  145. //
  146. // walk
  147. //
  148. mframe_t jorg_frames_start_walk [] =
  149. {
  150. ai_walk, 5, NULL,
  151. ai_walk, 6, NULL,
  152. ai_walk, 7, NULL,
  153. ai_walk, 9, NULL,
  154. ai_walk, 15, NULL
  155. };
  156. mmove_t jorg_move_start_walk = {FRAME_walk01, FRAME_walk05, jorg_frames_start_walk, NULL};
  157. mframe_t jorg_frames_walk [] =
  158. {
  159. ai_walk, 17, NULL,
  160. ai_walk, 0, NULL,
  161. ai_walk, 0, NULL,
  162. ai_walk, 0, NULL,
  163. ai_walk, 12, NULL,
  164. ai_walk, 8, NULL,
  165. ai_walk, 10, NULL,
  166. ai_walk, 33, NULL,
  167. ai_walk, 0, NULL,
  168. ai_walk, 0, NULL,
  169. ai_walk, 0, NULL,
  170. ai_walk, 9, NULL,
  171. ai_walk, 9, NULL,
  172. ai_walk, 9, NULL
  173. };
  174. mmove_t jorg_move_walk = {FRAME_walk06, FRAME_walk19, jorg_frames_walk, NULL};
  175. mframe_t jorg_frames_end_walk [] =
  176. {
  177. ai_walk, 11, NULL,
  178. ai_walk, 0, NULL,
  179. ai_walk, 0, NULL,
  180. ai_walk, 0, NULL,
  181. ai_walk, 8, NULL,
  182. ai_walk, -8, NULL
  183. };
  184. mmove_t jorg_move_end_walk = {FRAME_walk20, FRAME_walk25, jorg_frames_end_walk, NULL};
  185. void jorg_walk (edict_t *self)
  186. {
  187. self->monsterinfo.currentmove = &jorg_move_walk;
  188. }
  189. void jorg_run (edict_t *self)
  190. {
  191. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  192. self->monsterinfo.currentmove = &jorg_move_stand;
  193. else
  194. self->monsterinfo.currentmove = &jorg_move_run;
  195. }
  196. mframe_t jorg_frames_pain3 [] =
  197. {
  198. ai_move, -28, NULL,
  199. ai_move, -6, NULL,
  200. ai_move, -3, jorg_step_left,
  201. ai_move, -9, NULL,
  202. ai_move, 0, jorg_step_right,
  203. ai_move, 0, NULL,
  204. ai_move, 0, NULL,
  205. ai_move, 0, NULL,
  206. ai_move, -7, NULL,
  207. ai_move, 1, NULL,
  208. ai_move, -11, NULL,
  209. ai_move, -4, NULL,
  210. ai_move, 0, NULL,
  211. ai_move, 0, NULL,
  212. ai_move, 10, NULL,
  213. ai_move, 11, NULL,
  214. ai_move, 0, NULL,
  215. ai_move, 10, NULL,
  216. ai_move, 3, NULL,
  217. ai_move, 10, NULL,
  218. ai_move, 7, jorg_step_left,
  219. ai_move, 17, NULL,
  220. ai_move, 0, NULL,
  221. ai_move, 0, NULL,
  222. ai_move, 0, jorg_step_right
  223. };
  224. mmove_t jorg_move_pain3 = {FRAME_pain301, FRAME_pain325, jorg_frames_pain3, jorg_run};
  225. mframe_t jorg_frames_pain2 [] =
  226. {
  227. ai_move, 0, NULL,
  228. ai_move, 0, NULL,
  229. ai_move, 0, NULL
  230. };
  231. mmove_t jorg_move_pain2 = {FRAME_pain201, FRAME_pain203, jorg_frames_pain2, jorg_run};
  232. mframe_t jorg_frames_pain1 [] =
  233. {
  234. ai_move, 0, NULL,
  235. ai_move, 0, NULL,
  236. ai_move, 0, NULL
  237. };
  238. mmove_t jorg_move_pain1 = {FRAME_pain101, FRAME_pain103, jorg_frames_pain1, jorg_run};
  239. mframe_t jorg_frames_death1 [] =
  240. {
  241. ai_move, 0, NULL,
  242. ai_move, 0, NULL,
  243. ai_move, 0, NULL,
  244. ai_move, 0, NULL,
  245. ai_move, 0, NULL,
  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, // 10
  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,
  256. ai_move, 0, NULL,
  257. ai_move, 0, NULL,
  258. ai_move, 0, NULL,
  259. ai_move, 0, NULL,
  260. ai_move, 0, NULL, // 20
  261. ai_move, 0, NULL,
  262. ai_move, 0, NULL,
  263. ai_move, 0, NULL,
  264. ai_move, 0, NULL,
  265. ai_move, 0, NULL,
  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, // 30
  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,
  276. ai_move, 0, NULL,
  277. ai_move, 0, NULL,
  278. ai_move, 0, NULL,
  279. ai_move, 0, NULL,
  280. ai_move, 0, NULL, // 40
  281. ai_move, 0, NULL,
  282. ai_move, 0, NULL,
  283. ai_move, 0, NULL,
  284. ai_move, 0, NULL,
  285. ai_move, 0, NULL,
  286. ai_move, 0, NULL,
  287. ai_move, 0, NULL,
  288. ai_move, 0, NULL,
  289. ai_move, 0, MakronToss,
  290. ai_move, 0, BossExplode // 50
  291. };
  292. mmove_t jorg_move_death = {FRAME_death01, FRAME_death50, jorg_frames_death1, jorg_dead};
  293. mframe_t jorg_frames_attack2 []=
  294. {
  295. ai_charge, 0, NULL,
  296. ai_charge, 0, NULL,
  297. ai_charge, 0, NULL,
  298. ai_charge, 0, NULL,
  299. ai_charge, 0, NULL,
  300. ai_charge, 0, NULL,
  301. ai_charge, 0, jorgBFG,
  302. ai_move, 0, NULL,
  303. ai_move, 0, NULL,
  304. ai_move, 0, NULL,
  305. ai_move, 0, NULL,
  306. ai_move, 0, NULL,
  307. ai_move, 0, NULL
  308. };
  309. mmove_t jorg_move_attack2 = {FRAME_attak201, FRAME_attak213, jorg_frames_attack2, jorg_run};
  310. mframe_t jorg_frames_start_attack1 [] =
  311. {
  312. ai_charge, 0, NULL,
  313. ai_charge, 0, NULL,
  314. ai_charge, 0, NULL,
  315. ai_charge, 0, NULL,
  316. ai_charge, 0, NULL,
  317. ai_charge, 0, NULL,
  318. ai_charge, 0, NULL,
  319. ai_charge, 0, NULL
  320. };
  321. mmove_t jorg_move_start_attack1 = {FRAME_attak101, FRAME_attak108, jorg_frames_start_attack1, jorg_attack1};
  322. mframe_t jorg_frames_attack1[]=
  323. {
  324. ai_charge, 0, jorg_firebullet,
  325. ai_charge, 0, jorg_firebullet,
  326. ai_charge, 0, jorg_firebullet,
  327. ai_charge, 0, jorg_firebullet,
  328. ai_charge, 0, jorg_firebullet,
  329. ai_charge, 0, jorg_firebullet
  330. };
  331. mmove_t jorg_move_attack1 = {FRAME_attak109, FRAME_attak114, jorg_frames_attack1, jorg_reattack1};
  332. mframe_t jorg_frames_end_attack1[]=
  333. {
  334. ai_move, 0, NULL,
  335. ai_move, 0, NULL,
  336. ai_move, 0, NULL,
  337. ai_move, 0, NULL
  338. };
  339. mmove_t jorg_move_end_attack1 = {FRAME_attak115, FRAME_attak118, jorg_frames_end_attack1, jorg_run};
  340. void jorg_reattack1(edict_t *self)
  341. {
  342. if (visible(self, self->enemy))
  343. if (random() < 0.9)
  344. self->monsterinfo.currentmove = &jorg_move_attack1;
  345. else
  346. {
  347. self->s.sound = 0;
  348. self->monsterinfo.currentmove = &jorg_move_end_attack1;
  349. }
  350. else
  351. {
  352. self->s.sound = 0;
  353. self->monsterinfo.currentmove = &jorg_move_end_attack1;
  354. }
  355. }
  356. void jorg_attack1(edict_t *self)
  357. {
  358. self->monsterinfo.currentmove = &jorg_move_attack1;
  359. }
  360. void jorg_pain (edict_t *self, edict_t *other, float kick, int damage)
  361. {
  362. if (self->health < (self->max_health / 2))
  363. self->s.skinnum = 1;
  364. self->s.sound = 0;
  365. if (level.time < self->pain_debounce_time)
  366. return;
  367. // Lessen the chance of him going into his pain frames if he takes little damage
  368. if (damage <= 40)
  369. if (random()<=0.6)
  370. return;
  371. /*
  372. If he's entering his attack1 or using attack1, lessen the chance of him
  373. going into pain
  374. */
  375. if ( (self->s.frame >= FRAME_attak101) && (self->s.frame <= FRAME_attak108) )
  376. if (random() <= 0.005)
  377. return;
  378. if ( (self->s.frame >= FRAME_attak109) && (self->s.frame <= FRAME_attak114) )
  379. if (random() <= 0.00005)
  380. return;
  381. if ( (self->s.frame >= FRAME_attak201) && (self->s.frame <= FRAME_attak208) )
  382. if (random() <= 0.005)
  383. return;
  384. self->pain_debounce_time = level.time + 3;
  385. if (skill->value == 3)
  386. return; // no pain anims in nightmare
  387. if (damage <= 50)
  388. {
  389. gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM,0);
  390. self->monsterinfo.currentmove = &jorg_move_pain1;
  391. }
  392. else if (damage <= 100)
  393. {
  394. gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM,0);
  395. self->monsterinfo.currentmove = &jorg_move_pain2;
  396. }
  397. else
  398. {
  399. if (random() <= 0.3)
  400. {
  401. gi.sound (self, CHAN_VOICE, sound_pain3, 1, ATTN_NORM,0);
  402. self->monsterinfo.currentmove = &jorg_move_pain3;
  403. }
  404. }
  405. };
  406. void jorgBFG (edict_t *self)
  407. {
  408. vec3_t forward, right;
  409. vec3_t start;
  410. vec3_t dir;
  411. vec3_t vec;
  412. AngleVectors (self->s.angles, forward, right, NULL);
  413. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_BFG_1], forward, right, start);
  414. VectorCopy (self->enemy->s.origin, vec);
  415. vec[2] += self->enemy->viewheight;
  416. VectorSubtract (vec, start, dir);
  417. VectorNormalize (dir);
  418. gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM, 0);
  419. /*void monster_fire_bfg (edict_t *self,
  420. vec3_t start,
  421. vec3_t aimdir,
  422. int damage,
  423. int speed,
  424. int kick,
  425. float damage_radius,
  426. int flashtype)*/
  427. monster_fire_bfg (self, start, dir, 50, 300, 100, 200, MZ2_JORG_BFG_1);
  428. }
  429. void jorg_firebullet_right (edict_t *self)
  430. {
  431. vec3_t forward, right, target;
  432. vec3_t start;
  433. AngleVectors (self->s.angles, forward, right, NULL);
  434. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_R1], forward, right, start);
  435. VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  436. target[2] += self->enemy->viewheight;
  437. VectorSubtract (target, start, forward);
  438. VectorNormalize (forward);
  439. monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_R1);
  440. }
  441. void jorg_firebullet_left (edict_t *self)
  442. {
  443. vec3_t forward, right, target;
  444. vec3_t start;
  445. AngleVectors (self->s.angles, forward, right, NULL);
  446. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_JORG_MACHINEGUN_L1], forward, right, start);
  447. VectorMA (self->enemy->s.origin, -0.2, self->enemy->velocity, target);
  448. target[2] += self->enemy->viewheight;
  449. VectorSubtract (target, start, forward);
  450. VectorNormalize (forward);
  451. monster_fire_bullet (self, start, forward, 6, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MZ2_JORG_MACHINEGUN_L1);
  452. }
  453. void jorg_firebullet (edict_t *self)
  454. {
  455. jorg_firebullet_left(self);
  456. jorg_firebullet_right(self);
  457. };
  458. void jorg_attack(edict_t *self)
  459. {
  460. vec3_t vec;
  461. float range;
  462. VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  463. range = VectorLength (vec);
  464. if (random() <= 0.75)
  465. {
  466. gi.sound (self, CHAN_VOICE, sound_attack1, 1, ATTN_NORM,0);
  467. self->s.sound = gi.soundindex ("boss3/w_loop.wav");
  468. self->monsterinfo.currentmove = &jorg_move_start_attack1;
  469. }
  470. else
  471. {
  472. gi.sound (self, CHAN_VOICE, sound_attack2, 1, ATTN_NORM,0);
  473. self->monsterinfo.currentmove = &jorg_move_attack2;
  474. }
  475. }
  476. void jorg_dead (edict_t *self)
  477. {
  478. #if 0
  479. edict_t *tempent;
  480. /*
  481. VectorSet (self->mins, -16, -16, -24);
  482. VectorSet (self->maxs, 16, 16, -8);
  483. */
  484. // Jorg is on modelindex2. Do not clear him.
  485. VectorSet (self->mins, -60, -60, 0);
  486. VectorSet (self->maxs, 60, 60, 72);
  487. self->movetype = MOVETYPE_TOSS;
  488. self->nextthink = 0;
  489. gi.linkentity (self);
  490. tempent = G_Spawn();
  491. VectorCopy (self->s.origin, tempent->s.origin);
  492. VectorCopy (self->s.angles, tempent->s.angles);
  493. tempent->killtarget = self->killtarget;
  494. tempent->target = self->target;
  495. tempent->activator = self->enemy;
  496. self->killtarget = 0;
  497. self->target = 0;
  498. SP_monster_makron (tempent);
  499. #endif
  500. }
  501. void jorg_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  502. {
  503. gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
  504. self->deadflag = DEAD_DEAD;
  505. self->takedamage = DAMAGE_NO;
  506. self->s.sound = 0;
  507. self->count = 0;
  508. self->monsterinfo.currentmove = &jorg_move_death;
  509. }
  510. qboolean Jorg_CheckAttack (edict_t *self)
  511. {
  512. vec3_t spot1, spot2;
  513. vec3_t temp;
  514. float chance;
  515. trace_t tr;
  516. qboolean enemy_infront;
  517. int enemy_range;
  518. float enemy_yaw;
  519. if (self->enemy->health > 0)
  520. {
  521. // see if any entities are in the way of the shot
  522. VectorCopy (self->s.origin, spot1);
  523. spot1[2] += self->viewheight;
  524. VectorCopy (self->enemy->s.origin, spot2);
  525. spot2[2] += self->enemy->viewheight;
  526. tr = gi.trace (spot1, NULL, NULL, spot2, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_SLIME|CONTENTS_LAVA);
  527. // do we have a clear shot?
  528. if (tr.ent != self->enemy)
  529. return false;
  530. }
  531. enemy_infront = infront(self, self->enemy);
  532. enemy_range = range(self, self->enemy);
  533. VectorSubtract (self->enemy->s.origin, self->s.origin, temp);
  534. enemy_yaw = vectoyaw(temp);
  535. self->ideal_yaw = enemy_yaw;
  536. // melee attack
  537. if (enemy_range == RANGE_MELEE)
  538. {
  539. if (self->monsterinfo.melee)
  540. self->monsterinfo.attack_state = AS_MELEE;
  541. else
  542. self->monsterinfo.attack_state = AS_MISSILE;
  543. return true;
  544. }
  545. // missile attack
  546. if (!self->monsterinfo.attack)
  547. return false;
  548. if (level.time < self->monsterinfo.attack_finished)
  549. return false;
  550. if (enemy_range == RANGE_FAR)
  551. return false;
  552. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  553. {
  554. chance = 0.4;
  555. }
  556. else if (enemy_range == RANGE_MELEE)
  557. {
  558. chance = 0.8;
  559. }
  560. else if (enemy_range == RANGE_NEAR)
  561. {
  562. chance = 0.4;
  563. }
  564. else if (enemy_range == RANGE_MID)
  565. {
  566. chance = 0.2;
  567. }
  568. else
  569. {
  570. return false;
  571. }
  572. if (random () < chance)
  573. {
  574. self->monsterinfo.attack_state = AS_MISSILE;
  575. self->monsterinfo.attack_finished = level.time + 2*random();
  576. return true;
  577. }
  578. if (self->flags & FL_FLY)
  579. {
  580. if (random() < 0.3)
  581. self->monsterinfo.attack_state = AS_SLIDING;
  582. else
  583. self->monsterinfo.attack_state = AS_STRAIGHT;
  584. }
  585. return false;
  586. }
  587. void MakronPrecache (void);
  588. /*QUAKED monster_jorg (1 .5 0) (-80 -80 0) (90 90 140) Ambush Trigger_Spawn Sight
  589. */
  590. void SP_monster_jorg (edict_t *self)
  591. {
  592. if (deathmatch->value)
  593. {
  594. G_FreeEdict (self);
  595. return;
  596. }
  597. sound_pain1 = gi.soundindex ("boss3/bs3pain1.wav");
  598. sound_pain2 = gi.soundindex ("boss3/bs3pain2.wav");
  599. sound_pain3 = gi.soundindex ("boss3/bs3pain3.wav");
  600. sound_death = gi.soundindex ("boss3/bs3deth1.wav");
  601. sound_attack1 = gi.soundindex ("boss3/bs3atck1.wav");
  602. sound_attack2 = gi.soundindex ("boss3/bs3atck2.wav");
  603. sound_search1 = gi.soundindex ("boss3/bs3srch1.wav");
  604. sound_search2 = gi.soundindex ("boss3/bs3srch2.wav");
  605. sound_search3 = gi.soundindex ("boss3/bs3srch3.wav");
  606. sound_idle = gi.soundindex ("boss3/bs3idle1.wav");
  607. sound_step_left = gi.soundindex ("boss3/step1.wav");
  608. sound_step_right = gi.soundindex ("boss3/step2.wav");
  609. sound_firegun = gi.soundindex ("boss3/xfire.wav");
  610. sound_death_hit = gi.soundindex ("boss3/d_hit.wav");
  611. MakronPrecache ();
  612. self->movetype = MOVETYPE_STEP;
  613. self->solid = SOLID_BBOX;
  614. self->s.modelindex = gi.modelindex ("models/monsters/boss3/rider/tris.md2");
  615. self->s.modelindex2 = gi.modelindex ("models/monsters/boss3/jorg/tris.md2");
  616. VectorSet (self->mins, -80, -80, 0);
  617. VectorSet (self->maxs, 80, 80, 140);
  618. self->health = 3000;
  619. self->gib_health = -2000;
  620. self->mass = 1000;
  621. self->pain = jorg_pain;
  622. self->die = jorg_die;
  623. self->monsterinfo.stand = jorg_stand;
  624. self->monsterinfo.walk = jorg_walk;
  625. self->monsterinfo.run = jorg_run;
  626. self->monsterinfo.dodge = NULL;
  627. self->monsterinfo.attack = jorg_attack;
  628. self->monsterinfo.search = jorg_search;
  629. self->monsterinfo.melee = NULL;
  630. self->monsterinfo.sight = NULL;
  631. self->monsterinfo.checkattack = Jorg_CheckAttack;
  632. gi.linkentity (self);
  633. self->monsterinfo.currentmove = &jorg_move_stand;
  634. self->monsterinfo.scale = MODEL_SCALE;
  635. walkmonster_start(self);
  636. }