m_flipper.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. FLIPPER
  6. ==============================================================================
  7. */
  8. #include "g_local.h"
  9. #include "m_flipper.h"
  10. static int sound_chomp;
  11. static int sound_attack;
  12. static int sound_pain1;
  13. static int sound_pain2;
  14. static int sound_death;
  15. static int sound_idle;
  16. static int sound_search;
  17. static int sound_sight;
  18. void flipper_stand (edict_t *self);
  19. mframe_t flipper_frames_stand [] =
  20. {
  21. ai_stand, 0, NULL
  22. };
  23. mmove_t flipper_move_stand = {FRAME_flphor01, FRAME_flphor01, flipper_frames_stand, NULL};
  24. void flipper_stand (edict_t *self)
  25. {
  26. self->monsterinfo.currentmove = &flipper_move_stand;
  27. }
  28. #define FLIPPER_RUN_SPEED 24
  29. mframe_t flipper_frames_run [] =
  30. {
  31. ai_run, FLIPPER_RUN_SPEED, NULL, // 6
  32. ai_run, FLIPPER_RUN_SPEED, NULL,
  33. ai_run, FLIPPER_RUN_SPEED, NULL,
  34. ai_run, FLIPPER_RUN_SPEED, NULL,
  35. ai_run, FLIPPER_RUN_SPEED, NULL, // 10
  36. ai_run, FLIPPER_RUN_SPEED, NULL,
  37. ai_run, FLIPPER_RUN_SPEED, NULL,
  38. ai_run, FLIPPER_RUN_SPEED, NULL,
  39. ai_run, FLIPPER_RUN_SPEED, NULL,
  40. ai_run, FLIPPER_RUN_SPEED, NULL,
  41. ai_run, FLIPPER_RUN_SPEED, NULL,
  42. ai_run, FLIPPER_RUN_SPEED, NULL,
  43. ai_run, FLIPPER_RUN_SPEED, NULL,
  44. ai_run, FLIPPER_RUN_SPEED, NULL,
  45. ai_run, FLIPPER_RUN_SPEED, NULL, // 20
  46. ai_run, FLIPPER_RUN_SPEED, NULL,
  47. ai_run, FLIPPER_RUN_SPEED, NULL,
  48. ai_run, FLIPPER_RUN_SPEED, NULL,
  49. ai_run, FLIPPER_RUN_SPEED, NULL,
  50. ai_run, FLIPPER_RUN_SPEED, NULL,
  51. ai_run, FLIPPER_RUN_SPEED, NULL,
  52. ai_run, FLIPPER_RUN_SPEED, NULL,
  53. ai_run, FLIPPER_RUN_SPEED, NULL,
  54. ai_run, FLIPPER_RUN_SPEED, NULL // 29
  55. };
  56. mmove_t flipper_move_run_loop = {FRAME_flpver06, FRAME_flpver29, flipper_frames_run, NULL};
  57. void flipper_run_loop (edict_t *self)
  58. {
  59. self->monsterinfo.currentmove = &flipper_move_run_loop;
  60. }
  61. mframe_t flipper_frames_run_start [] =
  62. {
  63. ai_run, 8, NULL,
  64. ai_run, 8, NULL,
  65. ai_run, 8, NULL,
  66. ai_run, 8, NULL,
  67. ai_run, 8, NULL,
  68. ai_run, 8, NULL
  69. };
  70. mmove_t flipper_move_run_start = {FRAME_flpver01, FRAME_flpver06, flipper_frames_run_start, flipper_run_loop};
  71. void flipper_run (edict_t *self)
  72. {
  73. self->monsterinfo.currentmove = &flipper_move_run_start;
  74. }
  75. /* Standard Swimming */
  76. mframe_t flipper_frames_walk [] =
  77. {
  78. ai_walk, 4, NULL,
  79. ai_walk, 4, NULL,
  80. ai_walk, 4, NULL,
  81. ai_walk, 4, NULL,
  82. ai_walk, 4, NULL,
  83. ai_walk, 4, NULL,
  84. ai_walk, 4, NULL,
  85. ai_walk, 4, NULL,
  86. ai_walk, 4, NULL,
  87. ai_walk, 4, NULL,
  88. ai_walk, 4, NULL,
  89. ai_walk, 4, NULL,
  90. ai_walk, 4, NULL,
  91. ai_walk, 4, NULL,
  92. ai_walk, 4, NULL,
  93. ai_walk, 4, NULL,
  94. ai_walk, 4, NULL,
  95. ai_walk, 4, NULL,
  96. ai_walk, 4, NULL,
  97. ai_walk, 4, NULL,
  98. ai_walk, 4, NULL,
  99. ai_walk, 4, NULL,
  100. ai_walk, 4, NULL,
  101. ai_walk, 4, NULL
  102. };
  103. mmove_t flipper_move_walk = {FRAME_flphor01, FRAME_flphor24, flipper_frames_walk, NULL};
  104. void flipper_walk (edict_t *self)
  105. {
  106. self->monsterinfo.currentmove = &flipper_move_walk;
  107. }
  108. mframe_t flipper_frames_start_run [] =
  109. {
  110. ai_run, 8, NULL,
  111. ai_run, 8, NULL,
  112. ai_run, 8, NULL,
  113. ai_run, 8, NULL,
  114. ai_run, 8, flipper_run
  115. };
  116. mmove_t flipper_move_start_run = {FRAME_flphor01, FRAME_flphor05, flipper_frames_start_run, NULL};
  117. void flipper_start_run (edict_t *self)
  118. {
  119. self->monsterinfo.currentmove = &flipper_move_start_run;
  120. }
  121. mframe_t flipper_frames_pain2 [] =
  122. {
  123. ai_move, 0, NULL,
  124. ai_move, 0, NULL,
  125. ai_move, 0, NULL,
  126. ai_move, 0, NULL,
  127. ai_move, 0, NULL
  128. };
  129. mmove_t flipper_move_pain2 = {FRAME_flppn101, FRAME_flppn105, flipper_frames_pain2, flipper_run};
  130. mframe_t flipper_frames_pain1 [] =
  131. {
  132. ai_move, 0, NULL,
  133. ai_move, 0, NULL,
  134. ai_move, 0, NULL,
  135. ai_move, 0, NULL,
  136. ai_move, 0, NULL
  137. };
  138. mmove_t flipper_move_pain1 = {FRAME_flppn201, FRAME_flppn205, flipper_frames_pain1, flipper_run};
  139. void flipper_bite (edict_t *self)
  140. {
  141. vec3_t aim;
  142. VectorSet (aim, MELEE_DISTANCE, 0, 0);
  143. fire_hit (self, aim, 5, 0);
  144. }
  145. void flipper_preattack (edict_t *self)
  146. {
  147. gi.sound (self, CHAN_WEAPON, sound_chomp, 1, ATTN_NORM, 0);
  148. }
  149. mframe_t flipper_frames_attack [] =
  150. {
  151. ai_charge, 0, flipper_preattack,
  152. ai_charge, 0, NULL,
  153. ai_charge, 0, NULL,
  154. ai_charge, 0, NULL,
  155. ai_charge, 0, NULL,
  156. ai_charge, 0, NULL,
  157. ai_charge, 0, NULL,
  158. ai_charge, 0, NULL,
  159. ai_charge, 0, NULL,
  160. ai_charge, 0, NULL,
  161. ai_charge, 0, NULL,
  162. ai_charge, 0, NULL,
  163. ai_charge, 0, NULL,
  164. ai_charge, 0, flipper_bite,
  165. ai_charge, 0, NULL,
  166. ai_charge, 0, NULL,
  167. ai_charge, 0, NULL,
  168. ai_charge, 0, NULL,
  169. ai_charge, 0, flipper_bite,
  170. ai_charge, 0, NULL
  171. };
  172. mmove_t flipper_move_attack = {FRAME_flpbit01, FRAME_flpbit20, flipper_frames_attack, flipper_run};
  173. void flipper_melee(edict_t *self)
  174. {
  175. self->monsterinfo.currentmove = &flipper_move_attack;
  176. }
  177. void flipper_pain (edict_t *self, edict_t *other, float kick, int damage)
  178. {
  179. int n;
  180. if (self->health < (self->max_health / 2))
  181. self->s.skinnum = 1;
  182. if (level.time < self->pain_debounce_time)
  183. return;
  184. self->pain_debounce_time = level.time + 3;
  185. if (skill->value == 3)
  186. return; // no pain anims in nightmare
  187. n = (rand() + 1) % 2;
  188. if (n == 0)
  189. {
  190. gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
  191. self->monsterinfo.currentmove = &flipper_move_pain1;
  192. }
  193. else
  194. {
  195. gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
  196. self->monsterinfo.currentmove = &flipper_move_pain2;
  197. }
  198. }
  199. void flipper_dead (edict_t *self)
  200. {
  201. VectorSet (self->mins, -16, -16, -24);
  202. VectorSet (self->maxs, 16, 16, -8);
  203. self->movetype = MOVETYPE_TOSS;
  204. self->svflags |= SVF_DEADMONSTER;
  205. self->nextthink = 0;
  206. gi.linkentity (self);
  207. }
  208. mframe_t flipper_frames_death [] =
  209. {
  210. ai_move, 0, NULL,
  211. ai_move, 0, NULL,
  212. ai_move, 0, NULL,
  213. ai_move, 0, NULL,
  214. ai_move, 0, NULL,
  215. ai_move, 0, NULL,
  216. ai_move, 0, NULL,
  217. ai_move, 0, NULL,
  218. ai_move, 0, NULL,
  219. ai_move, 0, NULL,
  220. ai_move, 0, NULL,
  221. ai_move, 0, NULL,
  222. ai_move, 0, NULL,
  223. ai_move, 0, NULL,
  224. ai_move, 0, NULL,
  225. ai_move, 0, NULL,
  226. ai_move, 0, NULL,
  227. ai_move, 0, NULL,
  228. ai_move, 0, NULL,
  229. ai_move, 0, NULL,
  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,
  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, 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,
  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,
  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. };
  267. mmove_t flipper_move_death = {FRAME_flpdth01, FRAME_flpdth56, flipper_frames_death, flipper_dead};
  268. void flipper_sight (edict_t *self, edict_t *other)
  269. {
  270. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  271. }
  272. void flipper_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  273. {
  274. int n;
  275. // check for gib
  276. if (self->health <= self->gib_health)
  277. {
  278. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  279. for (n= 0; n < 2; n++)
  280. ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  281. for (n= 0; n < 2; n++)
  282. ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  283. ThrowHead (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  284. self->deadflag = DEAD_DEAD;
  285. return;
  286. }
  287. if (self->deadflag == DEAD_DEAD)
  288. return;
  289. // regular death
  290. gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
  291. self->deadflag = DEAD_DEAD;
  292. self->takedamage = DAMAGE_YES;
  293. self->monsterinfo.currentmove = &flipper_move_death;
  294. }
  295. /*QUAKED monster_flipper (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
  296. */
  297. void SP_monster_flipper (edict_t *self)
  298. {
  299. if (deathmatch->value)
  300. {
  301. G_FreeEdict (self);
  302. return;
  303. }
  304. sound_pain1 = gi.soundindex ("flipper/flppain1.wav");
  305. sound_pain2 = gi.soundindex ("flipper/flppain2.wav");
  306. sound_death = gi.soundindex ("flipper/flpdeth1.wav");
  307. sound_chomp = gi.soundindex ("flipper/flpatck1.wav");
  308. sound_attack = gi.soundindex ("flipper/flpatck2.wav");
  309. sound_idle = gi.soundindex ("flipper/flpidle1.wav");
  310. sound_search = gi.soundindex ("flipper/flpsrch1.wav");
  311. sound_sight = gi.soundindex ("flipper/flpsght1.wav");
  312. self->movetype = MOVETYPE_STEP;
  313. self->solid = SOLID_BBOX;
  314. self->s.modelindex = gi.modelindex ("models/monsters/flipper/tris.md2");
  315. VectorSet (self->mins, -16, -16, 0);
  316. VectorSet (self->maxs, 16, 16, 32);
  317. self->health = 50;
  318. self->gib_health = -30;
  319. self->mass = 100;
  320. self->pain = flipper_pain;
  321. self->die = flipper_die;
  322. self->monsterinfo.stand = flipper_stand;
  323. self->monsterinfo.walk = flipper_walk;
  324. self->monsterinfo.run = flipper_start_run;
  325. self->monsterinfo.melee = flipper_melee;
  326. self->monsterinfo.sight = flipper_sight;
  327. gi.linkentity (self);
  328. self->monsterinfo.currentmove = &flipper_move_stand;
  329. self->monsterinfo.scale = MODEL_SCALE;
  330. swimmonster_start (self);
  331. }