p_enemy.c 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2000,2002 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Enemy thinking, AI.
  31. * Action Pointer Functions
  32. * that are associated with states/frames.
  33. *
  34. *-----------------------------------------------------------------------------*/
  35. #include "doomstat.h"
  36. #include "m_random.h"
  37. #include "r_main.h"
  38. #include "p_maputl.h"
  39. #include "p_map.h"
  40. #include "p_setup.h"
  41. #include "p_spec.h"
  42. #include "s_sound.h"
  43. #include "sounds.h"
  44. #include "p_inter.h"
  45. #include "g_game.h"
  46. #include "p_enemy.h"
  47. #include "p_tick.h"
  48. #include "m_bbox.h"
  49. #include "lprintf.h"
  50. static mobj_t *current_actor;
  51. typedef enum {
  52. DI_EAST,
  53. DI_NORTHEAST,
  54. DI_NORTH,
  55. DI_NORTHWEST,
  56. DI_WEST,
  57. DI_SOUTHWEST,
  58. DI_SOUTH,
  59. DI_SOUTHEAST,
  60. DI_NODIR,
  61. NUMDIRS
  62. } dirtype_t;
  63. static void P_NewChaseDir(mobj_t *actor);
  64. void P_ZBumpCheck(mobj_t *); // phares
  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. // killough 5/5/98: reformatted, cleaned up
  78. static void P_RecursiveSound(sector_t *sec, int soundblocks,
  79. mobj_t *soundtarget)
  80. {
  81. int i;
  82. // wake up all monsters in this sector
  83. if (sec->validcount == validcount && sec->soundtraversed <= soundblocks+1)
  84. return; // already flooded
  85. sec->validcount = validcount;
  86. sec->soundtraversed = soundblocks+1;
  87. P_SetTarget(&sec->soundtarget, soundtarget);
  88. for (i=0; i<sec->linecount; i++)
  89. {
  90. sector_t *other;
  91. line_t *check = sec->lines[i];
  92. if (!(check->flags & ML_TWOSIDED))
  93. continue;
  94. P_LineOpening(check);
  95. if (openrange <= 0)
  96. continue; // closed door
  97. other=sides[check->sidenum[sides[check->sidenum[0]].sector==sec]].sector;
  98. if (!(check->flags & ML_SOUNDBLOCK))
  99. P_RecursiveSound(other, soundblocks, soundtarget);
  100. else
  101. if (!soundblocks)
  102. P_RecursiveSound(other, 1, soundtarget);
  103. }
  104. }
  105. //
  106. // P_NoiseAlert
  107. // If a monster yells at a player,
  108. // it will alert other monsters to the player.
  109. //
  110. void P_NoiseAlert(mobj_t *target, mobj_t *emitter)
  111. {
  112. validcount++;
  113. P_RecursiveSound(emitter->subsector->sector, 0, target);
  114. }
  115. //
  116. // P_CheckMeleeRange
  117. //
  118. static boolean P_CheckMeleeRange(mobj_t *actor)
  119. {
  120. mobj_t *pl = actor->target;
  121. return // killough 7/18/98: friendly monsters don't attack other friends
  122. pl && !(actor->flags & pl->flags & MF_FRIEND) &&
  123. (P_AproxDistance(pl->x-actor->x, pl->y-actor->y) <
  124. MELEERANGE - 20*FRACUNIT + pl->info->radius) &&
  125. P_CheckSight(actor, actor->target);
  126. }
  127. //
  128. // P_HitFriend()
  129. //
  130. // killough 12/98
  131. // This function tries to prevent shooting at friends
  132. static boolean P_HitFriend(mobj_t *actor)
  133. {
  134. return actor->flags & MF_FRIEND && actor->target &&
  135. (P_AimLineAttack(actor,
  136. R_PointToAngle2(actor->x, actor->y,
  137. actor->target->x, actor->target->y),
  138. P_AproxDistance(actor->x-actor->target->x,
  139. actor->y-actor->target->y), 0),
  140. linetarget) && linetarget != actor->target &&
  141. !((linetarget->flags ^ actor->flags) & MF_FRIEND);
  142. }
  143. //
  144. // P_CheckMissileRange
  145. //
  146. static boolean P_CheckMissileRange(mobj_t *actor)
  147. {
  148. fixed_t dist;
  149. if (!P_CheckSight(actor, actor->target))
  150. return false;
  151. if (actor->flags & MF_JUSTHIT)
  152. { // the target just hit the enemy, so fight back!
  153. actor->flags &= ~MF_JUSTHIT;
  154. /* killough 7/18/98: no friendly fire at corpses
  155. * killough 11/98: prevent too much infighting among friends
  156. * cph - yikes, talk about fitting everything on one line... */
  157. return
  158. !(actor->flags & MF_FRIEND) ||
  159. (actor->target->health > 0 &&
  160. (!(actor->target->flags & MF_FRIEND) ||
  161. (actor->target->player ?
  162. monster_infighting || P_Random(pr_defect) >128 :
  163. !(actor->target->flags & MF_JUSTHIT) && P_Random(pr_defect) >128)));
  164. }
  165. /* killough 7/18/98: friendly monsters don't attack other friendly
  166. * monsters or players (except when attacked, and then only once)
  167. */
  168. if (actor->flags & actor->target->flags & MF_FRIEND)
  169. return false;
  170. if (actor->reactiontime)
  171. return false; // do not attack yet
  172. // OPTIMIZE: get this from a global checksight
  173. dist = P_AproxDistance ( actor->x-actor->target->x,
  174. actor->y-actor->target->y) - 64*FRACUNIT;
  175. if (!actor->info->meleestate)
  176. dist -= 128*FRACUNIT; // no melee attack, so fire more
  177. dist >>= FRACBITS;
  178. if (actor->type == MT_VILE)
  179. if (dist > 14*64)
  180. return false; // too far away
  181. if (actor->type == MT_UNDEAD)
  182. {
  183. if (dist < 196)
  184. return false; // close for fist attack
  185. dist >>= 1;
  186. }
  187. if (actor->type == MT_CYBORG ||
  188. actor->type == MT_SPIDER ||
  189. actor->type == MT_SKULL)
  190. dist >>= 1;
  191. if (dist > 200)
  192. dist = 200;
  193. if (actor->type == MT_CYBORG && dist > 160)
  194. dist = 160;
  195. if (P_Random(pr_missrange) < dist)
  196. return false;
  197. if (P_HitFriend(actor))
  198. return false;
  199. return true;
  200. }
  201. /*
  202. * P_IsOnLift
  203. *
  204. * killough 9/9/98:
  205. *
  206. * Returns true if the object is on a lift. Used for AI,
  207. * since it may indicate the need for crowded conditions,
  208. * or that a monster should stay on the lift for a while
  209. * while it goes up or down.
  210. */
  211. static boolean P_IsOnLift(const mobj_t *actor)
  212. {
  213. const sector_t *sec = actor->subsector->sector;
  214. line_t line;
  215. int l;
  216. // Short-circuit: it's on a lift which is active.
  217. if (sec->floordata && ((thinker_t *) sec->floordata)->function==T_PlatRaise)
  218. return true;
  219. // Check to see if it's in a sector which can be activated as a lift.
  220. if ((line.tag = sec->tag))
  221. for (l = -1; (l = P_FindLineFromLineTag(&line, l)) >= 0;)
  222. switch (lines[l].special)
  223. {
  224. case 10: case 14: case 15: case 20: case 21: case 22:
  225. case 47: case 53: case 62: case 66: case 67: case 68:
  226. case 87: case 88: case 95: case 120: case 121: case 122:
  227. case 123: case 143: case 162: case 163: case 181: case 182:
  228. case 144: case 148: case 149: case 211: case 227: case 228:
  229. case 231: case 232: case 235: case 236:
  230. return true;
  231. }
  232. return false;
  233. }
  234. /*
  235. * P_IsUnderDamage
  236. *
  237. * killough 9/9/98:
  238. *
  239. * Returns nonzero if the object is under damage based on
  240. * their current position. Returns 1 if the damage is moderate,
  241. * -1 if it is serious. Used for AI.
  242. */
  243. static int P_IsUnderDamage(mobj_t *actor)
  244. {
  245. const struct msecnode_s *seclist;
  246. const ceiling_t *cl; // Crushing ceiling
  247. int dir = 0;
  248. for (seclist=actor->touching_sectorlist; seclist; seclist=seclist->m_tnext)
  249. if ((cl = seclist->m_sector->ceilingdata) &&
  250. cl->thinker.function == T_MoveCeiling)
  251. dir |= cl->direction;
  252. return dir;
  253. }
  254. //
  255. // P_Move
  256. // Move in the current direction,
  257. // returns false if the move is blocked.
  258. //
  259. static fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
  260. static fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
  261. // 1/11/98 killough: Limit removed on special lines crossed
  262. extern line_t **spechit; // New code -- killough
  263. extern int numspechit;
  264. static boolean P_Move(mobj_t *actor, boolean dropoff) /* killough 9/12/98 */
  265. {
  266. fixed_t tryx, tryy, deltax, deltay, origx, origy;
  267. boolean try_ok;
  268. int movefactor = ORIG_FRICTION_FACTOR; // killough 10/98
  269. int friction = ORIG_FRICTION;
  270. int speed;
  271. if (actor->movedir == DI_NODIR)
  272. return false;
  273. #ifdef RANGECHECK
  274. if ((unsigned)actor->movedir >= 8)
  275. I_Error ("P_Move: Weird actor->movedir!");
  276. #endif
  277. // killough 10/98: make monsters get affected by ice and sludge too:
  278. if (monster_friction)
  279. movefactor = P_GetMoveFactor(actor, &friction);
  280. speed = actor->info->speed;
  281. if (friction < ORIG_FRICTION && // sludge
  282. !(speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
  283. * speed) / ORIG_FRICTION_FACTOR))
  284. speed = 1; // always give the monster a little bit of speed
  285. tryx = (origx = actor->x) + (deltax = speed * xspeed[actor->movedir]);
  286. tryy = (origy = actor->y) + (deltay = speed * yspeed[actor->movedir]);
  287. try_ok = P_TryMove(actor, tryx, tryy, dropoff);
  288. // killough 10/98:
  289. // Let normal momentum carry them, instead of steptoeing them across ice.
  290. if (try_ok && friction > ORIG_FRICTION)
  291. {
  292. actor->x = origx;
  293. actor->y = origy;
  294. movefactor *= FRACUNIT / ORIG_FRICTION_FACTOR / 4;
  295. actor->momx += FixedMul(deltax, movefactor);
  296. actor->momy += FixedMul(deltay, movefactor);
  297. }
  298. if (!try_ok)
  299. { // open any specials
  300. int good;
  301. if (actor->flags & MF_FLOAT && floatok)
  302. {
  303. if (actor->z < tmfloorz) // must adjust height
  304. actor->z += FLOATSPEED;
  305. else
  306. actor->z -= FLOATSPEED;
  307. actor->flags |= MF_INFLOAT;
  308. return true;
  309. }
  310. if (!numspechit)
  311. return false;
  312. actor->movedir = DI_NODIR;
  313. /* if the special is not a door that can be opened, return false
  314. *
  315. * killough 8/9/98: this is what caused monsters to get stuck in
  316. * doortracks, because it thought that the monster freed itself
  317. * by opening a door, even if it was moving towards the doortrack,
  318. * and not the door itself.
  319. *
  320. * killough 9/9/98: If a line blocking the monster is activated,
  321. * return true 90% of the time. If a line blocking the monster is
  322. * not activated, but some other line is, return false 90% of the
  323. * time. A bit of randomness is needed to ensure it's free from
  324. * lockups, but for most cases, it returns the correct result.
  325. *
  326. * Do NOT simply return false 1/4th of the time (causes monsters to
  327. * back out when they shouldn't, and creates secondary stickiness).
  328. */
  329. for (good = false; numspechit--; )
  330. if (P_UseSpecialLine(actor, spechit[numspechit], 0))
  331. good |= spechit[numspechit] == blockline ? 1 : 2;
  332. /* cph - compatibility maze here
  333. * Boom v2.01 and orig. Doom return "good"
  334. * Boom v2.02 and LxDoom return good && (P_Random(pr_trywalk)&3)
  335. * MBF plays even more games
  336. */
  337. if (!good || comp[comp_doorstuck]) return good;
  338. if (!mbf_features)
  339. return (P_Random(pr_trywalk)&3); /* jff 8/13/98 */
  340. else /* finally, MBF code */
  341. return ((P_Random(pr_opendoor) >= 230) ^ (good & 1));
  342. }
  343. else
  344. actor->flags &= ~MF_INFLOAT;
  345. /* killough 11/98: fall more slowly, under gravity, if felldown==true */
  346. if (!(actor->flags & MF_FLOAT) &&
  347. (!felldown || !mbf_features))
  348. actor->z = actor->floorz;
  349. return true;
  350. }
  351. /*
  352. * P_SmartMove
  353. *
  354. * killough 9/12/98: Same as P_Move, except smarter
  355. */
  356. static boolean P_SmartMove(mobj_t *actor)
  357. {
  358. mobj_t *target = actor->target;
  359. int on_lift, dropoff = false, under_damage;
  360. /* killough 9/12/98: Stay on a lift if target is on one */
  361. on_lift = !comp[comp_staylift]
  362. && target && target->health > 0
  363. && target->subsector->sector->tag==actor->subsector->sector->tag &&
  364. P_IsOnLift(actor);
  365. under_damage = monster_avoid_hazards && P_IsUnderDamage(actor);
  366. // killough 10/98: allow dogs to drop off of taller ledges sometimes.
  367. // dropoff==1 means always allow it, dropoff==2 means only up to 128 high,
  368. // and only if the target is immediately on the other side of the line.
  369. #ifdef DOGS
  370. // haleyjd: allow all friends of HelperType to also jump down
  371. if ((actor->type == MT_DOGS || (actor->type == (HelperThing-1) && actor->flags&MF_FRIEND))
  372. && target && dog_jumping &&
  373. !((target->flags ^ actor->flags) & MF_FRIEND) &&
  374. P_AproxDistance(actor->x - target->x,
  375. actor->y - target->y) < FRACUNIT*144 &&
  376. P_Random(pr_dropoff) < 235)
  377. dropoff = 2;
  378. #endif
  379. if (!P_Move(actor, dropoff))
  380. return false;
  381. // killough 9/9/98: avoid crushing ceilings or other damaging areas
  382. if (
  383. (on_lift && P_Random(pr_stayonlift) < 230 && // Stay on lift
  384. !P_IsOnLift(actor))
  385. ||
  386. (monster_avoid_hazards && !under_damage && // Get away from damage
  387. (under_damage = P_IsUnderDamage(actor)) &&
  388. (under_damage < 0 || P_Random(pr_avoidcrush) < 200))
  389. )
  390. actor->movedir = DI_NODIR; // avoid the area (most of the time anyway)
  391. return true;
  392. }
  393. //
  394. // TryWalk
  395. // Attempts to move actor on
  396. // in its current (ob->moveangle) direction.
  397. // If blocked by either a wall or an actor
  398. // returns FALSE
  399. // If move is either clear or blocked only by a door,
  400. // returns TRUE and sets...
  401. // If a door is in the way,
  402. // an OpenDoor call is made to start it opening.
  403. //
  404. static boolean P_TryWalk(mobj_t *actor)
  405. {
  406. if (!P_SmartMove(actor))
  407. return false;
  408. actor->movecount = P_Random(pr_trywalk)&15;
  409. return true;
  410. }
  411. //
  412. // P_DoNewChaseDir
  413. //
  414. // killough 9/8/98:
  415. //
  416. // Most of P_NewChaseDir(), except for what
  417. // determines the new direction to take
  418. //
  419. static void P_DoNewChaseDir(mobj_t *actor, fixed_t deltax, fixed_t deltay)
  420. {
  421. dirtype_t xdir, ydir, tdir;
  422. dirtype_t olddir = actor->movedir;
  423. dirtype_t turnaround = olddir;
  424. if (turnaround != DI_NODIR) // find reverse direction
  425. turnaround ^= 4;
  426. xdir =
  427. deltax > 10*FRACUNIT ? DI_EAST :
  428. deltax < -10*FRACUNIT ? DI_WEST : DI_NODIR;
  429. ydir =
  430. deltay < -10*FRACUNIT ? DI_SOUTH :
  431. deltay > 10*FRACUNIT ? DI_NORTH : DI_NODIR;
  432. // try direct route
  433. if (xdir != DI_NODIR && ydir != DI_NODIR && turnaround !=
  434. (actor->movedir = deltay < 0 ? deltax > 0 ? DI_SOUTHEAST : DI_SOUTHWEST :
  435. deltax > 0 ? DI_NORTHEAST : DI_NORTHWEST) && P_TryWalk(actor))
  436. return;
  437. // try other directions
  438. if (P_Random(pr_newchase) > 200 || D_abs(deltay)>D_abs(deltax))
  439. tdir = xdir, xdir = ydir, ydir = tdir;
  440. if ((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR &&
  441. (actor->movedir = xdir, P_TryWalk(actor)))
  442. return; // either moved forward or attacked
  443. if ((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR &&
  444. (actor->movedir = ydir, P_TryWalk(actor)))
  445. return;
  446. // there is no direct path to the player, so pick another direction.
  447. if (olddir != DI_NODIR && (actor->movedir = olddir, P_TryWalk(actor)))
  448. return;
  449. // randomly determine direction of search
  450. if (P_Random(pr_newchasedir) & 1)
  451. {
  452. for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++)
  453. if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor)))
  454. return;
  455. }
  456. else
  457. for (tdir = DI_SOUTHEAST; tdir != DI_EAST-1; tdir--)
  458. if (tdir != turnaround && (actor->movedir = tdir, P_TryWalk(actor)))
  459. return;
  460. if ((actor->movedir = turnaround) != DI_NODIR && !P_TryWalk(actor))
  461. actor->movedir = DI_NODIR;
  462. }
  463. //
  464. // killough 11/98:
  465. //
  466. // Monsters try to move away from tall dropoffs.
  467. //
  468. // In Doom, they were never allowed to hang over dropoffs,
  469. // and would remain stuck if involuntarily forced over one.
  470. // This logic, combined with p_map.c (P_TryMove), allows
  471. // monsters to free themselves without making them tend to
  472. // hang over dropoffs.
  473. static fixed_t dropoff_deltax, dropoff_deltay, floorz;
  474. static boolean PIT_AvoidDropoff(line_t *line)
  475. {
  476. if (line->backsector && // Ignore one-sided linedefs
  477. tmbbox[BOXRIGHT] > line->bbox[BOXLEFT] &&
  478. tmbbox[BOXLEFT] < line->bbox[BOXRIGHT] &&
  479. tmbbox[BOXTOP] > line->bbox[BOXBOTTOM] && // Linedef must be contacted
  480. tmbbox[BOXBOTTOM] < line->bbox[BOXTOP] &&
  481. P_BoxOnLineSide(tmbbox, line) == -1)
  482. {
  483. fixed_t front = line->frontsector->floorheight;
  484. fixed_t back = line->backsector->floorheight;
  485. angle_t angle;
  486. // The monster must contact one of the two floors,
  487. // and the other must be a tall dropoff (more than 24).
  488. if (back == floorz && front < floorz - FRACUNIT*24)
  489. angle = R_PointToAngle2(0,0,line->dx,line->dy); // front side dropoff
  490. else
  491. if (front == floorz && back < floorz - FRACUNIT*24)
  492. angle = R_PointToAngle2(line->dx,line->dy,0,0); // back side dropoff
  493. else
  494. return true;
  495. // Move away from dropoff at a standard speed.
  496. // Multiple contacted linedefs are cumulative (e.g. hanging over corner)
  497. dropoff_deltax -= finesine[angle >> ANGLETOFINESHIFT]*32;
  498. dropoff_deltay += finecosine[angle >> ANGLETOFINESHIFT]*32;
  499. }
  500. return true;
  501. }
  502. //
  503. // Driver for above
  504. //
  505. static fixed_t P_AvoidDropoff(mobj_t *actor)
  506. {
  507. int yh=((tmbbox[BOXTOP] = actor->y+actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
  508. int yl=((tmbbox[BOXBOTTOM]= actor->y-actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
  509. int xh=((tmbbox[BOXRIGHT] = actor->x+actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
  510. int xl=((tmbbox[BOXLEFT] = actor->x-actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
  511. int bx, by;
  512. floorz = actor->z; // remember floor height
  513. dropoff_deltax = dropoff_deltay = 0;
  514. // check lines
  515. validcount++;
  516. for (bx=xl ; bx<=xh ; bx++)
  517. for (by=yl ; by<=yh ; by++)
  518. P_BlockLinesIterator(bx, by, PIT_AvoidDropoff); // all contacted lines
  519. return dropoff_deltax | dropoff_deltay; // Non-zero if movement prescribed
  520. }
  521. //
  522. // P_NewChaseDir
  523. //
  524. // killough 9/8/98: Split into two functions
  525. //
  526. static void P_NewChaseDir(mobj_t *actor)
  527. {
  528. mobj_t *target = actor->target;
  529. fixed_t deltax = target->x - actor->x;
  530. fixed_t deltay = target->y - actor->y;
  531. // killough 8/8/98: sometimes move away from target, keeping distance
  532. //
  533. // 1) Stay a certain distance away from a friend, to avoid being in their way
  534. // 2) Take advantage over an enemy without missiles, by keeping distance
  535. actor->strafecount = 0;
  536. if (mbf_features) {
  537. if (actor->floorz - actor->dropoffz > FRACUNIT*24 &&
  538. actor->z <= actor->floorz &&
  539. !(actor->flags & (MF_DROPOFF|MF_FLOAT)) &&
  540. !comp[comp_dropoff] &&
  541. P_AvoidDropoff(actor)) /* Move away from dropoff */
  542. {
  543. P_DoNewChaseDir(actor, dropoff_deltax, dropoff_deltay);
  544. // If moving away from dropoff, set movecount to 1 so that
  545. // small steps are taken to get monster away from dropoff.
  546. actor->movecount = 1;
  547. return;
  548. }
  549. else
  550. {
  551. fixed_t dist = P_AproxDistance(deltax, deltay);
  552. // Move away from friends when too close, except
  553. // in certain situations (e.g. a crowded lift)
  554. if (actor->flags & target->flags & MF_FRIEND &&
  555. distfriend << FRACBITS > dist &&
  556. !P_IsOnLift(target) && !P_IsUnderDamage(actor))
  557. {
  558. deltax = -deltax, deltay = -deltay;
  559. } else
  560. if (target->health > 0 && (actor->flags ^ target->flags) & MF_FRIEND)
  561. { // Live enemy target
  562. if (monster_backing &&
  563. actor->info->missilestate && actor->type != MT_SKULL &&
  564. ((!target->info->missilestate && dist < MELEERANGE*2) ||
  565. (target->player && dist < MELEERANGE*3 &&
  566. (target->player->readyweapon == wp_fist ||
  567. target->player->readyweapon == wp_chainsaw))))
  568. { // Back away from melee attacker
  569. actor->strafecount = P_Random(pr_enemystrafe) & 15;
  570. deltax = -deltax, deltay = -deltay;
  571. }
  572. }
  573. }
  574. }
  575. P_DoNewChaseDir(actor, deltax, deltay);
  576. // If strafing, set movecount to strafecount so that old Doom
  577. // logic still works the same, except in the strafing part
  578. if (actor->strafecount)
  579. actor->movecount = actor->strafecount;
  580. }
  581. //
  582. // P_IsVisible
  583. //
  584. // killough 9/9/98: whether a target is visible to a monster
  585. //
  586. static boolean P_IsVisible(mobj_t *actor, mobj_t *mo, boolean allaround)
  587. {
  588. if (!allaround)
  589. {
  590. angle_t an = R_PointToAngle2(actor->x, actor->y,
  591. mo->x, mo->y) - actor->angle;
  592. if (an > ANG90 && an < ANG270 &&
  593. P_AproxDistance(mo->x-actor->x, mo->y-actor->y) > MELEERANGE)
  594. return false;
  595. }
  596. return P_CheckSight(actor, mo);
  597. }
  598. //
  599. // PIT_FindTarget
  600. //
  601. // killough 9/5/98
  602. //
  603. // Finds monster targets for other monsters
  604. //
  605. static int current_allaround;
  606. static boolean PIT_FindTarget(mobj_t *mo)
  607. {
  608. mobj_t *actor = current_actor;
  609. if (!((mo->flags ^ actor->flags) & MF_FRIEND && // Invalid target
  610. mo->health > 0 && (mo->flags & MF_COUNTKILL || mo->type == MT_SKULL)))
  611. return true;
  612. // If the monster is already engaged in a one-on-one attack
  613. // with a healthy friend, don't attack around 60% the time
  614. {
  615. const mobj_t *targ = mo->target;
  616. if (targ && targ->target == mo &&
  617. P_Random(pr_skiptarget) > 100 &&
  618. (targ->flags ^ mo->flags) & MF_FRIEND &&
  619. targ->health*2 >= targ->info->spawnhealth)
  620. return true;
  621. }
  622. if (!P_IsVisible(actor, mo, current_allaround))
  623. return true;
  624. P_SetTarget(&actor->lastenemy, actor->target); // Remember previous target
  625. P_SetTarget(&actor->target, mo); // Found target
  626. // Move the selected monster to the end of its associated
  627. // list, so that it gets searched last next time.
  628. {
  629. thinker_t *cap = &thinkerclasscap[mo->flags & MF_FRIEND ?
  630. th_friends : th_enemies];
  631. (mo->thinker.cprev->cnext = mo->thinker.cnext)->cprev = mo->thinker.cprev;
  632. (mo->thinker.cprev = cap->cprev)->cnext = &mo->thinker;
  633. (mo->thinker.cnext = cap)->cprev = &mo->thinker;
  634. }
  635. return false;
  636. }
  637. //
  638. // P_LookForPlayers
  639. // If allaround is false, only look 180 degrees in front.
  640. // Returns true if a player is targeted.
  641. //
  642. static boolean P_LookForPlayers(mobj_t *actor, boolean allaround)
  643. {
  644. player_t *player;
  645. int stop, stopc, c;
  646. if (actor->flags & MF_FRIEND)
  647. { // killough 9/9/98: friendly monsters go about players differently
  648. int anyone;
  649. #if 0
  650. if (!allaround) // If you want friendly monsters not to awaken unprovoked
  651. return false;
  652. #endif
  653. // Go back to a player, no matter whether it's visible or not
  654. for (anyone=0; anyone<=1; anyone++)
  655. for (c=0; c<MAXPLAYERS; c++)
  656. if (playeringame[c] && players[c].playerstate==PST_LIVE &&
  657. (anyone || P_IsVisible(actor, players[c].mo, allaround)))
  658. {
  659. P_SetTarget(&actor->target, players[c].mo);
  660. // killough 12/98:
  661. // get out of refiring loop, to avoid hitting player accidentally
  662. if (actor->info->missilestate)
  663. {
  664. P_SetMobjState(actor, actor->info->seestate);
  665. actor->flags &= ~MF_JUSTHIT;
  666. }
  667. return true;
  668. }
  669. return false;
  670. }
  671. // Change mask of 3 to (MAXPLAYERS-1) -- killough 2/15/98:
  672. stop = (actor->lastlook-1)&(MAXPLAYERS-1);
  673. c = 0;
  674. stopc = !mbf_features &&
  675. !demo_compatibility && monsters_remember ?
  676. MAXPLAYERS : 2; // killough 9/9/98
  677. for (;; actor->lastlook = (actor->lastlook+1)&(MAXPLAYERS-1))
  678. {
  679. if (!playeringame[actor->lastlook])
  680. continue;
  681. // killough 2/15/98, 9/9/98:
  682. if (c++ == stopc || actor->lastlook == stop) // done looking
  683. {
  684. // e6y
  685. // Fixed Boom incompatibilities. The following code was missed.
  686. // There are no more desyncs on Donce's demos on horror.wad
  687. // Use last known enemy if no players sighted -- killough 2/15/98:
  688. if (!mbf_features && !demo_compatibility && monsters_remember)
  689. {
  690. if (actor->lastenemy && actor->lastenemy->health > 0)
  691. {
  692. actor->target = actor->lastenemy;
  693. actor->lastenemy = NULL;
  694. return true;
  695. }
  696. }
  697. return false;
  698. }
  699. player = &players[actor->lastlook];
  700. if (player->health <= 0)
  701. continue; // dead
  702. if (!P_IsVisible(actor, player->mo, allaround))
  703. continue;
  704. P_SetTarget(&actor->target, player->mo);
  705. /* killough 9/9/98: give monsters a threshold towards getting players
  706. * (we don't want it to be too easy for a player with dogs :)
  707. */
  708. if (!comp[comp_pursuit])
  709. actor->threshold = 60;
  710. return true;
  711. }
  712. }
  713. //
  714. // Friendly monsters, by Lee Killough 7/18/98
  715. //
  716. // Friendly monsters go after other monsters first, but
  717. // also return to owner if they cannot find any targets.
  718. // A marine's best friend :) killough 7/18/98, 9/98
  719. //
  720. static boolean P_LookForMonsters(mobj_t *actor, boolean allaround)
  721. {
  722. thinker_t *cap, *th;
  723. if (demo_compatibility)
  724. return false;
  725. if (actor->lastenemy && actor->lastenemy->health > 0 && monsters_remember &&
  726. !(actor->lastenemy->flags & actor->flags & MF_FRIEND)) // not friends
  727. {
  728. P_SetTarget(&actor->target, actor->lastenemy);
  729. P_SetTarget(&actor->lastenemy, NULL);
  730. return true;
  731. }
  732. /* Old demos do not support monster-seeking bots */
  733. if (!mbf_features)
  734. return false;
  735. // Search the threaded list corresponding to this object's potential targets
  736. cap = &thinkerclasscap[actor->flags & MF_FRIEND ? th_enemies : th_friends];
  737. // Search for new enemy
  738. if (cap->cnext != cap) // Empty list? bail out early
  739. {
  740. int x = (actor->x - bmaporgx)>>MAPBLOCKSHIFT;
  741. int y = (actor->y - bmaporgy)>>MAPBLOCKSHIFT;
  742. int d;
  743. current_actor = actor;
  744. current_allaround = allaround;
  745. // Search first in the immediate vicinity.
  746. if (!P_BlockThingsIterator(x, y, PIT_FindTarget))
  747. return true;
  748. for (d=1; d<5; d++)
  749. {
  750. int i = 1 - d;
  751. do
  752. if (!P_BlockThingsIterator(x+i, y-d, PIT_FindTarget) ||
  753. !P_BlockThingsIterator(x+i, y+d, PIT_FindTarget))
  754. return true;
  755. while (++i < d);
  756. do
  757. if (!P_BlockThingsIterator(x-d, y+i, PIT_FindTarget) ||
  758. !P_BlockThingsIterator(x+d, y+i, PIT_FindTarget))
  759. return true;
  760. while (--i + d >= 0);
  761. }
  762. { // Random number of monsters, to prevent patterns from forming
  763. int n = (P_Random(pr_friends) & 31) + 15;
  764. for (th = cap->cnext; th != cap; th = th->cnext)
  765. if (--n < 0)
  766. {
  767. // Only a subset of the monsters were searched. Move all of
  768. // the ones which were searched so far, to the end of the list.
  769. (cap->cnext->cprev = cap->cprev)->cnext = cap->cnext;
  770. (cap->cprev = th->cprev)->cnext = cap;
  771. (th->cprev = cap)->cnext = th;
  772. break;
  773. }
  774. else
  775. if (!PIT_FindTarget((mobj_t *) th)) // If target sighted
  776. return true;
  777. }
  778. }
  779. return false; // No monster found
  780. }
  781. //
  782. // P_LookForTargets
  783. //
  784. // killough 9/5/98: look for targets to go after, depending on kind of monster
  785. //
  786. static boolean P_LookForTargets(mobj_t *actor, int allaround)
  787. {
  788. return actor->flags & MF_FRIEND ?
  789. P_LookForMonsters(actor, allaround) || P_LookForPlayers (actor, allaround):
  790. P_LookForPlayers (actor, allaround) || P_LookForMonsters(actor, allaround);
  791. }
  792. //
  793. // P_HelpFriend
  794. //
  795. // killough 9/8/98: Help friends in danger of dying
  796. //
  797. static boolean P_HelpFriend(mobj_t *actor)
  798. {
  799. thinker_t *cap, *th;
  800. // If less than 33% health, self-preservation rules
  801. if (actor->health*3 < actor->info->spawnhealth)
  802. return false;
  803. current_actor = actor;
  804. current_allaround = true;
  805. // Possibly help a friend under 50% health
  806. cap = &thinkerclasscap[actor->flags & MF_FRIEND ? th_friends : th_enemies];
  807. for (th = cap->cnext; th != cap; th = th->cnext)
  808. if (((mobj_t *) th)->health*2 >= ((mobj_t *) th)->info->spawnhealth)
  809. {
  810. if (P_Random(pr_helpfriend) < 180)
  811. break;
  812. }
  813. else
  814. if (((mobj_t *) th)->flags & MF_JUSTHIT &&
  815. ((mobj_t *) th)->target &&
  816. ((mobj_t *) th)->target != actor->target &&
  817. !PIT_FindTarget(((mobj_t *) th)->target))
  818. {
  819. // Ignore any attacking monsters, while searching for friend
  820. actor->threshold = BASETHRESHOLD;
  821. return true;
  822. }
  823. return false;
  824. }
  825. //
  826. // A_KeenDie
  827. // DOOM II special, map 32.
  828. // Uses special tag 666.
  829. //
  830. void A_KeenDie(mobj_t* mo)
  831. {
  832. thinker_t *th;
  833. line_t junk;
  834. A_Fall(mo);
  835. // scan the remaining thinkers to see if all Keens are dead
  836. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  837. if (th->function == P_MobjThinker)
  838. {
  839. mobj_t *mo2 = (mobj_t *) th;
  840. if (mo2 != mo && mo2->type == mo->type && mo2->health > 0)
  841. return; // other Keen not dead
  842. }
  843. junk.tag = 666;
  844. EV_DoDoor(&junk,open);
  845. }
  846. //
  847. // ACTION ROUTINES
  848. //
  849. //
  850. // A_Look
  851. // Stay in state until a player is sighted.
  852. //
  853. void A_Look(mobj_t *actor)
  854. {
  855. mobj_t *targ = actor->subsector->sector->soundtarget;
  856. actor->threshold = 0; // any shot will wake up
  857. /* killough 7/18/98:
  858. * Friendly monsters go after other monsters first, but
  859. * also return to player, without attacking them, if they
  860. * cannot find any targets. A marine's best friend :)
  861. */
  862. actor->pursuecount = 0;
  863. if (!(actor->flags & MF_FRIEND && P_LookForTargets(actor, false)) &&
  864. !((targ = actor->subsector->sector->soundtarget) &&
  865. targ->flags & MF_SHOOTABLE &&
  866. (P_SetTarget(&actor->target, targ),
  867. !(actor->flags & MF_AMBUSH) || P_CheckSight(actor, targ))) &&
  868. (actor->flags & MF_FRIEND || !P_LookForTargets(actor, false)))
  869. return;
  870. // go into chase state
  871. if (actor->info->seesound)
  872. {
  873. int sound;
  874. switch (actor->info->seesound)
  875. {
  876. case sfx_posit1:
  877. case sfx_posit2:
  878. case sfx_posit3:
  879. sound = sfx_posit1+P_Random(pr_see)%3;
  880. break;
  881. case sfx_bgsit1:
  882. case sfx_bgsit2:
  883. sound = sfx_bgsit1+P_Random(pr_see)%2;
  884. break;
  885. default:
  886. sound = actor->info->seesound;
  887. break;
  888. }
  889. if (actor->type==MT_SPIDER || actor->type == MT_CYBORG)
  890. S_StartSound(NULL, sound); // full volume
  891. else
  892. S_StartSound(actor, sound);
  893. }
  894. P_SetMobjState(actor, actor->info->seestate);
  895. }
  896. //
  897. // A_KeepChasing
  898. //
  899. // killough 10/98:
  900. // Allows monsters to continue movement while attacking
  901. //
  902. static void A_KeepChasing(mobj_t *actor)
  903. {
  904. if (actor->movecount)
  905. {
  906. actor->movecount--;
  907. if (actor->strafecount)
  908. actor->strafecount--;
  909. P_SmartMove(actor);
  910. }
  911. }
  912. //
  913. // A_Chase
  914. // Actor has a melee attack,
  915. // so it tries to close as fast as possible
  916. //
  917. void A_Chase(mobj_t *actor)
  918. {
  919. if (actor->reactiontime)
  920. actor->reactiontime--;
  921. if (actor->threshold) { /* modify target threshold */
  922. if (!actor->target || actor->target->health <= 0)
  923. actor->threshold = 0;
  924. else
  925. actor->threshold--;
  926. }
  927. /* turn towards movement direction if not there yet
  928. * killough 9/7/98: keep facing towards target if strafing or backing out
  929. */
  930. if (actor->strafecount)
  931. A_FaceTarget(actor);
  932. else if (actor->movedir < 8)
  933. {
  934. int delta = (actor->angle &= (7<<29)) - (actor->movedir << 29);
  935. if (delta > 0)
  936. actor->angle -= ANG90/2;
  937. else
  938. if (delta < 0)
  939. actor->angle += ANG90/2;
  940. }
  941. if (!actor->target || !(actor->target->flags&MF_SHOOTABLE))
  942. {
  943. if (!P_LookForTargets(actor,true)) // look for a new target
  944. P_SetMobjState(actor, actor->info->spawnstate); // no new target
  945. return;
  946. }
  947. // do not attack twice in a row
  948. if (actor->flags & MF_JUSTATTACKED)
  949. {
  950. actor->flags &= ~MF_JUSTATTACKED;
  951. if (gameskill != sk_nightmare && !fastparm)
  952. P_NewChaseDir(actor);
  953. return;
  954. }
  955. // check for melee attack
  956. if (actor->info->meleestate && P_CheckMeleeRange(actor))
  957. {
  958. if (actor->info->attacksound)
  959. S_StartSound(actor, actor->info->attacksound);
  960. P_SetMobjState(actor, actor->info->meleestate);
  961. /* killough 8/98: remember an attack
  962. * cph - DEMOSYNC? */
  963. if (!actor->info->missilestate)
  964. actor->flags |= MF_JUSTHIT;
  965. return;
  966. }
  967. // check for missile attack
  968. if (actor->info->missilestate)
  969. if (!(gameskill < sk_nightmare && !fastparm && actor->movecount))
  970. if (P_CheckMissileRange(actor))
  971. {
  972. P_SetMobjState(actor, actor->info->missilestate);
  973. actor->flags |= MF_JUSTATTACKED;
  974. return;
  975. }
  976. if (!actor->threshold) {
  977. if (!mbf_features)
  978. { /* killough 9/9/98: for backward demo compatibility */
  979. if (netgame && !P_CheckSight(actor, actor->target) &&
  980. P_LookForPlayers(actor, true))
  981. return;
  982. }
  983. /* killough 7/18/98, 9/9/98: new monster AI */
  984. else if (help_friends && P_HelpFriend(actor))
  985. return; /* killough 9/8/98: Help friends in need */
  986. /* Look for new targets if current one is bad or is out of view */
  987. else if (actor->pursuecount)
  988. actor->pursuecount--;
  989. else {
  990. /* Our pursuit time has expired. We're going to think about
  991. * changing targets */
  992. actor->pursuecount = BASETHRESHOLD;
  993. /* Unless (we have a live target
  994. * and it's not friendly
  995. * and we can see it)
  996. * try to find a new one; return if sucessful */
  997. if (!(actor->target && actor->target->health > 0 &&
  998. ((comp[comp_pursuit] && !netgame) ||
  999. (((actor->target->flags ^ actor->flags) & MF_FRIEND ||
  1000. (!(actor->flags & MF_FRIEND) && monster_infighting)) &&
  1001. P_CheckSight(actor, actor->target))))
  1002. && P_LookForTargets(actor, true))
  1003. return;
  1004. /* (Current target was good, or no new target was found.)
  1005. *
  1006. * If monster is a missile-less friend, give up pursuit and
  1007. * return to player, if no attacks have occurred recently.
  1008. */
  1009. if (!actor->info->missilestate && actor->flags & MF_FRIEND) {
  1010. if (actor->flags & MF_JUSTHIT) /* if recent action, */
  1011. actor->flags &= ~MF_JUSTHIT; /* keep fighting */
  1012. else if (P_LookForPlayers(actor, true)) /* else return to player */
  1013. return;
  1014. }
  1015. }
  1016. }
  1017. if (actor->strafecount)
  1018. actor->strafecount--;
  1019. // chase towards player
  1020. if (--actor->movecount<0 || !P_SmartMove(actor))
  1021. P_NewChaseDir(actor);
  1022. // make active sound
  1023. if (actor->info->activesound && P_Random(pr_see)<3)
  1024. S_StartSound(actor, actor->info->activesound);
  1025. }
  1026. //
  1027. // A_FaceTarget
  1028. //
  1029. void A_FaceTarget(mobj_t *actor)
  1030. {
  1031. if (!actor->target)
  1032. return;
  1033. actor->flags &= ~MF_AMBUSH;
  1034. actor->angle = R_PointToAngle2(actor->x, actor->y,
  1035. actor->target->x, actor->target->y);
  1036. if (actor->target->flags & MF_SHADOW)
  1037. { // killough 5/5/98: remove dependence on order of evaluation:
  1038. int t = P_Random(pr_facetarget);
  1039. actor->angle += (t-P_Random(pr_facetarget))<<21;
  1040. }
  1041. }
  1042. //
  1043. // A_PosAttack
  1044. //
  1045. void A_PosAttack(mobj_t *actor)
  1046. {
  1047. int angle, damage, slope, t;
  1048. if (!actor->target)
  1049. return;
  1050. A_FaceTarget(actor);
  1051. angle = actor->angle;
  1052. slope = P_AimLineAttack(actor, angle, MISSILERANGE, 0); /* killough 8/2/98 */
  1053. S_StartSound(actor, sfx_pistol);
  1054. // killough 5/5/98: remove dependence on order of evaluation:
  1055. t = P_Random(pr_posattack);
  1056. angle += (t - P_Random(pr_posattack))<<20;
  1057. damage = (P_Random(pr_posattack)%5 + 1)*3;
  1058. P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
  1059. }
  1060. void A_SPosAttack(mobj_t* actor)
  1061. {
  1062. int i, bangle, slope;
  1063. if (!actor->target)
  1064. return;
  1065. S_StartSound(actor, sfx_shotgn);
  1066. A_FaceTarget(actor);
  1067. bangle = actor->angle;
  1068. slope = P_AimLineAttack(actor, bangle, MISSILERANGE, 0); /* killough 8/2/98 */
  1069. for (i=0; i<3; i++)
  1070. { // killough 5/5/98: remove dependence on order of evaluation:
  1071. int t = P_Random(pr_sposattack);
  1072. int angle = bangle + ((t - P_Random(pr_sposattack))<<20);
  1073. int damage = ((P_Random(pr_sposattack)%5)+1)*3;
  1074. P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
  1075. }
  1076. }
  1077. void A_CPosAttack(mobj_t *actor)
  1078. {
  1079. int angle, bangle, damage, slope, t;
  1080. if (!actor->target)
  1081. return;
  1082. S_StartSound(actor, sfx_shotgn);
  1083. A_FaceTarget(actor);
  1084. bangle = actor->angle;
  1085. slope = P_AimLineAttack(actor, bangle, MISSILERANGE, 0); /* killough 8/2/98 */
  1086. // killough 5/5/98: remove dependence on order of evaluation:
  1087. t = P_Random(pr_cposattack);
  1088. angle = bangle + ((t - P_Random(pr_cposattack))<<20);
  1089. damage = ((P_Random(pr_cposattack)%5)+1)*3;
  1090. P_LineAttack(actor, angle, MISSILERANGE, slope, damage);
  1091. }
  1092. void A_CPosRefire(mobj_t *actor)
  1093. {
  1094. // keep firing unless target got out of sight
  1095. A_FaceTarget(actor);
  1096. /* killough 12/98: Stop firing if a friend has gotten in the way */
  1097. if (P_HitFriend(actor))
  1098. goto stop;
  1099. /* killough 11/98: prevent refiring on friends continuously */
  1100. if (P_Random(pr_cposrefire) < 40) {
  1101. if (actor->target && actor->flags & actor->target->flags & MF_FRIEND)
  1102. goto stop;
  1103. else
  1104. return;
  1105. }
  1106. if (!actor->target || actor->target->health <= 0
  1107. || !P_CheckSight(actor, actor->target))
  1108. stop: P_SetMobjState(actor, actor->info->seestate);
  1109. }
  1110. void A_SpidRefire(mobj_t* actor)
  1111. {
  1112. // keep firing unless target got out of sight
  1113. A_FaceTarget(actor);
  1114. /* killough 12/98: Stop firing if a friend has gotten in the way */
  1115. if (P_HitFriend(actor))
  1116. goto stop;
  1117. if (P_Random(pr_spidrefire) < 10)
  1118. return;
  1119. // killough 11/98: prevent refiring on friends continuously
  1120. if (!actor->target || actor->target->health <= 0
  1121. || actor->flags & actor->target->flags & MF_FRIEND
  1122. || !P_CheckSight(actor, actor->target))
  1123. stop: P_SetMobjState(actor, actor->info->seestate);
  1124. }
  1125. void A_BspiAttack(mobj_t *actor)
  1126. {
  1127. if (!actor->target)
  1128. return;
  1129. A_FaceTarget(actor);
  1130. P_SpawnMissile(actor, actor->target, MT_ARACHPLAZ); // launch a missile
  1131. }
  1132. //
  1133. // A_TroopAttack
  1134. //
  1135. void A_TroopAttack(mobj_t *actor)
  1136. {
  1137. if (!actor->target)
  1138. return;
  1139. A_FaceTarget(actor);
  1140. if (P_CheckMeleeRange(actor))
  1141. {
  1142. int damage;
  1143. S_StartSound(actor, sfx_claw);
  1144. damage = (P_Random(pr_troopattack)%8+1)*3;
  1145. P_DamageMobj(actor->target, actor, actor, damage);
  1146. return;
  1147. }
  1148. P_SpawnMissile(actor, actor->target, MT_TROOPSHOT); // launch a missile
  1149. }
  1150. void A_SargAttack(mobj_t *actor)
  1151. {
  1152. if (!actor->target)
  1153. return;
  1154. A_FaceTarget(actor);
  1155. if (P_CheckMeleeRange(actor))
  1156. {
  1157. int damage = ((P_Random(pr_sargattack)%10)+1)*4;
  1158. P_DamageMobj(actor->target, actor, actor, damage);
  1159. }
  1160. }
  1161. void A_HeadAttack(mobj_t *actor)
  1162. {
  1163. if (!actor->target)
  1164. return;
  1165. A_FaceTarget (actor);
  1166. if (P_CheckMeleeRange(actor))
  1167. {
  1168. int damage = (P_Random(pr_headattack)%6+1)*10;
  1169. P_DamageMobj(actor->target, actor, actor, damage);
  1170. return;
  1171. }
  1172. P_SpawnMissile(actor, actor->target, MT_HEADSHOT); // launch a missile
  1173. }
  1174. void A_CyberAttack(mobj_t *actor)
  1175. {
  1176. if (!actor->target)
  1177. return;
  1178. A_FaceTarget(actor);
  1179. P_SpawnMissile(actor, actor->target, MT_ROCKET);
  1180. }
  1181. void A_BruisAttack(mobj_t *actor)
  1182. {
  1183. if (!actor->target)
  1184. return;
  1185. if (P_CheckMeleeRange(actor))
  1186. {
  1187. int damage;
  1188. S_StartSound(actor, sfx_claw);
  1189. damage = (P_Random(pr_bruisattack)%8+1)*10;
  1190. P_DamageMobj(actor->target, actor, actor, damage);
  1191. return;
  1192. }
  1193. P_SpawnMissile(actor, actor->target, MT_BRUISERSHOT); // launch a missile
  1194. }
  1195. //
  1196. // A_SkelMissile
  1197. //
  1198. void A_SkelMissile(mobj_t *actor)
  1199. {
  1200. mobj_t *mo;
  1201. if (!actor->target)
  1202. return;
  1203. A_FaceTarget (actor);
  1204. actor->z += 16*FRACUNIT; // so missile spawns higher
  1205. mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
  1206. actor->z -= 16*FRACUNIT; // back to normal
  1207. mo->x += mo->momx;
  1208. mo->y += mo->momy;
  1209. P_SetTarget(&mo->tracer, actor->target);
  1210. }
  1211. int TRACEANGLE = 0xc000000;
  1212. void A_Tracer(mobj_t *actor)
  1213. {
  1214. angle_t exact;
  1215. fixed_t dist;
  1216. fixed_t slope;
  1217. mobj_t *dest;
  1218. mobj_t *th;
  1219. /* killough 1/18/98: this is why some missiles do not have smoke
  1220. * and some do. Also, internal demos start at random gametics, thus
  1221. * the bug in which revenants cause internal demos to go out of sync.
  1222. *
  1223. * killough 3/6/98: fix revenant internal demo bug by subtracting
  1224. * levelstarttic from gametic.
  1225. *
  1226. * killough 9/29/98: use new "basetic" so that demos stay in sync
  1227. * during pauses and menu activations, while retaining old demo sync.
  1228. *
  1229. * leveltime would have been better to use to start with in Doom, but
  1230. * since old demos were recorded using gametic, we must stick with it,
  1231. * and improvise around it (using leveltime causes desync across levels).
  1232. */
  1233. if ((gametic-basetic) & 3)
  1234. return;
  1235. // spawn a puff of smoke behind the rocket
  1236. P_SpawnPuff(actor->x, actor->y, actor->z);
  1237. th = P_SpawnMobj (actor->x-actor->momx,
  1238. actor->y-actor->momy,
  1239. actor->z, MT_SMOKE);
  1240. th->momz = FRACUNIT;
  1241. th->tics -= P_Random(pr_tracer) & 3;
  1242. if (th->tics < 1)
  1243. th->tics = 1;
  1244. // adjust direction
  1245. dest = actor->tracer;
  1246. if (!dest || dest->health <= 0)
  1247. return;
  1248. // change angle
  1249. exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y);
  1250. if (exact != actor->angle) {
  1251. if (exact - actor->angle > 0x80000000)
  1252. {
  1253. actor->angle -= TRACEANGLE;
  1254. if (exact - actor->angle < 0x80000000)
  1255. actor->angle = exact;
  1256. }
  1257. else
  1258. {
  1259. actor->angle += TRACEANGLE;
  1260. if (exact - actor->angle > 0x80000000)
  1261. actor->angle = exact;
  1262. }
  1263. }
  1264. exact = actor->angle>>ANGLETOFINESHIFT;
  1265. actor->momx = FixedMul(actor->info->speed, finecosine[exact]);
  1266. actor->momy = FixedMul(actor->info->speed, finesine[exact]);
  1267. // change slope
  1268. dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
  1269. dist = dist / actor->info->speed;
  1270. if (dist < 1)
  1271. dist = 1;
  1272. slope = (dest->z+40*FRACUNIT - actor->z) / dist;
  1273. if (slope < actor->momz)
  1274. actor->momz -= FRACUNIT/8;
  1275. else
  1276. actor->momz += FRACUNIT/8;
  1277. }
  1278. void A_SkelWhoosh(mobj_t *actor)
  1279. {
  1280. if (!actor->target)
  1281. return;
  1282. A_FaceTarget(actor);
  1283. S_StartSound(actor,sfx_skeswg);
  1284. }
  1285. void A_SkelFist(mobj_t *actor)
  1286. {
  1287. if (!actor->target)
  1288. return;
  1289. A_FaceTarget(actor);
  1290. if (P_CheckMeleeRange(actor))
  1291. {
  1292. int damage = ((P_Random(pr_skelfist)%10)+1)*6;
  1293. S_StartSound(actor, sfx_skepch);
  1294. P_DamageMobj(actor->target, actor, actor, damage);
  1295. }
  1296. }
  1297. //
  1298. // PIT_VileCheck
  1299. // Detect a corpse that could be raised.
  1300. //
  1301. mobj_t* corpsehit;
  1302. mobj_t* vileobj;
  1303. fixed_t viletryx;
  1304. fixed_t viletryy;
  1305. static boolean PIT_VileCheck(mobj_t *thing)
  1306. {
  1307. int maxdist;
  1308. boolean check;
  1309. if (!(thing->flags & MF_CORPSE) )
  1310. return true; // not a monster
  1311. if (thing->tics != -1)
  1312. return true; // not lying still yet
  1313. if (thing->info->raisestate == S_NULL)
  1314. return true; // monster doesn't have a raise state
  1315. maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
  1316. if (D_abs(thing->x-viletryx) > maxdist || D_abs(thing->y-viletryy) > maxdist)
  1317. return true; // not actually touching
  1318. // Check to see if the radius and height are zero. If they are // phares
  1319. // then this is a crushed monster that has been turned into a // |
  1320. // gib. One of the options may be to ignore this guy. // V
  1321. // Option 1: the original, buggy method, -> ghost (compatibility)
  1322. // Option 2: ressurect the monster, but not as a ghost
  1323. // Option 3: ignore the gib
  1324. // if (Option3) // ^
  1325. // if ((thing->height == 0) && (thing->radius == 0)) // |
  1326. // return true; // phares
  1327. corpsehit = thing;
  1328. corpsehit->momx = corpsehit->momy = 0;
  1329. if (comp[comp_vile]) // phares
  1330. { // |
  1331. corpsehit->height <<= 2; // V
  1332. check = P_CheckPosition(corpsehit,corpsehit->x,corpsehit->y);
  1333. corpsehit->height >>= 2;
  1334. }
  1335. else
  1336. {
  1337. int height,radius;
  1338. height = corpsehit->height; // save temporarily
  1339. radius = corpsehit->radius; // save temporarily
  1340. corpsehit->height = corpsehit->info->height;
  1341. corpsehit->radius = corpsehit->info->radius;
  1342. corpsehit->flags |= MF_SOLID;
  1343. check = P_CheckPosition(corpsehit,corpsehit->x,corpsehit->y);
  1344. corpsehit->height = height; // restore
  1345. corpsehit->radius = radius; // restore // ^
  1346. corpsehit->flags &= ~MF_SOLID;
  1347. } // |
  1348. // phares
  1349. if (!check)
  1350. return true; // doesn't fit here
  1351. return false; // got one, so stop checking
  1352. }
  1353. //
  1354. // A_VileChase
  1355. // Check for ressurecting a body
  1356. //
  1357. void A_VileChase(mobj_t* actor)
  1358. {
  1359. int xl, xh;
  1360. int yl, yh;
  1361. int bx, by;
  1362. if (actor->movedir != DI_NODIR)
  1363. {
  1364. // check for corpses to raise
  1365. viletryx =
  1366. actor->x + actor->info->speed*xspeed[actor->movedir];
  1367. viletryy =
  1368. actor->y + actor->info->speed*yspeed[actor->movedir];
  1369. xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1370. xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1371. yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1372. yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1373. vileobj = actor;
  1374. for (bx=xl ; bx<=xh ; bx++)
  1375. {
  1376. for (by=yl ; by<=yh ; by++)
  1377. {
  1378. // Call PIT_VileCheck to check
  1379. // whether object is a corpse
  1380. // that canbe raised.
  1381. if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
  1382. {
  1383. mobjinfo_t *info;
  1384. // got one!
  1385. mobj_t* temp = actor->target;
  1386. actor->target = corpsehit;
  1387. A_FaceTarget(actor);
  1388. actor->target = temp;
  1389. P_SetMobjState(actor, S_VILE_HEAL1);
  1390. S_StartSound(corpsehit, sfx_slop);
  1391. info = corpsehit->info;
  1392. P_SetMobjState(corpsehit,info->raisestate);
  1393. if (comp[comp_vile]) // phares
  1394. corpsehit->height <<= 2; // |
  1395. else // V
  1396. {
  1397. corpsehit->height = info->height; // fix Ghost bug
  1398. corpsehit->radius = info->radius; // fix Ghost bug
  1399. } // phares
  1400. /* killough 7/18/98:
  1401. * friendliness is transferred from AV to raised corpse
  1402. */
  1403. corpsehit->flags =
  1404. (info->flags & ~MF_FRIEND) | (actor->flags & MF_FRIEND);
  1405. if (!((corpsehit->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL)))
  1406. totallive++;
  1407. corpsehit->health = info->spawnhealth;
  1408. P_SetTarget(&corpsehit->target, NULL); // killough 11/98
  1409. if (mbf_features)
  1410. { /* kilough 9/9/98 */
  1411. P_SetTarget(&corpsehit->lastenemy, NULL);
  1412. corpsehit->flags &= ~MF_JUSTHIT;
  1413. }
  1414. /* killough 8/29/98: add to appropriate thread */
  1415. P_UpdateThinker(&corpsehit->thinker);
  1416. return;
  1417. }
  1418. }
  1419. }
  1420. }
  1421. A_Chase(actor); // Return to normal attack.
  1422. }
  1423. //
  1424. // A_VileStart
  1425. //
  1426. void A_VileStart(mobj_t *actor)
  1427. {
  1428. S_StartSound(actor, sfx_vilatk);
  1429. }
  1430. //
  1431. // A_Fire
  1432. // Keep fire in front of player unless out of sight
  1433. //
  1434. void A_StartFire(mobj_t *actor)
  1435. {
  1436. S_StartSound(actor,sfx_flamst);
  1437. A_Fire(actor);
  1438. }
  1439. void A_FireCrackle(mobj_t* actor)
  1440. {
  1441. S_StartSound(actor,sfx_flame);
  1442. A_Fire(actor);
  1443. }
  1444. void A_Fire(mobj_t *actor)
  1445. {
  1446. unsigned an;
  1447. mobj_t *dest = actor->tracer;
  1448. if (!dest)
  1449. return;
  1450. // don't move it if the vile lost sight
  1451. if (!P_CheckSight(actor->target, dest) )
  1452. return;
  1453. an = dest->angle >> ANGLETOFINESHIFT;
  1454. P_UnsetThingPosition(actor);
  1455. actor->x = dest->x + FixedMul(24*FRACUNIT, finecosine[an]);
  1456. actor->y = dest->y + FixedMul(24*FRACUNIT, finesine[an]);
  1457. actor->z = dest->z;
  1458. P_SetThingPosition(actor);
  1459. }
  1460. //
  1461. // A_VileTarget
  1462. // Spawn the hellfire
  1463. //
  1464. void A_VileTarget(mobj_t *actor)
  1465. {
  1466. mobj_t *fog;
  1467. if (!actor->target)
  1468. return;
  1469. A_FaceTarget(actor);
  1470. // killough 12/98: fix Vile fog coordinates // CPhipps - compatibility optioned
  1471. fog = P_SpawnMobj(actor->target->x,
  1472. (compatibility_level < lxdoom_1_compatibility) ? actor->target->x : actor->target->y,
  1473. actor->target->z,MT_FIRE);
  1474. P_SetTarget(&actor->tracer, fog);
  1475. P_SetTarget(&fog->target, actor);
  1476. P_SetTarget(&fog->tracer, actor->target);
  1477. A_Fire(fog);
  1478. }
  1479. //
  1480. // A_VileAttack
  1481. //
  1482. void A_VileAttack(mobj_t *actor)
  1483. {
  1484. mobj_t *fire;
  1485. int an;
  1486. if (!actor->target)
  1487. return;
  1488. A_FaceTarget(actor);
  1489. if (!P_CheckSight(actor, actor->target))
  1490. return;
  1491. S_StartSound(actor, sfx_barexp);
  1492. P_DamageMobj(actor->target, actor, actor, 20);
  1493. actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
  1494. an = actor->angle >> ANGLETOFINESHIFT;
  1495. fire = actor->tracer;
  1496. if (!fire)
  1497. return;
  1498. // move the fire between the vile and the player
  1499. fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
  1500. fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);
  1501. P_RadiusAttack(fire, actor, 70);
  1502. }
  1503. //
  1504. // Mancubus attack,
  1505. // firing three missiles (bruisers)
  1506. // in three different directions?
  1507. // Doesn't look like it.
  1508. //
  1509. #define FATSPREAD (ANG90/8)
  1510. void A_FatRaise(mobj_t *actor)
  1511. {
  1512. A_FaceTarget(actor);
  1513. S_StartSound(actor, sfx_manatk);
  1514. }
  1515. void A_FatAttack1(mobj_t *actor)
  1516. {
  1517. mobj_t *mo;
  1518. int an;
  1519. if (!actor->target)
  1520. return;
  1521. A_FaceTarget(actor);
  1522. // Change direction to ...
  1523. actor->angle += FATSPREAD;
  1524. P_SpawnMissile(actor, actor->target, MT_FATSHOT);
  1525. mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1526. mo->angle += FATSPREAD;
  1527. an = mo->angle >> ANGLETOFINESHIFT;
  1528. mo->momx = FixedMul(mo->info->speed, finecosine[an]);
  1529. mo->momy = FixedMul(mo->info->speed, finesine[an]);
  1530. }
  1531. void A_FatAttack2(mobj_t *actor)
  1532. {
  1533. mobj_t *mo;
  1534. int an;
  1535. if (!actor->target)
  1536. return;
  1537. A_FaceTarget(actor);
  1538. // Now here choose opposite deviation.
  1539. actor->angle -= FATSPREAD;
  1540. P_SpawnMissile(actor, actor->target, MT_FATSHOT);
  1541. mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
  1542. mo->angle -= FATSPREAD*2;
  1543. an = mo->angle >> ANGLETOFINESHIFT;
  1544. mo->momx = FixedMul(mo->info->speed, finecosine[an]);
  1545. mo->momy = FixedMul(mo->info->speed, finesine[an]);
  1546. }
  1547. void A_FatAttack3(mobj_t *actor)
  1548. {
  1549. mobj_t *mo;
  1550. int an;
  1551. if (!actor->target)
  1552. return;
  1553. A_FaceTarget(actor);
  1554. mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
  1555. mo->angle -= FATSPREAD/2;
  1556. an = mo->angle >> ANGLETOFINESHIFT;
  1557. mo->momx = FixedMul(mo->info->speed, finecosine[an]);
  1558. mo->momy = FixedMul(mo->info->speed, finesine[an]);
  1559. mo = P_SpawnMissile(actor, actor->target, MT_FATSHOT);
  1560. mo->angle += FATSPREAD/2;
  1561. an = mo->angle >> ANGLETOFINESHIFT;
  1562. mo->momx = FixedMul(mo->info->speed, finecosine[an]);
  1563. mo->momy = FixedMul(mo->info->speed, finesine[an]);
  1564. }
  1565. //
  1566. // SkullAttack
  1567. // Fly at the player like a missile.
  1568. //
  1569. #define SKULLSPEED (20*FRACUNIT)
  1570. void A_SkullAttack(mobj_t *actor)
  1571. {
  1572. mobj_t *dest;
  1573. angle_t an;
  1574. int dist;
  1575. if (!actor->target)
  1576. return;
  1577. dest = actor->target;
  1578. actor->flags |= MF_SKULLFLY;
  1579. S_StartSound(actor, actor->info->attacksound);
  1580. A_FaceTarget(actor);
  1581. an = actor->angle >> ANGLETOFINESHIFT;
  1582. actor->momx = FixedMul(SKULLSPEED, finecosine[an]);
  1583. actor->momy = FixedMul(SKULLSPEED, finesine[an]);
  1584. dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y);
  1585. dist = dist / SKULLSPEED;
  1586. if (dist < 1)
  1587. dist = 1;
  1588. actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
  1589. }
  1590. //
  1591. // A_PainShootSkull
  1592. // Spawn a lost soul and launch it at the target
  1593. //
  1594. static void A_PainShootSkull(mobj_t *actor, angle_t angle)
  1595. {
  1596. fixed_t x,y,z;
  1597. mobj_t *newmobj;
  1598. angle_t an;
  1599. int prestep;
  1600. // The original code checked for 20 skulls on the level, // phares
  1601. // and wouldn't spit another one if there were. If not in // phares
  1602. // compatibility mode, we remove the limit. // phares
  1603. // phares
  1604. if (comp[comp_pain]) /* killough 10/98: compatibility-optioned */
  1605. {
  1606. // count total number of skulls currently on the level
  1607. int count = 0;
  1608. thinker_t *currentthinker = NULL;
  1609. while ((currentthinker = P_NextThinker(currentthinker,th_all)) != NULL)
  1610. if ((currentthinker->function == P_MobjThinker)
  1611. && ((mobj_t *)currentthinker)->type == MT_SKULL)
  1612. count++;
  1613. if (count > 20) // phares
  1614. return; // phares
  1615. }
  1616. // okay, there's room for another one
  1617. an = angle >> ANGLETOFINESHIFT;
  1618. prestep = 4*FRACUNIT + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
  1619. x = actor->x + FixedMul(prestep, finecosine[an]);
  1620. y = actor->y + FixedMul(prestep, finesine[an]);
  1621. z = actor->z + 8*FRACUNIT;
  1622. if (comp[comp_skull]) /* killough 10/98: compatibility-optioned */
  1623. newmobj = P_SpawnMobj(x, y, z, MT_SKULL); // phares
  1624. else // V
  1625. {
  1626. // Check whether the Lost Soul is being fired through a 1-sided
  1627. // wall or an impassible line, or a "monsters can't cross" line.
  1628. // If it is, then we don't allow the spawn. This is a bug fix, but
  1629. // it should be considered an enhancement, since it may disturb
  1630. // existing demos, so don't do it in compatibility mode.
  1631. if (Check_Sides(actor,x,y))
  1632. return;
  1633. newmobj = P_SpawnMobj(x, y, z, MT_SKULL);
  1634. // Check to see if the new Lost Soul's z value is above the
  1635. // ceiling of its new sector, or below the floor. If so, kill it.
  1636. if ((newmobj->z >
  1637. (newmobj->subsector->sector->ceilingheight - newmobj->height)) ||
  1638. (newmobj->z < newmobj->subsector->sector->floorheight))
  1639. {
  1640. // kill it immediately
  1641. P_DamageMobj(newmobj,actor,actor,10000);
  1642. return; // ^
  1643. } // |
  1644. } // phares
  1645. /* killough 7/20/98: PEs shoot lost souls with the same friendliness */
  1646. newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (actor->flags & MF_FRIEND);
  1647. /* killough 8/29/98: add to appropriate thread */
  1648. P_UpdateThinker(&newmobj->thinker);
  1649. // Check for movements.
  1650. // killough 3/15/98: don't jump over dropoffs:
  1651. if (!P_TryMove(newmobj, newmobj->x, newmobj->y, false))
  1652. {
  1653. // kill it immediately
  1654. P_DamageMobj(newmobj, actor, actor, 10000);
  1655. return;
  1656. }
  1657. P_SetTarget(&newmobj->target, actor->target);
  1658. A_SkullAttack(newmobj);
  1659. }
  1660. //
  1661. // A_PainAttack
  1662. // Spawn a lost soul and launch it at the target
  1663. //
  1664. void A_PainAttack(mobj_t *actor)
  1665. {
  1666. if (!actor->target)
  1667. return;
  1668. A_FaceTarget(actor);
  1669. A_PainShootSkull(actor, actor->angle);
  1670. }
  1671. void A_PainDie(mobj_t *actor)
  1672. {
  1673. A_Fall(actor);
  1674. A_PainShootSkull(actor, actor->angle+ANG90);
  1675. A_PainShootSkull(actor, actor->angle+ANG180);
  1676. A_PainShootSkull(actor, actor->angle+ANG270);
  1677. }
  1678. void A_Scream(mobj_t *actor)
  1679. {
  1680. int sound;
  1681. switch (actor->info->deathsound)
  1682. {
  1683. case 0:
  1684. return;
  1685. case sfx_podth1:
  1686. case sfx_podth2:
  1687. case sfx_podth3:
  1688. sound = sfx_podth1 + P_Random(pr_scream)%3;
  1689. break;
  1690. case sfx_bgdth1:
  1691. case sfx_bgdth2:
  1692. sound = sfx_bgdth1 + P_Random(pr_scream)%2;
  1693. break;
  1694. default:
  1695. sound = actor->info->deathsound;
  1696. break;
  1697. }
  1698. // Check for bosses.
  1699. if (actor->type==MT_SPIDER || actor->type == MT_CYBORG)
  1700. S_StartSound(NULL, sound); // full volume
  1701. else
  1702. S_StartSound(actor, sound);
  1703. }
  1704. void A_XScream(mobj_t *actor)
  1705. {
  1706. S_StartSound(actor, sfx_slop);
  1707. }
  1708. void A_Pain(mobj_t *actor)
  1709. {
  1710. if (actor->info->painsound)
  1711. S_StartSound(actor, actor->info->painsound);
  1712. }
  1713. void A_Fall(mobj_t *actor)
  1714. {
  1715. // actor is on ground, it can be walked over
  1716. actor->flags &= ~MF_SOLID;
  1717. }
  1718. //
  1719. // A_Explode
  1720. //
  1721. void A_Explode(mobj_t *thingy)
  1722. {
  1723. P_RadiusAttack( thingy, thingy->target, 128 );
  1724. }
  1725. //
  1726. // A_BossDeath
  1727. // Possibly trigger special effects
  1728. // if on first boss level
  1729. //
  1730. void A_BossDeath(mobj_t *mo)
  1731. {
  1732. thinker_t *th;
  1733. line_t junk;
  1734. int i;
  1735. if (gamemode == commercial)
  1736. {
  1737. if (gamemap != 7)
  1738. return;
  1739. if ((mo->type != MT_FATSO)
  1740. && (mo->type != MT_BABY))
  1741. return;
  1742. }
  1743. else
  1744. {
  1745. // e6y
  1746. // Additional check of gameepisode is necessary, because
  1747. // there is no right or wrong solution for E4M6 in original EXEs,
  1748. // there's nothing to emulate.
  1749. if (comp[comp_666] && gameepisode < 4)
  1750. {
  1751. // e6y
  1752. // Only following checks are present in doom2.exe ver. 1.666 and 1.9
  1753. // instead of separate checks for each episode in doomult.exe, plutonia.exe and tnt.exe
  1754. // There is no more desync on doom.wad\episode3.lmp
  1755. // http://www.doomworld.com/idgames/index.php?id=6909
  1756. if (gamemap != 8)
  1757. return;
  1758. if (mo->type == MT_BRUISER && gameepisode != 1)
  1759. return;
  1760. }
  1761. else
  1762. {
  1763. switch(gameepisode)
  1764. {
  1765. case 1:
  1766. if (gamemap != 8)
  1767. return;
  1768. if (mo->type != MT_BRUISER)
  1769. return;
  1770. break;
  1771. case 2:
  1772. if (gamemap != 8)
  1773. return;
  1774. if (mo->type != MT_CYBORG)
  1775. return;
  1776. break;
  1777. case 3:
  1778. if (gamemap != 8)
  1779. return;
  1780. if (mo->type != MT_SPIDER)
  1781. return;
  1782. break;
  1783. case 4:
  1784. switch(gamemap)
  1785. {
  1786. case 6:
  1787. if (mo->type != MT_CYBORG)
  1788. return;
  1789. break;
  1790. case 8:
  1791. if (mo->type != MT_SPIDER)
  1792. return;
  1793. break;
  1794. default:
  1795. return;
  1796. break;
  1797. }
  1798. break;
  1799. default:
  1800. if (gamemap != 8)
  1801. return;
  1802. break;
  1803. }
  1804. }
  1805. }
  1806. // make sure there is a player alive for victory
  1807. for (i=0; i<MAXPLAYERS; i++)
  1808. if (playeringame[i] && players[i].health > 0)
  1809. break;
  1810. if (i==MAXPLAYERS)
  1811. return; // no one left alive, so do not end game
  1812. // scan the remaining thinkers to see
  1813. // if all bosses are dead
  1814. for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  1815. if (th->function == P_MobjThinker)
  1816. {
  1817. mobj_t *mo2 = (mobj_t *) th;
  1818. if (mo2 != mo && mo2->type == mo->type && mo2->health > 0)
  1819. return; // other boss not dead
  1820. }
  1821. // victory!
  1822. if ( gamemode == commercial)
  1823. {
  1824. if (gamemap == 7)
  1825. {
  1826. if (mo->type == MT_FATSO)
  1827. {
  1828. junk.tag = 666;
  1829. EV_DoFloor(&junk,lowerFloorToLowest);
  1830. return;
  1831. }
  1832. if (mo->type == MT_BABY)
  1833. {
  1834. junk.tag = 667;
  1835. EV_DoFloor(&junk,raiseToTexture);
  1836. return;
  1837. }
  1838. }
  1839. }
  1840. else
  1841. {
  1842. switch(gameepisode)
  1843. {
  1844. case 1:
  1845. junk.tag = 666;
  1846. EV_DoFloor(&junk, lowerFloorToLowest);
  1847. return;
  1848. break;
  1849. case 4:
  1850. switch(gamemap)
  1851. {
  1852. case 6:
  1853. junk.tag = 666;
  1854. EV_DoDoor(&junk, blazeOpen);
  1855. return;
  1856. break;
  1857. case 8:
  1858. junk.tag = 666;
  1859. EV_DoFloor(&junk, lowerFloorToLowest);
  1860. return;
  1861. break;
  1862. }
  1863. }
  1864. }
  1865. G_ExitLevel();
  1866. }
  1867. void A_Hoof (mobj_t* mo)
  1868. {
  1869. S_StartSound(mo, sfx_hoof);
  1870. A_Chase(mo);
  1871. }
  1872. void A_Metal(mobj_t *mo)
  1873. {
  1874. S_StartSound(mo, sfx_metal);
  1875. A_Chase(mo);
  1876. }
  1877. void A_BabyMetal(mobj_t *mo)
  1878. {
  1879. S_StartSound(mo, sfx_bspwlk);
  1880. A_Chase(mo);
  1881. }
  1882. void A_OpenShotgun2(player_t *player, pspdef_t *psp)
  1883. {
  1884. S_StartSound(player->mo, sfx_dbopn);
  1885. }
  1886. void A_LoadShotgun2(player_t *player, pspdef_t *psp)
  1887. {
  1888. S_StartSound(player->mo, sfx_dbload);
  1889. }
  1890. void A_CloseShotgun2(player_t *player, pspdef_t *psp)
  1891. {
  1892. S_StartSound(player->mo, sfx_dbcls);
  1893. A_ReFire(player,psp);
  1894. }
  1895. // killough 2/7/98: Remove limit on icon landings:
  1896. mobj_t **braintargets;
  1897. int numbraintargets_alloc;
  1898. int numbraintargets;
  1899. struct brain_s brain; // killough 3/26/98: global state of boss brain
  1900. // killough 3/26/98: initialize icon landings at level startup,
  1901. // rather than at boss wakeup, to prevent savegame-related crashes
  1902. void P_SpawnBrainTargets(void) // killough 3/26/98: renamed old function
  1903. {
  1904. thinker_t *thinker;
  1905. // find all the target spots
  1906. numbraintargets = 0;
  1907. brain.targeton = 0;
  1908. brain.easy = 0; // killough 3/26/98: always init easy to 0
  1909. for (thinker = thinkercap.next ;
  1910. thinker != &thinkercap ;
  1911. thinker = thinker->next)
  1912. if (thinker->function == P_MobjThinker)
  1913. {
  1914. mobj_t *m = (mobj_t *) thinker;
  1915. if (m->type == MT_BOSSTARGET )
  1916. { // killough 2/7/98: remove limit on icon landings:
  1917. if (numbraintargets >= numbraintargets_alloc)
  1918. braintargets = realloc(braintargets,
  1919. (numbraintargets_alloc = numbraintargets_alloc ?
  1920. numbraintargets_alloc*2 : 32) *sizeof *braintargets);
  1921. braintargets[numbraintargets++] = m;
  1922. }
  1923. }
  1924. }
  1925. void A_BrainAwake(mobj_t *mo)
  1926. {
  1927. S_StartSound(NULL,sfx_bossit); // killough 3/26/98: only generates sound now
  1928. }
  1929. void A_BrainPain(mobj_t *mo)
  1930. {
  1931. S_StartSound(NULL,sfx_bospn);
  1932. }
  1933. void A_BrainScream(mobj_t *mo)
  1934. {
  1935. int x;
  1936. for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
  1937. {
  1938. int y = mo->y - 320*FRACUNIT;
  1939. int z = 128 + P_Random(pr_brainscream)*2*FRACUNIT;
  1940. mobj_t *th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1941. th->momz = P_Random(pr_brainscream)*512;
  1942. P_SetMobjState(th, S_BRAINEXPLODE1);
  1943. th->tics -= P_Random(pr_brainscream)&7;
  1944. if (th->tics < 1)
  1945. th->tics = 1;
  1946. }
  1947. S_StartSound(NULL,sfx_bosdth);
  1948. }
  1949. void A_BrainExplode(mobj_t *mo)
  1950. { // killough 5/5/98: remove dependence on order of evaluation:
  1951. int t = P_Random(pr_brainexp);
  1952. int x = mo->x + (t - P_Random(pr_brainexp))*2048;
  1953. int y = mo->y;
  1954. int z = 128 + P_Random(pr_brainexp)*2*FRACUNIT;
  1955. mobj_t *th = P_SpawnMobj(x,y,z, MT_ROCKET);
  1956. th->momz = P_Random(pr_brainexp)*512;
  1957. P_SetMobjState(th, S_BRAINEXPLODE1);
  1958. th->tics -= P_Random(pr_brainexp)&7;
  1959. if (th->tics < 1)
  1960. th->tics = 1;
  1961. }
  1962. void A_BrainDie(mobj_t *mo)
  1963. {
  1964. G_ExitLevel();
  1965. }
  1966. void A_BrainSpit(mobj_t *mo)
  1967. {
  1968. mobj_t *targ, *newmobj;
  1969. if (!numbraintargets) // killough 4/1/98: ignore if no targets
  1970. return;
  1971. brain.easy ^= 1; // killough 3/26/98: use brain struct
  1972. if (gameskill <= sk_easy && !brain.easy)
  1973. return;
  1974. // shoot a cube at current target
  1975. targ = braintargets[brain.targeton++]; // killough 3/26/98:
  1976. brain.targeton %= numbraintargets; // Use brain struct for targets
  1977. // spawn brain missile
  1978. newmobj = P_SpawnMissile(mo, targ, MT_SPAWNSHOT);
  1979. P_SetTarget(&newmobj->target, targ);
  1980. newmobj->reactiontime = (short)(((targ->y-mo->y)/newmobj->momy)/newmobj->state->tics);
  1981. // killough 7/18/98: brain friendliness is transferred
  1982. newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
  1983. // killough 8/29/98: add to appropriate thread
  1984. P_UpdateThinker(&newmobj->thinker);
  1985. S_StartSound(NULL, sfx_bospit);
  1986. }
  1987. // travelling cube sound
  1988. void A_SpawnSound(mobj_t *mo)
  1989. {
  1990. S_StartSound(mo,sfx_boscub);
  1991. A_SpawnFly(mo);
  1992. }
  1993. void A_SpawnFly(mobj_t *mo)
  1994. {
  1995. mobj_t *newmobj;
  1996. mobj_t *fog;
  1997. mobj_t *targ;
  1998. int r;
  1999. mobjtype_t type;
  2000. if (--mo->reactiontime)
  2001. return; // still flying
  2002. targ = mo->target;
  2003. // First spawn teleport fog.
  2004. fog = P_SpawnMobj(targ->x, targ->y, targ->z, MT_SPAWNFIRE);
  2005. S_StartSound(fog, sfx_telept);
  2006. // Randomly select monster to spawn.
  2007. r = P_Random(pr_spawnfly);
  2008. // Probability distribution (kind of :), decreasing likelihood.
  2009. if ( r<50 )
  2010. type = MT_TROOP;
  2011. else if (r<90)
  2012. type = MT_SERGEANT;
  2013. else if (r<120)
  2014. type = MT_SHADOWS;
  2015. else if (r<130)
  2016. type = MT_PAIN;
  2017. else if (r<160)
  2018. type = MT_HEAD;
  2019. else if (r<162)
  2020. type = MT_VILE;
  2021. else if (r<172)
  2022. type = MT_UNDEAD;
  2023. else if (r<192)
  2024. type = MT_BABY;
  2025. else if (r<222)
  2026. type = MT_FATSO;
  2027. else if (r<246)
  2028. type = MT_KNIGHT;
  2029. else
  2030. type = MT_BRUISER;
  2031. newmobj = P_SpawnMobj(targ->x, targ->y, targ->z, type);
  2032. /* killough 7/18/98: brain friendliness is transferred */
  2033. newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
  2034. /* killough 8/29/98: add to appropriate thread */
  2035. P_UpdateThinker(&newmobj->thinker);
  2036. if (P_LookForTargets(newmobj,true)) /* killough 9/4/98 */
  2037. P_SetMobjState(newmobj, newmobj->info->seestate);
  2038. // telefrag anything in this spot
  2039. P_TeleportMove(newmobj, newmobj->x, newmobj->y, true); /* killough 8/9/98 */
  2040. // remove self (i.e., cube).
  2041. P_RemoveMobj(mo);
  2042. }
  2043. void A_PlayerScream(mobj_t *mo)
  2044. {
  2045. int sound = sfx_pldeth; // Default death sound.
  2046. if (gamemode != shareware && mo->health < -50)
  2047. sound = sfx_pdiehi; // IF THE PLAYER DIES LESS THAN -50% WITHOUT GIBBING
  2048. S_StartSound(mo, sound);
  2049. }
  2050. /* cph - MBF-added codepointer functions */
  2051. // killough 11/98: kill an object
  2052. void A_Die(mobj_t *actor)
  2053. {
  2054. P_DamageMobj(actor, NULL, NULL, actor->health);
  2055. }
  2056. //
  2057. // A_Detonate
  2058. // killough 8/9/98: same as A_Explode, except that the damage is variable
  2059. //
  2060. void A_Detonate(mobj_t *mo)
  2061. {
  2062. P_RadiusAttack(mo, mo->target, mo->info->damage);
  2063. }
  2064. //
  2065. // killough 9/98: a mushroom explosion effect, sorta :)
  2066. // Original idea: Linguica
  2067. //
  2068. void A_Mushroom(mobj_t *actor)
  2069. {
  2070. int i, j, n = actor->info->damage;
  2071. A_Explode(actor); // First make normal explosion
  2072. // Now launch mushroom cloud
  2073. for (i = -n; i <= n; i += 8)
  2074. for (j = -n; j <= n; j += 8)
  2075. {
  2076. mobj_t target = *actor, *mo;
  2077. target.x += i << FRACBITS; // Aim in many directions from source
  2078. target.y += j << FRACBITS;
  2079. target.z += P_AproxDistance(i,j) << (FRACBITS+2); // Aim up fairly high
  2080. mo = P_SpawnMissile(actor, &target, MT_FATSHOT); // Launch fireball
  2081. mo->momx >>= 1;
  2082. mo->momy >>= 1; // Slow it down a bit
  2083. mo->momz >>= 1;
  2084. mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity
  2085. }
  2086. }
  2087. //
  2088. // killough 11/98
  2089. //
  2090. // The following were inspired by Len Pitre
  2091. //
  2092. // A small set of highly-sought-after code pointers
  2093. //
  2094. void A_Spawn(mobj_t *mo)
  2095. {
  2096. if (mo->state->misc1)
  2097. {
  2098. /* mobj_t *newmobj = */
  2099. P_SpawnMobj(mo->x, mo->y, (mo->state->misc2 << FRACBITS) + mo->z,
  2100. mo->state->misc1 - 1);
  2101. /* CPhipps - no friendlyness (yet)
  2102. newmobj->flags = (newmobj->flags & ~MF_FRIEND) | (mo->flags & MF_FRIEND);
  2103. */
  2104. }
  2105. }
  2106. void A_Turn(mobj_t *mo)
  2107. {
  2108. mo->angle += (unsigned int)(((uint_64_t) mo->state->misc1 << 32) / 360);
  2109. }
  2110. void A_Face(mobj_t *mo)
  2111. {
  2112. mo->angle = (unsigned int)(((uint_64_t) mo->state->misc1 << 32) / 360);
  2113. }
  2114. void A_Scratch(mobj_t *mo)
  2115. {
  2116. mo->target && (A_FaceTarget(mo), P_CheckMeleeRange(mo)) ?
  2117. mo->state->misc2 ? S_StartSound(mo, mo->state->misc2) : (void) 0,
  2118. P_DamageMobj(mo->target, mo, mo, mo->state->misc1) : (void) 0;
  2119. }
  2120. void A_PlaySound(mobj_t *mo)
  2121. {
  2122. S_StartSound(mo->state->misc2 ? NULL : mo, mo->state->misc1);
  2123. }
  2124. void A_RandomJump(mobj_t *mo)
  2125. {
  2126. if (P_Random(pr_randomjump) < mo->state->misc2)
  2127. P_SetMobjState(mo, mo->state->misc1);
  2128. }
  2129. //
  2130. // This allows linedef effects to be activated inside deh frames.
  2131. //
  2132. void A_LineEffect(mobj_t *mo)
  2133. {
  2134. static line_t junk;
  2135. player_t player;
  2136. player_t *oldplayer;
  2137. junk = *lines;
  2138. oldplayer = mo->player;
  2139. mo->player = &player;
  2140. player.health = 100;
  2141. junk.special = (short)mo->state->misc1;
  2142. if (!junk.special)
  2143. return;
  2144. junk.tag = (short)mo->state->misc2;
  2145. if (!P_UseSpecialLine(mo, &junk, 0))
  2146. P_CrossSpecialLine(&junk, 0, mo);
  2147. mo->state->misc1 = junk.special;
  2148. mo->player = oldplayer;
  2149. }