p_enemy.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Enemy thinking, AI.
  21. // Action Pointer Functions
  22. // that are associated with states/frames.
  23. //
  24. //-----------------------------------------------------------------------------
  25. static const char
  26. rcsid[] = "$Id: p_enemy.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
  27. #include <stdlib.h>
  28. #include "m_random.h"
  29. #include "i_system.h"
  30. #include "doomdef.h"
  31. #include "p_local.h"
  32. #include "s_sound.h"
  33. #include "g_game.h"
  34. // State.
  35. #include "doomstat.h"
  36. #include "r_state.h"
  37. // Data.
  38. #include "sounds.h"
  39. typedef enum
  40. {
  41. DI_EAST,
  42. DI_NORTHEAST,
  43. DI_NORTH,
  44. DI_NORTHWEST,
  45. DI_WEST,
  46. DI_SOUTHWEST,
  47. DI_SOUTH,
  48. DI_SOUTHEAST,
  49. DI_NODIR,
  50. NUMDIRS
  51. } dirtype_t;
  52. //
  53. // P_NewChaseDir related LUT.
  54. //
  55. dirtype_t opposite[] =
  56. {
  57. DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
  58. DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
  59. };
  60. dirtype_t diags[] =
  61. {
  62. DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
  63. };
  64. void A_Fall (mobj_t *actor);
  65. //
  66. // ENEMY THINKING
  67. // Enemies are allways spawned
  68. // with targetplayer = -1, threshold = 0
  69. // Most monsters are spawned unaware of all players,
  70. // but some can be made preaware
  71. //
  72. //
  73. // Called by P_NoiseAlert.
  74. // Recursively traverse adjacent sectors,
  75. // sound blocking lines cut off traversal.
  76. //
  77. mobj_t* soundtarget;
  78. void
  79. P_RecursiveSound
  80. ( sector_t* sec,
  81. int soundblocks )
  82. {
  83. int i;
  84. line_t* check;
  85. sector_t* other;
  86. // wake up all monsters in this sector
  87. if (sec->validcount == validcount
  88. && sec->soundtraversed <= soundblocks+1)
  89. {
  90. return; // already flooded
  91. }
  92. sec->validcount = validcount;
  93. sec->soundtraversed = soundblocks+1;
  94. sec->soundtarget = soundtarget;
  95. for (i=0 ;i<sec->linecount ; i++)
  96. {
  97. check = sec->lines[i];
  98. if (! (check->flags & ML_TWOSIDED) )
  99. continue;
  100. P_LineOpening (check);
  101. if (openrange <= 0)
  102. continue; // closed door
  103. if ( sides[ check->sidenum[0] ].sector == sec)
  104. other = sides[ check->sidenum[1] ] .sector;
  105. else
  106. other = sides[ check->sidenum[0] ].sector;
  107. if (check->flags & ML_SOUNDBLOCK)
  108. {
  109. if (!soundblocks)
  110. P_RecursiveSound (other, 1);
  111. }
  112. else
  113. P_RecursiveSound (other, soundblocks);
  114. }
  115. }
  116. //
  117. // P_NoiseAlert
  118. // If a monster yells at a player,
  119. // it will alert other monsters to the player.
  120. //
  121. void
  122. P_NoiseAlert
  123. ( mobj_t* target,
  124. mobj_t* emmiter )
  125. {
  126. soundtarget = target;
  127. validcount++;
  128. P_RecursiveSound (emmiter->subsector->sector, 0);
  129. }
  130. //
  131. // P_CheckMeleeRange
  132. //
  133. boolean P_CheckMeleeRange (mobj_t* actor)
  134. {
  135. mobj_t* pl;
  136. fixed_t dist;
  137. if (!actor->target)
  138. return false;
  139. pl = actor->target;
  140. dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
  141. if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
  142. return false;
  143. if (! P_CheckSight (actor, actor->target) )
  144. return false;
  145. return true;
  146. }
  147. //
  148. // P_CheckMissileRange
  149. //
  150. boolean P_CheckMissileRange (mobj_t* actor)
  151. {
  152. fixed_t dist;
  153. if (! P_CheckSight (actor, actor->target) )
  154. return false;
  155. if ( actor->flags & MF_JUSTHIT )
  156. {
  157. // the target just hit the enemy,
  158. // so fight back!
  159. actor->flags &= ~MF_JUSTHIT;
  160. return true;
  161. }
  162. if (actor->reactiontime)
  163. return false; // do not attack yet
  164. // OPTIMIZE: get this from a global checksight
  165. dist = P_AproxDistance ( actor->x-actor->target->x,
  166. actor->y-actor->target->y) - 64*FRACUNIT;
  167. if (!actor->info->meleestate)
  168. dist -= 128*FRACUNIT; // no melee attack, so fire more
  169. dist >>= 16;
  170. if (actor->type == MT_VILE)
  171. {
  172. if (dist > 14*64)
  173. return false; // too far away
  174. }
  175. if (actor->type == MT_UNDEAD)
  176. {
  177. if (dist < 196)
  178. return false; // close for fist attack
  179. dist >>= 1;
  180. }
  181. if (actor->type == MT_CYBORG
  182. || actor->type == MT_SPIDER
  183. || actor->type == MT_SKULL)
  184. {
  185. dist >>= 1;
  186. }
  187. if (dist > 200)
  188. dist = 200;
  189. if (actor->type == MT_CYBORG && dist > 160)
  190. dist = 160;
  191. if (P_Random () < dist)
  192. return false;
  193. return true;
  194. }
  195. //
  196. // P_Move
  197. // Move in the current direction,
  198. // returns false if the move is blocked.
  199. //
  200. fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
  201. fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
  202. #define MAXSPECIALCROSS 8
  203. extern line_t* spechit[MAXSPECIALCROSS];
  204. extern int numspechit;
  205. boolean P_Move (mobj_t* actor)
  206. {
  207. fixed_t tryx;
  208. fixed_t tryy;
  209. line_t* ld;
  210. // warning: 'catch', 'throw', and 'try'
  211. // are all C++ reserved words
  212. boolean try_ok;
  213. boolean good;
  214. if (actor->movedir == DI_NODIR)
  215. return false;
  216. if ((unsigned)actor->movedir >= 8)
  217. I_Error ("Weird actor->movedir!");
  218. tryx = actor->x + actor->info->speed*xspeed[actor->movedir];
  219. tryy = actor->y + actor->info->speed*yspeed[actor->movedir];
  220. try_ok = P_TryMove (actor, tryx, tryy);
  221. if (!try_ok)
  222. {
  223. // open any specials
  224. if (actor->flags & MF_FLOAT && floatok)
  225. {
  226. // must adjust height
  227. if (actor->z < tmfloorz)
  228. actor->z += FLOATSPEED;
  229. else
  230. actor->z -= FLOATSPEED;
  231. actor->flags |= MF_INFLOAT;
  232. return true;
  233. }
  234. if (!numspechit)
  235. return false;
  236. actor->movedir = DI_NODIR;
  237. good = false;
  238. while (numspechit--)
  239. {
  240. ld = spechit[numspechit];
  241. // if the special is not a door
  242. // that can be opened,
  243. // return false
  244. if (P_UseSpecialLine (actor, ld,0))
  245. good = true;
  246. }
  247. return good;
  248. }
  249. else
  250. {
  251. actor->flags &= ~MF_INFLOAT;
  252. }
  253. if (! (actor->flags & MF_FLOAT) )
  254. actor->z = actor->floorz;
  255. return true;
  256. }
  257. //
  258. // TryWalk
  259. // Attempts to move actor on
  260. // in its current (ob->moveangle) direction.
  261. // If blocked by either a wall or an actor
  262. // returns FALSE
  263. // If move is either clear or blocked only by a door,
  264. // returns TRUE and sets...
  265. // If a door is in the way,
  266. // an OpenDoor call is made to start it opening.
  267. //
  268. boolean P_TryWalk (mobj_t* actor)
  269. {
  270. if (!P_Move (actor))
  271. {
  272. return false;
  273. }
  274. actor->movecount = P_Random()&15;
  275. return true;
  276. }
  277. void P_NewChaseDir (mobj_t* actor)
  278. {
  279. fixed_t deltax;
  280. fixed_t deltay;
  281. dirtype_t d[3];
  282. int tdir;
  283. dirtype_t olddir;
  284. dirtype_t turnaround;
  285. if (!actor->target)
  286. I_Error ("P_NewChaseDir: called with no target");
  287. olddir = actor->movedir;
  288. turnaround=opposite[olddir];
  289. deltax = actor->target->x - actor->x;
  290. deltay = actor->target->y - actor->y;
  291. if (deltax>10*FRACUNIT)
  292. d[1]= DI_EAST;
  293. else if (deltax<-10*FRACUNIT)
  294. d[1]= DI_WEST;
  295. else
  296. d[1]=DI_NODIR;
  297. if (deltay<-10*FRACUNIT)
  298. d[2]= DI_SOUTH;
  299. else if (deltay>10*FRACUNIT)
  300. d[2]= DI_NORTH;
  301. else
  302. d[2]=DI_NODIR;
  303. // try direct route
  304. if (d[1] != DI_NODIR
  305. && d[2] != DI_NODIR)
  306. {
  307. actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
  308. if (actor->movedir != turnaround && P_TryWalk(actor))
  309. return;
  310. }
  311. // try other directions
  312. if (P_Random() > 200
  313. || abs(deltay)>abs(deltax))
  314. {
  315. tdir=d[1];
  316. d[1]=d[2];
  317. d[2]=tdir;
  318. }
  319. if (d[1]==turnaround)
  320. d[1]=DI_NODIR;
  321. if (d[2]==turnaround)
  322. d[2]=DI_NODIR;
  323. if (d[1]!=DI_NODIR)
  324. {
  325. actor->movedir = d[1];
  326. if (P_TryWalk(actor))
  327. {
  328. // either moved forward or attacked
  329. return;
  330. }
  331. }
  332. if (d[2]!=DI_NODIR)
  333. {
  334. actor->movedir =d[2];
  335. if (P_TryWalk(actor))
  336. return;
  337. }
  338. // there is no direct path to the player,
  339. // so pick another direction.
  340. if (olddir!=DI_NODIR)
  341. {
  342. actor->movedir =olddir;
  343. if (P_TryWalk(actor))
  344. return;
  345. }
  346. // randomly determine direction of search
  347. if (P_Random()&1)
  348. {
  349. for ( tdir=DI_EAST;
  350. tdir<=DI_SOUTHEAST;
  351. tdir++ )
  352. {
  353. if (tdir!=turnaround)
  354. {
  355. actor->movedir =tdir;
  356. if ( P_TryWalk(actor) )
  357. return;
  358. }
  359. }
  360. }
  361. else
  362. {
  363. for ( tdir=DI_SOUTHEAST;
  364. tdir != (DI_EAST-1);
  365. tdir-- )
  366. {
  367. if (tdir!=turnaround)
  368. {
  369. actor->movedir =tdir;
  370. if ( P_TryWalk(actor) )
  371. return;
  372. }
  373. }
  374. }
  375. if (turnaround != DI_NODIR)
  376. {
  377. actor->movedir =turnaround;
  378. if ( P_TryWalk(actor) )
  379. return;
  380. }
  381. actor->movedir = DI_NODIR; // can not move
  382. }
  383. //
  384. // P_LookForPlayers
  385. // If allaround is false, only look 180 degrees in front.
  386. // Returns true if a player is targeted.
  387. //
  388. boolean
  389. P_LookForPlayers
  390. ( mobj_t* actor,
  391. boolean allaround )
  392. {
  393. int c;
  394. int stop;
  395. player_t* player;
  396. sector_t* sector;
  397. angle_t an;
  398. fixed_t dist;
  399. sector = actor->subsector->sector;
  400. c = 0;
  401. stop = (actor->lastlook-1)&3;
  402. for ( ; ; actor->lastlook = (actor->lastlook+1)&3 )
  403. {
  404. if (!playeringame[actor->lastlook])
  405. continue;
  406. if (c++ == 2
  407. || actor->lastlook == stop)
  408. {
  409. // done looking
  410. return false;
  411. }
  412. player = &players[actor->lastlook];
  413. if (player->health <= 0)
  414. continue; // dead
  415. if (!P_CheckSight (actor, player->mo))
  416. continue; // out of sight
  417. if (!allaround)
  418. {
  419. an = R_PointToAngle2 (actor->x,
  420. actor->y,
  421. player->mo->x,
  422. player->mo->y)
  423. - actor->angle;
  424. if (an > ANG90 && an < ANG270)
  425. {
  426. dist = P_AproxDistance (player->mo->x - actor->x,
  427. player->mo->y - actor->y);
  428. // if real close, react anyway
  429. if (dist > MELEERANGE)
  430. continue; // behind back
  431. }
  432. }
  433. actor->target = player->mo;
  434. return true;
  435. }
  436. return false;
  437. }
  438. //
  439. // A_KeenDie
  440. // DOOM II special, map 32.
  441. // Uses special tag 666.
  442. //
  443. void A_KeenDie (mobj_t* mo)
  444. {
  445. thinker_t* th;
  446. mobj_t* mo2;
  447. line_t junk;
  448. A_Fall (mo);
  449. // scan the remaining thinkers
  450. // to see if all Keens are dead
  451. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  452. {
  453. if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  454. continue;
  455. mo2 = (mobj_t *)th;
  456. if (mo2 != mo
  457. && mo2->type == mo->type
  458. && mo2->health > 0)
  459. {
  460. // other Keen not dead
  461. return;
  462. }
  463. }
  464. junk.tag = 666;
  465. EV_DoDoor(&junk,open);
  466. }
  467. //
  468. // ACTION ROUTINES
  469. //
  470. //
  471. // A_Look
  472. // Stay in state until a player is sighted.
  473. //
  474. void A_Look (mobj_t* actor)
  475. {
  476. mobj_t* targ;
  477. actor->threshold = 0; // any shot will wake up
  478. targ = actor->subsector->sector->soundtarget;
  479. if (targ
  480. && (targ->flags & MF_SHOOTABLE) )
  481. {
  482. actor->target = targ;
  483. if ( actor->flags & MF_AMBUSH )
  484. {
  485. if (P_CheckSight (actor, actor->target))
  486. goto seeyou;
  487. }
  488. else
  489. goto seeyou;
  490. }
  491. if (!P_LookForPlayers (actor, false) )
  492. return;
  493. // go into chase state
  494. seeyou:
  495. if (actor->info->seesound)
  496. {
  497. int sound;
  498. switch (actor->info->seesound)
  499. {
  500. case sfx_posit1:
  501. case sfx_posit2:
  502. case sfx_posit3:
  503. sound = sfx_posit1+P_Random()%3;
  504. break;
  505. case sfx_bgsit1:
  506. case sfx_bgsit2:
  507. sound = sfx_bgsit1+P_Random()%2;
  508. break;
  509. default:
  510. sound = actor->info->seesound;
  511. break;
  512. }
  513. if (actor->type==MT_SPIDER
  514. || actor->type == MT_CYBORG)
  515. {
  516. // full volume
  517. S_StartSound (NULL, sound);
  518. }
  519. else
  520. S_StartSound (actor, sound);
  521. }
  522. P_SetMobjState (actor, actor->info->seestate);
  523. }
  524. //
  525. // A_Chase
  526. // Actor has a melee attack,
  527. // so it tries to close as fast as possible
  528. //
  529. void A_Chase (mobj_t* actor)
  530. {
  531. int delta;
  532. if (actor->reactiontime)
  533. actor->reactiontime--;
  534. // modify target threshold
  535. if (actor->threshold)
  536. {
  537. if (!actor->target
  538. || actor->target->health <= 0)
  539. {
  540. actor->threshold = 0;
  541. }
  542. else
  543. actor->threshold--;
  544. }
  545. // turn towards movement direction if not there yet
  546. if (actor->movedir < 8)
  547. {
  548. actor->angle &= (7<<29);
  549. delta = actor->angle - (actor->movedir << 29);
  550. if (delta > 0)
  551. actor->angle -= ANG90/2;
  552. else if (delta < 0)
  553. actor->angle += ANG90/2;
  554. }
  555. if (!actor->target
  556. || !(actor->target->flags&MF_SHOOTABLE))
  557. {
  558. // look for a new target
  559. if (P_LookForPlayers(actor,true))
  560. return; // got a new target
  561. P_SetMobjState (actor, actor->info->spawnstate);
  562. return;
  563. }
  564. // do not attack twice in a row
  565. if (actor->flags & MF_JUSTATTACKED)
  566. {
  567. actor->flags &= ~MF_JUSTATTACKED;
  568. if (gameskill != sk_nightmare && !fastparm)
  569. P_NewChaseDir (actor);
  570. return;
  571. }
  572. // check for melee attack
  573. if (actor->info->meleestate
  574. && P_CheckMeleeRange (actor))
  575. {
  576. if (actor->info->attacksound)
  577. S_StartSound (actor, actor->info->attacksound);
  578. P_SetMobjState (actor, actor->info->meleestate);
  579. return;
  580. }
  581. // check for missile attack
  582. if (actor->info->missilestate)
  583. {
  584. if (gameskill < sk_nightmare
  585. && !fastparm && actor->movecount)
  586. {
  587. goto nomissile;
  588. }
  589. if (!P_CheckMissileRange (actor))
  590. goto nomissile;
  591. P_SetMobjState (actor, actor->info->missilestate);
  592. actor->flags |= MF_JUSTATTACKED;
  593. return;
  594. }
  595. // ?
  596. nomissile:
  597. // possibly choose another target
  598. if (netgame
  599. && !actor->threshold
  600. && !P_CheckSight (actor, actor->target) )
  601. {
  602. if (P_LookForPlayers(actor,true))
  603. return; // got a new target
  604. }
  605. // chase towards player
  606. if (--actor->movecount<0
  607. || !P_Move (actor))
  608. {
  609. P_NewChaseDir (actor);
  610. }
  611. // make active sound
  612. if (actor->info->activesound
  613. && P_Random () < 3)
  614. {
  615. S_StartSound (actor, actor->info->activesound);
  616. }
  617. }
  618. //
  619. // A_FaceTarget
  620. //
  621. void A_FaceTarget (mobj_t* actor)
  622. {
  623. if (!actor->target)
  624. return;
  625. actor->flags &= ~MF_AMBUSH;
  626. actor->angle = R_PointToAngle2 (actor->x,
  627. actor->y,
  628. actor->target->x,
  629. actor->target->y);
  630. if (actor->target->flags & MF_SHADOW)
  631. actor->angle += (P_Random()-P_Random())<<21;
  632. }
  633. //
  634. // A_PosAttack
  635. //
  636. void A_PosAttack (mobj_t* actor)
  637. {
  638. int angle;
  639. int damage;
  640. int slope;
  641. if (!actor->target)
  642. return;
  643. A_FaceTarget (actor);
  644. angle = actor->angle;
  645. slope = P_AimLineAttack (actor, angle, MISSILERANGE);
  646. S_StartSound (actor, sfx_pistol);
  647. angle += (P_Random()-P_Random())<<20;
  648. damage = ((P_Random()%5)+1)*3;
  649. P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  650. }
  651. void A_SPosAttack (mobj_t* actor)
  652. {
  653. int i;
  654. int angle;
  655. int bangle;
  656. int damage;
  657. int slope;
  658. if (!actor->target)
  659. return;
  660. S_StartSound (actor, sfx_shotgn);
  661. A_FaceTarget (actor);
  662. bangle = actor->angle;
  663. slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  664. for (i=0 ; i<3 ; i++)
  665. {
  666. angle = bangle + ((P_Random()-P_Random())<<20);
  667. damage = ((P_Random()%5)+1)*3;
  668. P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  669. }
  670. }
  671. void A_CPosAttack (mobj_t* actor)
  672. {
  673. int angle;
  674. int bangle;
  675. int damage;
  676. int slope;
  677. if (!actor->target)
  678. return;
  679. S_StartSound (actor, sfx_shotgn);
  680. A_FaceTarget (actor);
  681. bangle = actor->angle;
  682. slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  683. angle = bangle + ((P_Random()-P_Random())<<20);
  684. damage = ((P_Random()%5)+1)*3;
  685. P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  686. }
  687. void A_CPosRefire (mobj_t* actor)
  688. {
  689. // keep firing unless target got out of sight
  690. A_FaceTarget (actor);
  691. if (P_Random () < 40)
  692. return;
  693. if (!actor->target
  694. || actor->target->health <= 0
  695. || !P_CheckSight (actor, actor->target) )
  696. {
  697. P_SetMobjState (actor, actor->info->seestate);
  698. }
  699. }
  700. void A_SpidRefire (mobj_t* actor)
  701. {
  702. // keep firing unless target got out of sight
  703. A_FaceTarget (actor);
  704. if (P_Random () < 10)
  705. return;
  706. if (!actor->target
  707. || actor->target->health <= 0
  708. || !P_CheckSight (actor, actor->target) )
  709. {
  710. P_SetMobjState (actor, actor->info->seestate);
  711. }
  712. }
  713. void A_BspiAttack (mobj_t *actor)
  714. {
  715. if (!actor->target)
  716. return;
  717. A_FaceTarget (actor);
  718. // launch a missile
  719. P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
  720. }
  721. //
  722. // A_TroopAttack
  723. //
  724. void A_TroopAttack (mobj_t* actor)
  725. {
  726. int damage;
  727. if (!actor->target)
  728. return;
  729. A_FaceTarget (actor);
  730. if (P_CheckMeleeRange (actor))
  731. {
  732. S_StartSound (actor, sfx_claw);
  733. damage = (P_Random()%8+1)*3;
  734. P_DamageMobj (actor->target, actor, actor, damage);
  735. return;
  736. }
  737. // launch a missile
  738. P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
  739. }
  740. void A_SargAttack (mobj_t* actor)
  741. {
  742. int damage;
  743. if (!actor->target)
  744. return;
  745. A_FaceTarget (actor);
  746. if (P_CheckMeleeRange (actor))
  747. {
  748. damage = ((P_Random()%10)+1)*4;
  749. P_DamageMobj (actor->target, actor, actor, damage);
  750. }
  751. }
  752. void A_HeadAttack (mobj_t* actor)
  753. {
  754. int damage;
  755. if (!actor->target)
  756. return;
  757. A_FaceTarget (actor);
  758. if (P_CheckMeleeRange (actor))
  759. {
  760. damage = (P_Random()%6+1)*10;
  761. P_DamageMobj (actor->target, actor, actor, damage);
  762. return;
  763. }
  764. // launch a missile
  765. P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
  766. }
  767. void A_CyberAttack (mobj_t* actor)
  768. {
  769. if (!actor->target)
  770. return;
  771. A_FaceTarget (actor);
  772. P_SpawnMissile (actor, actor->target, MT_ROCKET);
  773. }
  774. void A_BruisAttack (mobj_t* actor)
  775. {
  776. int damage;
  777. if (!actor->target)
  778. return;
  779. if (P_CheckMeleeRange (actor))
  780. {
  781. S_StartSound (actor, sfx_claw);
  782. damage = (P_Random()%8+1)*10;
  783. P_DamageMobj (actor->target, actor, actor, damage);
  784. return;
  785. }
  786. // launch a missile
  787. P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
  788. }
  789. //
  790. // A_SkelMissile
  791. //
  792. void A_SkelMissile (mobj_t* actor)
  793. {
  794. mobj_t* mo;
  795. if (!actor->target)
  796. return;
  797. A_FaceTarget (actor);
  798. actor->z += 16*FRACUNIT; // so missile spawns higher
  799. mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
  800. actor->z -= 16*FRACUNIT; // back to normal
  801. mo->x += mo->momx;
  802. mo->y += mo->momy;
  803. mo->tracer = actor->target;
  804. }
  805. int TRACEANGLE = 0xc000000;
  806. void A_Tracer (mobj_t* actor)
  807. {
  808. angle_t exact;
  809. fixed_t dist;
  810. fixed_t slope;
  811. mobj_t* dest;
  812. mobj_t* th;
  813. if (gametic & 3)
  814. return;
  815. // spawn a puff of smoke behind the rocket
  816. P_SpawnPuff (actor->x, actor->y, actor->z);
  817. th = P_SpawnMobj (actor->x-actor->momx,
  818. actor->y-actor->momy,
  819. actor->z, MT_SMOKE);
  820. th->momz = FRACUNIT;
  821. th->tics -= P_Random()&3;
  822. if (th->tics < 1)
  823. th->tics = 1;
  824. // adjust direction
  825. dest = actor->tracer;
  826. if (!dest || dest->health <= 0)
  827. return;
  828. // change angle
  829. exact = R_PointToAngle2 (actor->x,
  830. actor->y,
  831. dest->x,
  832. dest->y);
  833. if (exact != actor->angle)
  834. {
  835. if (exact - actor->angle > 0x80000000)
  836. {
  837. actor->angle -= TRACEANGLE;
  838. if (exact - actor->angle < 0x80000000)
  839. actor->angle = exact;
  840. }
  841. else
  842. {
  843. actor->angle += TRACEANGLE;
  844. if (exact - actor->angle > 0x80000000)
  845. actor->angle = exact;
  846. }
  847. }
  848. exact = actor->angle>>ANGLETOFINESHIFT;
  849. actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
  850. actor->momy = FixedMul (actor->info->speed, finesine[exact]);
  851. // change slope
  852. dist = P_AproxDistance (dest->x - actor->x,
  853. dest->y - actor->y);
  854. dist = dist / actor->info->speed;
  855. if (dist < 1)
  856. dist = 1;
  857. slope = (dest->z+40*FRACUNIT - actor->z) / dist;
  858. if (slope < actor->momz)
  859. actor->momz -= FRACUNIT/8;
  860. else
  861. actor->momz += FRACUNIT/8;
  862. }
  863. void A_SkelWhoosh (mobj_t* actor)
  864. {
  865. if (!actor->target)
  866. return;
  867. A_FaceTarget (actor);
  868. S_StartSound (actor,sfx_skeswg);
  869. }
  870. void A_SkelFist (mobj_t* actor)
  871. {
  872. int damage;
  873. if (!actor->target)
  874. return;
  875. A_FaceTarget (actor);
  876. if (P_CheckMeleeRange (actor))
  877. {
  878. damage = ((P_Random()%10)+1)*6;
  879. S_StartSound (actor, sfx_skepch);
  880. P_DamageMobj (actor->target, actor, actor, damage);
  881. }
  882. }
  883. //
  884. // PIT_VileCheck
  885. // Detect a corpse that could be raised.
  886. //
  887. mobj_t* corpsehit;
  888. mobj_t* vileobj;
  889. fixed_t viletryx;
  890. fixed_t viletryy;
  891. boolean PIT_VileCheck (mobj_t* thing)
  892. {
  893. int maxdist;
  894. boolean check;
  895. if (!(thing->flags & MF_CORPSE) )
  896. return true; // not a monster
  897. if (thing->tics != -1)
  898. return true; // not lying still yet
  899. if (thing->info->raisestate == S_NULL)
  900. return true; // monster doesn't have a raise state
  901. maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
  902. if ( abs(thing->x - viletryx) > maxdist
  903. || abs(thing->y - viletryy) > maxdist )
  904. return true; // not actually touching
  905. corpsehit = thing;
  906. corpsehit->momx = corpsehit->momy = 0;
  907. corpsehit->height <<= 2;
  908. check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
  909. corpsehit->height >>= 2;
  910. if (!check)
  911. return true; // doesn't fit here
  912. return false; // got one, so stop checking
  913. }
  914. //
  915. // A_VileChase
  916. // Check for ressurecting a body
  917. //
  918. void A_VileChase (mobj_t* actor)
  919. {
  920. int xl;
  921. int xh;
  922. int yl;
  923. int yh;
  924. int bx;
  925. int by;
  926. mobjinfo_t* info;
  927. mobj_t* temp;
  928. if (actor->movedir != DI_NODIR)
  929. {
  930. // check for corpses to raise
  931. viletryx =
  932. actor->x + actor->info->speed*xspeed[actor->movedir];
  933. viletryy =
  934. actor->y + actor->info->speed*yspeed[actor->movedir];
  935. xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  936. xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  937. yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  938. yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  939. vileobj = actor;
  940. for (bx=xl ; bx<=xh ; bx++)
  941. {
  942. for (by=yl ; by<=yh ; by++)
  943. {
  944. // Call PIT_VileCheck to check
  945. // whether object is a corpse
  946. // that canbe raised.
  947. if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
  948. {
  949. // got one!
  950. temp = actor->target;
  951. actor->target = corpsehit;
  952. A_FaceTarget (actor);
  953. actor->target = temp;
  954. P_SetMobjState (actor, S_VILE_HEAL1);
  955. S_StartSound (corpsehit, sfx_slop);
  956. info = corpsehit->info;
  957. P_SetMobjState (corpsehit,info->raisestate);
  958. corpsehit->height <<= 2;
  959. corpsehit->flags = info->flags;
  960. corpsehit->health = info->spawnhealth;
  961. corpsehit->target = NULL;
  962. return;
  963. }
  964. }
  965. }
  966. }
  967. // Return to normal attack.
  968. A_Chase (actor);
  969. }
  970. //
  971. // A_VileStart
  972. //
  973. void A_VileStart (mobj_t* actor)
  974. {
  975. S_StartSound (actor, sfx_vilatk);
  976. }
  977. //
  978. // A_Fire
  979. // Keep fire in front of player unless out of sight
  980. //
  981. void A_Fire (mobj_t* actor);
  982. void A_StartFire (mobj_t* actor)
  983. {
  984. S_StartSound(actor,sfx_flamst);
  985. A_Fire(actor);
  986. }
  987. void A_FireCrackle (mobj_t* actor)
  988. {
  989. S_StartSound(actor,sfx_flame);
  990. A_Fire(actor);
  991. }
  992. void A_Fire (mobj_t* actor)
  993. {
  994. mobj_t* dest;
  995. unsigned an;
  996. dest = actor->tracer;
  997. if (!dest)
  998. return;
  999. // don't move it if the vile lost sight
  1000. if (!P_CheckSight (actor->target, dest) )
  1001. return;
  1002. an = dest->angle >> ANGLETOFINESHIFT;
  1003. P_UnsetThingPosition (actor);
  1004. actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
  1005. actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
  1006. actor->z = dest->z;
  1007. P_SetThingPosition (actor);
  1008. }
  1009. //
  1010. // A_VileTarget
  1011. // Spawn the hellfire
  1012. //
  1013. void A_VileTarget (mobj_t* actor)
  1014. {
  1015. mobj_t* fog;
  1016. if (!actor->target)
  1017. return;
  1018. A_FaceTarget (actor);
  1019. fog = P_SpawnMobj (actor->target->x,
  1020. actor->target->x,
  1021. actor->target->z, MT_FIRE);
  1022. actor->tracer = fog;
  1023. fog->target = actor;
  1024. fog->tracer = actor->target;
  1025. A_Fire (fog);
  1026. }
  1027. //
  1028. // A_VileAttack
  1029. //
  1030. void A_VileAttack (mobj_t* actor)
  1031. {
  1032. mobj_t* fire;
  1033. int an;
  1034. if (!actor->target)
  1035. return;
  1036. A_FaceTarget (actor);
  1037. if (!P_CheckSight (actor, actor->target) )
  1038. return;
  1039. S_StartSound (actor, sfx_barexp);
  1040. P_DamageMobj (actor->target, actor, actor, 20);
  1041. actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
  1042. an = actor->angle >> ANGLETOFINESHIFT;
  1043. fire = actor->tracer;
  1044. if (!fire)
  1045. return;
  1046. // move the fire between the vile and the player
  1047. fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
  1048. fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
  1049. P_RadiusAttack (fire, actor, 70 );
  1050. }
  1051. //
  1052. // Mancubus attack,
  1053. // firing three missiles (bruisers)
  1054. // in three different directions?
  1055. // Doesn't look like it.
  1056. //
  1057. #define FATSPREAD (ANG90/8)
  1058. void A_FatRaise (mobj_t *actor)
  1059. {
  1060. A_FaceTarget (actor);
  1061. S_StartSound (actor, sfx_manatk);
  1062. }
  1063. void A_FatAttack1 (mobj_t* actor)
  1064. {
  1065. mobj_t* mo;
  1066. int an;
  1067. A_FaceTarget (actor);
  1068. // Change direction to ...
  1069. actor->angle += FATSPREAD;
  1070. P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1071. mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1072. mo->angle += FATSPREAD;
  1073. an = mo->angle >> ANGLETOFINESHIFT;
  1074. mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1075. mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1076. }
  1077. void A_FatAttack2 (mobj_t* actor)
  1078. {
  1079. mobj_t* mo;
  1080. int an;
  1081. A_FaceTarget (actor);
  1082. // Now here choose opposite deviation.
  1083. actor->angle -= FATSPREAD;
  1084. P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1085. mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1086. mo->angle -= FATSPREAD*2;
  1087. an = mo->angle >> ANGLETOFINESHIFT;
  1088. mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1089. mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1090. }
  1091. void A_FatAttack3 (mobj_t* actor)
  1092. {
  1093. mobj_t* mo;
  1094. int an;
  1095. A_FaceTarget (actor);
  1096. mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1097. mo->angle -= FATSPREAD/2;
  1098. an = mo->angle >> ANGLETOFINESHIFT;
  1099. mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1100. mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1101. mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1102. mo->angle += FATSPREAD/2;
  1103. an = mo->angle >> ANGLETOFINESHIFT;
  1104. mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1105. mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1106. }
  1107. //
  1108. // SkullAttack
  1109. // Fly at the player like a missile.
  1110. //
  1111. #define SKULLSPEED (20*FRACUNIT)
  1112. void A_SkullAttack (mobj_t* actor)
  1113. {
  1114. mobj_t* dest;
  1115. angle_t an;
  1116. int dist;
  1117. if (!actor->target)
  1118. return;
  1119. dest = actor->target;
  1120. actor->flags |= MF_SKULLFLY;
  1121. S_StartSound (actor, actor->info->attacksound);
  1122. A_FaceTarget (actor);
  1123. an = actor->angle >> ANGLETOFINESHIFT;
  1124. actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
  1125. actor->momy = FixedMul (SKULLSPEED, finesine[an]);
  1126. dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
  1127. dist = dist / SKULLSPEED;
  1128. if (dist < 1)
  1129. dist = 1;
  1130. actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
  1131. }
  1132. //
  1133. // A_PainShootSkull
  1134. // Spawn a lost soul and launch it at the target
  1135. //
  1136. void
  1137. A_PainShootSkull
  1138. ( mobj_t* actor,
  1139. angle_t angle )
  1140. {
  1141. fixed_t x;
  1142. fixed_t y;
  1143. fixed_t z;
  1144. mobj_t* newmobj;
  1145. angle_t an;
  1146. int prestep;
  1147. int count;
  1148. thinker_t* currentthinker;
  1149. // count total number of skull currently on the level
  1150. count = 0;
  1151. currentthinker = thinkercap.next;
  1152. while (currentthinker != &thinkercap)
  1153. {
  1154. if ( (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
  1155. && ((mobj_t *)currentthinker)->type == MT_SKULL)
  1156. count++;
  1157. currentthinker = currentthinker->next;
  1158. }
  1159. // if there are allready 20 skulls on the level,
  1160. // don't spit another one
  1161. if (count > 20)
  1162. return;
  1163. // okay, there's playe for another one
  1164. an = angle >> ANGLETOFINESHIFT;
  1165. prestep =
  1166. 4*FRACUNIT
  1167. + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
  1168. x = actor->x + FixedMul (prestep, finecosine[an]);
  1169. y = actor->y + FixedMul (prestep, finesine[an]);
  1170. z = actor->z + 8*FRACUNIT;
  1171. newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
  1172. // Check for movements.
  1173. if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
  1174. {
  1175. // kill it immediately
  1176. P_DamageMobj (newmobj,actor,actor,10000);
  1177. return;
  1178. }
  1179. newmobj->target = actor->target;
  1180. A_SkullAttack (newmobj);
  1181. }
  1182. //
  1183. // A_PainAttack
  1184. // Spawn a lost soul and launch it at the target
  1185. //
  1186. void A_PainAttack (mobj_t* actor)
  1187. {
  1188. if (!actor->target)
  1189. return;
  1190. A_FaceTarget (actor);
  1191. A_PainShootSkull (actor, actor->angle);
  1192. }
  1193. void A_PainDie (mobj_t* actor)
  1194. {
  1195. A_Fall (actor);
  1196. A_PainShootSkull (actor, actor->angle+ANG90);
  1197. A_PainShootSkull (actor, actor->angle+ANG180);
  1198. A_PainShootSkull (actor, actor->angle+ANG270);
  1199. }
  1200. void A_Scream (mobj_t* actor)
  1201. {
  1202. int sound;
  1203. switch (actor->info->deathsound)
  1204. {
  1205. case 0:
  1206. return;
  1207. case sfx_podth1:
  1208. case sfx_podth2:
  1209. case sfx_podth3:
  1210. sound = sfx_podth1 + P_Random ()%3;
  1211. break;
  1212. case sfx_bgdth1:
  1213. case sfx_bgdth2:
  1214. sound = sfx_bgdth1 + P_Random ()%2;
  1215. break;
  1216. default:
  1217. sound = actor->info->deathsound;
  1218. break;
  1219. }
  1220. // Check for bosses.
  1221. if (actor->type==MT_SPIDER
  1222. || actor->type == MT_CYBORG)
  1223. {
  1224. // full volume
  1225. S_StartSound (NULL, sound);
  1226. }
  1227. else
  1228. S_StartSound (actor, sound);
  1229. }
  1230. void A_XScream (mobj_t* actor)
  1231. {
  1232. S_StartSound (actor, sfx_slop);
  1233. }
  1234. void A_Pain (mobj_t* actor)
  1235. {
  1236. if (actor->info->painsound)
  1237. S_StartSound (actor, actor->info->painsound);
  1238. }
  1239. void A_Fall (mobj_t *actor)
  1240. {
  1241. // actor is on ground, it can be walked over
  1242. actor->flags &= ~MF_SOLID;
  1243. // So change this if corpse objects
  1244. // are meant to be obstacles.
  1245. }
  1246. //
  1247. // A_Explode
  1248. //
  1249. void A_Explode (mobj_t* thingy)
  1250. {
  1251. P_RadiusAttack ( thingy, thingy->target, 128 );
  1252. }
  1253. //
  1254. // A_BossDeath
  1255. // Possibly trigger special effects
  1256. // if on first boss level
  1257. //
  1258. void A_BossDeath (mobj_t* mo)
  1259. {
  1260. thinker_t* th;
  1261. mobj_t* mo2;
  1262. line_t junk;
  1263. int i;
  1264. if ( gamemode == commercial)
  1265. {
  1266. if (gamemap != 7)
  1267. return;
  1268. if ((mo->type != MT_FATSO)
  1269. && (mo->type != MT_BABY))
  1270. return;
  1271. }
  1272. else
  1273. {
  1274. switch(gameepisode)
  1275. {
  1276. case 1:
  1277. if (gamemap != 8)
  1278. return;
  1279. if (mo->type != MT_BRUISER)
  1280. return;
  1281. break;
  1282. case 2:
  1283. if (gamemap != 8)
  1284. return;
  1285. if (mo->type != MT_CYBORG)
  1286. return;
  1287. break;
  1288. case 3:
  1289. if (gamemap != 8)
  1290. return;
  1291. if (mo->type != MT_SPIDER)
  1292. return;
  1293. break;
  1294. case 4:
  1295. switch(gamemap)
  1296. {
  1297. case 6:
  1298. if (mo->type != MT_CYBORG)
  1299. return;
  1300. break;
  1301. case 8:
  1302. if (mo->type != MT_SPIDER)
  1303. return;
  1304. break;
  1305. default:
  1306. return;
  1307. break;
  1308. }
  1309. break;
  1310. default:
  1311. if (gamemap != 8)
  1312. return;
  1313. break;
  1314. }
  1315. }
  1316. // make sure there is a player alive for victory
  1317. for (i=0 ; i<MAXPLAYERS ; i++)
  1318. if (playeringame[i] && players[i].health > 0)
  1319. break;
  1320. if (i==MAXPLAYERS)
  1321. return; // no one left alive, so do not end game
  1322. // scan the remaining thinkers to see
  1323. // if all bosses are dead
  1324. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  1325. {
  1326. if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  1327. continue;
  1328. mo2 = (mobj_t *)th;
  1329. if (mo2 != mo
  1330. && mo2->type == mo->type
  1331. && mo2->health > 0)
  1332. {
  1333. // other boss not dead
  1334. return;
  1335. }
  1336. }
  1337. // victory!
  1338. if ( gamemode == commercial)
  1339. {
  1340. if (gamemap == 7)
  1341. {
  1342. if (mo->type == MT_FATSO)
  1343. {
  1344. junk.tag = 666;
  1345. EV_DoFloor(&junk,lowerFloorToLowest);
  1346. return;
  1347. }
  1348. if (mo->type == MT_BABY)
  1349. {
  1350. junk.tag = 667;
  1351. EV_DoFloor(&junk,raiseToTexture);
  1352. return;
  1353. }
  1354. }
  1355. }
  1356. else
  1357. {
  1358. switch(gameepisode)
  1359. {
  1360. case 1:
  1361. junk.tag = 666;
  1362. EV_DoFloor (&junk, lowerFloorToLowest);
  1363. return;
  1364. break;
  1365. case 4:
  1366. switch(gamemap)
  1367. {
  1368. case 6:
  1369. junk.tag = 666;
  1370. EV_DoDoor (&junk, blazeOpen);
  1371. return;
  1372. break;
  1373. case 8:
  1374. junk.tag = 666;
  1375. EV_DoFloor (&junk, lowerFloorToLowest);
  1376. return;
  1377. break;
  1378. }
  1379. }
  1380. }
  1381. G_ExitLevel ();
  1382. }
  1383. void A_Hoof (mobj_t* mo)
  1384. {
  1385. S_StartSound (mo, sfx_hoof);
  1386. A_Chase (mo);
  1387. }
  1388. void A_Metal (mobj_t* mo)
  1389. {
  1390. S_StartSound (mo, sfx_metal);
  1391. A_Chase (mo);
  1392. }
  1393. void A_BabyMetal (mobj_t* mo)
  1394. {
  1395. S_StartSound (mo, sfx_bspwlk);
  1396. A_Chase (mo);
  1397. }
  1398. void
  1399. A_OpenShotgun2
  1400. ( player_t* player,
  1401. pspdef_t* psp )
  1402. {
  1403. S_StartSound (player->mo, sfx_dbopn);
  1404. }
  1405. void
  1406. A_LoadShotgun2
  1407. ( player_t* player,
  1408. pspdef_t* psp )
  1409. {
  1410. S_StartSound (player->mo, sfx_dbload);
  1411. }
  1412. void
  1413. A_ReFire
  1414. ( player_t* player,
  1415. pspdef_t* psp );
  1416. void
  1417. A_CloseShotgun2
  1418. ( player_t* player,
  1419. pspdef_t* psp )
  1420. {
  1421. S_StartSound (player->mo, sfx_dbcls);
  1422. A_ReFire(player,psp);
  1423. }
  1424. mobj_t* braintargets[32];
  1425. int numbraintargets;
  1426. int braintargeton;
  1427. void A_BrainAwake (mobj_t* mo)
  1428. {
  1429. thinker_t* thinker;
  1430. mobj_t* m;
  1431. // find all the target spots
  1432. numbraintargets = 0;
  1433. braintargeton = 0;
  1434. thinker = thinkercap.next;
  1435. for (thinker = thinkercap.next ;
  1436. thinker != &thinkercap ;
  1437. thinker = thinker->next)
  1438. {
  1439. if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
  1440. continue; // not a mobj
  1441. m = (mobj_t *)thinker;
  1442. if (m->type == MT_BOSSTARGET )
  1443. {
  1444. braintargets[numbraintargets] = m;
  1445. numbraintargets++;
  1446. }
  1447. }
  1448. S_StartSound (NULL,sfx_bossit);
  1449. }
  1450. void A_BrainPain (mobj_t* mo)
  1451. {
  1452. S_StartSound (NULL,sfx_bospn);
  1453. }
  1454. void A_BrainScream (mobj_t* mo)
  1455. {
  1456. int x;
  1457. int y;
  1458. int z;
  1459. mobj_t* th;
  1460. for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
  1461. {
  1462. y = mo->y - 320*FRACUNIT;
  1463. z = 128 + P_Random()*2*FRACUNIT;
  1464. th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1465. th->momz = P_Random()*512;
  1466. P_SetMobjState (th, S_BRAINEXPLODE1);
  1467. th->tics -= P_Random()&7;
  1468. if (th->tics < 1)
  1469. th->tics = 1;
  1470. }
  1471. S_StartSound (NULL,sfx_bosdth);
  1472. }
  1473. void A_BrainExplode (mobj_t* mo)
  1474. {
  1475. int x;
  1476. int y;
  1477. int z;
  1478. mobj_t* th;
  1479. x = mo->x + (P_Random () - P_Random ())*2048;
  1480. y = mo->y;
  1481. z = 128 + P_Random()*2*FRACUNIT;
  1482. th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1483. th->momz = P_Random()*512;
  1484. P_SetMobjState (th, S_BRAINEXPLODE1);
  1485. th->tics -= P_Random()&7;
  1486. if (th->tics < 1)
  1487. th->tics = 1;
  1488. }
  1489. void A_BrainDie (mobj_t* mo)
  1490. {
  1491. G_ExitLevel ();
  1492. }
  1493. void A_BrainSpit (mobj_t* mo)
  1494. {
  1495. mobj_t* targ;
  1496. mobj_t* newmobj;
  1497. static int easy = 0;
  1498. easy ^= 1;
  1499. if (gameskill <= sk_easy && (!easy))
  1500. return;
  1501. // shoot a cube at current target
  1502. targ = braintargets[braintargeton];
  1503. braintargeton = (braintargeton+1)%numbraintargets;
  1504. // spawn brain missile
  1505. newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
  1506. newmobj->target = targ;
  1507. newmobj->reactiontime =
  1508. ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
  1509. S_StartSound(NULL, sfx_bospit);
  1510. }
  1511. void A_SpawnFly (mobj_t* mo);
  1512. // travelling cube sound
  1513. void A_SpawnSound (mobj_t* mo)
  1514. {
  1515. S_StartSound (mo,sfx_boscub);
  1516. A_SpawnFly(mo);
  1517. }
  1518. void A_SpawnFly (mobj_t* mo)
  1519. {
  1520. mobj_t* newmobj;
  1521. mobj_t* fog;
  1522. mobj_t* targ;
  1523. int r;
  1524. mobjtype_t type;
  1525. if (--mo->reactiontime)
  1526. return; // still flying
  1527. targ = mo->target;
  1528. // First spawn teleport fog.
  1529. fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
  1530. S_StartSound (fog, sfx_telept);
  1531. // Randomly select monster to spawn.
  1532. r = P_Random ();
  1533. // Probability distribution (kind of :),
  1534. // decreasing likelihood.
  1535. if ( r<50 )
  1536. type = MT_TROOP;
  1537. else if (r<90)
  1538. type = MT_SERGEANT;
  1539. else if (r<120)
  1540. type = MT_SHADOWS;
  1541. else if (r<130)
  1542. type = MT_PAIN;
  1543. else if (r<160)
  1544. type = MT_HEAD;
  1545. else if (r<162)
  1546. type = MT_VILE;
  1547. else if (r<172)
  1548. type = MT_UNDEAD;
  1549. else if (r<192)
  1550. type = MT_BABY;
  1551. else if (r<222)
  1552. type = MT_FATSO;
  1553. else if (r<246)
  1554. type = MT_KNIGHT;
  1555. else
  1556. type = MT_BRUISER;
  1557. newmobj = P_SpawnMobj (targ->x, targ->y, targ->z, type);
  1558. if (P_LookForPlayers (newmobj, true) )
  1559. P_SetMobjState (newmobj, newmobj->info->seestate);
  1560. // telefrag anything in this spot
  1561. P_TeleportMove (newmobj, newmobj->x, newmobj->y);
  1562. // remove self (i.e., cube).
  1563. P_RemoveMobj (mo);
  1564. }
  1565. void A_PlayerScream (mobj_t* mo)
  1566. {
  1567. // Default death sound.
  1568. int sound = sfx_pldeth;
  1569. if ( (gamemode == commercial)
  1570. && (mo->health < -50))
  1571. {
  1572. // IF THE PLAYER DIES
  1573. // LESS THAN -50% WITHOUT GIBBING
  1574. sound = sfx_pdiehi;
  1575. }
  1576. S_StartSound (mo, sound);
  1577. }