p_enemy.cpp 38 KB

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