m_gekk.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. xatrix
  5. gekk.c
  6. */
  7. #include "g_local.h"
  8. #include "m_gekk.h"
  9. static int sound_swing;
  10. static int sound_hit;
  11. static int sound_hit2;
  12. static int sound_death;
  13. static int sound_pain1;
  14. static int sound_sight;
  15. static int sound_search;
  16. static int sound_step1;
  17. static int sound_step2;
  18. static int sound_step3;
  19. static int sound_thud;
  20. static int sound_chantlow;
  21. static int sound_chantmid;
  22. static int sound_chanthigh;
  23. void gekk_swim (edict_t *self);
  24. extern void gekk_jump_takeoff (edict_t *self);
  25. extern void gekk_jump_takeoff2 (edict_t *self);
  26. extern void gekk_check_landing (edict_t *self);
  27. extern void gekk_check_landing2 (edict_t *self);
  28. extern void gekk_stop_skid (edict_t *self);
  29. extern void water_to_land (edict_t *self);
  30. extern void land_to_water (edict_t *self);
  31. extern void gekk_check_underwater (edict_t *self);
  32. extern void gekk_bite (edict_t *self);
  33. extern void gekk_hit_left (edict_t *self);
  34. extern void gekk_hit_right (edict_t *self);
  35. extern void gekk_run_start (edict_t *self);
  36. extern mmove_t gekk_move_attack1;
  37. extern mmove_t gekk_move_attack2;
  38. extern mmove_t gekk_move_chant;
  39. extern mmove_t gekk_move_swim_start;
  40. extern mmove_t gekk_move_swim_loop;
  41. extern mmove_t gekk_move_spit;
  42. extern mmove_t gekk_move_run_start;
  43. extern qboolean gekk_check_jump (edict_t *self);
  44. //
  45. // CHECKATTACK
  46. //
  47. qboolean gekk_check_melee (edict_t *self)
  48. {
  49. if (!self->enemy && self->enemy->health <= 0)
  50. return false;
  51. if (range (self, self->enemy) == RANGE_MELEE)
  52. return true;
  53. return false;
  54. }
  55. qboolean gekk_check_jump (edict_t *self)
  56. {
  57. vec3_t v;
  58. float distance;
  59. if (self->absmin[2] > (self->enemy->absmin[2] + 0.75 * self->enemy->size[2]))
  60. return false;
  61. if (self->absmax[2] < (self->enemy->absmin[2] + 0.25 * self->enemy->size[2]))
  62. return false;
  63. v[0] = self->s.origin[0] - self->enemy->s.origin[0];
  64. v[1] = self->s.origin[1] - self->enemy->s.origin[1];
  65. v[2] = 0;
  66. distance = VectorLength(v);
  67. if (distance < 100)
  68. {
  69. return false;
  70. }
  71. if (distance > 100)
  72. {
  73. if (random() < 0.9)
  74. return false;
  75. }
  76. return true;
  77. }
  78. qboolean gekk_check_jump_close (edict_t *self)
  79. {
  80. vec3_t v;
  81. float distance;
  82. v[0] = self->s.origin[0] - self->enemy->s.origin[0];
  83. v[1] = self->s.origin[1] - self->enemy->s.origin[1];
  84. v[2] = 0;
  85. distance = VectorLength(v);
  86. if (distance < 100)
  87. {
  88. if (self->s.origin[2] < self->enemy->s.origin[2])
  89. return true;
  90. else
  91. return false;
  92. }
  93. return true;
  94. }
  95. qboolean gekk_checkattack (edict_t *self)
  96. {
  97. if (!self->enemy || self->enemy->health <= 0)
  98. return false;
  99. if (gekk_check_melee(self))
  100. {
  101. self->monsterinfo.attack_state = AS_MELEE;
  102. return true;
  103. }
  104. if (gekk_check_jump(self))
  105. {
  106. self->monsterinfo.attack_state = AS_MISSILE;
  107. return true;
  108. }
  109. if (gekk_check_jump_close (self) && !self->waterlevel)
  110. {
  111. self->monsterinfo.attack_state = AS_MISSILE;
  112. return true;
  113. }
  114. return false;
  115. }
  116. //
  117. // SOUNDS
  118. //
  119. void gekk_step (edict_t *self)
  120. {
  121. int n;
  122. n = (rand() + 1) % 3;
  123. if (n == 0)
  124. gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0);
  125. else if (n == 1)
  126. gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0);
  127. else
  128. gi.sound (self, CHAN_VOICE, sound_step3, 1, ATTN_NORM, 0);
  129. }
  130. void gekk_sight (edict_t *self, edict_t *other)
  131. {
  132. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  133. }
  134. void gekk_search (edict_t *self)
  135. {
  136. float r;
  137. if (self->spawnflags & 8)
  138. {
  139. r = random();
  140. if (r < 0.33)
  141. gi.sound (self, CHAN_VOICE, sound_chantlow, 1, ATTN_NORM, 0);
  142. else if (r < 0.66)
  143. gi.sound (self, CHAN_VOICE, sound_chantmid, 1, ATTN_NORM, 0);
  144. else
  145. gi.sound (self, CHAN_VOICE, sound_chanthigh, 1, ATTN_NORM, 0);
  146. }
  147. else
  148. gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
  149. self->health += 10 + (10 * random());
  150. if (self->health > self->max_health)
  151. self->health = self->max_health;
  152. if (self->health < (self->max_health /4))
  153. self->s.skinnum = 2;
  154. else if (self->health < (self->max_health / 2))
  155. self->s.skinnum = 1;
  156. else
  157. self->s.skinnum = 0;
  158. }
  159. void gekk_swing (edict_t *self)
  160. {
  161. gi.sound (self, CHAN_VOICE, sound_swing, 1, ATTN_NORM, 0);
  162. }
  163. extern mmove_t gekk_move_run;
  164. void gekk_face (edict_t *self)
  165. {
  166. self->monsterinfo.currentmove = &gekk_move_run;
  167. }
  168. //
  169. // STAND
  170. //
  171. void ai_stand2 (edict_t *self, float dist)
  172. {
  173. if (self->spawnflags & 8)
  174. {
  175. ai_move (self, dist);
  176. if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time))
  177. {
  178. if (self->monsterinfo.idle_time)
  179. {
  180. self->monsterinfo.idle (self);
  181. self->monsterinfo.idle_time = level.time + 15 + random() * 15;
  182. }
  183. else
  184. {
  185. self->monsterinfo.idle_time = level.time + random() * 15;
  186. }
  187. }
  188. }
  189. else
  190. ai_stand (self, dist);
  191. }
  192. mframe_t gekk_frames_stand [] =
  193. {
  194. ai_stand2, 0, NULL,
  195. ai_stand2, 0, NULL,
  196. ai_stand2, 0, NULL,
  197. ai_stand2, 0, NULL,
  198. ai_stand2, 0, NULL,
  199. ai_stand2, 0, NULL,
  200. ai_stand2, 0, NULL,
  201. ai_stand2, 0, NULL,
  202. ai_stand2, 0, NULL,
  203. ai_stand2, 0, NULL, // 10
  204. ai_stand2, 0, NULL,
  205. ai_stand2, 0, NULL,
  206. ai_stand2, 0, NULL,
  207. ai_stand2, 0, NULL,
  208. ai_stand2, 0, NULL,
  209. ai_stand2, 0, NULL,
  210. ai_stand2, 0, NULL,
  211. ai_stand2, 0, NULL,
  212. ai_stand2, 0, NULL,
  213. ai_stand2, 0, NULL, // 20
  214. ai_stand2, 0, NULL,
  215. ai_stand2, 0, NULL,
  216. ai_stand2, 0, NULL,
  217. ai_stand2, 0, NULL,
  218. ai_stand2, 0, NULL,
  219. ai_stand2, 0, NULL,
  220. ai_stand2, 0, NULL,
  221. ai_stand2, 0, NULL,
  222. ai_stand2, 0, NULL,
  223. ai_stand2, 0, NULL, // 30
  224. ai_stand2, 0, NULL,
  225. ai_stand2, 0, NULL,
  226. ai_stand2, 0, NULL,
  227. ai_stand2, 0, NULL,
  228. ai_stand2, 0, NULL,
  229. ai_stand2, 0, NULL,
  230. ai_stand2, 0, NULL,
  231. ai_stand2, 0, NULL,
  232. ai_stand2, 0, gekk_check_underwater,
  233. };
  234. mmove_t gekk_move_stand = {FRAME_stand_01, FRAME_stand_39, gekk_frames_stand, NULL};
  235. mframe_t gekk_frames_standunderwater[] =
  236. {
  237. ai_stand2, 0, NULL,
  238. ai_stand2, 0, NULL,
  239. ai_stand2, 0, NULL,
  240. ai_stand2, 0, gekk_check_underwater
  241. };
  242. mmove_t gekk_move_standunderwater = {FRAME_amb_01, FRAME_amb_04, gekk_frames_standunderwater, NULL};
  243. void gekk_swim_loop (edict_t *self)
  244. {
  245. self->flags |= FL_SWIM;
  246. self->monsterinfo.currentmove = &gekk_move_swim_loop;
  247. }
  248. mframe_t gekk_frames_swim [] =
  249. {
  250. ai_run, 16, NULL,
  251. ai_run, 16, NULL,
  252. ai_run, 16, NULL,
  253. ai_run, 16, gekk_swim
  254. };
  255. mmove_t gekk_move_swim_loop = {FRAME_amb_01, FRAME_amb_04, gekk_frames_swim, gekk_swim_loop};
  256. mframe_t gekk_frames_swim_start [] =
  257. {
  258. ai_run, 14, NULL,
  259. ai_run, 14, NULL,
  260. ai_run, 14, NULL,
  261. ai_run, 14, NULL,
  262. ai_run, 16, NULL,
  263. ai_run, 16, NULL,
  264. ai_run, 16, NULL,
  265. ai_run, 18, NULL,
  266. ai_run, 18, gekk_hit_left,
  267. ai_run, 18, NULL,
  268. ai_run, 20, NULL,
  269. ai_run, 20, NULL,
  270. ai_run, 22, NULL,
  271. ai_run, 22, NULL,
  272. ai_run, 24, gekk_hit_right,
  273. ai_run, 24, NULL,
  274. ai_run, 26, NULL,
  275. ai_run, 26, NULL,
  276. ai_run, 24, NULL,
  277. ai_run, 24, NULL,
  278. ai_run, 22, gekk_bite,
  279. ai_run, 22, NULL,
  280. ai_run, 22, NULL,
  281. ai_run, 22, NULL,
  282. ai_run, 22, NULL,
  283. ai_run, 22, NULL,
  284. ai_run, 22, NULL,
  285. ai_run, 22, NULL,
  286. ai_run, 18, NULL,
  287. ai_run, 18, NULL,
  288. ai_run, 18, NULL,
  289. ai_run, 18, NULL
  290. };
  291. mmove_t gekk_move_swim_start = {FRAME_swim_01, FRAME_swim_32, gekk_frames_swim_start, gekk_swim_loop};
  292. void gekk_swim (edict_t *self)
  293. {
  294. if (gekk_checkattack)
  295. if (!self->enemy->waterlevel && random() > 0.7)
  296. water_to_land (self);
  297. else
  298. self->monsterinfo.currentmove = &gekk_move_swim_start;
  299. }
  300. void gekk_stand (edict_t *self)
  301. {
  302. if (self->waterlevel)
  303. self->monsterinfo.currentmove = &gekk_move_standunderwater;
  304. else
  305. self->monsterinfo.currentmove = &gekk_move_stand;
  306. }
  307. void gekk_chant (edict_t *self)
  308. {
  309. self->monsterinfo.currentmove = &gekk_move_chant;
  310. }
  311. //
  312. // IDLE
  313. //
  314. void gekk_idle_loop (edict_t *self)
  315. {
  316. if (random() > 0.75 && self->health < self->max_health)
  317. self->monsterinfo.nextframe = FRAME_idle_01;
  318. }
  319. mframe_t gekk_frames_idle [] =
  320. {
  321. ai_stand2, 0, gekk_search,
  322. ai_stand2, 0, NULL,
  323. ai_stand2, 0, NULL,
  324. ai_stand2, 0, NULL,
  325. ai_stand2, 0, NULL,
  326. ai_stand2, 0, NULL,
  327. ai_stand2, 0, NULL,
  328. ai_stand2, 0, NULL,
  329. ai_stand2, 0, NULL,
  330. ai_stand2, 0, NULL,
  331. ai_stand2, 0, NULL,
  332. ai_stand2, 0, NULL,
  333. ai_stand2, 0, NULL,
  334. ai_stand2, 0, NULL,
  335. ai_stand2, 0, NULL,
  336. ai_stand2, 0, NULL,
  337. ai_stand2, 0, NULL,
  338. ai_stand2, 0, NULL,
  339. ai_stand2, 0, NULL,
  340. ai_stand2, 0, NULL,
  341. ai_stand2, 0, NULL,
  342. ai_stand2, 0, NULL,
  343. ai_stand2, 0, NULL,
  344. ai_stand2, 0, NULL,
  345. ai_stand2, 0, NULL,
  346. ai_stand2, 0, NULL,
  347. ai_stand2, 0, NULL,
  348. ai_stand2, 0, NULL,
  349. ai_stand2, 0, NULL,
  350. ai_stand2, 0, NULL,
  351. ai_stand2, 0, NULL,
  352. ai_stand2, 0, gekk_idle_loop
  353. };
  354. mmove_t gekk_move_idle = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_stand};
  355. mmove_t gekk_move_idle2 = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle, gekk_face};
  356. mframe_t gekk_frames_idle2 [] =
  357. {
  358. ai_move, 0, gekk_search,
  359. ai_move, 0, NULL,
  360. ai_move, 0, NULL,
  361. ai_move, 0, NULL,
  362. ai_move, 0, NULL,
  363. ai_move, 0, NULL,
  364. ai_move, 0, NULL,
  365. ai_move, 0, NULL,
  366. ai_move, 0, NULL,
  367. ai_move, 0, NULL,
  368. ai_move, 0, NULL,
  369. ai_move, 0, NULL,
  370. ai_move, 0, NULL,
  371. ai_move, 0, NULL,
  372. ai_move, 0, NULL,
  373. ai_move, 0, NULL,
  374. ai_move, 0, NULL,
  375. ai_move, 0, NULL,
  376. ai_move, 0, NULL,
  377. ai_move, 0, NULL,
  378. ai_move, 0, NULL,
  379. ai_move, 0, NULL,
  380. ai_move, 0, NULL,
  381. ai_move, 0, NULL,
  382. ai_move, 0, NULL,
  383. ai_move, 0, NULL,
  384. ai_move, 0, NULL,
  385. ai_move, 0, NULL,
  386. ai_move, 0, NULL,
  387. ai_move, 0, NULL,
  388. ai_move, 0, NULL,
  389. ai_move, 0, gekk_idle_loop
  390. };
  391. mmove_t gekk_move_chant = {FRAME_idle_01, FRAME_idle_32, gekk_frames_idle2, gekk_chant};
  392. void gekk_idle (edict_t *self)
  393. {
  394. if (!self->waterlevel)
  395. self->monsterinfo.currentmove = &gekk_move_idle;
  396. else
  397. self->monsterinfo.currentmove = &gekk_move_swim_start;
  398. // gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  399. }
  400. //
  401. // WALK
  402. //
  403. void gekk_walk (edict_t *self);
  404. mframe_t gekk_frames_walk[] =
  405. {
  406. ai_walk, 3.849, gekk_check_underwater, // frame 0
  407. ai_walk, 19.606, NULL, // frame 1
  408. ai_walk, 25.583, NULL, // frame 2
  409. ai_walk, 34.625, gekk_step, // frame 3
  410. ai_walk, 27.365, NULL, // frame 4
  411. ai_walk, 28.480, NULL, // frame 5
  412. };
  413. mmove_t gekk_move_walk = {FRAME_run_01, FRAME_run_06, gekk_frames_walk, NULL};
  414. void gekk_walk (edict_t *self)
  415. {
  416. self->monsterinfo.currentmove = &gekk_move_walk;
  417. }
  418. //
  419. // RUN
  420. //
  421. void gekk_run_start (edict_t *self)
  422. {
  423. if (self->waterlevel)
  424. {
  425. self->monsterinfo.currentmove = &gekk_move_swim_start;
  426. }
  427. else
  428. {
  429. self->monsterinfo.currentmove = &gekk_move_run_start;
  430. }
  431. }
  432. void gekk_run (edict_t *self)
  433. {
  434. if (self->waterlevel)
  435. {
  436. self->monsterinfo.currentmove = &gekk_move_swim_start;
  437. return;
  438. }
  439. else
  440. {
  441. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  442. self->monsterinfo.currentmove = &gekk_move_stand;
  443. else
  444. self->monsterinfo.currentmove = &gekk_move_run;
  445. }
  446. }
  447. mframe_t gekk_frames_run[] =
  448. {
  449. ai_run, 3.849, gekk_check_underwater, // frame 0
  450. ai_run, 19.606, NULL, // frame 1
  451. ai_run, 25.583, NULL, // frame 2
  452. ai_run, 34.625, gekk_step, // frame 3
  453. ai_run, 27.365, NULL, // frame 4
  454. ai_run, 28.480, NULL, // frame 5
  455. };
  456. mmove_t gekk_move_run = {FRAME_run_01, FRAME_run_06, gekk_frames_run, NULL};
  457. mframe_t gekk_frames_run_st[] =
  458. {
  459. ai_run, 0.212, NULL, // frame 0
  460. ai_run, 19.753, NULL, // frame 1
  461. };
  462. mmove_t gekk_move_run_start = {FRAME_stand_01, FRAME_stand_02, gekk_frames_run_st, gekk_run};
  463. //
  464. // MELEE
  465. //
  466. void gekk_hit_left (edict_t *self)
  467. {
  468. vec3_t aim;
  469. VectorSet (aim, MELEE_DISTANCE, self->mins[0], 8);
  470. if (fire_hit (self, aim, (15 + (rand() %5)), 100))
  471. gi.sound (self, CHAN_WEAPON, sound_hit, 1, ATTN_NORM, 0);
  472. else
  473. gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
  474. }
  475. void gekk_hit_right (edict_t *self)
  476. {
  477. vec3_t aim;
  478. VectorSet (aim, MELEE_DISTANCE, self->maxs[0], 8);
  479. if (fire_hit (self, aim, (15 + (rand() %5)), 100))
  480. gi.sound (self, CHAN_WEAPON, sound_hit2, 1, ATTN_NORM, 0);
  481. else
  482. gi.sound (self, CHAN_WEAPON, sound_swing, 1, ATTN_NORM, 0);
  483. }
  484. void gekk_check_refire (edict_t *self)
  485. {
  486. if (!self->enemy || !self->enemy->inuse || self->enemy->health <= 0)
  487. return;
  488. if (random() < (skill->value * 0.1))
  489. {
  490. if (range (self, self->enemy) == RANGE_MELEE)
  491. {
  492. if (self->s.frame == FRAME_clawatk3_09)
  493. self->monsterinfo.currentmove = &gekk_move_attack2;
  494. else if (self->s.frame == FRAME_clawatk5_09)
  495. self->monsterinfo.currentmove = &gekk_move_attack1;
  496. }
  497. }
  498. }
  499. void loogie_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
  500. {
  501. if (other == self->owner)
  502. return;
  503. if (surf && (surf->flags & SURF_SKY))
  504. {
  505. G_FreeEdict (self);
  506. return;
  507. }
  508. if (self->owner->client)
  509. PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT);
  510. if (other->takedamage)
  511. T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, MOD_GEKK);
  512. G_FreeEdict (self);
  513. };
  514. void fire_loogie (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed)
  515. {
  516. edict_t *loogie;
  517. trace_t tr;
  518. VectorNormalize (dir);
  519. loogie = G_Spawn();
  520. VectorCopy (start, loogie->s.origin);
  521. VectorCopy (start, loogie->s.old_origin);
  522. vectoangles (dir, loogie->s.angles);
  523. VectorScale (dir, speed, loogie->velocity);
  524. loogie->movetype = MOVETYPE_FLYMISSILE;
  525. loogie->clipmask = MASK_SHOT;
  526. loogie->solid = SOLID_BBOX;
  527. loogie->s.effects |= RF_FULLBRIGHT;
  528. VectorClear (loogie->mins);
  529. VectorClear (loogie->maxs);
  530. loogie->s.modelindex = gi.modelindex ("models/objects/loogy/tris.md2");
  531. loogie->owner = self;
  532. loogie->touch = loogie_touch;
  533. loogie->nextthink = level.time + 2;
  534. loogie->think = G_FreeEdict;
  535. loogie->dmg = damage;
  536. gi.linkentity (loogie);
  537. tr = gi.trace (self->s.origin, NULL, NULL, loogie->s.origin, loogie, MASK_SHOT);
  538. if (tr.fraction < 1.0)
  539. {
  540. VectorMA (loogie->s.origin, -10, dir, loogie->s.origin);
  541. loogie->touch (loogie, tr.ent, NULL, NULL);
  542. }
  543. }
  544. void loogie (edict_t *self)
  545. {
  546. vec3_t start;
  547. vec3_t forward, right, up;
  548. vec3_t end;
  549. vec3_t dir;
  550. vec3_t gekkoffset;
  551. VectorSet (gekkoffset, -18, -0.8, 24);
  552. if (!self->enemy || self->enemy->health <= 0)
  553. return;
  554. AngleVectors (self->s.angles, forward, right, up);
  555. G_ProjectSource (self->s.origin, gekkoffset, forward, right, start);
  556. VectorMA (start, 2, up, start);
  557. VectorCopy (self->enemy->s.origin, end);
  558. end[2] += self->enemy->viewheight;
  559. VectorSubtract (end, start, dir);
  560. fire_loogie (self, start, dir, 5, 550);
  561. }
  562. void reloogie (edict_t *self)
  563. {
  564. if (random() > 0.8 && self->health < self->max_health)
  565. {
  566. self->monsterinfo.currentmove = &gekk_move_idle2;
  567. return;
  568. }
  569. if (self->enemy->health >= 0)
  570. if (random() > 0.7 && (range(self, self->enemy) == RANGE_NEAR))
  571. self->monsterinfo.currentmove = &gekk_move_spit;
  572. }
  573. mframe_t gekk_frames_spit [] =
  574. {
  575. ai_charge, 0.000, NULL,
  576. ai_charge, 0.000, NULL,
  577. ai_charge, 0.000, NULL,
  578. ai_charge, 0.000, NULL,
  579. ai_charge, 0.000, NULL,
  580. ai_charge, 0.000, loogie,
  581. ai_charge, 0.000, reloogie
  582. };
  583. mmove_t gekk_move_spit = {FRAME_spit_01, FRAME_spit_07, gekk_frames_spit, gekk_run_start};
  584. mframe_t gekk_frames_attack1 [] =
  585. {
  586. ai_charge, 0, NULL,
  587. ai_charge, 0, NULL,
  588. ai_charge, 0, NULL,
  589. ai_charge, 0, gekk_hit_left,
  590. ai_charge, 0, NULL,
  591. ai_charge, 0, NULL,
  592. ai_charge, 0, NULL,
  593. ai_charge, 0, NULL,
  594. ai_charge, 0, gekk_check_refire
  595. };
  596. mmove_t gekk_move_attack1 = {FRAME_clawatk3_01, FRAME_clawatk3_09, gekk_frames_attack1, gekk_run_start};
  597. mframe_t gekk_frames_attack2[] =
  598. {
  599. ai_charge, 0.000, NULL,
  600. ai_charge, 0.000, NULL,
  601. ai_charge, 0.000, gekk_hit_left,
  602. ai_charge, 0.000, NULL,
  603. ai_charge, 0.000, NULL,
  604. ai_charge, 0.000, gekk_hit_right,
  605. ai_charge, 0.000, NULL,
  606. ai_charge, 0.000, NULL,
  607. ai_charge, 0.000, gekk_check_refire
  608. };
  609. mmove_t gekk_move_attack2 = {FRAME_clawatk5_01, FRAME_clawatk5_09, gekk_frames_attack2, gekk_run_start};
  610. void gekk_check_underwater (edict_t *self)
  611. {
  612. if (self->waterlevel)
  613. {
  614. land_to_water (self);
  615. }
  616. }
  617. mframe_t gekk_frames_leapatk[] =
  618. {
  619. ai_charge, 0.000, NULL, // frame 0
  620. ai_charge, -0.387, NULL, // frame 1
  621. ai_charge, -1.113, NULL, // frame 2
  622. ai_charge, -0.237, NULL, // frame 3
  623. ai_charge, 6.720, gekk_jump_takeoff, // frame 4 last frame on ground
  624. ai_charge, 6.414, NULL, // frame 5 leaves ground
  625. ai_charge, 0.163, NULL, // frame 6
  626. ai_charge, 28.316, NULL, // frame 7
  627. ai_charge, 24.198, NULL, // frame 8
  628. ai_charge, 31.742, NULL, // frame 9
  629. ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air
  630. ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground
  631. ai_charge, 20.122, gekk_stop_skid, // frame 12
  632. ai_charge, -1.042, gekk_stop_skid, // frame 13
  633. ai_charge, 2.556, gekk_stop_skid, // frame 14
  634. ai_charge, 0.544, gekk_stop_skid, // frame 15
  635. ai_charge, 1.862, gekk_stop_skid, // frame 16
  636. ai_charge, 1.224, gekk_stop_skid, // frame 17
  637. ai_charge, -0.457, gekk_check_underwater, // frame 18
  638. };
  639. mmove_t gekk_move_leapatk = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk, gekk_run_start};
  640. mframe_t gekk_frames_leapatk2[] =
  641. {
  642. ai_charge, 0.000, NULL, // frame 0
  643. ai_charge, -0.387, NULL, // frame 1
  644. ai_charge, -1.113, NULL, // frame 2
  645. ai_charge, -0.237, NULL, // frame 3
  646. ai_charge, 6.720, gekk_jump_takeoff2, // frame 4 last frame on ground
  647. ai_charge, 6.414, NULL, // frame 5 leaves ground
  648. ai_charge, 0.163, NULL, // frame 6
  649. ai_charge, 28.316, NULL, // frame 7
  650. ai_charge, 24.198, NULL, // frame 8
  651. ai_charge, 31.742, NULL, // frame 9
  652. ai_charge, 35.977, gekk_check_landing, // frame 10 last frame in air
  653. ai_charge, 12.303, gekk_stop_skid, // frame 11 feet back on ground
  654. ai_charge, 20.122, gekk_stop_skid, // frame 12
  655. ai_charge, -1.042, gekk_stop_skid, // frame 13
  656. ai_charge, 2.556, gekk_stop_skid, // frame 14
  657. ai_charge, 0.544, gekk_stop_skid, // frame 15
  658. ai_charge, 1.862, gekk_stop_skid, // frame 16
  659. ai_charge, 1.224, gekk_stop_skid, // frame 17
  660. ai_charge, -0.457, gekk_check_underwater, // frame 18
  661. };
  662. mmove_t gekk_move_leapatk2 = {FRAME_leapatk_01, FRAME_leapatk_19, gekk_frames_leapatk2, gekk_run_start};
  663. void gekk_bite (edict_t *self)
  664. {
  665. vec3_t aim;
  666. VectorSet (aim, MELEE_DISTANCE, 0, 0);
  667. fire_hit (self, aim, 5, 0);
  668. }
  669. void gekk_preattack (edict_t *self)
  670. {
  671. // underwater attack sound
  672. // gi.sound (self, CHAN_WEAPON, something something underwater sound, 1, ATTN_NORM, 0);
  673. return;
  674. }
  675. mframe_t gekk_frames_attack [] =
  676. {
  677. ai_charge, 16, gekk_preattack,
  678. ai_charge, 16, NULL,
  679. ai_charge, 16, NULL,
  680. ai_charge, 16, NULL,
  681. ai_charge, 16, gekk_bite,
  682. ai_charge, 16, NULL,
  683. ai_charge, 16, NULL,
  684. ai_charge, 16, NULL,
  685. ai_charge, 16, NULL,
  686. ai_charge, 16, gekk_bite,
  687. ai_charge, 16, NULL,
  688. ai_charge, 16, NULL,
  689. ai_charge, 16, NULL,
  690. ai_charge, 16, gekk_hit_left,
  691. ai_charge, 16, NULL,
  692. ai_charge, 16, NULL,
  693. ai_charge, 16, NULL,
  694. ai_charge, 16, NULL,
  695. ai_charge, 16, gekk_hit_right,
  696. ai_charge, 16, NULL,
  697. ai_charge, 16, NULL
  698. };
  699. mmove_t gekk_move_attack = {FRAME_attack_01, FRAME_attack_21, gekk_frames_attack, gekk_run_start};
  700. void gekk_melee (edict_t *self)
  701. {
  702. float r;
  703. if (self->waterlevel)
  704. {
  705. self->monsterinfo.currentmove = &gekk_move_attack;
  706. }
  707. else
  708. {
  709. r = random();
  710. if (r > 0.66)
  711. self->monsterinfo.currentmove = &gekk_move_attack1;
  712. else
  713. self->monsterinfo.currentmove = &gekk_move_attack2;
  714. }
  715. }
  716. //
  717. // ATTACK
  718. //
  719. void gekk_jump_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
  720. {
  721. if (self->health <= 0)
  722. {
  723. self->touch = NULL;
  724. return;
  725. }
  726. if (other->takedamage)
  727. {
  728. if (VectorLength(self->velocity) > 200)
  729. {
  730. vec3_t point;
  731. vec3_t normal;
  732. int damage;
  733. VectorCopy (self->velocity, normal);
  734. VectorNormalize(normal);
  735. VectorMA (self->s.origin, self->maxs[0], normal, point);
  736. damage = 10 + 10 * random();
  737. T_Damage (other, self, self, self->velocity, point, normal, damage, damage, 0, MOD_GEKK);
  738. }
  739. }
  740. if (!M_CheckBottom (self))
  741. {
  742. if (self->groundentity)
  743. {
  744. self->monsterinfo.nextframe = FRAME_leapatk_11;
  745. self->touch = NULL;
  746. }
  747. return;
  748. }
  749. self->touch = NULL;
  750. }
  751. void gekk_jump_takeoff (edict_t *self)
  752. {
  753. vec3_t forward;
  754. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  755. AngleVectors (self->s.angles, forward, NULL, NULL);
  756. self->s.origin[2] += 1;
  757. // high jump
  758. if (gekk_check_jump (self))
  759. {
  760. VectorScale (forward, 700, self->velocity);
  761. self->velocity[2] = 250;
  762. }
  763. else
  764. {
  765. VectorScale (forward, 250, self->velocity);
  766. self->velocity[2] = 400;
  767. }
  768. self->groundentity = NULL;
  769. self->monsterinfo.aiflags |= AI_DUCKED;
  770. self->monsterinfo.attack_finished = level.time + 3;
  771. self->touch = gekk_jump_touch;
  772. }
  773. void gekk_jump_takeoff2 (edict_t *self)
  774. {
  775. vec3_t forward;
  776. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  777. AngleVectors (self->s.angles, forward, NULL, NULL);
  778. self->s.origin[2] = self->enemy->s.origin[2];
  779. if (gekk_check_jump (self))
  780. {
  781. VectorScale (forward, 300, self->velocity);
  782. self->velocity[2] = 250;
  783. }
  784. else
  785. {
  786. VectorScale (forward, 150, self->velocity);
  787. self->velocity[2] = 300;
  788. }
  789. self->groundentity = NULL;
  790. self->monsterinfo.aiflags |= AI_DUCKED;
  791. self->monsterinfo.attack_finished = level.time + 3;
  792. self->touch = gekk_jump_touch;
  793. }
  794. void gekk_stop_skid (edict_t *self)
  795. {
  796. if (self->groundentity)
  797. {
  798. VectorClear (self->velocity);
  799. }
  800. }
  801. void gekk_check_landing (edict_t *self)
  802. {
  803. if (self->groundentity)
  804. {
  805. gi.sound (self, CHAN_WEAPON, sound_thud, 1, ATTN_NORM, 0);
  806. self->monsterinfo.attack_finished = 0;
  807. self->monsterinfo.aiflags &= ~AI_DUCKED;
  808. VectorClear (self->velocity);
  809. return;
  810. }
  811. // note to self
  812. // causing skid
  813. if (level.time > self->monsterinfo.attack_finished)
  814. self->monsterinfo.nextframe = FRAME_leapatk_11;
  815. else
  816. {
  817. self->monsterinfo.nextframe = FRAME_leapatk_12;
  818. }
  819. }
  820. void gekk_jump (edict_t *self)
  821. {
  822. if (self->flags & FL_SWIM || self->waterlevel)
  823. {
  824. return;
  825. }
  826. else
  827. {
  828. //if (random() > 0.8 && self->health < self->max_health)
  829. // self->monsterinfo.currentmove = &gekk_move_idle2;
  830. //else
  831. {
  832. if (random() > 0.5 && (range (self, self->enemy) >= RANGE_NEAR))
  833. self->monsterinfo.currentmove = &gekk_move_spit;
  834. else if (random() > 0.8)
  835. self->monsterinfo.currentmove = &gekk_move_spit;
  836. else
  837. self->monsterinfo.currentmove = &gekk_move_leapatk;
  838. }
  839. }
  840. }
  841. //
  842. // PAIN
  843. //
  844. mframe_t gekk_frames_pain[] =
  845. {
  846. ai_move, 0.000, NULL, // frame 0
  847. ai_move, 0.000, NULL, // frame 1
  848. ai_move, 0.000, NULL, // frame 2
  849. ai_move, 0.000, NULL, // frame 3
  850. ai_move, 0.000, NULL, // frame 4
  851. ai_move, 0.000, NULL, // frame 5
  852. };
  853. mmove_t gekk_move_pain = {FRAME_pain_01, FRAME_pain_06, gekk_frames_pain, gekk_run_start};
  854. mframe_t gekk_frames_pain1[] =
  855. {
  856. ai_move, 0.000, NULL, // frame 0
  857. ai_move, 0.000, NULL, // frame 1
  858. ai_move, 0.000, NULL, // frame 2
  859. ai_move, 0.000, NULL, // frame 3
  860. ai_move, 0.000, NULL, // frame 4
  861. ai_move, 0.000, NULL, // frame 5
  862. ai_move, 0.000, NULL, // frame 6
  863. ai_move, 0.000, NULL, // frame 7
  864. ai_move, 0.000, NULL, // frame 8
  865. ai_move, 0.000, NULL, // frame 9
  866. ai_move, 0.000, gekk_check_underwater
  867. };
  868. mmove_t gekk_move_pain1 = {FRAME_pain3_01, FRAME_pain3_11, gekk_frames_pain1, gekk_run_start};
  869. mframe_t gekk_frames_pain2[] =
  870. {
  871. ai_move, 0.000, NULL, // frame 0
  872. ai_move, 0.000, NULL, // frame 1
  873. ai_move, 0.000, NULL, // frame 2
  874. ai_move, 0.000, NULL, // frame 3
  875. ai_move, 0.000, NULL, // frame 4
  876. ai_move, 0.000, NULL, // frame 5
  877. ai_move, 0.000, NULL, // frame 6
  878. ai_move, 0.000, NULL, // frame 7
  879. ai_move, 0.000, NULL, // frame 8
  880. ai_move, 0.000, NULL, // frame 9
  881. ai_move, 0.000, NULL, // frame 10
  882. ai_move, 0.000, NULL, // frame 11
  883. ai_move, 0.000, gekk_check_underwater,
  884. };
  885. mmove_t gekk_move_pain2 = {FRAME_pain4_01, FRAME_pain4_13, gekk_frames_pain2, gekk_run_start};
  886. void gekk_pain (edict_t *self, edict_t *other, float kick, int damage)
  887. {
  888. float r;
  889. if (self->spawnflags & 8)
  890. {
  891. self->spawnflags &= ~8;
  892. return;
  893. }
  894. if (self->health < (self->max_health /4))
  895. self->s.skinnum = 2;
  896. else if (self->health < (self->max_health / 2))
  897. self->s.skinnum = 1;
  898. if (level.time < self->pain_debounce_time)
  899. return;
  900. self->pain_debounce_time = level.time + 3;
  901. gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
  902. if (self->waterlevel)
  903. {
  904. if (!self->flags & FL_SWIM)
  905. self->flags |= FL_SWIM;
  906. self->monsterinfo.currentmove = &gekk_move_pain;
  907. }
  908. else
  909. {
  910. r = random();
  911. if (r > 0.5)
  912. self->monsterinfo.currentmove = &gekk_move_pain1;
  913. else
  914. self->monsterinfo.currentmove = &gekk_move_pain2;
  915. }
  916. }
  917. //
  918. // DEATH
  919. //
  920. void gekk_dead (edict_t *self)
  921. {
  922. // fix this because of no blocking problem
  923. if (self->waterlevel)
  924. {
  925. return;
  926. }
  927. else
  928. {
  929. VectorSet (self->mins, -16, -16, -24);
  930. VectorSet (self->maxs, 16, 16, -8);
  931. self->movetype = MOVETYPE_TOSS;
  932. self->svflags |= SVF_DEADMONSTER;
  933. self->nextthink = 0;
  934. gi.linkentity (self);
  935. }
  936. }
  937. void gekk_gibfest (edict_t *self)
  938. {
  939. int damage = 20;
  940. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  941. ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC);
  942. ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
  943. ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
  944. ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC);
  945. ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC);
  946. ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
  947. ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
  948. ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC);
  949. self->deadflag = DEAD_DEAD;
  950. }
  951. void isgibfest (edict_t *self)
  952. {
  953. if (random() > 0.9)
  954. gekk_gibfest (self);
  955. }
  956. mframe_t gekk_frames_death1[] =
  957. {
  958. ai_move, -5.151, NULL, // frame 0
  959. ai_move, -12.223, NULL, // frame 1
  960. ai_move, -11.484, NULL, // frame 2
  961. ai_move, -17.952, NULL, // frame 3
  962. ai_move, -6.953, NULL, // frame 4
  963. ai_move, -7.393, NULL, // frame 5
  964. ai_move, -10.713, NULL, // frame 6
  965. ai_move, -17.464, NULL, // frame 7
  966. ai_move, -11.678, NULL, // frame 8
  967. ai_move, -11.678, NULL // frame 9
  968. };
  969. mmove_t gekk_move_death1 = {FRAME_death1_01, FRAME_death1_10, gekk_frames_death1, gekk_dead};
  970. mframe_t gekk_frames_death3[] =
  971. {
  972. ai_move, 0.000, NULL, // frame 0
  973. ai_move, 0.022, NULL, // frame 1
  974. ai_move, 0.169, NULL, // frame 2
  975. ai_move, -0.710, NULL, // frame 3
  976. ai_move, -13.446, NULL, // frame 4
  977. ai_move, -7.654, isgibfest, // frame 5
  978. ai_move, -31.951, NULL, // frame 6
  979. };
  980. mmove_t gekk_move_death3 = {FRAME_death3_01, FRAME_death3_07, gekk_frames_death3, gekk_dead};
  981. mframe_t gekk_frames_death4[] =
  982. {
  983. ai_move, 5.103, NULL, // frame 0
  984. ai_move, -4.808, NULL, // frame 1
  985. ai_move, -10.509, NULL, // frame 2
  986. ai_move, -9.899, NULL, // frame 3
  987. ai_move, 4.033, isgibfest, // frame 4
  988. ai_move, -5.197, NULL, // frame 5
  989. ai_move, -0.919, NULL, // frame 6
  990. ai_move, -8.821, NULL, // frame 7
  991. ai_move, -5.626, NULL, // frame 8
  992. ai_move, -8.865, isgibfest, // frame 9
  993. ai_move, -0.845, NULL, // frame 10
  994. ai_move, 1.986, NULL, // frame 11
  995. ai_move, 0.170, NULL, // frame 12
  996. ai_move, 1.339, isgibfest, // frame 13
  997. ai_move, -0.922, NULL, // frame 14
  998. ai_move, 0.818, NULL, // frame 15
  999. ai_move, -1.288, NULL, // frame 16
  1000. ai_move, -1.408, isgibfest, // frame 17
  1001. ai_move, -7.787, NULL, // frame 18
  1002. ai_move, -3.995, NULL, // frame 19
  1003. ai_move, -4.604, NULL, // frame 20
  1004. ai_move, -1.715, isgibfest, // frame 21
  1005. ai_move, -0.564, NULL, // frame 22
  1006. ai_move, -0.597, NULL, // frame 23
  1007. ai_move, 0.074, NULL, // frame 24
  1008. ai_move, -0.309, isgibfest, // frame 25
  1009. ai_move, -0.395, NULL, // frame 26
  1010. ai_move, -0.501, NULL, // frame 27
  1011. ai_move, -0.325, NULL, // frame 28
  1012. ai_move, -0.931, isgibfest, // frame 29
  1013. ai_move, -1.433, NULL, // frame 30
  1014. ai_move, -1.626, NULL, // frame 31
  1015. ai_move, 4.680, NULL, // frame 32
  1016. ai_move, 0.560, NULL, // frame 33
  1017. ai_move, -0.549, gekk_gibfest // frame 34
  1018. };
  1019. mmove_t gekk_move_death4 = {FRAME_death4_01, FRAME_death4_35, gekk_frames_death4, gekk_dead};
  1020. mframe_t gekk_frames_wdeath[] =
  1021. {
  1022. ai_move, 0.000, NULL, // frame 0
  1023. ai_move, 0.000, NULL, // frame 1
  1024. ai_move, 0.000, NULL, // frame 2
  1025. ai_move, 0.000, NULL, // frame 3
  1026. ai_move, 0.000, NULL, // frame 4
  1027. ai_move, 0.000, NULL, // frame 5
  1028. ai_move, 0.000, NULL, // frame 6
  1029. ai_move, 0.000, NULL, // frame 7
  1030. ai_move, 0.000, NULL, // frame 8
  1031. ai_move, 0.000, NULL, // frame 9
  1032. ai_move, 0.000, NULL, // frame 10
  1033. ai_move, 0.000, NULL, // frame 11
  1034. ai_move, 0.000, NULL, // frame 12
  1035. ai_move, 0.000, NULL, // frame 13
  1036. ai_move, 0.000, NULL, // frame 14
  1037. ai_move, 0.000, NULL, // frame 15
  1038. ai_move, 0.000, NULL, // frame 16
  1039. ai_move, 0.000, NULL, // frame 17
  1040. ai_move, 0.000, NULL, // frame 18
  1041. ai_move, 0.000, NULL, // frame 19
  1042. ai_move, 0.000, NULL, // frame 20
  1043. ai_move, 0.000, NULL, // frame 21
  1044. ai_move, 0.000, NULL, // frame 22
  1045. ai_move, 0.000, NULL, // frame 23
  1046. ai_move, 0.000, NULL, // frame 24
  1047. ai_move, 0.000, NULL, // frame 25
  1048. ai_move, 0.000, NULL, // frame 26
  1049. ai_move, 0.000, NULL, // frame 27
  1050. ai_move, 0.000, NULL, // frame 28
  1051. ai_move, 0.000, NULL, // frame 29
  1052. ai_move, 0.000, NULL, // frame 30
  1053. ai_move, 0.000, NULL, // frame 31
  1054. ai_move, 0.000, NULL, // frame 32
  1055. ai_move, 0.000, NULL, // frame 33
  1056. ai_move, 0.000, NULL, // frame 34
  1057. ai_move, 0.000, NULL, // frame 35
  1058. ai_move, 0.000, NULL, // frame 36
  1059. ai_move, 0.000, NULL, // frame 37
  1060. ai_move, 0.000, NULL, // frame 38
  1061. ai_move, 0.000, NULL, // frame 39
  1062. ai_move, 0.000, NULL, // frame 40
  1063. ai_move, 0.000, NULL, // frame 41
  1064. ai_move, 0.000, NULL, // frame 42
  1065. ai_move, 0.000, NULL, // frame 43
  1066. ai_move, 0.000, NULL // frame 44
  1067. };
  1068. mmove_t gekk_move_wdeath = {FRAME_wdeath_01, FRAME_wdeath_45, gekk_frames_wdeath, gekk_dead};
  1069. void gekk_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  1070. {
  1071. float r;
  1072. if (self->health <= self->gib_health)
  1073. {
  1074. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  1075. ThrowGibACID (self, "models/objects/gekkgib/pelvis/tris.md2", damage, GIB_ORGANIC);
  1076. ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
  1077. ThrowGibACID (self, "models/objects/gekkgib/arm/tris.md2", damage, GIB_ORGANIC);
  1078. ThrowGibACID (self, "models/objects/gekkgib/torso/tris.md2", damage, GIB_ORGANIC);
  1079. ThrowGibACID (self, "models/objects/gekkgib/claw/tris.md2", damage, GIB_ORGANIC);
  1080. ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
  1081. ThrowGibACID (self, "models/objects/gekkgib/leg/tris.md2", damage, GIB_ORGANIC);
  1082. ThrowHeadACID (self, "models/objects/gekkgib/head/tris.md2", damage, GIB_ORGANIC);
  1083. self->deadflag = DEAD_DEAD;
  1084. return;
  1085. }
  1086. if (self->deadflag == DEAD_DEAD)
  1087. return;
  1088. gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
  1089. self->deadflag = DEAD_DEAD;
  1090. self->takedamage = DAMAGE_YES;
  1091. self->s.skinnum = 2;
  1092. if (self->waterlevel)
  1093. self->monsterinfo.currentmove = &gekk_move_wdeath;
  1094. else
  1095. {
  1096. r = random();
  1097. if (r > 0.66)
  1098. self->monsterinfo.currentmove = &gekk_move_death1;
  1099. else if (r > 0.33)
  1100. self->monsterinfo.currentmove = &gekk_move_death3;
  1101. else
  1102. self->monsterinfo.currentmove = &gekk_move_death4;
  1103. }
  1104. }
  1105. /*
  1106. duck
  1107. */
  1108. void gekk_duck_down (edict_t *self)
  1109. {
  1110. if (self->monsterinfo.aiflags & AI_DUCKED)
  1111. return;
  1112. self->monsterinfo.aiflags |= AI_DUCKED;
  1113. self->maxs[2] -= 32;
  1114. self->takedamage = DAMAGE_YES;
  1115. self->monsterinfo.pausetime = level.time + 1;
  1116. gi.linkentity (self);
  1117. }
  1118. void gekk_duck_up (edict_t *self)
  1119. {
  1120. self->monsterinfo.aiflags &= ~AI_DUCKED;
  1121. self->maxs[2] += 32;
  1122. self->takedamage = DAMAGE_AIM;
  1123. gi.linkentity (self);
  1124. }
  1125. void gekk_duck_hold (edict_t *self)
  1126. {
  1127. if (level.time >= self->monsterinfo.pausetime)
  1128. self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  1129. else
  1130. self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  1131. }
  1132. mframe_t gekk_frames_lduck[] =
  1133. {
  1134. ai_move, 0.000, NULL, // frame 0
  1135. ai_move, 0.000, NULL, // frame 1
  1136. ai_move, 0.000, NULL, // frame 2
  1137. ai_move, 0.000, NULL, // frame 3
  1138. ai_move, 0.000, NULL, // frame 4
  1139. ai_move, 0.000, NULL, // frame 5
  1140. ai_move, 0.000, NULL, // frame 6
  1141. ai_move, 0.000, NULL, // frame 7
  1142. ai_move, 0.000, NULL, // frame 8
  1143. ai_move, 0.000, NULL, // frame 9
  1144. ai_move, 0.000, NULL, // frame 10
  1145. ai_move, 0.000, NULL, // frame 11
  1146. ai_move, 0.000, NULL // frame 12
  1147. };
  1148. mmove_t gekk_move_lduck = {FRAME_lduck_01, FRAME_lduck_13, gekk_frames_lduck, gekk_run_start};
  1149. mframe_t gekk_frames_rduck[] =
  1150. {
  1151. ai_move, 0.000, NULL, // frame 0
  1152. ai_move, 0.000, NULL, // frame 1
  1153. ai_move, 0.000, NULL, // frame 2
  1154. ai_move, 0.000, NULL, // frame 3
  1155. ai_move, 0.000, NULL, // frame 4
  1156. ai_move, 0.000, NULL, // frame 5
  1157. ai_move, 0.000, NULL, // frame 6
  1158. ai_move, 0.000, NULL, // frame 7
  1159. ai_move, 0.000, NULL, // frame 8
  1160. ai_move, 0.000, NULL, // frame 9
  1161. ai_move, 0.000, NULL, // frame 10
  1162. ai_move, 0.000, NULL, // frame 11
  1163. ai_move, 0.000, NULL // frame 12
  1164. };
  1165. mmove_t gekk_move_rduck = {FRAME_rduck_01, FRAME_rduck_13, gekk_frames_rduck, gekk_run_start};
  1166. void gekk_dodge (edict_t *self, edict_t *attacker, float eta)
  1167. {
  1168. float r;
  1169. r = random();
  1170. if (r > 0.25)
  1171. return;
  1172. if (!self->enemy)
  1173. self->enemy = attacker;
  1174. if (self->waterlevel)
  1175. {
  1176. self->monsterinfo.currentmove = &gekk_move_attack;
  1177. return;
  1178. }
  1179. if (skill->value == 0)
  1180. {
  1181. r = random();
  1182. if (r > 0.5)
  1183. self->monsterinfo.currentmove = &gekk_move_lduck;
  1184. else
  1185. self->monsterinfo.currentmove = &gekk_move_rduck;
  1186. return;
  1187. }
  1188. self->monsterinfo.pausetime = level.time + eta + 0.3;
  1189. r = random();
  1190. if (skill->value == 1)
  1191. {
  1192. if (r > 0.33)
  1193. {
  1194. r = random();
  1195. if (r > 0.5)
  1196. self->monsterinfo.currentmove = &gekk_move_lduck;
  1197. else
  1198. self->monsterinfo.currentmove = &gekk_move_rduck;
  1199. }
  1200. else
  1201. {
  1202. r = random();
  1203. if (r > 0.66)
  1204. self->monsterinfo.currentmove = &gekk_move_attack1;
  1205. else
  1206. self->monsterinfo.currentmove = &gekk_move_attack2;
  1207. }
  1208. return;
  1209. }
  1210. if (skill->value == 2)
  1211. {
  1212. if (r > 0.66)
  1213. {
  1214. r = random();
  1215. if (r > 0.5)
  1216. self->monsterinfo.currentmove = &gekk_move_lduck;
  1217. else
  1218. self->monsterinfo.currentmove = &gekk_move_rduck;
  1219. }
  1220. else
  1221. {
  1222. r = random();
  1223. if (r > 0.66)
  1224. self->monsterinfo.currentmove = &gekk_move_attack1;
  1225. else
  1226. self->monsterinfo.currentmove = &gekk_move_attack2;
  1227. }
  1228. return;
  1229. }
  1230. r = random();
  1231. if (r > 0.66)
  1232. self->monsterinfo.currentmove = &gekk_move_attack1;
  1233. else
  1234. self->monsterinfo.currentmove = &gekk_move_attack2;
  1235. }
  1236. //
  1237. // SPAWN
  1238. //
  1239. /*QUAKED monster_gekk (1 .5 0) (-24 -24 -24) (24 24 24) Ambush Trigger_Spawn Sight Chant
  1240. */
  1241. void SP_monster_gekk (edict_t *self)
  1242. {
  1243. if (deathmatch->value)
  1244. {
  1245. G_FreeEdict (self);
  1246. return;
  1247. }
  1248. sound_swing = gi.soundindex ("gek/gk_atck1.wav");
  1249. sound_hit = gi.soundindex ("gek/gk_atck2.wav");
  1250. sound_hit2 = gi.soundindex ("gek/gk_atck3.wav");
  1251. sound_death = gi.soundindex ("gek/gk_deth1.wav");
  1252. sound_pain1 = gi.soundindex ("gek/gk_pain1.wav");
  1253. sound_sight = gi.soundindex ("gek/gk_sght1.wav");
  1254. sound_search = gi.soundindex ("gek/gk_idle1.wav");
  1255. sound_step1 = gi.soundindex ("gek/gk_step1.wav");
  1256. sound_step2 = gi.soundindex ("gek/gk_step2.wav");
  1257. sound_step3 = gi.soundindex ("gek/gk_step3.wav");
  1258. sound_thud = gi.soundindex ("mutant/thud1.wav");
  1259. sound_chantlow = gi.soundindex ("gek/gek_low.wav");
  1260. sound_chantmid = gi.soundindex ("gek/gek_mid.wav");
  1261. sound_chanthigh = gi.soundindex ("gek/gek_high.wav");
  1262. self->movetype = MOVETYPE_STEP;
  1263. self->solid = SOLID_BBOX;
  1264. self->s.modelindex = gi.modelindex ("models/monsters/gekk/tris.md2");
  1265. VectorSet (self->mins, -24, -24, -24);
  1266. VectorSet (self->maxs, 24, 24, 24);
  1267. gi.modelindex ("models/objects/gekkgib/pelvis/tris.md2");
  1268. gi.modelindex ("models/objects/gekkgib/arm/tris.md2");
  1269. gi.modelindex ("models/objects/gekkgib/torso/tris.md2");
  1270. gi.modelindex ("models/objects/gekkgib/claw/tris.md2");
  1271. gi.modelindex ("models/objects/gekkgib/leg/tris.md2");
  1272. gi.modelindex ("models/objects/gekkgib/head/tris.md2");
  1273. self->health = 125;
  1274. self->gib_health = -30;
  1275. self->mass = 300;
  1276. self->pain = gekk_pain;
  1277. self->die = gekk_die;
  1278. self->monsterinfo.stand = gekk_stand;
  1279. self->monsterinfo.walk = gekk_walk;
  1280. self->monsterinfo.run = gekk_run_start;
  1281. self->monsterinfo.dodge = gekk_dodge;
  1282. self->monsterinfo.attack = gekk_jump;
  1283. self->monsterinfo.melee = gekk_melee;
  1284. self->monsterinfo.sight = gekk_sight;
  1285. self->monsterinfo.search = gekk_search;
  1286. self->monsterinfo.idle = gekk_idle;
  1287. self->monsterinfo.checkattack = gekk_checkattack;
  1288. gi.linkentity (self);
  1289. self->monsterinfo.currentmove = &gekk_move_stand;
  1290. self->monsterinfo.scale = MODEL_SCALE;
  1291. walkmonster_start (self);
  1292. if (self->spawnflags & 8)
  1293. self->monsterinfo.currentmove = &gekk_move_chant;
  1294. }
  1295. void water_to_land (edict_t *self)
  1296. {
  1297. self->flags &= ~FL_SWIM;
  1298. self->yaw_speed = 20;
  1299. self->viewheight = 25;
  1300. self->monsterinfo.currentmove = &gekk_move_leapatk2;
  1301. VectorSet (self->mins, -24, -24, -24);
  1302. VectorSet (self->maxs, 24, 24, 24);
  1303. }
  1304. void land_to_water (edict_t *self)
  1305. {
  1306. self->flags |= FL_SWIM;
  1307. self->yaw_speed = 10;
  1308. self->viewheight = 10;
  1309. self->monsterinfo.currentmove = &gekk_move_swim_start;
  1310. VectorSet (self->mins, -24, -24, -24);
  1311. VectorSet (self->maxs, 24, 24, 16);
  1312. }