m_gladb.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. GLADIATOR BOSS
  6. ==============================================================================
  7. */
  8. #include "g_local.h"
  9. #include "m_gladiator.h"
  10. static int sound_pain1;
  11. static int sound_pain2;
  12. static int sound_die;
  13. static int sound_gun;
  14. static int sound_cleaver_swing;
  15. static int sound_cleaver_hit;
  16. static int sound_cleaver_miss;
  17. static int sound_idle;
  18. static int sound_search;
  19. static int sound_sight;
  20. void gladb_idle (edict_t *self)
  21. {
  22. gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  23. }
  24. void gladb_sight (edict_t *self, edict_t *other)
  25. {
  26. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  27. }
  28. void gladb_search (edict_t *self)
  29. {
  30. gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
  31. }
  32. void gladb_cleaver_swing (edict_t *self)
  33. {
  34. gi.sound (self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0);
  35. }
  36. mframe_t gladb_frames_stand [] =
  37. {
  38. ai_stand, 0, NULL,
  39. ai_stand, 0, NULL,
  40. ai_stand, 0, NULL,
  41. ai_stand, 0, NULL,
  42. ai_stand, 0, NULL,
  43. ai_stand, 0, NULL,
  44. ai_stand, 0, NULL
  45. };
  46. mmove_t gladb_move_stand = {FRAME_stand1, FRAME_stand7, gladb_frames_stand, NULL};
  47. void gladb_stand (edict_t *self)
  48. {
  49. self->monsterinfo.currentmove = &gladb_move_stand;
  50. }
  51. mframe_t gladb_frames_walk [] =
  52. {
  53. ai_walk, 15, NULL,
  54. ai_walk, 7, NULL,
  55. ai_walk, 6, NULL,
  56. ai_walk, 5, NULL,
  57. ai_walk, 2, NULL,
  58. ai_walk, 0, NULL,
  59. ai_walk, 2, NULL,
  60. ai_walk, 8, NULL,
  61. ai_walk, 12, NULL,
  62. ai_walk, 8, NULL,
  63. ai_walk, 5, NULL,
  64. ai_walk, 5, NULL,
  65. ai_walk, 2, NULL,
  66. ai_walk, 2, NULL,
  67. ai_walk, 1, NULL,
  68. ai_walk, 8, NULL
  69. };
  70. mmove_t gladb_move_walk = {FRAME_walk1, FRAME_walk16, gladb_frames_walk, NULL};
  71. void gladb_walk (edict_t *self)
  72. {
  73. self->monsterinfo.currentmove = &gladb_move_walk;
  74. }
  75. mframe_t gladb_frames_run [] =
  76. {
  77. ai_run, 23, NULL,
  78. ai_run, 14, NULL,
  79. ai_run, 14, NULL,
  80. ai_run, 21, NULL,
  81. ai_run, 12, NULL,
  82. ai_run, 13, NULL
  83. };
  84. mmove_t gladb_move_run = {FRAME_run1, FRAME_run6, gladb_frames_run, NULL};
  85. void gladb_run (edict_t *self)
  86. {
  87. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  88. self->monsterinfo.currentmove = &gladb_move_stand;
  89. else
  90. self->monsterinfo.currentmove = &gladb_move_run;
  91. }
  92. void GladbMelee (edict_t *self)
  93. {
  94. vec3_t aim;
  95. VectorSet (aim, MELEE_DISTANCE, self->mins[0], -4);
  96. if (fire_hit (self, aim, (20 + (rand() %5)), 300))
  97. gi.sound (self, CHAN_AUTO, sound_cleaver_hit, 1, ATTN_NORM, 0);
  98. else
  99. gi.sound (self, CHAN_AUTO, sound_cleaver_miss, 1, ATTN_NORM, 0);
  100. }
  101. mframe_t gladb_frames_attack_melee [] =
  102. {
  103. ai_charge, 0, NULL,
  104. ai_charge, 0, NULL,
  105. ai_charge, 0, NULL,
  106. ai_charge, 0, NULL,
  107. ai_charge, 0, gladb_cleaver_swing,
  108. ai_charge, 0, NULL,
  109. ai_charge, 0, GladbMelee,
  110. ai_charge, 0, NULL,
  111. ai_charge, 0, NULL,
  112. ai_charge, 0, NULL,
  113. ai_charge, 0, gladb_cleaver_swing,
  114. ai_charge, 0, NULL,
  115. ai_charge, 0, NULL,
  116. ai_charge, 0, GladbMelee,
  117. ai_charge, 0, NULL,
  118. ai_charge, 0, NULL,
  119. ai_charge, 0, NULL
  120. };
  121. mmove_t gladb_move_attack_melee = {FRAME_melee1, FRAME_melee17, gladb_frames_attack_melee, gladb_run};
  122. void gladb_melee(edict_t *self)
  123. {
  124. self->monsterinfo.currentmove = &gladb_move_attack_melee;
  125. }
  126. void gladbGun (edict_t *self)
  127. {
  128. vec3_t start;
  129. vec3_t dir;
  130. vec3_t forward, right;
  131. AngleVectors (self->s.angles, forward, right, NULL);
  132. G_ProjectSource (self->s.origin, monster_flash_offset[MZ2_GLADIATOR_RAILGUN_1], forward, right, start);
  133. // calc direction to where we targted
  134. VectorSubtract (self->pos1, start, dir);
  135. VectorNormalize (dir);
  136. fire_plasma (self, start, dir, 100, 725, 60, 60);
  137. }
  138. void gladbGun_check (edict_t *self)
  139. {
  140. if (skill->value == 3)
  141. gladbGun (self);
  142. }
  143. mframe_t gladb_frames_attack_gun [] =
  144. {
  145. ai_charge, 0, NULL,
  146. ai_charge, 0, NULL,
  147. ai_charge, 0, gladbGun,
  148. ai_charge, 0, NULL,
  149. ai_charge, 0, NULL,
  150. ai_charge, 0, gladbGun,
  151. ai_charge, 0, NULL,
  152. ai_charge, 0, NULL,
  153. ai_charge, 0, gladbGun_check
  154. };
  155. mmove_t gladb_move_attack_gun = {FRAME_attack1, FRAME_attack9, gladb_frames_attack_gun, gladb_run};
  156. void gladb_attack(edict_t *self)
  157. {
  158. float range;
  159. vec3_t v;
  160. // a small safe zone
  161. VectorSubtract (self->s.origin, self->enemy->s.origin, v);
  162. range = VectorLength(v);
  163. if (range <= (MELEE_DISTANCE + 32))
  164. return;
  165. // charge up the railgun
  166. gi.sound (self, CHAN_WEAPON, sound_gun, 1, ATTN_NORM, 0);
  167. VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot
  168. self->pos1[2] += self->enemy->viewheight;
  169. self->monsterinfo.currentmove = &gladb_move_attack_gun;
  170. }
  171. mframe_t gladb_frames_pain [] =
  172. {
  173. ai_move, 0, NULL,
  174. ai_move, 0, NULL,
  175. ai_move, 0, NULL,
  176. ai_move, 0, NULL,
  177. ai_move, 0, NULL,
  178. ai_move, 0, NULL
  179. };
  180. mmove_t gladb_move_pain = {FRAME_pain1, FRAME_pain6, gladb_frames_pain, gladb_run};
  181. mframe_t gladb_frames_pain_air [] =
  182. {
  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,
  189. ai_move, 0, NULL
  190. };
  191. mmove_t gladb_move_pain_air = {FRAME_painup1, FRAME_painup7, gladb_frames_pain_air, gladb_run};
  192. void gladb_pain (edict_t *self, edict_t *other, float kick, int damage)
  193. {
  194. if (self->health < (self->max_health / 2))
  195. self->s.skinnum = 1;
  196. if (level.time < self->pain_debounce_time)
  197. {
  198. if ((self->velocity[2] > 100) && (self->monsterinfo.currentmove == &gladb_move_pain))
  199. self->monsterinfo.currentmove = &gladb_move_pain_air;
  200. return;
  201. }
  202. self->pain_debounce_time = level.time + 3;
  203. if (random() < 0.5)
  204. gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
  205. else
  206. gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
  207. if (self->velocity[2] > 100)
  208. self->monsterinfo.currentmove = &gladb_move_pain_air;
  209. else
  210. self->monsterinfo.currentmove = &gladb_move_pain;
  211. }
  212. void gladb_dead (edict_t *self)
  213. {
  214. VectorSet (self->mins, -16, -16, -24);
  215. VectorSet (self->maxs, 16, 16, -8);
  216. self->movetype = MOVETYPE_TOSS;
  217. self->svflags |= SVF_DEADMONSTER;
  218. self->nextthink = 0;
  219. gi.linkentity (self);
  220. }
  221. mframe_t gladb_frames_death [] =
  222. {
  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. };
  246. mmove_t gladb_move_death = {FRAME_death1, FRAME_death22, gladb_frames_death, gladb_dead};
  247. void gladb_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  248. {
  249. int n;
  250. // check for gib
  251. if (self->health <= self->gib_health)
  252. {
  253. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  254. for (n= 0; n < 2; n++)
  255. ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  256. for (n= 0; n < 4; n++)
  257. ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  258. ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  259. self->deadflag = DEAD_DEAD;
  260. return;
  261. }
  262. if (self->deadflag == DEAD_DEAD)
  263. return;
  264. // regular death
  265. gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
  266. self->deadflag = DEAD_DEAD;
  267. self->takedamage = DAMAGE_YES;
  268. self->monsterinfo.currentmove = &gladb_move_death;
  269. }
  270. /*QUAKED monster_gladb (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight
  271. */
  272. void SP_monster_gladb (edict_t *self)
  273. {
  274. if (deathmatch->value)
  275. {
  276. G_FreeEdict (self);
  277. return;
  278. }
  279. sound_pain1 = gi.soundindex ("gladiator/pain.wav");
  280. sound_pain2 = gi.soundindex ("gladiator/gldpain2.wav");
  281. sound_die = gi.soundindex ("gladiator/glddeth2.wav");
  282. // note to self
  283. // need to change to PHALANX sound
  284. sound_gun = gi.soundindex ("weapons/plasshot.wav");
  285. sound_cleaver_swing = gi.soundindex ("gladiator/melee1.wav");
  286. sound_cleaver_hit = gi.soundindex ("gladiator/melee2.wav");
  287. sound_cleaver_miss = gi.soundindex ("gladiator/melee3.wav");
  288. sound_idle = gi.soundindex ("gladiator/gldidle1.wav");
  289. sound_search = gi.soundindex ("gladiator/gldsrch1.wav");
  290. sound_sight = gi.soundindex ("gladiator/sight.wav");
  291. self->movetype = MOVETYPE_STEP;
  292. self->solid = SOLID_BBOX;
  293. self->s.modelindex = gi.modelindex ("models/monsters/gladb/tris.md2");
  294. VectorSet (self->mins, -32, -32, -24);
  295. VectorSet (self->maxs, 32, 32, 64);
  296. self->health = 800;
  297. self->gib_health = -175;
  298. self->mass = 350;
  299. self->pain = gladb_pain;
  300. self->die = gladb_die;
  301. self->monsterinfo.stand = gladb_stand;
  302. self->monsterinfo.walk = gladb_walk;
  303. self->monsterinfo.run = gladb_run;
  304. self->monsterinfo.dodge = NULL;
  305. self->monsterinfo.attack = gladb_attack;
  306. self->monsterinfo.melee = gladb_melee;
  307. self->monsterinfo.sight = gladb_sight;
  308. self->monsterinfo.idle = gladb_idle;
  309. self->monsterinfo.search = gladb_search;
  310. gi.linkentity (self);
  311. self->monsterinfo.currentmove = &gladb_move_stand;
  312. self->monsterinfo.scale = MODEL_SCALE;
  313. self->monsterinfo.power_armor_type = POWER_ARMOR_SHIELD;
  314. self->monsterinfo.power_armor_power = 400;
  315. walkmonster_start (self);
  316. }