P_MOBJ.C 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. // P_mobj.c
  2. #include "DoomDef.h"
  3. #include "P_local.h"
  4. #include "sounds.h"
  5. #include "soundst.h"
  6. void G_PlayerReborn (int player);
  7. void P_SpawnMapThing (mapthing_t *mthing);
  8. mobjtype_t PuffType;
  9. mobj_t *MissileMobj;
  10. static fixed_t FloatBobOffsets[64] =
  11. {
  12. 0, 51389, 102283, 152192,
  13. 200636, 247147, 291278, 332604,
  14. 370727, 405280, 435929, 462380,
  15. 484378, 501712, 514213, 521763,
  16. 524287, 521763, 514213, 501712,
  17. 484378, 462380, 435929, 405280,
  18. 370727, 332604, 291278, 247147,
  19. 200636, 152192, 102283, 51389,
  20. -1, -51390, -102284, -152193,
  21. -200637, -247148, -291279, -332605,
  22. -370728, -405281, -435930, -462381,
  23. -484380, -501713, -514215, -521764,
  24. -524288, -521764, -514214, -501713,
  25. -484379, -462381, -435930, -405280,
  26. -370728, -332605, -291279, -247148,
  27. -200637, -152193, -102284, -51389
  28. };
  29. //----------------------------------------------------------------------------
  30. //
  31. // FUNC P_SetMobjState
  32. //
  33. // Returns true if the mobj is still present.
  34. //
  35. //----------------------------------------------------------------------------
  36. boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
  37. {
  38. state_t *st;
  39. if(state == S_NULL)
  40. { // Remove mobj
  41. mobj->state = S_NULL;
  42. P_RemoveMobj(mobj);
  43. return(false);
  44. }
  45. st = &states[state];
  46. mobj->state = st;
  47. mobj->tics = st->tics;
  48. mobj->sprite = st->sprite;
  49. mobj->frame = st->frame;
  50. if(st->action)
  51. { // Call action function
  52. st->action(mobj);
  53. }
  54. return(true);
  55. }
  56. //----------------------------------------------------------------------------
  57. //
  58. // FUNC P_SetMobjStateNF
  59. //
  60. // Same as P_SetMobjState, but does not call the state function.
  61. //
  62. //----------------------------------------------------------------------------
  63. boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
  64. {
  65. state_t *st;
  66. if(state == S_NULL)
  67. { // Remove mobj
  68. mobj->state = S_NULL;
  69. P_RemoveMobj(mobj);
  70. return(false);
  71. }
  72. st = &states[state];
  73. mobj->state = st;
  74. mobj->tics = st->tics;
  75. mobj->sprite = st->sprite;
  76. mobj->frame = st->frame;
  77. return(true);
  78. }
  79. //----------------------------------------------------------------------------
  80. //
  81. // PROC P_ExplodeMissile
  82. //
  83. //----------------------------------------------------------------------------
  84. void P_ExplodeMissile(mobj_t *mo)
  85. {
  86. if(mo->type == MT_WHIRLWIND)
  87. {
  88. if(++mo->special2 < 60)
  89. {
  90. return;
  91. }
  92. }
  93. mo->momx = mo->momy = mo->momz = 0;
  94. P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
  95. //mo->tics -= P_Random()&3;
  96. mo->flags &= ~MF_MISSILE;
  97. if(mo->info->deathsound)
  98. {
  99. S_StartSound(mo, mo->info->deathsound);
  100. }
  101. }
  102. //----------------------------------------------------------------------------
  103. //
  104. // PROC P_FloorBounceMissile
  105. //
  106. //----------------------------------------------------------------------------
  107. void P_FloorBounceMissile(mobj_t *mo)
  108. {
  109. mo->momz = -mo->momz;
  110. P_SetMobjState(mo, mobjinfo[mo->type].deathstate);
  111. }
  112. //----------------------------------------------------------------------------
  113. //
  114. // PROC P_ThrustMobj
  115. //
  116. //----------------------------------------------------------------------------
  117. void P_ThrustMobj(mobj_t *mo, angle_t angle, fixed_t move)
  118. {
  119. angle >>= ANGLETOFINESHIFT;
  120. mo->momx += FixedMul(move, finecosine[angle]);
  121. mo->momy += FixedMul(move, finesine[angle]);
  122. }
  123. //----------------------------------------------------------------------------
  124. //
  125. // FUNC P_FaceMobj
  126. //
  127. // Returns 1 if 'source' needs to turn clockwise, or 0 if 'source' needs
  128. // to turn counter clockwise. 'delta' is set to the amount 'source'
  129. // needs to turn.
  130. //
  131. //----------------------------------------------------------------------------
  132. int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta)
  133. {
  134. angle_t diff;
  135. angle_t angle1;
  136. angle_t angle2;
  137. angle1 = source->angle;
  138. angle2 = R_PointToAngle2(source->x, source->y, target->x, target->y);
  139. if(angle2 > angle1)
  140. {
  141. diff = angle2-angle1;
  142. if(diff > ANGLE_180)
  143. {
  144. *delta = ANGLE_MAX-diff;
  145. return(0);
  146. }
  147. else
  148. {
  149. *delta = diff;
  150. return(1);
  151. }
  152. }
  153. else
  154. {
  155. diff = angle1-angle2;
  156. if(diff > ANGLE_180)
  157. {
  158. *delta = ANGLE_MAX-diff;
  159. return(1);
  160. }
  161. else
  162. {
  163. *delta = diff;
  164. return(0);
  165. }
  166. }
  167. }
  168. //----------------------------------------------------------------------------
  169. //
  170. // FUNC P_SeekerMissile
  171. //
  172. // The missile special1 field must be mobj_t *target. Returns true if
  173. // target was tracked, false if not.
  174. //
  175. //----------------------------------------------------------------------------
  176. boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax)
  177. {
  178. int dir;
  179. int dist;
  180. angle_t delta;
  181. angle_t angle;
  182. mobj_t *target;
  183. target = (mobj_t *)actor->special1;
  184. if(target == NULL)
  185. {
  186. return(false);
  187. }
  188. if(!(target->flags&MF_SHOOTABLE))
  189. { // Target died
  190. actor->special1 = 0;
  191. return(false);
  192. }
  193. dir = P_FaceMobj(actor, target, &delta);
  194. if(delta > thresh)
  195. {
  196. delta >>= 1;
  197. if(delta > turnMax)
  198. {
  199. delta = turnMax;
  200. }
  201. }
  202. if(dir)
  203. { // Turn clockwise
  204. actor->angle += delta;
  205. }
  206. else
  207. { // Turn counter clockwise
  208. actor->angle -= delta;
  209. }
  210. angle = actor->angle>>ANGLETOFINESHIFT;
  211. actor->momx = FixedMul(actor->info->speed, finecosine[angle]);
  212. actor->momy = FixedMul(actor->info->speed, finesine[angle]);
  213. if(actor->z+actor->height < target->z ||
  214. target->z+target->height < actor->z)
  215. { // Need to seek vertically
  216. dist = P_AproxDistance(target->x-actor->x, target->y-actor->y);
  217. dist = dist/actor->info->speed;
  218. if(dist < 1)
  219. {
  220. dist = 1;
  221. }
  222. actor->momz = (target->z-actor->z)/dist;
  223. }
  224. return(true);
  225. }
  226. //----------------------------------------------------------------------------
  227. //
  228. // PROC P_XYMovement
  229. //
  230. //----------------------------------------------------------------------------
  231. #define STOPSPEED 0x1000
  232. #define FRICTION_NORMAL 0xe800
  233. #define FRICTION_LOW 0xf900
  234. #define FRICTION_FLY 0xeb00
  235. void P_XYMovement(mobj_t *mo)
  236. {
  237. fixed_t ptryx, ptryy;
  238. player_t *player;
  239. fixed_t xmove, ymove;
  240. int special;
  241. static int windTab[3] = {2048*5, 2048*10, 2048*25};
  242. if(!mo->momx && !mo->momy)
  243. {
  244. if(mo->flags&MF_SKULLFLY)
  245. { // A flying mobj slammed into something
  246. mo->flags &= ~MF_SKULLFLY;
  247. mo->momx = mo->momy = mo->momz = 0;
  248. P_SetMobjState(mo, mo->info->seestate);
  249. }
  250. return;
  251. }
  252. special = mo->subsector->sector->special;
  253. if(mo->flags2&MF2_WINDTHRUST)
  254. {
  255. switch(special)
  256. {
  257. case 40: case 41: case 42: // Wind_East
  258. P_ThrustMobj(mo, 0, windTab[special-40]);
  259. break;
  260. case 43: case 44: case 45: // Wind_North
  261. P_ThrustMobj(mo, ANG90, windTab[special-43]);
  262. break;
  263. case 46: case 47: case 48: // Wind_South
  264. P_ThrustMobj(mo, ANG270, windTab[special-46]);
  265. break;
  266. case 49: case 50: case 51: // Wind_West
  267. P_ThrustMobj(mo, ANG180, windTab[special-49]);
  268. break;
  269. }
  270. }
  271. player = mo->player;
  272. if(mo->momx > MAXMOVE)
  273. {
  274. mo->momx = MAXMOVE;
  275. }
  276. else if(mo->momx < -MAXMOVE)
  277. {
  278. mo->momx = -MAXMOVE;
  279. }
  280. if(mo->momy > MAXMOVE)
  281. {
  282. mo->momy = MAXMOVE;
  283. }
  284. else if(mo->momy < -MAXMOVE)
  285. {
  286. mo->momy = -MAXMOVE;
  287. }
  288. xmove = mo->momx;
  289. ymove = mo->momy;
  290. do
  291. {
  292. if(xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
  293. {
  294. ptryx = mo->x+xmove/2;
  295. ptryy = mo->y+ymove/2;
  296. xmove >>= 1;
  297. ymove >>= 1;
  298. }
  299. else
  300. {
  301. ptryx = mo->x + xmove;
  302. ptryy = mo->y + ymove;
  303. xmove = ymove = 0;
  304. }
  305. if(!P_TryMove(mo, ptryx, ptryy))
  306. { // Blocked move
  307. if(mo->flags2&MF2_SLIDE)
  308. { // Try to slide along it
  309. P_SlideMove(mo);
  310. }
  311. else if(mo->flags&MF_MISSILE)
  312. { // Explode a missile
  313. if(ceilingline && ceilingline->backsector
  314. && ceilingline->backsector->ceilingpic == skyflatnum)
  315. { // Hack to prevent missiles exploding against the sky
  316. if(mo->type == MT_BLOODYSKULL)
  317. {
  318. mo->momx = mo->momy = 0;
  319. mo->momz = -FRACUNIT;
  320. }
  321. else
  322. {
  323. P_RemoveMobj(mo);
  324. }
  325. return;
  326. }
  327. P_ExplodeMissile(mo);
  328. }
  329. //else if(mo->info->crashstate)
  330. //{
  331. // mo->momx = mo->momy = 0;
  332. // P_SetMobjState(mo, mo->info->crashstate);
  333. // return;
  334. //}
  335. else
  336. {
  337. mo->momx = mo->momy = 0;
  338. }
  339. }
  340. } while(xmove || ymove);
  341. // Friction
  342. if(player && player->cheats&CF_NOMOMENTUM)
  343. { // Debug option for no sliding at all
  344. mo->momx = mo->momy = 0;
  345. return;
  346. }
  347. if(mo->flags&(MF_MISSILE|MF_SKULLFLY))
  348. { // No friction for missiles
  349. return;
  350. }
  351. if(mo->z > mo->floorz && !(mo->flags2&MF2_FLY) && !(mo->flags2&MF2_ONMOBJ))
  352. { // No friction when falling
  353. return;
  354. }
  355. if(mo->flags&MF_CORPSE)
  356. { // Don't stop sliding if halfway off a step with some momentum
  357. if(mo->momx > FRACUNIT/4 || mo->momx < -FRACUNIT/4
  358. || mo->momy > FRACUNIT/4 || mo->momy < -FRACUNIT/4)
  359. {
  360. if(mo->floorz != mo->subsector->sector->floorheight)
  361. {
  362. return;
  363. }
  364. }
  365. }
  366. if(mo->momx > -STOPSPEED && mo->momx < STOPSPEED
  367. && mo->momy > -STOPSPEED && mo->momy < STOPSPEED
  368. && (!player || (player->cmd.forwardmove == 0
  369. && player->cmd.sidemove == 0)))
  370. { // If in a walking frame, stop moving
  371. if(player)
  372. {
  373. if(player->chickenTics)
  374. {
  375. if((unsigned)((player->mo->state-states)
  376. -S_CHICPLAY_RUN1) < 4)
  377. {
  378. P_SetMobjState(player->mo, S_CHICPLAY);
  379. }
  380. }
  381. else
  382. {
  383. if((unsigned)((player->mo->state-states)
  384. -S_PLAY_RUN1) < 4)
  385. {
  386. P_SetMobjState(player->mo, S_PLAY);
  387. }
  388. }
  389. }
  390. mo->momx = 0;
  391. mo->momy = 0;
  392. }
  393. else
  394. {
  395. if(mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
  396. &&!(mo->flags2&MF2_ONMOBJ))
  397. {
  398. mo->momx = FixedMul(mo->momx, FRICTION_FLY);
  399. mo->momy = FixedMul(mo->momy, FRICTION_FLY);
  400. }
  401. else if(special == 15) // Friction_Low
  402. {
  403. mo->momx = FixedMul(mo->momx, FRICTION_LOW);
  404. mo->momy = FixedMul(mo->momy, FRICTION_LOW);
  405. }
  406. else
  407. {
  408. mo->momx = FixedMul(mo->momx, FRICTION_NORMAL);
  409. mo->momy = FixedMul(mo->momy, FRICTION_NORMAL);
  410. }
  411. }
  412. }
  413. /*
  414. ===============
  415. =
  416. = P_ZMovement
  417. =
  418. ===============
  419. */
  420. void P_ZMovement(mobj_t *mo)
  421. {
  422. int dist;
  423. int delta;
  424. //
  425. // check for smooth step up
  426. //
  427. if (mo->player && mo->z < mo->floorz)
  428. {
  429. mo->player->viewheight -= mo->floorz-mo->z;
  430. mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight)>>3;
  431. }
  432. //
  433. // adjust height
  434. //
  435. mo->z += mo->momz;
  436. if(mo->flags&MF_FLOAT && mo->target)
  437. { // float down towards target if too close
  438. if(!(mo->flags&MF_SKULLFLY) && !(mo->flags&MF_INFLOAT))
  439. {
  440. dist = P_AproxDistance(mo->x-mo->target->x, mo->y-mo->target->y);
  441. delta =( mo->target->z+(mo->height>>1))-mo->z;
  442. if (delta < 0 && dist < -(delta*3))
  443. mo->z -= FLOATSPEED;
  444. else if (delta > 0 && dist < (delta*3))
  445. mo->z += FLOATSPEED;
  446. }
  447. }
  448. if(mo->player && mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)
  449. && leveltime&2)
  450. {
  451. mo->z += finesine[(FINEANGLES/20*leveltime>>2)&FINEMASK];
  452. }
  453. //
  454. // clip movement
  455. //
  456. if(mo->z <= mo->floorz)
  457. { // Hit the floor
  458. if(mo->flags&MF_MISSILE)
  459. {
  460. mo->z = mo->floorz;
  461. if(mo->flags2&MF2_FLOORBOUNCE)
  462. {
  463. P_FloorBounceMissile(mo);
  464. return;
  465. }
  466. else if(mo->type == MT_MNTRFX2)
  467. { // Minotaur floor fire can go up steps
  468. return;
  469. }
  470. else
  471. {
  472. P_ExplodeMissile(mo);
  473. return;
  474. }
  475. }
  476. if(mo->z-mo->momz > mo->floorz)
  477. { // Spawn splashes, etc.
  478. P_HitFloor(mo);
  479. }
  480. mo->z = mo->floorz;
  481. if(mo->momz < 0)
  482. {
  483. if(mo->player && mo->momz < -GRAVITY*8
  484. && !(mo->flags2&MF2_FLY)) // squat down
  485. {
  486. mo->player->deltaviewheight = mo->momz>>3;
  487. S_StartSound(mo, sfx_plroof);
  488. #ifdef __WATCOMC__
  489. if(!useexterndriver)
  490. {
  491. mo->player->centering = true;
  492. }
  493. #else
  494. mo->player->centering = true;
  495. #endif
  496. }
  497. mo->momz = 0;
  498. }
  499. if(mo->flags&MF_SKULLFLY)
  500. { // The skull slammed into something
  501. mo->momz = -mo->momz;
  502. }
  503. if(mo->info->crashstate && (mo->flags&MF_CORPSE))
  504. {
  505. P_SetMobjState(mo, mo->info->crashstate);
  506. return;
  507. }
  508. }
  509. else if(mo->flags2&MF2_LOGRAV)
  510. {
  511. if(mo->momz == 0)
  512. mo->momz = -(GRAVITY>>3)*2;
  513. else
  514. mo->momz -= GRAVITY>>3;
  515. }
  516. else if (! (mo->flags & MF_NOGRAVITY) )
  517. {
  518. if (mo->momz == 0)
  519. mo->momz = -GRAVITY*2;
  520. else
  521. mo->momz -= GRAVITY;
  522. }
  523. if (mo->z + mo->height > mo->ceilingz)
  524. { // hit the ceiling
  525. if (mo->momz > 0)
  526. mo->momz = 0;
  527. mo->z = mo->ceilingz - mo->height;
  528. if (mo->flags & MF_SKULLFLY)
  529. { // the skull slammed into something
  530. mo->momz = -mo->momz;
  531. }
  532. if (mo->flags & MF_MISSILE)
  533. {
  534. if(mo->subsector->sector->ceilingpic == skyflatnum)
  535. {
  536. if(mo->type == MT_BLOODYSKULL)
  537. {
  538. mo->momx = mo->momy = 0;
  539. mo->momz = -FRACUNIT;
  540. }
  541. else
  542. {
  543. P_RemoveMobj(mo);
  544. }
  545. return;
  546. }
  547. P_ExplodeMissile(mo);
  548. return;
  549. }
  550. }
  551. }
  552. /*
  553. ================
  554. =
  555. = P_NightmareRespawn
  556. =
  557. ================
  558. */
  559. void P_NightmareRespawn (mobj_t *mobj)
  560. {
  561. fixed_t x,y,z;
  562. subsector_t *ss;
  563. mobj_t *mo;
  564. mapthing_t *mthing;
  565. x = mobj->spawnpoint.x << FRACBITS;
  566. y = mobj->spawnpoint.y << FRACBITS;
  567. if (!P_CheckPosition (mobj, x, y) )
  568. return; // somthing is occupying it's position
  569. // spawn a teleport fog at old spot
  570. mo = P_SpawnMobj (mobj->x, mobj->y,
  571. mobj->subsector->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
  572. S_StartSound (mo, sfx_telept);
  573. // spawn a teleport fog at the new spot
  574. ss = R_PointInSubsector (x,y);
  575. mo = P_SpawnMobj (x, y, ss->sector->floorheight+TELEFOGHEIGHT, MT_TFOG);
  576. S_StartSound (mo, sfx_telept);
  577. // spawn the new monster
  578. mthing = &mobj->spawnpoint;
  579. // spawn it
  580. if (mobj->info->flags & MF_SPAWNCEILING)
  581. z = ONCEILINGZ;
  582. else
  583. z = ONFLOORZ;
  584. mo = P_SpawnMobj (x,y,z, mobj->type);
  585. mo->spawnpoint = mobj->spawnpoint;
  586. mo->angle = ANG45 * (mthing->angle/45);
  587. if (mthing->options & MTF_AMBUSH)
  588. mo->flags |= MF_AMBUSH;
  589. mo->reactiontime = 18;
  590. // remove the old monster
  591. P_RemoveMobj (mobj);
  592. }
  593. //----------------------------------------------------------------------------
  594. //
  595. // PROC P_BlasterMobjThinker
  596. //
  597. // Thinker for the ultra-fast blaster PL2 ripper-spawning missile.
  598. //
  599. //----------------------------------------------------------------------------
  600. void P_BlasterMobjThinker(mobj_t *mobj)
  601. {
  602. int i;
  603. fixed_t xfrac;
  604. fixed_t yfrac;
  605. fixed_t zfrac;
  606. fixed_t z;
  607. boolean changexy;
  608. // Handle movement
  609. if(mobj->momx || mobj->momy ||
  610. (mobj->z != mobj->floorz) || mobj->momz)
  611. {
  612. xfrac = mobj->momx>>3;
  613. yfrac = mobj->momy>>3;
  614. zfrac = mobj->momz>>3;
  615. changexy = xfrac || yfrac;
  616. for(i = 0; i < 8; i++)
  617. {
  618. if(changexy)
  619. {
  620. if(!P_TryMove(mobj, mobj->x+xfrac, mobj->y+yfrac))
  621. { // Blocked move
  622. P_ExplodeMissile(mobj);
  623. return;
  624. }
  625. }
  626. mobj->z += zfrac;
  627. if(mobj->z <= mobj->floorz)
  628. { // Hit the floor
  629. mobj->z = mobj->floorz;
  630. P_HitFloor(mobj);
  631. P_ExplodeMissile(mobj);
  632. return;
  633. }
  634. if(mobj->z+mobj->height > mobj->ceilingz)
  635. { // Hit the ceiling
  636. mobj->z = mobj->ceilingz-mobj->height;
  637. P_ExplodeMissile(mobj);
  638. return;
  639. }
  640. if(changexy && (P_Random() < 64))
  641. {
  642. z = mobj->z-8*FRACUNIT;
  643. if(z < mobj->floorz)
  644. {
  645. z = mobj->floorz;
  646. }
  647. P_SpawnMobj(mobj->x, mobj->y, z, MT_BLASTERSMOKE);
  648. }
  649. }
  650. }
  651. // Advance the state
  652. if(mobj->tics != -1)
  653. {
  654. mobj->tics--;
  655. while(!mobj->tics)
  656. {
  657. if(!P_SetMobjState(mobj, mobj->state->nextstate))
  658. { // mobj was removed
  659. return;
  660. }
  661. }
  662. }
  663. }
  664. //----------------------------------------------------------------------------
  665. //
  666. // PROC P_MobjThinker
  667. //
  668. //----------------------------------------------------------------------------
  669. void P_MobjThinker(mobj_t *mobj)
  670. {
  671. mobj_t *onmo;
  672. // Handle X and Y momentums
  673. if(mobj->momx || mobj->momy || (mobj->flags&MF_SKULLFLY))
  674. {
  675. P_XYMovement(mobj);
  676. if(mobj->thinker.function == (think_t)-1)
  677. { // mobj was removed
  678. return;
  679. }
  680. }
  681. if(mobj->flags2&MF2_FLOATBOB)
  682. { // Floating item bobbing motion
  683. mobj->z = mobj->floorz+FloatBobOffsets[(mobj->health++)&63];
  684. }
  685. else if((mobj->z != mobj->floorz) || mobj->momz)
  686. { // Handle Z momentum and gravity
  687. if(mobj->flags2&MF2_PASSMOBJ)
  688. {
  689. if(!(onmo = P_CheckOnmobj(mobj)))
  690. {
  691. P_ZMovement(mobj);
  692. }
  693. else
  694. {
  695. if(mobj->player && mobj->momz < 0)
  696. {
  697. mobj->flags2 |= MF2_ONMOBJ;
  698. mobj->momz = 0;
  699. }
  700. if(mobj->player && (onmo->player || onmo->type == MT_POD))
  701. {
  702. mobj->momx = onmo->momx;
  703. mobj->momy = onmo->momy;
  704. if(onmo->z < onmo->floorz)
  705. {
  706. mobj->z += onmo->floorz-onmo->z;
  707. if(onmo->player)
  708. {
  709. onmo->player->viewheight -= onmo->floorz-onmo->z;
  710. onmo->player->deltaviewheight = (VIEWHEIGHT-
  711. onmo->player->viewheight)>>3;
  712. }
  713. onmo->z = onmo->floorz;
  714. }
  715. }
  716. }
  717. }
  718. else
  719. {
  720. P_ZMovement(mobj);
  721. }
  722. if(mobj->thinker.function == (think_t)-1)
  723. { // mobj was removed
  724. return;
  725. }
  726. }
  727. //
  728. // cycle through states, calling action functions at transitions
  729. //
  730. if(mobj->tics != -1)
  731. {
  732. mobj->tics--;
  733. // you can cycle through multiple states in a tic
  734. while(!mobj->tics)
  735. {
  736. if(!P_SetMobjState(mobj, mobj->state->nextstate))
  737. { // mobj was removed
  738. return;
  739. }
  740. }
  741. }
  742. else
  743. { // Check for monster respawn
  744. if(!(mobj->flags&MF_COUNTKILL))
  745. {
  746. return;
  747. }
  748. if(!respawnmonsters)
  749. {
  750. return;
  751. }
  752. mobj->movecount++;
  753. if(mobj->movecount < 12*35)
  754. {
  755. return;
  756. }
  757. if(leveltime&31)
  758. {
  759. return;
  760. }
  761. if(P_Random() > 4)
  762. {
  763. return;
  764. }
  765. P_NightmareRespawn(mobj);
  766. }
  767. }
  768. /*
  769. ===============
  770. =
  771. = P_SpawnMobj
  772. =
  773. ===============
  774. */
  775. mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
  776. {
  777. mobj_t *mobj;
  778. state_t *st;
  779. mobjinfo_t *info;
  780. fixed_t space;
  781. mobj = Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
  782. memset(mobj, 0, sizeof(*mobj));
  783. info = &mobjinfo[type];
  784. mobj->type = type;
  785. mobj->info = info;
  786. mobj->x = x;
  787. mobj->y = y;
  788. mobj->radius = info->radius;
  789. mobj->height = info->height;
  790. mobj->flags = info->flags;
  791. mobj->flags2 = info->flags2;
  792. mobj->damage = info->damage;
  793. mobj->health = info->spawnhealth;
  794. if(gameskill != sk_nightmare)
  795. {
  796. mobj->reactiontime = info->reactiontime;
  797. }
  798. mobj->lastlook = P_Random()%MAXPLAYERS;
  799. // Set the state, but do not use P_SetMobjState, because action
  800. // routines can't be called yet. If the spawnstate has an action
  801. // routine, it will not be called.
  802. st = &states[info->spawnstate];
  803. mobj->state = st;
  804. mobj->tics = st->tics;
  805. mobj->sprite = st->sprite;
  806. mobj->frame = st->frame;
  807. // Set subsector and/or block links.
  808. P_SetThingPosition(mobj);
  809. mobj->floorz = mobj->subsector->sector->floorheight;
  810. mobj->ceilingz = mobj->subsector->sector->ceilingheight;
  811. if(z == ONFLOORZ)
  812. {
  813. mobj->z = mobj->floorz;
  814. }
  815. else if(z == ONCEILINGZ)
  816. {
  817. mobj->z = mobj->ceilingz-mobj->info->height;
  818. }
  819. else if(z == FLOATRANDZ)
  820. {
  821. space = ((mobj->ceilingz)-(mobj->info->height))-mobj->floorz;
  822. if(space > 48*FRACUNIT)
  823. {
  824. space -= 40*FRACUNIT;
  825. mobj->z = ((space*P_Random())>>8)+mobj->floorz+40*FRACUNIT;
  826. }
  827. else
  828. {
  829. mobj->z = mobj->floorz;
  830. }
  831. }
  832. else
  833. {
  834. mobj->z = z;
  835. }
  836. if(mobj->flags2&MF2_FOOTCLIP && P_GetThingFloorType(mobj) != FLOOR_SOLID
  837. && mobj->floorz == mobj->subsector->sector->floorheight)
  838. {
  839. mobj->flags2 |= MF2_FEETARECLIPPED;
  840. }
  841. else
  842. {
  843. mobj->flags2 &= ~MF2_FEETARECLIPPED;
  844. }
  845. mobj->thinker.function = P_MobjThinker;
  846. P_AddThinker(&mobj->thinker);
  847. return(mobj);
  848. }
  849. /*
  850. ===============
  851. =
  852. = P_RemoveMobj
  853. =
  854. ===============
  855. */
  856. void P_RemoveMobj(mobj_t *mobj)
  857. {
  858. // unlink from sector and block lists
  859. P_UnsetThingPosition (mobj);
  860. // stop any playing sound
  861. S_StopSound(mobj);
  862. // free block
  863. P_RemoveThinker((thinker_t *)mobj);
  864. }
  865. //=============================================================================
  866. /*
  867. ============
  868. =
  869. = P_SpawnPlayer
  870. =
  871. = Called when a player is spawned on the level
  872. = Most of the player structure stays unchanged between levels
  873. ============
  874. */
  875. void P_SpawnPlayer(mapthing_t *mthing)
  876. {
  877. player_t *p;
  878. fixed_t x,y,z;
  879. mobj_t *mobj;
  880. int i;
  881. extern int playerkeys;
  882. if (!playeringame[mthing->type-1])
  883. return; // not playing
  884. p = &players[mthing->type-1];
  885. if (p->playerstate == PST_REBORN)
  886. G_PlayerReborn (mthing->type-1);
  887. x = mthing->x << FRACBITS;
  888. y = mthing->y << FRACBITS;
  889. z = ONFLOORZ;
  890. mobj = P_SpawnMobj (x,y,z, MT_PLAYER);
  891. if (mthing->type > 1) // set color translations for player sprites
  892. mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
  893. mobj->angle = ANG45 * (mthing->angle/45);
  894. mobj->player = p;
  895. mobj->health = p->health;
  896. p->mo = mobj;
  897. p->playerstate = PST_LIVE;
  898. p->refire = 0;
  899. p->message = NULL;
  900. p->damagecount = 0;
  901. p->bonuscount = 0;
  902. p->chickenTics = 0;
  903. p->rain1 = NULL;
  904. p->rain2 = NULL;
  905. p->extralight = 0;
  906. p->fixedcolormap = 0;
  907. p->viewheight = VIEWHEIGHT;
  908. P_SetupPsprites(p); // setup gun psprite
  909. if(deathmatch)
  910. { // Give all keys in death match mode
  911. for(i = 0; i < NUMKEYS; i++)
  912. {
  913. p->keys[i] = true;
  914. if(p == &players[consoleplayer])
  915. {
  916. playerkeys = 7;
  917. UpdateState |= I_STATBAR;
  918. }
  919. }
  920. }
  921. else if(p == &players[consoleplayer])
  922. {
  923. playerkeys = 0;
  924. UpdateState |= I_STATBAR;
  925. }
  926. }
  927. //----------------------------------------------------------------------------
  928. //
  929. // PROC P_SpawnMapThing
  930. //
  931. // The fields of the mapthing should already be in host byte order.
  932. //
  933. //----------------------------------------------------------------------------
  934. void P_SpawnMapThing(mapthing_t *mthing)
  935. {
  936. int i;
  937. int bit;
  938. mobj_t *mobj;
  939. fixed_t x, y, z;
  940. // count deathmatch start positions
  941. if(mthing->type == 11)
  942. {
  943. if(deathmatch_p < &deathmatchstarts[10])
  944. {
  945. memcpy(deathmatch_p, mthing, sizeof(*mthing));
  946. deathmatch_p++;
  947. }
  948. return;
  949. }
  950. // check for players specially
  951. if(mthing->type <= 4)
  952. {
  953. // save spots for respawning in network games
  954. playerstarts[mthing->type-1] = *mthing;
  955. if(!deathmatch)
  956. {
  957. P_SpawnPlayer(mthing);
  958. }
  959. return;
  960. }
  961. // Ambient sound sequences
  962. if(mthing->type >= 1200 && mthing->type < 1300)
  963. {
  964. P_AddAmbientSfx(mthing->type-1200);
  965. return;
  966. }
  967. // Check for boss spots
  968. if(mthing->type == 56) // Monster_BossSpot
  969. {
  970. P_AddBossSpot(mthing->x<<FRACBITS, mthing->y<<FRACBITS,
  971. ANG45*(mthing->angle/45));
  972. return;
  973. }
  974. // check for apropriate skill level
  975. if (!netgame && (mthing->options & 16) )
  976. return;
  977. if (gameskill == sk_baby)
  978. bit = 1;
  979. else if (gameskill == sk_nightmare)
  980. bit = 4;
  981. else
  982. bit = 1<<(gameskill-1);
  983. if (!(mthing->options & bit) )
  984. return;
  985. // find which type to spawn
  986. for (i=0 ; i< NUMMOBJTYPES ; i++)
  987. if (mthing->type == mobjinfo[i].doomednum)
  988. break;
  989. if (i==NUMMOBJTYPES)
  990. I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",mthing->type
  991. , mthing->x, mthing->y);
  992. // don't spawn keys and players in deathmatch
  993. if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
  994. return;
  995. // don't spawn any monsters if -nomonsters
  996. if (nomonsters && (mobjinfo[i].flags & MF_COUNTKILL) )
  997. return;
  998. // spawn it
  999. switch(i)
  1000. { // Special stuff
  1001. case MT_WSKULLROD:
  1002. case MT_WPHOENIXROD:
  1003. case MT_AMSKRDWIMPY:
  1004. case MT_AMSKRDHEFTY:
  1005. case MT_AMPHRDWIMPY:
  1006. case MT_AMPHRDHEFTY:
  1007. case MT_AMMACEWIMPY:
  1008. case MT_AMMACEHEFTY:
  1009. case MT_ARTISUPERHEAL:
  1010. case MT_ARTITELEPORT:
  1011. case MT_ITEMSHIELD2:
  1012. if(shareware)
  1013. { // Don't place on map in shareware version
  1014. return;
  1015. }
  1016. break;
  1017. case MT_WMACE:
  1018. if(!shareware)
  1019. { // Put in the mace spot list
  1020. P_AddMaceSpot(mthing);
  1021. return;
  1022. }
  1023. return;
  1024. default:
  1025. break;
  1026. }
  1027. x = mthing->x<<FRACBITS;
  1028. y = mthing->y<<FRACBITS;
  1029. if(mobjinfo[i].flags&MF_SPAWNCEILING)
  1030. {
  1031. z = ONCEILINGZ;
  1032. }
  1033. else if(mobjinfo[i].flags2&MF2_SPAWNFLOAT)
  1034. {
  1035. z = FLOATRANDZ;
  1036. }
  1037. else
  1038. {
  1039. z = ONFLOORZ;
  1040. }
  1041. mobj = P_SpawnMobj(x, y, z, i);
  1042. if(mobj->flags2&MF2_FLOATBOB)
  1043. { // Seed random starting index for bobbing motion
  1044. mobj->health = P_Random();
  1045. }
  1046. if(mobj->tics > 0)
  1047. {
  1048. mobj->tics = 1+(P_Random()%mobj->tics);
  1049. }
  1050. if(mobj->flags&MF_COUNTKILL)
  1051. {
  1052. totalkills++;
  1053. mobj->spawnpoint = *mthing;
  1054. }
  1055. if(mobj->flags&MF_COUNTITEM)
  1056. {
  1057. totalitems++;
  1058. }
  1059. mobj->angle = ANG45*(mthing->angle/45);
  1060. if(mthing->options&MTF_AMBUSH)
  1061. {
  1062. mobj->flags |= MF_AMBUSH;
  1063. }
  1064. }
  1065. /*
  1066. ===============================================================================
  1067. GAME SPAWN FUNCTIONS
  1068. ===============================================================================
  1069. */
  1070. //---------------------------------------------------------------------------
  1071. //
  1072. // PROC P_SpawnPuff
  1073. //
  1074. //---------------------------------------------------------------------------
  1075. extern fixed_t attackrange;
  1076. void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z)
  1077. {
  1078. mobj_t *puff;
  1079. z += ((P_Random()-P_Random())<<10);
  1080. puff = P_SpawnMobj(x, y, z, PuffType);
  1081. if(puff->info->attacksound)
  1082. {
  1083. S_StartSound(puff, puff->info->attacksound);
  1084. }
  1085. switch(PuffType)
  1086. {
  1087. case MT_BEAKPUFF:
  1088. case MT_STAFFPUFF:
  1089. puff->momz = FRACUNIT;
  1090. break;
  1091. case MT_GAUNTLETPUFF1:
  1092. case MT_GAUNTLETPUFF2:
  1093. puff->momz = .8*FRACUNIT;
  1094. default:
  1095. break;
  1096. }
  1097. }
  1098. /*
  1099. ================
  1100. =
  1101. = P_SpawnBlood
  1102. =
  1103. ================
  1104. */
  1105. /*
  1106. void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage)
  1107. {
  1108. mobj_t *th;
  1109. z += ((P_Random()-P_Random())<<10);
  1110. th = P_SpawnMobj (x,y,z, MT_BLOOD);
  1111. th->momz = FRACUNIT*2;
  1112. th->tics -= P_Random()&3;
  1113. if (damage <= 12 && damage >= 9)
  1114. P_SetMobjState (th,S_BLOOD2);
  1115. else if (damage < 9)
  1116. P_SetMobjState (th,S_BLOOD3);
  1117. }
  1118. */
  1119. //---------------------------------------------------------------------------
  1120. //
  1121. // PROC P_BloodSplatter
  1122. //
  1123. //---------------------------------------------------------------------------
  1124. void P_BloodSplatter(fixed_t x, fixed_t y, fixed_t z, mobj_t *originator)
  1125. {
  1126. mobj_t *mo;
  1127. mo = P_SpawnMobj(x, y, z, MT_BLOODSPLATTER);
  1128. mo->target = originator;
  1129. mo->momx = (P_Random()-P_Random())<<9;
  1130. mo->momy = (P_Random()-P_Random())<<9;
  1131. mo->momz = FRACUNIT*2;
  1132. }
  1133. //---------------------------------------------------------------------------
  1134. //
  1135. // PROC P_RipperBlood
  1136. //
  1137. //---------------------------------------------------------------------------
  1138. void P_RipperBlood(mobj_t *mo)
  1139. {
  1140. mobj_t *th;
  1141. fixed_t x, y, z;
  1142. x = mo->x+((P_Random()-P_Random())<<12);
  1143. y = mo->y+((P_Random()-P_Random())<<12);
  1144. z = mo->z+((P_Random()-P_Random())<<12);
  1145. th = P_SpawnMobj(x, y, z, MT_BLOOD);
  1146. th->flags |= MF_NOGRAVITY;
  1147. th->momx = mo->momx>>1;
  1148. th->momy = mo->momy>>1;
  1149. th->tics += P_Random()&3;
  1150. }
  1151. //---------------------------------------------------------------------------
  1152. //
  1153. // FUNC P_GetThingFloorType
  1154. //
  1155. //---------------------------------------------------------------------------
  1156. int P_GetThingFloorType(mobj_t *thing)
  1157. {
  1158. return(TerrainTypes[thing->subsector->sector->floorpic]);
  1159. /*
  1160. if(thing->subsector->sector->floorpic
  1161. == W_GetNumForName("FLTWAWA1")-firstflat)
  1162. {
  1163. return(FLOOR_WATER);
  1164. }
  1165. else
  1166. {
  1167. return(FLOOR_SOLID);
  1168. }
  1169. */
  1170. }
  1171. //---------------------------------------------------------------------------
  1172. //
  1173. // FUNC P_HitFloor
  1174. //
  1175. //---------------------------------------------------------------------------
  1176. int P_HitFloor(mobj_t *thing)
  1177. {
  1178. mobj_t *mo;
  1179. if(thing->floorz != thing->subsector->sector->floorheight)
  1180. { // don't splash if landing on the edge above water/lava/etc....
  1181. return(FLOOR_SOLID);
  1182. }
  1183. switch(P_GetThingFloorType(thing))
  1184. {
  1185. case FLOOR_WATER:
  1186. P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASHBASE);
  1187. mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SPLASH);
  1188. mo->target = thing;
  1189. mo->momx = (P_Random()-P_Random())<<8;
  1190. mo->momy = (P_Random()-P_Random())<<8;
  1191. mo->momz = 2*FRACUNIT+(P_Random()<<8);
  1192. S_StartSound(mo, sfx_gloop);
  1193. return(FLOOR_WATER);
  1194. case FLOOR_LAVA:
  1195. P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASPLASH);
  1196. mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_LAVASMOKE);
  1197. mo->momz = FRACUNIT+(P_Random()<<7);
  1198. S_StartSound(mo, sfx_burn);
  1199. return(FLOOR_LAVA);
  1200. case FLOOR_SLUDGE:
  1201. P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGESPLASH);
  1202. mo = P_SpawnMobj(thing->x, thing->y, ONFLOORZ, MT_SLUDGECHUNK);
  1203. mo->target = thing;
  1204. mo->momx = (P_Random()-P_Random())<<8;
  1205. mo->momy = (P_Random()-P_Random())<<8;
  1206. mo->momz = FRACUNIT+(P_Random()<<8);
  1207. return(FLOOR_SLUDGE);
  1208. }
  1209. return(FLOOR_SOLID);
  1210. }
  1211. //---------------------------------------------------------------------------
  1212. //
  1213. // FUNC P_CheckMissileSpawn
  1214. //
  1215. // Returns true if the missile is at a valid spawn point, otherwise
  1216. // explodes it and returns false.
  1217. //
  1218. //---------------------------------------------------------------------------
  1219. boolean P_CheckMissileSpawn(mobj_t *missile)
  1220. {
  1221. //missile->tics -= P_Random()&3;
  1222. // move a little forward so an angle can be computed if it
  1223. // immediately explodes
  1224. missile->x += (missile->momx>>1);
  1225. missile->y += (missile->momy>>1);
  1226. missile->z += (missile->momz>>1);
  1227. if(!P_TryMove(missile, missile->x, missile->y))
  1228. {
  1229. P_ExplodeMissile(missile);
  1230. return(false);
  1231. }
  1232. return(true);
  1233. }
  1234. //---------------------------------------------------------------------------
  1235. //
  1236. // FUNC P_SpawnMissile
  1237. //
  1238. // Returns NULL if the missile exploded immediately, otherwise returns
  1239. // a mobj_t pointer to the missile.
  1240. //
  1241. //---------------------------------------------------------------------------
  1242. mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
  1243. {
  1244. fixed_t z;
  1245. mobj_t *th;
  1246. angle_t an;
  1247. int dist;
  1248. switch(type)
  1249. {
  1250. case MT_MNTRFX1: // Minotaur swing attack missile
  1251. z = source->z+40*FRACUNIT;
  1252. break;
  1253. case MT_MNTRFX2: // Minotaur floor fire missile
  1254. z = ONFLOORZ;
  1255. break;
  1256. case MT_SRCRFX1: // Sorcerer Demon fireball
  1257. z = source->z+48*FRACUNIT;
  1258. break;
  1259. case MT_KNIGHTAXE: // Knight normal axe
  1260. case MT_REDAXE: // Knight red power axe
  1261. z = source->z+36*FRACUNIT;
  1262. break;
  1263. default:
  1264. z = source->z+32*FRACUNIT;
  1265. break;
  1266. }
  1267. if(source->flags2&MF2_FEETARECLIPPED)
  1268. {
  1269. z -= FOOTCLIPSIZE;
  1270. }
  1271. th = P_SpawnMobj(source->x, source->y, z, type);
  1272. if(th->info->seesound)
  1273. {
  1274. S_StartSound(th, th->info->seesound);
  1275. }
  1276. th->target = source; // Originator
  1277. an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
  1278. if(dest->flags&MF_SHADOW)
  1279. { // Invisible target
  1280. an += (P_Random()-P_Random())<<21;
  1281. }
  1282. th->angle = an;
  1283. an >>= ANGLETOFINESHIFT;
  1284. th->momx = FixedMul(th->info->speed, finecosine[an]);
  1285. th->momy = FixedMul(th->info->speed, finesine[an]);
  1286. dist = P_AproxDistance(dest->x - source->x, dest->y - source->y);
  1287. dist = dist/th->info->speed;
  1288. if(dist < 1)
  1289. {
  1290. dist = 1;
  1291. }
  1292. th->momz = (dest->z-source->z)/dist;
  1293. return(P_CheckMissileSpawn(th) ? th : NULL);
  1294. }
  1295. //---------------------------------------------------------------------------
  1296. //
  1297. // FUNC P_SpawnMissileAngle
  1298. //
  1299. // Returns NULL if the missile exploded immediately, otherwise returns
  1300. // a mobj_t pointer to the missile.
  1301. //
  1302. //---------------------------------------------------------------------------
  1303. mobj_t *P_SpawnMissileAngle(mobj_t *source, mobjtype_t type,
  1304. angle_t angle, fixed_t momz)
  1305. {
  1306. fixed_t z;
  1307. mobj_t *mo;
  1308. switch(type)
  1309. {
  1310. case MT_MNTRFX1: // Minotaur swing attack missile
  1311. z = source->z+40*FRACUNIT;
  1312. break;
  1313. case MT_MNTRFX2: // Minotaur floor fire missile
  1314. z = ONFLOORZ;
  1315. break;
  1316. case MT_SRCRFX1: // Sorcerer Demon fireball
  1317. z = source->z+48*FRACUNIT;
  1318. break;
  1319. default:
  1320. z = source->z+32*FRACUNIT;
  1321. break;
  1322. }
  1323. if(source->flags2&MF2_FEETARECLIPPED)
  1324. {
  1325. z -= FOOTCLIPSIZE;
  1326. }
  1327. mo = P_SpawnMobj(source->x, source->y, z, type);
  1328. if(mo->info->seesound)
  1329. {
  1330. S_StartSound(mo, mo->info->seesound);
  1331. }
  1332. mo->target = source; // Originator
  1333. mo->angle = angle;
  1334. angle >>= ANGLETOFINESHIFT;
  1335. mo->momx = FixedMul(mo->info->speed, finecosine[angle]);
  1336. mo->momy = FixedMul(mo->info->speed, finesine[angle]);
  1337. mo->momz = momz;
  1338. return(P_CheckMissileSpawn(mo) ? mo : NULL);
  1339. }
  1340. /*
  1341. ================
  1342. =
  1343. = P_SpawnPlayerMissile
  1344. =
  1345. = Tries to aim at a nearby monster
  1346. ================
  1347. */
  1348. mobj_t *P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type)
  1349. {
  1350. angle_t an;
  1351. fixed_t x, y, z, slope;
  1352. // Try to find a target
  1353. an = source->angle;
  1354. slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
  1355. if(!linetarget)
  1356. {
  1357. an += 1<<26;
  1358. slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
  1359. if(!linetarget)
  1360. {
  1361. an -= 2<<26;
  1362. slope = P_AimLineAttack(source, an, 16*64*FRACUNIT);
  1363. }
  1364. if(!linetarget)
  1365. {
  1366. an = source->angle;
  1367. slope = ((source->player->lookdir)<<FRACBITS)/173;
  1368. }
  1369. }
  1370. x = source->x;
  1371. y = source->y;
  1372. z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
  1373. if(source->flags2&MF2_FEETARECLIPPED)
  1374. {
  1375. z -= FOOTCLIPSIZE;
  1376. }
  1377. MissileMobj = P_SpawnMobj(x, y, z, type);
  1378. if(MissileMobj->info->seesound)
  1379. {
  1380. S_StartSound(MissileMobj, MissileMobj->info->seesound);
  1381. }
  1382. MissileMobj->target = source;
  1383. MissileMobj->angle = an;
  1384. MissileMobj->momx = FixedMul(MissileMobj->info->speed,
  1385. finecosine[an>>ANGLETOFINESHIFT]);
  1386. MissileMobj->momy = FixedMul(MissileMobj->info->speed,
  1387. finesine[an>>ANGLETOFINESHIFT]);
  1388. MissileMobj->momz = FixedMul(MissileMobj->info->speed, slope);
  1389. if(MissileMobj->type == MT_BLASTERFX1)
  1390. { // Ultra-fast ripper spawning missile
  1391. MissileMobj->x += (MissileMobj->momx>>3);
  1392. MissileMobj->y += (MissileMobj->momy>>3);
  1393. MissileMobj->z += (MissileMobj->momz>>3);
  1394. }
  1395. else
  1396. { // Normal missile
  1397. MissileMobj->x += (MissileMobj->momx>>1);
  1398. MissileMobj->y += (MissileMobj->momy>>1);
  1399. MissileMobj->z += (MissileMobj->momz>>1);
  1400. }
  1401. if(!P_TryMove(MissileMobj, MissileMobj->x, MissileMobj->y))
  1402. { // Exploded immediately
  1403. P_ExplodeMissile(MissileMobj);
  1404. return(NULL);
  1405. }
  1406. return(MissileMobj);
  1407. }
  1408. //---------------------------------------------------------------------------
  1409. //
  1410. // PROC P_SPMAngle
  1411. //
  1412. //---------------------------------------------------------------------------
  1413. mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle)
  1414. {
  1415. mobj_t *th;
  1416. angle_t an;
  1417. fixed_t x, y, z, slope;
  1418. //
  1419. // see which target is to be aimed at
  1420. //
  1421. an = angle;
  1422. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  1423. if (!linetarget)
  1424. {
  1425. an += 1<<26;
  1426. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  1427. if (!linetarget)
  1428. {
  1429. an -= 2<<26;
  1430. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  1431. }
  1432. if (!linetarget)
  1433. {
  1434. an = angle;
  1435. slope = ((source->player->lookdir)<<FRACBITS)/173;
  1436. }
  1437. }
  1438. x = source->x;
  1439. y = source->y;
  1440. z = source->z + 4*8*FRACUNIT+((source->player->lookdir)<<FRACBITS)/173;
  1441. if(source->flags2&MF2_FEETARECLIPPED)
  1442. {
  1443. z -= FOOTCLIPSIZE;
  1444. }
  1445. th = P_SpawnMobj(x, y, z, type);
  1446. if(th->info->seesound)
  1447. {
  1448. S_StartSound(th, th->info->seesound);
  1449. }
  1450. th->target = source;
  1451. th->angle = an;
  1452. th->momx = FixedMul(th->info->speed, finecosine[an>>ANGLETOFINESHIFT]);
  1453. th->momy = FixedMul(th->info->speed, finesine[an>>ANGLETOFINESHIFT]);
  1454. th->momz = FixedMul(th->info->speed, slope);
  1455. return(P_CheckMissileSpawn(th) ? th : NULL);
  1456. }
  1457. //---------------------------------------------------------------------------
  1458. //
  1459. // PROC A_ContMobjSound
  1460. //
  1461. //---------------------------------------------------------------------------
  1462. void A_ContMobjSound(mobj_t *actor)
  1463. {
  1464. switch(actor->type)
  1465. {
  1466. case MT_KNIGHTAXE:
  1467. S_StartSound(actor, sfx_kgtatk);
  1468. break;
  1469. case MT_MUMMYFX1:
  1470. S_StartSound(actor, sfx_mumhed);
  1471. break;
  1472. default:
  1473. break;
  1474. }
  1475. }