m_soldier.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. // Copyright (c) ZeniMax Media Inc.
  2. // Licensed under the GNU General Public License 2.0.
  3. /*
  4. ==============================================================================
  5. SOLDIER
  6. ==============================================================================
  7. */
  8. #include "g_local.h"
  9. #include "m_soldier.h"
  10. //ROGUE
  11. #define RUN_SHOOT 1
  12. #define CHECK_TARGET 1
  13. //ROGUE
  14. static int sound_idle;
  15. static int sound_sight1;
  16. static int sound_sight2;
  17. static int sound_pain_light;
  18. static int sound_pain;
  19. static int sound_pain_ss;
  20. static int sound_death_light;
  21. static int sound_death;
  22. static int sound_death_ss;
  23. static int sound_cock;
  24. void soldier_duck_up (edict_t *self);
  25. void soldier_start_charge (edict_t *self)
  26. {
  27. self->monsterinfo.aiflags |= AI_CHARGING;
  28. }
  29. void soldier_stop_charge (edict_t *self)
  30. {
  31. self->monsterinfo.aiflags &= ~AI_CHARGING;
  32. }
  33. void soldier_idle (edict_t *self)
  34. {
  35. if (random() > 0.8)
  36. gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  37. }
  38. void soldier_cock (edict_t *self)
  39. {
  40. if (self->s.frame == FRAME_stand322)
  41. gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_IDLE, 0);
  42. else
  43. gi.sound (self, CHAN_WEAPON, sound_cock, 1, ATTN_NORM, 0);
  44. }
  45. // STAND
  46. void soldier_stand (edict_t *self);
  47. mframe_t soldier_frames_stand1 [] =
  48. {
  49. ai_stand, 0, soldier_idle,
  50. ai_stand, 0, NULL,
  51. ai_stand, 0, NULL,
  52. ai_stand, 0, NULL,
  53. ai_stand, 0, NULL,
  54. ai_stand, 0, NULL,
  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,
  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,
  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. };
  80. mmove_t soldier_move_stand1 = {FRAME_stand101, FRAME_stand130, soldier_frames_stand1, soldier_stand};
  81. mframe_t soldier_frames_stand3 [] =
  82. {
  83. ai_stand, 0, NULL,
  84. ai_stand, 0, NULL,
  85. ai_stand, 0, NULL,
  86. ai_stand, 0, NULL,
  87. ai_stand, 0, NULL,
  88. ai_stand, 0, NULL,
  89. ai_stand, 0, NULL,
  90. ai_stand, 0, NULL,
  91. ai_stand, 0, NULL,
  92. ai_stand, 0, NULL,
  93. ai_stand, 0, NULL,
  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, 0, NULL,
  101. ai_stand, 0, NULL,
  102. ai_stand, 0, NULL,
  103. ai_stand, 0, NULL,
  104. ai_stand, 0, soldier_cock,
  105. ai_stand, 0, NULL,
  106. ai_stand, 0, NULL,
  107. ai_stand, 0, NULL,
  108. ai_stand, 0, NULL,
  109. ai_stand, 0, NULL,
  110. ai_stand, 0, NULL,
  111. ai_stand, 0, NULL,
  112. ai_stand, 0, NULL,
  113. ai_stand, 0, NULL,
  114. ai_stand, 0, NULL,
  115. ai_stand, 0, NULL,
  116. ai_stand, 0, NULL,
  117. ai_stand, 0, NULL,
  118. ai_stand, 0, NULL,
  119. ai_stand, 0, NULL,
  120. ai_stand, 0, NULL,
  121. ai_stand, 0, NULL
  122. };
  123. mmove_t soldier_move_stand3 = {FRAME_stand301, FRAME_stand339, soldier_frames_stand3, soldier_stand};
  124. #if 0
  125. mframe_t soldier_frames_stand4 [] =
  126. {
  127. ai_stand, 0, NULL,
  128. ai_stand, 0, NULL,
  129. ai_stand, 0, NULL,
  130. ai_stand, 0, NULL,
  131. ai_stand, 0, NULL,
  132. ai_stand, 0, NULL,
  133. ai_stand, 0, NULL,
  134. ai_stand, 0, NULL,
  135. ai_stand, 0, NULL,
  136. ai_stand, 0, NULL,
  137. ai_stand, 0, NULL,
  138. ai_stand, 0, NULL,
  139. ai_stand, 0, NULL,
  140. ai_stand, 0, NULL,
  141. ai_stand, 0, NULL,
  142. ai_stand, 0, NULL,
  143. ai_stand, 0, NULL,
  144. ai_stand, 0, NULL,
  145. ai_stand, 0, NULL,
  146. ai_stand, 0, NULL,
  147. ai_stand, 0, NULL,
  148. ai_stand, 0, NULL,
  149. ai_stand, 0, NULL,
  150. ai_stand, 0, NULL,
  151. ai_stand, 0, NULL,
  152. ai_stand, 0, NULL,
  153. ai_stand, 0, NULL,
  154. ai_stand, 0, NULL,
  155. ai_stand, 0, NULL,
  156. ai_stand, 0, NULL,
  157. ai_stand, 0, NULL,
  158. ai_stand, 0, NULL,
  159. ai_stand, 0, NULL,
  160. ai_stand, 0, NULL,
  161. ai_stand, 0, NULL,
  162. ai_stand, 0, NULL,
  163. ai_stand, 0, NULL,
  164. ai_stand, 0, NULL,
  165. ai_stand, 0, NULL,
  166. ai_stand, 0, NULL,
  167. ai_stand, 0, NULL,
  168. ai_stand, 0, NULL,
  169. ai_stand, 0, NULL,
  170. ai_stand, 0, NULL,
  171. ai_stand, 0, NULL,
  172. ai_stand, 0, NULL,
  173. ai_stand, 4, NULL,
  174. ai_stand, 1, NULL,
  175. ai_stand, -1, NULL,
  176. ai_stand, -2, NULL,
  177. ai_stand, 0, NULL,
  178. ai_stand, 0, NULL
  179. };
  180. mmove_t soldier_move_stand4 = {FRAME_stand401, FRAME_stand452, soldier_frames_stand4, NULL};
  181. #endif
  182. void soldier_stand (edict_t *self)
  183. {
  184. if ((self->monsterinfo.currentmove == &soldier_move_stand3) || (random() < 0.8))
  185. self->monsterinfo.currentmove = &soldier_move_stand1;
  186. else
  187. self->monsterinfo.currentmove = &soldier_move_stand3;
  188. }
  189. //
  190. // WALK
  191. //
  192. void soldier_walk1_random (edict_t *self)
  193. {
  194. if (random() > 0.1)
  195. self->monsterinfo.nextframe = FRAME_walk101;
  196. }
  197. mframe_t soldier_frames_walk1 [] =
  198. {
  199. ai_walk, 3, NULL,
  200. ai_walk, 6, NULL,
  201. ai_walk, 2, NULL,
  202. ai_walk, 2, NULL,
  203. ai_walk, 2, NULL,
  204. ai_walk, 1, NULL,
  205. ai_walk, 6, NULL,
  206. ai_walk, 5, NULL,
  207. ai_walk, 3, NULL,
  208. ai_walk, -1, soldier_walk1_random,
  209. ai_walk, 0, NULL,
  210. ai_walk, 0, NULL,
  211. ai_walk, 0, NULL,
  212. ai_walk, 0, NULL,
  213. ai_walk, 0, NULL,
  214. ai_walk, 0, NULL,
  215. ai_walk, 0, NULL,
  216. ai_walk, 0, NULL,
  217. ai_walk, 0, NULL,
  218. ai_walk, 0, NULL,
  219. ai_walk, 0, NULL,
  220. ai_walk, 0, NULL,
  221. ai_walk, 0, NULL,
  222. ai_walk, 0, NULL,
  223. ai_walk, 0, NULL,
  224. ai_walk, 0, NULL,
  225. ai_walk, 0, NULL,
  226. ai_walk, 0, NULL,
  227. ai_walk, 0, NULL,
  228. ai_walk, 0, NULL,
  229. ai_walk, 0, NULL,
  230. ai_walk, 0, NULL,
  231. ai_walk, 0, NULL
  232. };
  233. mmove_t soldier_move_walk1 = {FRAME_walk101, FRAME_walk133, soldier_frames_walk1, NULL};
  234. mframe_t soldier_frames_walk2 [] =
  235. {
  236. ai_walk, 4, NULL,
  237. ai_walk, 4, NULL,
  238. ai_walk, 9, NULL,
  239. ai_walk, 8, NULL,
  240. ai_walk, 5, NULL,
  241. ai_walk, 1, NULL,
  242. ai_walk, 3, NULL,
  243. ai_walk, 7, NULL,
  244. ai_walk, 6, NULL,
  245. ai_walk, 7, NULL
  246. };
  247. mmove_t soldier_move_walk2 = {FRAME_walk209, FRAME_walk218, soldier_frames_walk2, NULL};
  248. void soldier_walk (edict_t *self)
  249. {
  250. if (random() < 0.5)
  251. self->monsterinfo.currentmove = &soldier_move_walk1;
  252. else
  253. self->monsterinfo.currentmove = &soldier_move_walk2;
  254. }
  255. //
  256. // RUN
  257. //
  258. void soldier_run (edict_t *self);
  259. mframe_t soldier_frames_start_run [] =
  260. {
  261. ai_run, 7, NULL,
  262. ai_run, 5, NULL
  263. };
  264. mmove_t soldier_move_start_run = {FRAME_run01, FRAME_run02, soldier_frames_start_run, soldier_run};
  265. #ifdef RUN_SHOOT
  266. void soldier_fire (edict_t *self, int);
  267. void soldier_fire_run (edict_t *self) {
  268. if ((self->s.skinnum <= 1) && (self->enemy) && visible(self, self->enemy)) {
  269. soldier_fire(self, 0);
  270. }
  271. }
  272. #endif
  273. mframe_t soldier_frames_run [] =
  274. {
  275. ai_run, 10, NULL,
  276. ai_run, 11, monster_done_dodge,
  277. ai_run, 11, NULL,
  278. ai_run, 16, NULL,
  279. ai_run, 10, NULL,
  280. ai_run, 15, monster_done_dodge
  281. };
  282. mmove_t soldier_move_run = {FRAME_run03, FRAME_run08, soldier_frames_run, NULL};
  283. void soldier_run (edict_t *self)
  284. {
  285. monster_done_dodge (self);
  286. if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  287. {
  288. self->monsterinfo.currentmove = &soldier_move_stand1;
  289. return;
  290. }
  291. if (self->monsterinfo.currentmove == &soldier_move_walk1 ||
  292. self->monsterinfo.currentmove == &soldier_move_walk2 ||
  293. self->monsterinfo.currentmove == &soldier_move_start_run)
  294. {
  295. self->monsterinfo.currentmove = &soldier_move_run;
  296. }
  297. else
  298. {
  299. self->monsterinfo.currentmove = &soldier_move_start_run;
  300. }
  301. }
  302. //
  303. // PAIN
  304. //
  305. mframe_t soldier_frames_pain1 [] =
  306. {
  307. ai_move, -3, NULL,
  308. ai_move, 4, NULL,
  309. ai_move, 1, NULL,
  310. ai_move, 1, NULL,
  311. ai_move, 0, NULL
  312. };
  313. mmove_t soldier_move_pain1 = {FRAME_pain101, FRAME_pain105, soldier_frames_pain1, soldier_run};
  314. mframe_t soldier_frames_pain2 [] =
  315. {
  316. ai_move, -13, NULL,
  317. ai_move, -1, NULL,
  318. ai_move, 2, NULL,
  319. ai_move, 4, NULL,
  320. ai_move, 2, NULL,
  321. ai_move, 3, NULL,
  322. ai_move, 2, NULL
  323. };
  324. mmove_t soldier_move_pain2 = {FRAME_pain201, FRAME_pain207, soldier_frames_pain2, soldier_run};
  325. mframe_t soldier_frames_pain3 [] =
  326. {
  327. ai_move, -8, NULL,
  328. ai_move, 10, NULL,
  329. ai_move, -4, NULL,
  330. ai_move, -1, NULL,
  331. ai_move, -3, NULL,
  332. ai_move, 0, NULL,
  333. ai_move, 3, NULL,
  334. ai_move, 0, NULL,
  335. ai_move, 0, NULL,
  336. ai_move, 0, NULL,
  337. ai_move, 0, NULL,
  338. ai_move, 1, NULL,
  339. ai_move, 0, NULL,
  340. ai_move, 1, NULL,
  341. ai_move, 2, NULL,
  342. ai_move, 4, NULL,
  343. ai_move, 3, NULL,
  344. ai_move, 2, NULL
  345. };
  346. mmove_t soldier_move_pain3 = {FRAME_pain301, FRAME_pain318, soldier_frames_pain3, soldier_run};
  347. mframe_t soldier_frames_pain4 [] =
  348. {
  349. ai_move, 0, NULL,
  350. ai_move, 0, NULL,
  351. ai_move, 0, NULL,
  352. ai_move, -10, NULL,
  353. ai_move, -6, NULL,
  354. ai_move, 8, NULL,
  355. ai_move, 4, NULL,
  356. ai_move, 1, NULL,
  357. ai_move, 0, NULL,
  358. ai_move, 2, NULL,
  359. ai_move, 5, NULL,
  360. ai_move, 2, NULL,
  361. ai_move, -1, NULL,
  362. ai_move, -1, NULL,
  363. ai_move, 3, NULL,
  364. ai_move, 2, NULL,
  365. ai_move, 0, NULL
  366. };
  367. mmove_t soldier_move_pain4 = {FRAME_pain401, FRAME_pain417, soldier_frames_pain4, soldier_run};
  368. void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
  369. {
  370. float r;
  371. int n;
  372. if (self->health < (self->max_health / 2))
  373. self->s.skinnum |= 1;
  374. monster_done_dodge (self);
  375. soldier_stop_charge(self);
  376. // if we're blind firing, this needs to be turned off here
  377. self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
  378. if (level.time < self->pain_debounce_time)
  379. {
  380. if ((self->velocity[2] > 100) && ( (self->monsterinfo.currentmove == &soldier_move_pain1) || (self->monsterinfo.currentmove == &soldier_move_pain2) || (self->monsterinfo.currentmove == &soldier_move_pain3)))
  381. {
  382. // PMM - clear duck flag
  383. if (self->monsterinfo.aiflags & AI_DUCKED)
  384. monster_duck_up(self);
  385. self->monsterinfo.currentmove = &soldier_move_pain4;
  386. }
  387. return;
  388. }
  389. self->pain_debounce_time = level.time + 3;
  390. n = self->s.skinnum | 1;
  391. if (n == 1)
  392. gi.sound (self, CHAN_VOICE, sound_pain_light, 1, ATTN_NORM, 0);
  393. else if (n == 3)
  394. gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
  395. else
  396. gi.sound (self, CHAN_VOICE, sound_pain_ss, 1, ATTN_NORM, 0);
  397. if (self->velocity[2] > 100)
  398. {
  399. // PMM - clear duck flag
  400. if (self->monsterinfo.aiflags & AI_DUCKED)
  401. monster_duck_up(self);
  402. self->monsterinfo.currentmove = &soldier_move_pain4;
  403. // self->monsterinfo.pausetime = 0;
  404. return;
  405. }
  406. if (skill->value == 3)
  407. return; // no pain anims in nightmare
  408. r = random();
  409. if (r < 0.33)
  410. self->monsterinfo.currentmove = &soldier_move_pain1;
  411. else if (r < 0.66)
  412. self->monsterinfo.currentmove = &soldier_move_pain2;
  413. else
  414. self->monsterinfo.currentmove = &soldier_move_pain3;
  415. // PMM - clear duck flag
  416. if (self->monsterinfo.aiflags & AI_DUCKED)
  417. monster_duck_up(self);
  418. // self->monsterinfo.pausetime = 0;
  419. }
  420. //
  421. // ATTACK
  422. //
  423. static int blaster_flash [] = {MZ2_SOLDIER_BLASTER_1, MZ2_SOLDIER_BLASTER_2, MZ2_SOLDIER_BLASTER_3, MZ2_SOLDIER_BLASTER_4, MZ2_SOLDIER_BLASTER_5, MZ2_SOLDIER_BLASTER_6, MZ2_SOLDIER_BLASTER_7, MZ2_SOLDIER_BLASTER_8};
  424. static int shotgun_flash [] = {MZ2_SOLDIER_SHOTGUN_1, MZ2_SOLDIER_SHOTGUN_2, MZ2_SOLDIER_SHOTGUN_3, MZ2_SOLDIER_SHOTGUN_4, MZ2_SOLDIER_SHOTGUN_5, MZ2_SOLDIER_SHOTGUN_6, MZ2_SOLDIER_SHOTGUN_7, MZ2_SOLDIER_SHOTGUN_8};
  425. static int machinegun_flash [] = {MZ2_SOLDIER_MACHINEGUN_1, MZ2_SOLDIER_MACHINEGUN_2, MZ2_SOLDIER_MACHINEGUN_3, MZ2_SOLDIER_MACHINEGUN_4, MZ2_SOLDIER_MACHINEGUN_5, MZ2_SOLDIER_MACHINEGUN_6, MZ2_SOLDIER_MACHINEGUN_7, MZ2_SOLDIER_MACHINEGUN_8};
  426. //void soldier_fire (edict_t *self, int flash_number) PMM
  427. void soldier_fire (edict_t *self, int in_flash_number)
  428. {
  429. vec3_t start;
  430. vec3_t forward, right, up;
  431. vec3_t aim;
  432. vec3_t dir;
  433. vec3_t end;
  434. float r, u;
  435. int flash_index;
  436. int flash_number;
  437. #ifdef RUN_SHOOT
  438. vec3_t aim_norm;
  439. float angle;
  440. #endif
  441. #ifdef CHECK_TARGET
  442. trace_t tr;
  443. vec3_t aim_good;
  444. #endif
  445. if ((!self->enemy) || (!self->enemy->inuse))
  446. {
  447. self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  448. return;
  449. }
  450. if (in_flash_number < 0)
  451. {
  452. flash_number = -1 * in_flash_number;
  453. }
  454. else
  455. flash_number = in_flash_number;
  456. if (self->s.skinnum < 2)
  457. flash_index = blaster_flash[flash_number];
  458. else if (self->s.skinnum < 4)
  459. flash_index = shotgun_flash[flash_number];
  460. else
  461. flash_index = machinegun_flash[flash_number];
  462. AngleVectors (self->s.angles, forward, right, NULL);
  463. G_ProjectSource (self->s.origin, monster_flash_offset[flash_index], forward, right, start);
  464. if (flash_number == 5 || flash_number == 6) // he's dead
  465. {
  466. VectorCopy (forward, aim);
  467. }
  468. else
  469. {
  470. VectorCopy (self->enemy->s.origin, end);
  471. end[2] += self->enemy->viewheight;
  472. VectorSubtract (end, start, aim);
  473. #ifdef CHECK_TARGET
  474. VectorCopy (end, aim_good);
  475. #endif
  476. #ifdef RUN_SHOOT
  477. //PMM
  478. if (in_flash_number < 0)
  479. {
  480. VectorCopy (aim, aim_norm);
  481. VectorNormalize (aim_norm);
  482. angle = DotProduct (aim_norm, forward);
  483. //gi.dprintf ("Dot Product: %f", DotProduct (aim_norm, forward));
  484. if (angle < 0.9) // ~25 degree angle
  485. {
  486. // if(g_showlogic && g_showlogic->value)
  487. // gi.dprintf (" not firing due to bad dotprod %f\n", angle);
  488. return;
  489. }
  490. // else
  491. // {
  492. // if(g_showlogic && g_showlogic->value)
  493. // gi.dprintf (" firing: dotprod = %f\n", angle);
  494. // }
  495. }
  496. //-PMM
  497. #endif
  498. vectoangles (aim, dir);
  499. AngleVectors (dir, forward, right, up);
  500. if (skill->value < 2)
  501. {
  502. r = crandom()*1000;
  503. u = crandom()*500;
  504. }
  505. else
  506. {
  507. r = crandom()*500;
  508. u = crandom()*250;
  509. }
  510. VectorMA (start, 8192, forward, end);
  511. VectorMA (end, r, right, end);
  512. VectorMA (end, u, up, end);
  513. VectorSubtract (end, start, aim);
  514. VectorNormalize (aim);
  515. }
  516. #ifdef CHECK_TARGET
  517. if (!(flash_number == 5 || flash_number == 6)) // he's dead
  518. {
  519. tr = gi.trace (start, NULL, NULL, aim_good, self, MASK_SHOT);
  520. if ((tr.ent != self->enemy) && (tr.ent != world))
  521. {
  522. // if(g_showlogic && g_showlogic->value)
  523. // gi.dprintf ("infantry shot aborted due to bad target\n");
  524. return;
  525. }
  526. }
  527. #endif
  528. if (self->s.skinnum <= 1)
  529. {
  530. monster_fire_blaster (self, start, aim, 5, 600, flash_index, EF_BLASTER);
  531. }
  532. else if (self->s.skinnum <= 3)
  533. {
  534. monster_fire_shotgun (self, start, aim, 2, 1, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SHOTGUN_COUNT, flash_index);
  535. }
  536. else
  537. {
  538. // PMM - changed to wait from pausetime to not interfere with dodge code
  539. if (!(self->monsterinfo.aiflags & AI_HOLD_FRAME))
  540. self->wait = level.time + (3 + rand() % 8) * FRAMETIME;
  541. monster_fire_bullet (self, start, aim, 2, 4, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, flash_index);
  542. if (level.time >= self->wait)
  543. self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  544. else
  545. self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  546. }
  547. }
  548. // ATTACK1 (blaster/shotgun)
  549. void soldier_fire1 (edict_t *self)
  550. {
  551. soldier_fire (self, 0);
  552. }
  553. void soldier_attack1_refire1 (edict_t *self)
  554. {
  555. // PMM - blindfire
  556. if (self->monsterinfo.aiflags & AI_MANUAL_STEERING)
  557. {
  558. self->monsterinfo.aiflags &= ~AI_MANUAL_STEERING;
  559. return;
  560. }
  561. // pmm
  562. if (!self->enemy)
  563. return;
  564. if (self->s.skinnum > 1)
  565. return;
  566. if (self->enemy->health <= 0)
  567. return;
  568. if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  569. self->monsterinfo.nextframe = FRAME_attak102;
  570. else
  571. self->monsterinfo.nextframe = FRAME_attak110;
  572. }
  573. void soldier_attack1_refire2 (edict_t *self)
  574. {
  575. if (!self->enemy)
  576. return;
  577. if (self->s.skinnum < 2)
  578. return;
  579. if (self->enemy->health <= 0)
  580. return;
  581. if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  582. self->monsterinfo.nextframe = FRAME_attak102;
  583. }
  584. mframe_t soldier_frames_attack1 [] =
  585. {
  586. ai_charge, 0, NULL,
  587. ai_charge, 0, NULL,
  588. ai_charge, 0, soldier_fire1,
  589. ai_charge, 0, NULL,
  590. ai_charge, 0, NULL,
  591. ai_charge, 0, soldier_attack1_refire1,
  592. ai_charge, 0, NULL,
  593. ai_charge, 0, soldier_cock,
  594. ai_charge, 0, soldier_attack1_refire2,
  595. ai_charge, 0, NULL,
  596. ai_charge, 0, NULL,
  597. ai_charge, 0, NULL
  598. };
  599. mmove_t soldier_move_attack1 = {FRAME_attak101, FRAME_attak112, soldier_frames_attack1, soldier_run};
  600. // ATTACK2 (blaster/shotgun)
  601. void soldier_fire2 (edict_t *self)
  602. {
  603. soldier_fire (self, 1);
  604. }
  605. void soldier_attack2_refire1 (edict_t *self)
  606. {
  607. if (!self->enemy)
  608. return;
  609. if (self->s.skinnum > 1)
  610. return;
  611. if (self->enemy->health <= 0)
  612. return;
  613. if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  614. self->monsterinfo.nextframe = FRAME_attak204;
  615. else
  616. self->monsterinfo.nextframe = FRAME_attak216;
  617. }
  618. void soldier_attack2_refire2 (edict_t *self)
  619. {
  620. if (!self->enemy)
  621. return;
  622. if (self->s.skinnum < 2)
  623. return;
  624. if (self->enemy->health <= 0)
  625. return;
  626. if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  627. self->monsterinfo.nextframe = FRAME_attak204;
  628. }
  629. mframe_t soldier_frames_attack2 [] =
  630. {
  631. ai_charge, 0, NULL,
  632. ai_charge, 0, NULL,
  633. ai_charge, 0, NULL,
  634. ai_charge, 0, NULL,
  635. ai_charge, 0, soldier_fire2,
  636. ai_charge, 0, NULL,
  637. ai_charge, 0, NULL,
  638. ai_charge, 0, soldier_attack2_refire1,
  639. ai_charge, 0, NULL,
  640. ai_charge, 0, NULL,
  641. ai_charge, 0, NULL,
  642. ai_charge, 0, NULL,
  643. ai_charge, 0, soldier_cock,
  644. ai_charge, 0, NULL,
  645. ai_charge, 0, soldier_attack2_refire2,
  646. ai_charge, 0, NULL,
  647. ai_charge, 0, NULL,
  648. ai_charge, 0, NULL
  649. };
  650. mmove_t soldier_move_attack2 = {FRAME_attak201, FRAME_attak218, soldier_frames_attack2, soldier_run};
  651. // ATTACK3 (duck and shoot)
  652. /*
  653. void soldier_duck_down (edict_t *self)
  654. {
  655. if ((g_showlogic) && (g_showlogic->value))
  656. gi.dprintf ("duck down - %d!\n", self->s.frame);
  657. self->monsterinfo.aiflags |= AI_DUCKED;
  658. // self->maxs[2] -= 32;
  659. self->maxs[2] = self->monsterinfo.base_height - 32;
  660. self->takedamage = DAMAGE_YES;
  661. if (self->monsterinfo.duck_wait_time < level.time)
  662. {
  663. if ((g_showlogic) && (g_showlogic->value))
  664. gi.dprintf ("soldier duck with no time!\n");
  665. self->monsterinfo.duck_wait_time = level.time + 1;
  666. }
  667. gi.linkentity (self);
  668. }
  669. void soldier_duck_up (edict_t *self)
  670. {
  671. if ((g_showlogic) && (g_showlogic->value))
  672. gi.dprintf ("duck up - %d!\n", self->s.frame);
  673. self->monsterinfo.aiflags &= ~AI_DUCKED;
  674. // self->maxs[2] += 32;
  675. self->maxs[2] = self->monsterinfo.base_height;
  676. self->takedamage = DAMAGE_AIM;
  677. gi.linkentity (self);
  678. }
  679. */
  680. void soldier_fire3 (edict_t *self)
  681. {
  682. monster_duck_down (self);
  683. soldier_fire (self, 2);
  684. }
  685. void soldier_attack3_refire (edict_t *self)
  686. {
  687. if ((level.time + 0.4) < self->monsterinfo.duck_wait_time)
  688. self->monsterinfo.nextframe = FRAME_attak303;
  689. }
  690. mframe_t soldier_frames_attack3 [] =
  691. {
  692. ai_charge, 0, NULL,
  693. ai_charge, 0, NULL,
  694. ai_charge, 0, soldier_fire3,
  695. ai_charge, 0, NULL,
  696. ai_charge, 0, NULL,
  697. ai_charge, 0, soldier_attack3_refire,
  698. ai_charge, 0, monster_duck_up,
  699. ai_charge, 0, NULL,
  700. ai_charge, 0, NULL
  701. };
  702. mmove_t soldier_move_attack3 = {FRAME_attak301, FRAME_attak309, soldier_frames_attack3, soldier_run};
  703. // ATTACK4 (machinegun)
  704. void soldier_fire4 (edict_t *self)
  705. {
  706. soldier_fire (self, 3);
  707. //
  708. // if (self->enemy->health <= 0)
  709. // return;
  710. //
  711. // if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  712. // self->monsterinfo.nextframe = FRAME_attak402;
  713. }
  714. mframe_t soldier_frames_attack4 [] =
  715. {
  716. ai_charge, 0, NULL,
  717. ai_charge, 0, NULL,
  718. ai_charge, 0, soldier_fire4,
  719. ai_charge, 0, NULL,
  720. ai_charge, 0, NULL,
  721. ai_charge, 0, NULL
  722. };
  723. mmove_t soldier_move_attack4 = {FRAME_attak401, FRAME_attak406, soldier_frames_attack4, soldier_run};
  724. #if 0
  725. // ATTACK5 (prone)
  726. void soldier_fire5 (edict_t *self)
  727. {
  728. soldier_fire (self, 4);
  729. }
  730. void soldier_attack5_refire (edict_t *self)
  731. {
  732. if (!self->enemy)
  733. return;
  734. if (self->enemy->health <= 0)
  735. return;
  736. if ( ((skill->value == 3) && (random() < 0.5)) || (range(self, self->enemy) == RANGE_MELEE) )
  737. self->monsterinfo.nextframe = FRAME_attak505;
  738. }
  739. mframe_t soldier_frames_attack5 [] =
  740. {
  741. ai_charge, 8, NULL,
  742. ai_charge, 8, NULL,
  743. ai_charge, 0, NULL,
  744. ai_charge, 0, NULL,
  745. ai_charge, 0, soldier_fire5,
  746. ai_charge, 0, NULL,
  747. ai_charge, 0, NULL,
  748. ai_charge, 0, soldier_attack5_refire
  749. };
  750. mmove_t soldier_move_attack5 = {FRAME_attak501, FRAME_attak508, soldier_frames_attack5, soldier_run};
  751. #endif
  752. // ATTACK6 (run & shoot)
  753. void soldier_fire8 (edict_t *self)
  754. {
  755. soldier_fire (self, -7);
  756. // self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  757. // self->monsterinfo.pausetime = level.time + 1000000;
  758. }
  759. void soldier_attack6_refire (edict_t *self)
  760. {
  761. // PMM - make sure dodge & charge bits are cleared
  762. monster_done_dodge (self);
  763. soldier_stop_charge (self);
  764. if (!self->enemy)
  765. return;
  766. if (self->enemy->health <= 0)
  767. return;
  768. // if (range(self, self->enemy) < RANGE_MID)
  769. if (range(self, self->enemy) < RANGE_NEAR)
  770. return;
  771. if ((skill->value == 3) || ((random() < (0.25*((float)skill->value)))))
  772. self->monsterinfo.nextframe = FRAME_runs03;
  773. }
  774. mframe_t soldier_frames_attack6 [] =
  775. {
  776. // PMM
  777. // ai_run, 10, NULL,
  778. ai_run, 10, soldier_start_charge,
  779. ai_run, 4, NULL,
  780. ai_run, 12, soldier_fire8,
  781. ai_run, 11, NULL,
  782. ai_run, 13, monster_done_dodge,
  783. ai_run, 18, NULL,
  784. ai_run, 15, NULL,
  785. ai_run, 14, NULL,
  786. ai_run, 11, NULL,
  787. ai_run, 8, NULL,
  788. ai_run, 11, NULL,
  789. ai_run, 12, NULL,
  790. ai_run, 12, NULL,
  791. ai_run, 17, soldier_attack6_refire
  792. };
  793. mmove_t soldier_move_attack6 = {FRAME_runs01, FRAME_runs14, soldier_frames_attack6, soldier_run};
  794. void soldier_attack(edict_t *self)
  795. {
  796. float r, chance;
  797. monster_done_dodge (self);
  798. // PMM - blindfire!
  799. if (self->monsterinfo.attack_state == AS_BLIND)
  800. {
  801. // setup shot probabilities
  802. if (self->monsterinfo.blind_fire_delay < 1.0)
  803. chance = 1.0;
  804. else if (self->monsterinfo.blind_fire_delay < 7.5)
  805. chance = 0.4;
  806. else
  807. chance = 0.1;
  808. r = random();
  809. // minimum of 2 seconds, plus 0-3, after the shots are done
  810. self->monsterinfo.blind_fire_delay += 2.1 + 2.0 + random()*3.0;
  811. // don't shoot at the origin
  812. if (VectorCompare (self->monsterinfo.blind_fire_target, vec3_origin))
  813. return;
  814. // don't shoot if the dice say not to
  815. if (r > chance)
  816. {
  817. // if ((g_showlogic) && (g_showlogic->value))
  818. // gi.dprintf ("blindfire - NO SHOT\n");
  819. return;
  820. }
  821. // turn on manual steering to signal both manual steering and blindfire
  822. self->monsterinfo.aiflags |= AI_MANUAL_STEERING;
  823. self->monsterinfo.currentmove = &soldier_move_attack1;
  824. self->monsterinfo.attack_finished = level.time + 1.5 + random();
  825. return;
  826. }
  827. // pmm
  828. // PMM - added this so the soldiers now run toward you and shoot instead of just stopping and shooting
  829. // if ((range(self, self->enemy) >= RANGE_MID) && (r < (skill->value*0.25) && (self->s.skinnum <= 3)))
  830. r = random();
  831. if ((!(self->monsterinfo.aiflags & (AI_BLOCKED|AI_STAND_GROUND))) &&
  832. (range(self, self->enemy) >= RANGE_NEAR) &&
  833. (r < (skill->value*0.25) &&
  834. (self->s.skinnum <= 3)))
  835. {
  836. self->monsterinfo.currentmove = &soldier_move_attack6;
  837. }
  838. else
  839. {
  840. if (self->s.skinnum < 4)
  841. {
  842. if (random() < 0.5)
  843. self->monsterinfo.currentmove = &soldier_move_attack1;
  844. else
  845. self->monsterinfo.currentmove = &soldier_move_attack2;
  846. }
  847. else
  848. {
  849. self->monsterinfo.currentmove = &soldier_move_attack4;
  850. }
  851. }
  852. }
  853. //
  854. // SIGHT
  855. //
  856. void soldier_sight(edict_t *self, edict_t *other)
  857. {
  858. if (random() < 0.5)
  859. gi.sound (self, CHAN_VOICE, sound_sight1, 1, ATTN_NORM, 0);
  860. else
  861. gi.sound (self, CHAN_VOICE, sound_sight2, 1, ATTN_NORM, 0);
  862. // if ((skill->value > 0) && (self->enemy) && (range(self, self->enemy) >= RANGE_MID))
  863. if ((skill->value > 0) && (self->enemy) && (range(self, self->enemy) >= RANGE_NEAR))
  864. {
  865. // PMM - don't let machinegunners run & shoot
  866. if ((random() > 0.75) && (self->s.skinnum <= 3))
  867. self->monsterinfo.currentmove = &soldier_move_attack6;
  868. }
  869. }
  870. //
  871. // DUCK
  872. //
  873. /*
  874. void soldier_duck_hold (edict_t *self)
  875. {
  876. if (level.time >= self->monsterinfo.duck_wait_time)
  877. self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  878. else
  879. self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  880. }
  881. */
  882. mframe_t soldier_frames_duck [] =
  883. {
  884. ai_move, 5, monster_duck_down,
  885. ai_move, -1, monster_duck_hold,
  886. ai_move, 1, NULL,
  887. ai_move, 0, monster_duck_up,
  888. ai_move, 5, NULL
  889. };
  890. mmove_t soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run};
  891. /*
  892. void soldier_dodge (edict_t *self, edict_t *attacker, float eta, trace_t *tr)
  893. {
  894. //===========
  895. //PMM - rogue rewrite of dodge code.
  896. // lots o' changes in here. Basically, they now check the tr and see if ducking would help,
  897. // and if it doesn't, they dodge like mad
  898. float r = random();
  899. float height;
  900. if ((g_showlogic) && (g_showlogic->value))
  901. {
  902. if (self->monsterinfo.aiflags & AI_DODGING)
  903. gi.dprintf ("dodging - ");
  904. if (self->monsterinfo.aiflags & AI_DUCKED)
  905. gi.dprintf ("ducked - ");
  906. }
  907. if (!self->enemy)
  908. {
  909. self->enemy = attacker;
  910. FoundTarget (self);
  911. }
  912. // PMM - don't bother if it's going to hit anyway; fix for weird in-your-face etas (I was
  913. // seeing numbers like 13 and 14)
  914. if ((eta < 0.1) || (eta > 5))
  915. {
  916. if ((g_showlogic) && (g_showlogic->value))
  917. gi.dprintf ("timeout\n");
  918. return;
  919. }
  920. // skill level determination..
  921. if (r > (0.25*((skill->value)+1)))
  922. {
  923. if ((g_showlogic) && (g_showlogic->value))
  924. gi.dprintf ("skillout\n");
  925. return;
  926. }
  927. // stop charging, since we're going to dodge (somehow) instead
  928. soldier_stop_charge (self);
  929. height = self->absmax[2]-32-1; // the -1 is because the absmax is s.origin + maxs + 1
  930. // if we're ducking already, or the shot is at our knees
  931. if ((tr->endpos[2] <= height) || (self->monsterinfo.aiflags & AI_DUCKED))
  932. {
  933. vec3_t right, diff;
  934. // if we're already dodging, just finish the sequence, i.e. don't do anything else
  935. if (self->monsterinfo.aiflags & AI_DODGING)
  936. {
  937. if ((g_showlogic) && (g_showlogic->value))
  938. gi.dprintf ("already dodging\n");
  939. return;
  940. }
  941. AngleVectors (self->s.angles, NULL, right, NULL);
  942. VectorSubtract (tr->endpos, self->s.origin, diff);
  943. if (DotProduct (right, diff) < 0)
  944. {
  945. self->monsterinfo.lefty = 1;
  946. // gi.dprintf ("left\n");
  947. } else {
  948. // gi.dprintf ("right\n");
  949. }
  950. // if it doesn't sense to duck, try to strafe and shoot
  951. // we don't want the machine gun guys running & shooting (looks bad)
  952. // if we are currently ducked, unduck
  953. if (self->monsterinfo.aiflags & AI_DUCKED)
  954. {
  955. if ((g_showlogic) && (g_showlogic->value))
  956. gi.dprintf ("unducking - ");
  957. soldier_duck_up(self);
  958. }
  959. self->monsterinfo.aiflags |= AI_DODGING;
  960. self->monsterinfo.attack_state = AS_SLIDING;
  961. if (self->s.skinnum <= 3)
  962. {
  963. if ((g_showlogic) && (g_showlogic->value))
  964. gi.dprintf ("shooting back!\n");
  965. self->monsterinfo.currentmove = &soldier_move_attack6;
  966. }
  967. else
  968. {
  969. if ((g_showlogic) && (g_showlogic->value))
  970. gi.dprintf ("strafing away!\n");
  971. self->monsterinfo.currentmove = &soldier_move_start_run;
  972. }
  973. return;
  974. }
  975. // if we're here, we're ducking, so clear the dodge bit if it's set
  976. if ((g_showlogic) && (g_showlogic->value))
  977. gi.dprintf ("ducking!\n");
  978. if (skill->value == 0)
  979. {
  980. // set this prematurely; it doesn't hurt, and prevents extra iterations
  981. self->monsterinfo.aiflags |= AI_DUCKED;
  982. monster_done_dodge (self);
  983. self->monsterinfo.currentmove = &soldier_move_duck;
  984. // PMM - stupid dodge
  985. self->monsterinfo.duck_wait_time = level.time + eta + 1;
  986. return;
  987. }
  988. // PMM - since we're only ducking some of the time, this needs to be moved down below
  989. // self->monsterinfo.duck_wait_time = level.time + eta + 0.3;
  990. r = random();
  991. // set this prematurely; it doesn't hurt, and prevents extra iterations
  992. self->monsterinfo.aiflags |= AI_DUCKED;
  993. monster_done_dodge (self);
  994. if (r > (skill->value * 0.33))
  995. {
  996. self->monsterinfo.currentmove = &soldier_move_duck;
  997. self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
  998. // has to be done immediately otherwise he can get stuck
  999. soldier_duck_down(self);
  1000. }
  1001. else
  1002. {
  1003. // has to be done immediately otherwise he can get stuck
  1004. soldier_duck_down(self);
  1005. self->monsterinfo.duck_wait_time = level.time + eta + 1;
  1006. self->monsterinfo.currentmove = &soldier_move_attack3;
  1007. self->monsterinfo.nextframe = FRAME_attak301;
  1008. }
  1009. return;
  1010. //PMM
  1011. //===========
  1012. }
  1013. */
  1014. // pmm - blocking code
  1015. qboolean soldier_blocked (edict_t *self, float dist)
  1016. {
  1017. // don't do anything if you're dodging
  1018. if ((self->monsterinfo.aiflags & AI_DODGING) || (self->monsterinfo.aiflags & AI_DUCKED))
  1019. return false;
  1020. if(blocked_checkshot (self, 0.25 + (0.05 * skill->value) ))
  1021. return true;
  1022. // if(blocked_checkjump (self, dist, 192, 40))
  1023. // {
  1024. // soldier_jump(self);
  1025. // return true;
  1026. // }
  1027. if(blocked_checkplat (self, dist))
  1028. return true;
  1029. return false;
  1030. }
  1031. //
  1032. // DEATH
  1033. //
  1034. void soldier_fire6 (edict_t *self)
  1035. {
  1036. soldier_fire (self, 5);
  1037. }
  1038. void soldier_fire7 (edict_t *self)
  1039. {
  1040. soldier_fire (self, 6);
  1041. }
  1042. void soldier_dead (edict_t *self)
  1043. {
  1044. VectorSet (self->mins, -16, -16, -24);
  1045. VectorSet (self->maxs, 16, 16, -8);
  1046. self->movetype = MOVETYPE_TOSS;
  1047. self->svflags |= SVF_DEADMONSTER;
  1048. self->nextthink = 0;
  1049. gi.linkentity (self);
  1050. }
  1051. // pmm - this quickie does a location trace to try to grow the bounding box
  1052. //
  1053. // this is because the frames are off; the origin is at the guy's feet.
  1054. void soldier_dead2 (edict_t *self)
  1055. {
  1056. vec3_t tempmins, tempmaxs, temporg;
  1057. trace_t tr;
  1058. VectorCopy (self->s.origin, temporg);
  1059. // this is because location traces done at the floor are guaranteed to hit the floor
  1060. // (inside the sv_trace code it grows the bbox by 1 in all directions)
  1061. temporg[2] += 1;
  1062. VectorSet (tempmins, -32, -32, -24);
  1063. VectorSet (tempmaxs, 32, 32, -8);
  1064. tr = gi.trace (temporg, tempmins, tempmaxs, temporg, self, MASK_SOLID);
  1065. if (tr.startsolid || tr.allsolid)
  1066. {
  1067. VectorSet (self->mins, -16, -16, -24);
  1068. VectorSet (self->maxs, 16, 16, -8);
  1069. }
  1070. else
  1071. {
  1072. VectorCopy (tempmins, self->mins);
  1073. VectorCopy (tempmaxs, self->maxs);
  1074. }
  1075. self->movetype = MOVETYPE_TOSS;
  1076. self->svflags |= SVF_DEADMONSTER;
  1077. self->nextthink = 0;
  1078. gi.linkentity (self);
  1079. }
  1080. mframe_t soldier_frames_death1 [] =
  1081. {
  1082. ai_move, 0, NULL,
  1083. ai_move, -10, NULL,
  1084. ai_move, -10, NULL,
  1085. ai_move, -10, NULL,
  1086. ai_move, -5, NULL,
  1087. ai_move, 0, NULL,
  1088. ai_move, 0, NULL,
  1089. ai_move, 0, NULL,
  1090. ai_move, 0, NULL,
  1091. ai_move, 0, NULL,
  1092. ai_move, 0, NULL,
  1093. ai_move, 0, NULL,
  1094. ai_move, 0, NULL,
  1095. ai_move, 0, NULL,
  1096. ai_move, 0, NULL,
  1097. ai_move, 0, NULL,
  1098. ai_move, 0, NULL,
  1099. ai_move, 0, NULL,
  1100. ai_move, 0, NULL,
  1101. ai_move, 0, NULL,
  1102. ai_move, 0, NULL,
  1103. ai_move, 0, soldier_fire6,
  1104. ai_move, 0, NULL,
  1105. ai_move, 0, NULL,
  1106. ai_move, 0, soldier_fire7,
  1107. ai_move, 0, NULL,
  1108. ai_move, 0, NULL,
  1109. ai_move, 0, NULL,
  1110. ai_move, 0, NULL,
  1111. ai_move, 0, NULL,
  1112. ai_move, 0, NULL,
  1113. ai_move, 0, NULL,
  1114. ai_move, 0, NULL,
  1115. ai_move, 0, NULL,
  1116. ai_move, 0, NULL,
  1117. ai_move, 0, NULL
  1118. };
  1119. mmove_t soldier_move_death1 = {FRAME_death101, FRAME_death136, soldier_frames_death1, soldier_dead};
  1120. mframe_t soldier_frames_death2 [] =
  1121. {
  1122. ai_move, -5, NULL,
  1123. ai_move, -5, NULL,
  1124. ai_move, -5, NULL,
  1125. ai_move, 0, NULL,
  1126. ai_move, 0, NULL,
  1127. ai_move, 0, NULL,
  1128. ai_move, 0, NULL,
  1129. ai_move, 0, NULL,
  1130. ai_move, 0, NULL,
  1131. ai_move, 0, NULL,
  1132. ai_move, 0, NULL,
  1133. ai_move, 0, NULL,
  1134. ai_move, 0, NULL,
  1135. ai_move, 0, NULL,
  1136. ai_move, 0, NULL,
  1137. ai_move, 0, NULL,
  1138. ai_move, 0, NULL,
  1139. ai_move, 0, NULL,
  1140. ai_move, 0, NULL,
  1141. ai_move, 0, NULL,
  1142. ai_move, 0, NULL,
  1143. ai_move, 0, NULL,
  1144. ai_move, 0, NULL,
  1145. ai_move, 0, NULL,
  1146. ai_move, 0, NULL,
  1147. ai_move, 0, NULL,
  1148. ai_move, 0, NULL,
  1149. ai_move, 0, NULL,
  1150. ai_move, 0, NULL,
  1151. ai_move, 0, NULL,
  1152. ai_move, 0, NULL,
  1153. ai_move, 0, NULL,
  1154. ai_move, 0, NULL,
  1155. ai_move, 0, NULL,
  1156. ai_move, 0, NULL
  1157. };
  1158. mmove_t soldier_move_death2 = {FRAME_death201, FRAME_death235, soldier_frames_death2, soldier_dead};
  1159. mframe_t soldier_frames_death3 [] =
  1160. {
  1161. ai_move, -5, NULL,
  1162. ai_move, -5, NULL,
  1163. ai_move, -5, NULL,
  1164. ai_move, 0, NULL,
  1165. ai_move, 0, NULL,
  1166. ai_move, 0, NULL,
  1167. ai_move, 0, NULL,
  1168. ai_move, 0, NULL,
  1169. ai_move, 0, NULL,
  1170. ai_move, 0, NULL,
  1171. ai_move, 0, NULL,
  1172. ai_move, 0, NULL,
  1173. ai_move, 0, NULL,
  1174. ai_move, 0, NULL,
  1175. ai_move, 0, NULL,
  1176. ai_move, 0, NULL,
  1177. ai_move, 0, NULL,
  1178. ai_move, 0, NULL,
  1179. ai_move, 0, NULL,
  1180. ai_move, 0, NULL,
  1181. ai_move, 0, NULL,
  1182. ai_move, 0, NULL,
  1183. ai_move, 0, NULL,
  1184. ai_move, 0, NULL,
  1185. ai_move, 0, NULL,
  1186. ai_move, 0, NULL,
  1187. ai_move, 0, NULL,
  1188. ai_move, 0, NULL,
  1189. ai_move, 0, NULL,
  1190. ai_move, 0, NULL,
  1191. ai_move, 0, NULL,
  1192. ai_move, 0, NULL,
  1193. ai_move, 0, NULL,
  1194. ai_move, 0, NULL,
  1195. ai_move, 0, NULL,
  1196. ai_move, 0, NULL,
  1197. ai_move, 0, NULL,
  1198. ai_move, 0, NULL,
  1199. ai_move, 0, NULL,
  1200. ai_move, 0, NULL,
  1201. ai_move, 0, NULL,
  1202. ai_move, 0, NULL,
  1203. ai_move, 0, NULL,
  1204. ai_move, 0, NULL,
  1205. ai_move, 0, NULL,
  1206. };
  1207. mmove_t soldier_move_death3 = {FRAME_death301, FRAME_death345, soldier_frames_death3, soldier_dead};
  1208. mframe_t soldier_frames_death4 [] =
  1209. {
  1210. ai_move, 0, NULL,
  1211. ai_move, 0, NULL,
  1212. ai_move, 0, NULL,
  1213. ai_move, 0, NULL,
  1214. ai_move, 0, NULL,
  1215. ai_move, 0, NULL,
  1216. ai_move, 0, NULL,
  1217. ai_move, 0, NULL,
  1218. ai_move, 0, NULL,
  1219. ai_move, 0, NULL,
  1220. ai_move, 0, NULL,
  1221. ai_move, 0, NULL,
  1222. ai_move, 0, NULL,
  1223. ai_move, 0, NULL,
  1224. ai_move, 0, NULL,
  1225. ai_move, 0, NULL,
  1226. ai_move, 0, NULL,
  1227. ai_move, 0, NULL,
  1228. ai_move, 0, NULL,
  1229. ai_move, 0, NULL,
  1230. ai_move, 0, NULL,
  1231. ai_move, 0, NULL,
  1232. ai_move, 0, NULL,
  1233. ai_move, 0, NULL,
  1234. ai_move, 0, NULL,
  1235. ai_move, 0, NULL,
  1236. ai_move, 0, NULL,
  1237. ai_move, 0, NULL,
  1238. ai_move, 0, NULL,
  1239. ai_move, 0, NULL,
  1240. ai_move, 0, NULL,
  1241. ai_move, 0, NULL,
  1242. ai_move, 0, NULL,
  1243. ai_move, 0, NULL,
  1244. ai_move, 0, NULL,
  1245. ai_move, 0, NULL,
  1246. ai_move, 0, NULL,
  1247. ai_move, 0, NULL,
  1248. ai_move, 0, NULL,
  1249. ai_move, 0, NULL,
  1250. ai_move, 0, NULL,
  1251. ai_move, 0, NULL,
  1252. ai_move, 0, NULL,
  1253. ai_move, 0, NULL,
  1254. ai_move, 0, NULL,
  1255. ai_move, 0, NULL,
  1256. ai_move, 0, NULL,
  1257. ai_move, 0, NULL,
  1258. ai_move, 0, NULL,
  1259. ai_move, 0, NULL,
  1260. ai_move, 0, NULL,
  1261. ai_move, 0, NULL,
  1262. ai_move, 0, NULL
  1263. };
  1264. // PMM -changed to soldier_dead2 to get a larger bounding box
  1265. mmove_t soldier_move_death4 = {FRAME_death401, FRAME_death453, soldier_frames_death4, soldier_dead2};
  1266. mframe_t soldier_frames_death5 [] =
  1267. {
  1268. ai_move, -5, NULL,
  1269. ai_move, -5, NULL,
  1270. ai_move, -5, NULL,
  1271. ai_move, 0, NULL,
  1272. ai_move, 0, NULL,
  1273. ai_move, 0, NULL,
  1274. ai_move, 0, NULL,
  1275. ai_move, 0, NULL,
  1276. ai_move, 0, NULL,
  1277. ai_move, 0, NULL,
  1278. ai_move, 0, NULL,
  1279. ai_move, 0, NULL,
  1280. ai_move, 0, NULL,
  1281. ai_move, 0, NULL,
  1282. ai_move, 0, NULL,
  1283. ai_move, 0, NULL,
  1284. ai_move, 0, NULL,
  1285. ai_move, 0, NULL,
  1286. ai_move, 0, NULL,
  1287. ai_move, 0, NULL,
  1288. ai_move, 0, NULL,
  1289. ai_move, 0, NULL,
  1290. ai_move, 0, NULL,
  1291. ai_move, 0, NULL
  1292. };
  1293. mmove_t soldier_move_death5 = {FRAME_death501, FRAME_death524, soldier_frames_death5, soldier_dead};
  1294. mframe_t soldier_frames_death6 [] =
  1295. {
  1296. ai_move, 0, NULL,
  1297. ai_move, 0, NULL,
  1298. ai_move, 0, NULL,
  1299. ai_move, 0, NULL,
  1300. ai_move, 0, NULL,
  1301. ai_move, 0, NULL,
  1302. ai_move, 0, NULL,
  1303. ai_move, 0, NULL,
  1304. ai_move, 0, NULL,
  1305. ai_move, 0, NULL
  1306. };
  1307. mmove_t soldier_move_death6 = {FRAME_death601, FRAME_death610, soldier_frames_death6, soldier_dead};
  1308. void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  1309. {
  1310. int n;
  1311. // check for gib
  1312. if (self->health <= self->gib_health)
  1313. {
  1314. gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
  1315. for (n= 0; n < 3; n++)
  1316. ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC);
  1317. ThrowGib (self, "models/objects/gibs/chest/tris.md2", damage, GIB_ORGANIC);
  1318. ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC);
  1319. self->deadflag = DEAD_DEAD;
  1320. return;
  1321. }
  1322. if (self->deadflag == DEAD_DEAD)
  1323. return;
  1324. // regular death
  1325. self->deadflag = DEAD_DEAD;
  1326. self->takedamage = DAMAGE_YES;
  1327. self->s.skinnum |= 1;
  1328. if (self->s.skinnum == 1)
  1329. gi.sound (self, CHAN_VOICE, sound_death_light, 1, ATTN_NORM, 0);
  1330. else if (self->s.skinnum == 3)
  1331. gi.sound (self, CHAN_VOICE, sound_death, 1, ATTN_NORM, 0);
  1332. else // (self->s.skinnum == 5)
  1333. gi.sound (self, CHAN_VOICE, sound_death_ss, 1, ATTN_NORM, 0);
  1334. if (fabs((self->s.origin[2] + self->viewheight) - point[2]) <= 4)
  1335. {
  1336. // head shot
  1337. self->monsterinfo.currentmove = &soldier_move_death3;
  1338. return;
  1339. }
  1340. n = rand() % 5;
  1341. if (n == 0)
  1342. self->monsterinfo.currentmove = &soldier_move_death1;
  1343. else if (n == 1)
  1344. self->monsterinfo.currentmove = &soldier_move_death2;
  1345. else if (n == 2)
  1346. self->monsterinfo.currentmove = &soldier_move_death4;
  1347. else if (n == 3)
  1348. self->monsterinfo.currentmove = &soldier_move_death5;
  1349. else
  1350. self->monsterinfo.currentmove = &soldier_move_death6;
  1351. }
  1352. //
  1353. // NEW DODGE CODE
  1354. //
  1355. void soldier_sidestep (edict_t *self)
  1356. {
  1357. if (self->s.skinnum <= 3)
  1358. {
  1359. // if ((g_showlogic) && (g_showlogic->value))
  1360. // gi.dprintf ("shooting back!\n");
  1361. if (self->monsterinfo.currentmove != &soldier_move_attack6)
  1362. self->monsterinfo.currentmove = &soldier_move_attack6;
  1363. }
  1364. else
  1365. {
  1366. // if ((g_showlogic) && (g_showlogic->value))
  1367. // gi.dprintf ("strafing away!\n");
  1368. if (self->monsterinfo.currentmove != &soldier_move_start_run)
  1369. self->monsterinfo.currentmove = &soldier_move_start_run;
  1370. }
  1371. }
  1372. void soldier_duck (edict_t *self, float eta)
  1373. {
  1374. float r;
  1375. // has to be done immediately otherwise he can get stuck
  1376. monster_duck_down(self);
  1377. if (skill->value == 0)
  1378. {
  1379. // PMM - stupid dodge
  1380. self->monsterinfo.nextframe = FRAME_duck01;
  1381. self->monsterinfo.currentmove = &soldier_move_duck;
  1382. self->monsterinfo.duck_wait_time = level.time + eta + 1;
  1383. return;
  1384. }
  1385. r = random();
  1386. if (r > (skill->value * 0.3))
  1387. {
  1388. self->monsterinfo.nextframe = FRAME_duck01;
  1389. self->monsterinfo.currentmove = &soldier_move_duck;
  1390. self->monsterinfo.duck_wait_time = level.time + eta + (0.1 * (3 - skill->value));
  1391. }
  1392. else
  1393. {
  1394. self->monsterinfo.nextframe = FRAME_attak301;
  1395. self->monsterinfo.currentmove = &soldier_move_attack3;
  1396. self->monsterinfo.duck_wait_time = level.time + eta + 1;
  1397. }
  1398. return;
  1399. }
  1400. //=========
  1401. //ROGUE
  1402. void soldier_blind (edict_t *self);
  1403. mframe_t soldier_frames_blind [] =
  1404. {
  1405. ai_move, 0, soldier_idle,
  1406. ai_move, 0, NULL,
  1407. ai_move, 0, NULL,
  1408. ai_move, 0, NULL,
  1409. ai_move, 0, NULL,
  1410. ai_move, 0, NULL,
  1411. ai_move, 0, NULL,
  1412. ai_move, 0, NULL,
  1413. ai_move, 0, NULL,
  1414. ai_move, 0, NULL,
  1415. ai_move, 0, NULL,
  1416. ai_move, 0, NULL,
  1417. ai_move, 0, NULL,
  1418. ai_move, 0, NULL,
  1419. ai_move, 0, NULL,
  1420. ai_move, 0, NULL,
  1421. ai_move, 0, NULL,
  1422. ai_move, 0, NULL,
  1423. ai_move, 0, NULL,
  1424. ai_move, 0, NULL,
  1425. ai_move, 0, NULL,
  1426. ai_move, 0, NULL,
  1427. ai_move, 0, NULL,
  1428. ai_move, 0, NULL,
  1429. ai_move, 0, NULL,
  1430. ai_move, 0, NULL,
  1431. ai_move, 0, NULL,
  1432. ai_move, 0, NULL,
  1433. ai_move, 0, NULL,
  1434. ai_move, 0, NULL
  1435. };
  1436. mmove_t soldier_move_blind = {FRAME_stand101, FRAME_stand130, soldier_frames_blind, soldier_blind};
  1437. void soldier_blind (edict_t *self)
  1438. {
  1439. self->monsterinfo.currentmove = &soldier_move_blind;
  1440. }
  1441. //ROGUE
  1442. //=========
  1443. //
  1444. // SPAWN
  1445. //
  1446. void SP_monster_soldier_x (edict_t *self)
  1447. {
  1448. self->s.modelindex = gi.modelindex ("models/monsters/soldier/tris.md2");
  1449. //PMM
  1450. // self->s.effects |= EF_SPLATTER;
  1451. //PMM
  1452. self->monsterinfo.scale = MODEL_SCALE;
  1453. VectorSet (self->mins, -16, -16, -24);
  1454. VectorSet (self->maxs, 16, 16, 32);
  1455. self->movetype = MOVETYPE_STEP;
  1456. self->solid = SOLID_BBOX;
  1457. sound_idle = gi.soundindex ("soldier/solidle1.wav");
  1458. sound_sight1 = gi.soundindex ("soldier/solsght1.wav");
  1459. sound_sight2 = gi.soundindex ("soldier/solsrch1.wav");
  1460. sound_cock = gi.soundindex ("infantry/infatck3.wav");
  1461. self->mass = 100;
  1462. self->pain = soldier_pain;
  1463. self->die = soldier_die;
  1464. self->monsterinfo.stand = soldier_stand;
  1465. self->monsterinfo.walk = soldier_walk;
  1466. self->monsterinfo.run = soldier_run;
  1467. self->monsterinfo.dodge = M_MonsterDodge;
  1468. self->monsterinfo.attack = soldier_attack;
  1469. self->monsterinfo.melee = NULL;
  1470. self->monsterinfo.sight = soldier_sight;
  1471. //=====
  1472. //ROGUE
  1473. self->monsterinfo.blocked = soldier_blocked;
  1474. self->monsterinfo.duck = soldier_duck;
  1475. self->monsterinfo.unduck = monster_duck_up;
  1476. self->monsterinfo.sidestep = soldier_sidestep;
  1477. if(self->spawnflags & 8) // blind
  1478. self->monsterinfo.stand = soldier_blind;
  1479. //ROGUE
  1480. //=====
  1481. gi.linkentity (self);
  1482. self->monsterinfo.stand (self);
  1483. walkmonster_start (self);
  1484. }
  1485. /*QUAKED monster_soldier_light (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
  1486. Blind - monster will just stand there until triggered
  1487. */
  1488. void SP_monster_soldier_light (edict_t *self)
  1489. {
  1490. if (deathmatch->value)
  1491. {
  1492. G_FreeEdict (self);
  1493. return;
  1494. }
  1495. SP_monster_soldier_x (self);
  1496. sound_pain_light = gi.soundindex ("soldier/solpain2.wav");
  1497. sound_death_light = gi.soundindex ("soldier/soldeth2.wav");
  1498. gi.modelindex ("models/objects/laser/tris.md2");
  1499. gi.soundindex ("misc/lasfly.wav");
  1500. gi.soundindex ("soldier/solatck2.wav");
  1501. self->s.skinnum = 0;
  1502. self->health = 20;
  1503. self->gib_health = -30;
  1504. // PMM - blindfire
  1505. self->monsterinfo.blindfire = true;
  1506. }
  1507. /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
  1508. Blind - monster will just stand there until triggered
  1509. */
  1510. void SP_monster_soldier (edict_t *self)
  1511. {
  1512. if (deathmatch->value)
  1513. {
  1514. G_FreeEdict (self);
  1515. return;
  1516. }
  1517. SP_monster_soldier_x (self);
  1518. sound_pain = gi.soundindex ("soldier/solpain1.wav");
  1519. sound_death = gi.soundindex ("soldier/soldeth1.wav");
  1520. gi.soundindex ("soldier/solatck1.wav");
  1521. self->s.skinnum = 2;
  1522. self->health = 30;
  1523. self->gib_health = -30;
  1524. }
  1525. /*QUAKED monster_soldier_ss (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight Blind
  1526. Blind - monster will just stand there until triggered
  1527. */
  1528. void SP_monster_soldier_ss (edict_t *self)
  1529. {
  1530. if (deathmatch->value)
  1531. {
  1532. G_FreeEdict (self);
  1533. return;
  1534. }
  1535. SP_monster_soldier_x (self);
  1536. sound_pain_ss = gi.soundindex ("soldier/solpain3.wav");
  1537. sound_death_ss = gi.soundindex ("soldier/soldeth3.wav");
  1538. gi.soundindex ("soldier/solatck3.wav");
  1539. self->s.skinnum = 4;
  1540. self->health = 40;
  1541. self->gib_health = -30;
  1542. }