m_gladiator.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. GLADIATOR
  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 gladiator_idle (edict_t *self)
  21. {
  22. gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  23. }
  24. void gladiator_sight (edict_t *self, edict_t *other)
  25. {
  26. gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  27. }
  28. void gladiator_search (edict_t *self)
  29. {
  30. gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
  31. }
  32. void gladiator_cleaver_swing (edict_t *self)
  33. {
  34. gi.sound (self, CHAN_WEAPON, sound_cleaver_swing, 1, ATTN_NORM, 0);
  35. }
  36. mframe_t gladiator_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 gladiator_move_stand = {FRAME_stand1, FRAME_stand7, gladiator_frames_stand, NULL};
  47. void gladiator_stand (edict_t *self)
  48. {
  49. self->monsterinfo.currentmove = &gladiator_move_stand;
  50. }
  51. mframe_t gladiator_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 gladiator_move_walk = {FRAME_walk1, FRAME_walk16, gladiator_frames_walk, NULL};
  71. void gladiator_walk (edict_t *self)
  72. {
  73. self->monsterinfo.currentmove = &gladiator_move_walk;
  74. }
  75. mframe_t gladiator_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 gladiator_move_run = {FRAME_run1, FRAME_run6, gladiator_frames_run, NULL};
  85. void gladiator_run (edict_t *self)
  86. {
  87. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  88. self->monsterinfo.currentmove = &gladiator_move_stand;
  89. else
  90. self->monsterinfo.currentmove = &gladiator_move_run;
  91. }
  92. void GaldiatorMelee (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 gladiator_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, gladiator_cleaver_swing,
  108. ai_charge, 0, NULL,
  109. ai_charge, 0, GaldiatorMelee,
  110. ai_charge, 0, NULL,
  111. ai_charge, 0, NULL,
  112. ai_charge, 0, NULL,
  113. ai_charge, 0, gladiator_cleaver_swing,
  114. ai_charge, 0, NULL,
  115. ai_charge, 0, NULL,
  116. ai_charge, 0, GaldiatorMelee,
  117. ai_charge, 0, NULL,
  118. ai_charge, 0, NULL,
  119. ai_charge, 0, NULL
  120. };
  121. mmove_t gladiator_move_attack_melee = {FRAME_melee1, FRAME_melee17, gladiator_frames_attack_melee, gladiator_run};
  122. void gladiator_melee(edict_t *self)
  123. {
  124. self->monsterinfo.currentmove = &gladiator_move_attack_melee;
  125. }
  126. void GladiatorGun (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. monster_fire_railgun (self, start, dir, 50, 100, MZ2_GLADIATOR_RAILGUN_1);
  137. }
  138. mframe_t gladiator_frames_attack_gun [] =
  139. {
  140. ai_charge, 0, NULL,
  141. ai_charge, 0, NULL,
  142. ai_charge, 0, NULL,
  143. ai_charge, 0, GladiatorGun,
  144. ai_charge, 0, NULL,
  145. ai_charge, 0, NULL,
  146. ai_charge, 0, NULL,
  147. ai_charge, 0, NULL,
  148. ai_charge, 0, NULL
  149. };
  150. mmove_t gladiator_move_attack_gun = {FRAME_attack1, FRAME_attack9, gladiator_frames_attack_gun, gladiator_run};
  151. void gladiator_attack(edict_t *self)
  152. {
  153. float range;
  154. vec3_t v;
  155. // a small safe zone
  156. VectorSubtract (self->s.origin, self->enemy->s.origin, v);
  157. range = VectorLength(v);
  158. if (range <= (MELEE_DISTANCE + 32))
  159. return;
  160. // charge up the railgun
  161. gi.sound (self, CHAN_WEAPON, sound_gun, 1, ATTN_NORM, 0);
  162. VectorCopy (self->enemy->s.origin, self->pos1); //save for aiming the shot
  163. self->pos1[2] += self->enemy->viewheight;
  164. self->monsterinfo.currentmove = &gladiator_move_attack_gun;
  165. }
  166. mframe_t gladiator_frames_pain [] =
  167. {
  168. ai_move, 0, NULL,
  169. ai_move, 0, NULL,
  170. ai_move, 0, NULL,
  171. ai_move, 0, NULL,
  172. ai_move, 0, NULL,
  173. ai_move, 0, NULL
  174. };
  175. mmove_t gladiator_move_pain = {FRAME_pain1, FRAME_pain6, gladiator_frames_pain, gladiator_run};
  176. mframe_t gladiator_frames_pain_air [] =
  177. {
  178. ai_move, 0, NULL,
  179. ai_move, 0, NULL,
  180. ai_move, 0, NULL,
  181. ai_move, 0, NULL,
  182. ai_move, 0, NULL,
  183. ai_move, 0, NULL,
  184. ai_move, 0, NULL
  185. };
  186. mmove_t gladiator_move_pain_air = {FRAME_painup1, FRAME_painup7, gladiator_frames_pain_air, gladiator_run};
  187. void gladiator_pain (edict_t *self, edict_t *other, float kick, int damage)
  188. {
  189. if (self->health < (self->max_health / 2))
  190. self->s.skinnum = 1;
  191. if (level.time < self->pain_debounce_time)
  192. {
  193. if ((self->velocity[2] > 100) && (self->monsterinfo.currentmove == &gladiator_move_pain))
  194. self->monsterinfo.currentmove = &gladiator_move_pain_air;
  195. return;
  196. }
  197. self->pain_debounce_time = level.time + 3;
  198. if (random() < 0.5)
  199. gi.sound (self, CHAN_VOICE, sound_pain1, 1, ATTN_NORM, 0);
  200. else
  201. gi.sound (self, CHAN_VOICE, sound_pain2, 1, ATTN_NORM, 0);
  202. if (skill->value == 3)
  203. return; // no pain anims in nightmare
  204. if (self->velocity[2] > 100)
  205. self->monsterinfo.currentmove = &gladiator_move_pain_air;
  206. else
  207. self->monsterinfo.currentmove = &gladiator_move_pain;
  208. }
  209. void gladiator_dead (edict_t *self)
  210. {
  211. VectorSet (self->mins, -16, -16, -24);
  212. VectorSet (self->maxs, 16, 16, -8);
  213. self->movetype = MOVETYPE_TOSS;
  214. self->svflags |= SVF_DEADMONSTER;
  215. self->nextthink = 0;
  216. gi.linkentity (self);
  217. }
  218. mframe_t gladiator_frames_death [] =
  219. {
  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. };
  243. mmove_t gladiator_move_death = {FRAME_death1, FRAME_death22, gladiator_frames_death, gladiator_dead};
  244. void gladiator_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  245. {
  246. int n;
  247. // check for gib
  248. if (self->health <= self->gib_health)
  249. {
  250. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  251. for (n= 0; n < 2; n++)
  252. ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC);
  253. for (n= 0; n < 4; n++)
  254. ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  255. ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  256. self->deadflag = DEAD_DEAD;
  257. return;
  258. }
  259. if (self->deadflag == DEAD_DEAD)
  260. return;
  261. // regular death
  262. gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
  263. self->deadflag = DEAD_DEAD;
  264. self->takedamage = DAMAGE_YES;
  265. self->monsterinfo.currentmove = &gladiator_move_death;
  266. }
  267. //===========
  268. //PGM
  269. qboolean gladiator_blocked (edict_t *self, float dist)
  270. {
  271. if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
  272. return true;
  273. if(blocked_checkplat (self, dist))
  274. return true;
  275. return false;
  276. }
  277. //PGM
  278. //===========
  279. /*QUAKED monster_gladiator (1 .5 0) (-32 -32 -24) (32 32 64) Ambush Trigger_Spawn Sight
  280. */
  281. void SP_monster_gladiator (edict_t *self)
  282. {
  283. if (deathmatch->value)
  284. {
  285. G_FreeEdict (self);
  286. return;
  287. }
  288. sound_pain1 = gi.soundindex ("gladiator/pain.wav");
  289. sound_pain2 = gi.soundindex ("gladiator/gldpain2.wav");
  290. sound_die = gi.soundindex ("gladiator/glddeth2.wav");
  291. sound_gun = gi.soundindex ("gladiator/railgun.wav");
  292. sound_cleaver_swing = gi.soundindex ("gladiator/melee1.wav");
  293. sound_cleaver_hit = gi.soundindex ("gladiator/melee2.wav");
  294. sound_cleaver_miss = gi.soundindex ("gladiator/melee3.wav");
  295. sound_idle = gi.soundindex ("gladiator/gldidle1.wav");
  296. sound_search = gi.soundindex ("gladiator/gldsrch1.wav");
  297. sound_sight = gi.soundindex ("gladiator/sight.wav");
  298. self->movetype = MOVETYPE_STEP;
  299. self->solid = SOLID_BBOX;
  300. self->s.modelindex = gi.modelindex ("models/monsters/gladiatr/tris.md2");
  301. VectorSet (self->mins, -32, -32, -24);
  302. VectorSet (self->maxs, 32, 32, 64);
  303. self->health = 400;
  304. self->gib_health = -175;
  305. self->mass = 400;
  306. self->pain = gladiator_pain;
  307. self->die = gladiator_die;
  308. self->monsterinfo.stand = gladiator_stand;
  309. self->monsterinfo.walk = gladiator_walk;
  310. self->monsterinfo.run = gladiator_run;
  311. self->monsterinfo.dodge = NULL;
  312. self->monsterinfo.attack = gladiator_attack;
  313. self->monsterinfo.melee = gladiator_melee;
  314. self->monsterinfo.sight = gladiator_sight;
  315. self->monsterinfo.idle = gladiator_idle;
  316. self->monsterinfo.search = gladiator_search;
  317. self->monsterinfo.blocked = gladiator_blocked; // PGM
  318. gi.linkentity (self);
  319. self->monsterinfo.currentmove = &gladiator_move_stand;
  320. self->monsterinfo.scale = MODEL_SCALE;
  321. walkmonster_start (self);
  322. }