p_mobj.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. // Emacs style mode select -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Moving object handling. Spawn functions.
  21. //
  22. //-----------------------------------------------------------------------------
  23. static const char
  24. rcsid[] = "$Id: p_mobj.c,v 1.5 1997/02/03 22:45:12 b1 Exp $";
  25. #include "i_system.h"
  26. #include "z_zone.h"
  27. #include "m_random.h"
  28. #include "doomdef.h"
  29. #include "p_local.h"
  30. #include "sounds.h"
  31. #include "st_stuff.h"
  32. #include "hu_stuff.h"
  33. #include "s_sound.h"
  34. #include "doomstat.h"
  35. void G_PlayerReborn (int player);
  36. void P_SpawnMapThing (mapthing_t* mthing);
  37. //
  38. // P_SetMobjState
  39. // Returns true if the mobj is still present.
  40. //
  41. int test;
  42. boolean
  43. P_SetMobjState
  44. ( mobj_t* mobj,
  45. statenum_t state )
  46. {
  47. state_t* st;
  48. do
  49. {
  50. if (state == S_NULL)
  51. {
  52. mobj->state = (state_t *) S_NULL;
  53. P_RemoveMobj (mobj);
  54. return false;
  55. }
  56. st = &states[state];
  57. mobj->state = st;
  58. mobj->tics = st->tics;
  59. mobj->sprite = st->sprite;
  60. mobj->frame = st->frame;
  61. // Modified handling.
  62. // Call action functions when the state is set
  63. if (st->action.acp1)
  64. st->action.acp1(mobj);
  65. state = st->nextstate;
  66. } while (!mobj->tics);
  67. return true;
  68. }
  69. //
  70. // P_ExplodeMissile
  71. //
  72. void P_ExplodeMissile (mobj_t* mo)
  73. {
  74. mo->momx = mo->momy = mo->momz = 0;
  75. P_SetMobjState (mo, mobjinfo[mo->type].deathstate);
  76. mo->tics -= P_Random()&3;
  77. if (mo->tics < 1)
  78. mo->tics = 1;
  79. mo->flags &= ~MF_MISSILE;
  80. if (mo->info->deathsound)
  81. S_StartSound (mo, mo->info->deathsound);
  82. }
  83. //
  84. // P_XYMovement
  85. //
  86. #define STOPSPEED 0x1000
  87. #define FRICTION 0xe800
  88. void P_XYMovement (mobj_t* mo)
  89. {
  90. fixed_t ptryx;
  91. fixed_t ptryy;
  92. player_t* player;
  93. fixed_t xmove;
  94. fixed_t ymove;
  95. if (!mo->momx && !mo->momy)
  96. {
  97. if (mo->flags & MF_SKULLFLY)
  98. {
  99. // the skull slammed into something
  100. mo->flags &= ~MF_SKULLFLY;
  101. mo->momx = mo->momy = mo->momz = 0;
  102. P_SetMobjState (mo, mo->info->spawnstate);
  103. }
  104. return;
  105. }
  106. player = mo->player;
  107. if (mo->momx > MAXMOVE)
  108. mo->momx = MAXMOVE;
  109. else if (mo->momx < -MAXMOVE)
  110. mo->momx = -MAXMOVE;
  111. if (mo->momy > MAXMOVE)
  112. mo->momy = MAXMOVE;
  113. else if (mo->momy < -MAXMOVE)
  114. mo->momy = -MAXMOVE;
  115. xmove = mo->momx;
  116. ymove = mo->momy;
  117. do
  118. {
  119. if (xmove > MAXMOVE/2 || ymove > MAXMOVE/2)
  120. {
  121. ptryx = mo->x + xmove/2;
  122. ptryy = mo->y + ymove/2;
  123. xmove >>= 1;
  124. ymove >>= 1;
  125. }
  126. else
  127. {
  128. ptryx = mo->x + xmove;
  129. ptryy = mo->y + ymove;
  130. xmove = ymove = 0;
  131. }
  132. if (!P_TryMove (mo, ptryx, ptryy))
  133. {
  134. // blocked move
  135. if (mo->player)
  136. { // try to slide along it
  137. P_SlideMove (mo);
  138. }
  139. else if (mo->flags & MF_MISSILE)
  140. {
  141. // explode a missile
  142. if (ceilingline &&
  143. ceilingline->backsector &&
  144. ceilingline->backsector->ceilingpic == skyflatnum)
  145. {
  146. // Hack to prevent missiles exploding
  147. // against the sky.
  148. // Does not handle sky floors.
  149. P_RemoveMobj (mo);
  150. return;
  151. }
  152. P_ExplodeMissile (mo);
  153. }
  154. else
  155. mo->momx = mo->momy = 0;
  156. }
  157. } while (xmove || ymove);
  158. // slow down
  159. if (player && player->cheats & CF_NOMOMENTUM)
  160. {
  161. // debug option for no sliding at all
  162. mo->momx = mo->momy = 0;
  163. return;
  164. }
  165. if (mo->flags & (MF_MISSILE | MF_SKULLFLY) )
  166. return; // no friction for missiles ever
  167. if (mo->z > mo->floorz)
  168. return; // no friction when airborne
  169. if (mo->flags & MF_CORPSE)
  170. {
  171. // do not stop sliding
  172. // if halfway off a step with some momentum
  173. if (mo->momx > FRACUNIT/4
  174. || mo->momx < -FRACUNIT/4
  175. || mo->momy > FRACUNIT/4
  176. || mo->momy < -FRACUNIT/4)
  177. {
  178. if (mo->floorz != mo->subsector->sector->floorheight)
  179. return;
  180. }
  181. }
  182. if (mo->momx > -STOPSPEED
  183. && mo->momx < STOPSPEED
  184. && mo->momy > -STOPSPEED
  185. && mo->momy < STOPSPEED
  186. && (!player
  187. || (player->cmd.forwardmove== 0
  188. && player->cmd.sidemove == 0 ) ) )
  189. {
  190. // if in a walking frame, stop moving
  191. if ( player&&(unsigned)((player->mo->state - states)- S_PLAY_RUN1) < 4)
  192. P_SetMobjState (player->mo, S_PLAY);
  193. mo->momx = 0;
  194. mo->momy = 0;
  195. }
  196. else
  197. {
  198. mo->momx = FixedMul (mo->momx, FRICTION);
  199. mo->momy = FixedMul (mo->momy, FRICTION);
  200. }
  201. }
  202. //
  203. // P_ZMovement
  204. //
  205. void P_ZMovement (mobj_t* mo)
  206. {
  207. fixed_t dist;
  208. fixed_t delta;
  209. // check for smooth step up
  210. if (mo->player && mo->z < mo->floorz)
  211. {
  212. mo->player->viewheight -= mo->floorz-mo->z;
  213. mo->player->deltaviewheight
  214. = (VIEWHEIGHT - mo->player->viewheight)>>3;
  215. }
  216. // adjust height
  217. mo->z += mo->momz;
  218. if ( mo->flags & MF_FLOAT
  219. && mo->target)
  220. {
  221. // float down towards target if too close
  222. if ( !(mo->flags & MF_SKULLFLY)
  223. && !(mo->flags & MF_INFLOAT) )
  224. {
  225. dist = P_AproxDistance (mo->x - mo->target->x,
  226. mo->y - mo->target->y);
  227. delta =(mo->target->z + (mo->height>>1)) - mo->z;
  228. if (delta<0 && dist < -(delta*3) )
  229. mo->z -= FLOATSPEED;
  230. else if (delta>0 && dist < (delta*3) )
  231. mo->z += FLOATSPEED;
  232. }
  233. }
  234. // clip movement
  235. if (mo->z <= mo->floorz)
  236. {
  237. // hit the floor
  238. // Note (id):
  239. // somebody left this after the setting momz to 0,
  240. // kinda useless there.
  241. if (mo->flags & MF_SKULLFLY)
  242. {
  243. // the skull slammed into something
  244. mo->momz = -mo->momz;
  245. }
  246. if (mo->momz < 0)
  247. {
  248. if (mo->player
  249. && mo->momz < -GRAVITY*8)
  250. {
  251. // Squat down.
  252. // Decrease viewheight for a moment
  253. // after hitting the ground (hard),
  254. // and utter appropriate sound.
  255. mo->player->deltaviewheight = mo->momz>>3;
  256. S_StartSound (mo, sfx_oof);
  257. }
  258. mo->momz = 0;
  259. }
  260. mo->z = mo->floorz;
  261. if ( (mo->flags & MF_MISSILE)
  262. && !(mo->flags & MF_NOCLIP) )
  263. {
  264. P_ExplodeMissile (mo);
  265. return;
  266. }
  267. }
  268. else if (! (mo->flags & MF_NOGRAVITY) )
  269. {
  270. if (mo->momz == 0)
  271. mo->momz = -GRAVITY*2;
  272. else
  273. mo->momz -= GRAVITY;
  274. }
  275. if (mo->z + mo->height > mo->ceilingz)
  276. {
  277. // hit the ceiling
  278. if (mo->momz > 0)
  279. mo->momz = 0;
  280. {
  281. mo->z = mo->ceilingz - mo->height;
  282. }
  283. if (mo->flags & MF_SKULLFLY)
  284. { // the skull slammed into something
  285. mo->momz = -mo->momz;
  286. }
  287. if ( (mo->flags & MF_MISSILE)
  288. && !(mo->flags & MF_NOCLIP) )
  289. {
  290. P_ExplodeMissile (mo);
  291. return;
  292. }
  293. }
  294. }
  295. //
  296. // P_NightmareRespawn
  297. //
  298. void
  299. P_NightmareRespawn (mobj_t* mobj)
  300. {
  301. fixed_t x;
  302. fixed_t y;
  303. fixed_t z;
  304. subsector_t* ss;
  305. mobj_t* mo;
  306. mapthing_t* mthing;
  307. x = mobj->spawnpoint.x << FRACBITS;
  308. y = mobj->spawnpoint.y << FRACBITS;
  309. // somthing is occupying it's position?
  310. if (!P_CheckPosition (mobj, x, y) )
  311. return; // no respwan
  312. // spawn a teleport fog at old spot
  313. // because of removal of the body?
  314. mo = P_SpawnMobj (mobj->x,
  315. mobj->y,
  316. mobj->subsector->sector->floorheight , MT_TFOG);
  317. // initiate teleport sound
  318. S_StartSound (mo, sfx_telept);
  319. // spawn a teleport fog at the new spot
  320. ss = R_PointInSubsector (x,y);
  321. mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_TFOG);
  322. S_StartSound (mo, sfx_telept);
  323. // spawn the new monster
  324. mthing = &mobj->spawnpoint;
  325. // spawn it
  326. if (mobj->info->flags & MF_SPAWNCEILING)
  327. z = ONCEILINGZ;
  328. else
  329. z = ONFLOORZ;
  330. // inherit attributes from deceased one
  331. mo = P_SpawnMobj (x,y,z, mobj->type);
  332. mo->spawnpoint = mobj->spawnpoint;
  333. mo->angle = ANG45 * (mthing->angle/45);
  334. if (mthing->options & MTF_AMBUSH)
  335. mo->flags |= MF_AMBUSH;
  336. mo->reactiontime = 18;
  337. // remove the old monster,
  338. P_RemoveMobj (mobj);
  339. }
  340. //
  341. // P_MobjThinker
  342. //
  343. void P_MobjThinker (mobj_t* mobj)
  344. {
  345. // momentum movement
  346. if (mobj->momx
  347. || mobj->momy
  348. || (mobj->flags&MF_SKULLFLY) )
  349. {
  350. P_XYMovement (mobj);
  351. // FIXME: decent NOP/NULL/Nil function pointer please.
  352. if (mobj->thinker.function.acv == (actionf_v) (-1))
  353. return; // mobj was removed
  354. }
  355. if ( (mobj->z != mobj->floorz)
  356. || mobj->momz )
  357. {
  358. P_ZMovement (mobj);
  359. // FIXME: decent NOP/NULL/Nil function pointer please.
  360. if (mobj->thinker.function.acv == (actionf_v) (-1))
  361. return; // mobj was removed
  362. }
  363. // cycle through states,
  364. // calling action functions at transitions
  365. if (mobj->tics != -1)
  366. {
  367. mobj->tics--;
  368. // you can cycle through multiple states in a tic
  369. if (!mobj->tics)
  370. if (!P_SetMobjState (mobj, mobj->state->nextstate) )
  371. return; // freed itself
  372. }
  373. else
  374. {
  375. // check for nightmare respawn
  376. if (! (mobj->flags & MF_COUNTKILL) )
  377. return;
  378. if (!respawnmonsters)
  379. return;
  380. mobj->movecount++;
  381. if (mobj->movecount < 12*35)
  382. return;
  383. if ( leveltime&31 )
  384. return;
  385. if (P_Random () > 4)
  386. return;
  387. P_NightmareRespawn (mobj);
  388. }
  389. }
  390. //
  391. // P_SpawnMobj
  392. //
  393. mobj_t*
  394. P_SpawnMobj
  395. ( fixed_t x,
  396. fixed_t y,
  397. fixed_t z,
  398. mobjtype_t type )
  399. {
  400. mobj_t* mobj;
  401. state_t* st;
  402. mobjinfo_t* info;
  403. mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
  404. memset (mobj, 0, sizeof (*mobj));
  405. info = &mobjinfo[type];
  406. mobj->type = type;
  407. mobj->info = info;
  408. mobj->x = x;
  409. mobj->y = y;
  410. mobj->radius = info->radius;
  411. mobj->height = info->height;
  412. mobj->flags = info->flags;
  413. mobj->health = info->spawnhealth;
  414. if (gameskill != sk_nightmare)
  415. mobj->reactiontime = info->reactiontime;
  416. mobj->lastlook = P_Random () % MAXPLAYERS;
  417. // do not set the state with P_SetMobjState,
  418. // because action routines can not be called yet
  419. st = &states[info->spawnstate];
  420. mobj->state = st;
  421. mobj->tics = st->tics;
  422. mobj->sprite = st->sprite;
  423. mobj->frame = st->frame;
  424. // set subsector and/or block links
  425. P_SetThingPosition (mobj);
  426. mobj->floorz = mobj->subsector->sector->floorheight;
  427. mobj->ceilingz = mobj->subsector->sector->ceilingheight;
  428. if (z == ONFLOORZ)
  429. mobj->z = mobj->floorz;
  430. else if (z == ONCEILINGZ)
  431. mobj->z = mobj->ceilingz - mobj->info->height;
  432. else
  433. mobj->z = z;
  434. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
  435. P_AddThinker (&mobj->thinker);
  436. return mobj;
  437. }
  438. //
  439. // P_RemoveMobj
  440. //
  441. mapthing_t itemrespawnque[ITEMQUESIZE];
  442. int itemrespawntime[ITEMQUESIZE];
  443. int iquehead;
  444. int iquetail;
  445. void P_RemoveMobj (mobj_t* mobj)
  446. {
  447. if ((mobj->flags & MF_SPECIAL)
  448. && !(mobj->flags & MF_DROPPED)
  449. && (mobj->type != MT_INV)
  450. && (mobj->type != MT_INS))
  451. {
  452. itemrespawnque[iquehead] = mobj->spawnpoint;
  453. itemrespawntime[iquehead] = leveltime;
  454. iquehead = (iquehead+1)&(ITEMQUESIZE-1);
  455. // lose one off the end?
  456. if (iquehead == iquetail)
  457. iquetail = (iquetail+1)&(ITEMQUESIZE-1);
  458. }
  459. // unlink from sector and block lists
  460. P_UnsetThingPosition (mobj);
  461. // stop any playing sound
  462. S_StopSound (mobj);
  463. // free block
  464. P_RemoveThinker ((thinker_t*)mobj);
  465. }
  466. //
  467. // P_RespawnSpecials
  468. //
  469. void P_RespawnSpecials (void)
  470. {
  471. fixed_t x;
  472. fixed_t y;
  473. fixed_t z;
  474. subsector_t* ss;
  475. mobj_t* mo;
  476. mapthing_t* mthing;
  477. int i;
  478. // only respawn items in deathmatch
  479. if (deathmatch != 2)
  480. return; //
  481. // nothing left to respawn?
  482. if (iquehead == iquetail)
  483. return;
  484. // wait at least 30 seconds
  485. if (leveltime - itemrespawntime[iquetail] < 30*35)
  486. return;
  487. mthing = &itemrespawnque[iquetail];
  488. x = mthing->x << FRACBITS;
  489. y = mthing->y << FRACBITS;
  490. // spawn a teleport fog at the new spot
  491. ss = R_PointInSubsector (x,y);
  492. mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG);
  493. S_StartSound (mo, sfx_itmbk);
  494. // find which type to spawn
  495. for (i=0 ; i< NUMMOBJTYPES ; i++)
  496. {
  497. if (mthing->type == mobjinfo[i].doomednum)
  498. break;
  499. }
  500. // spawn it
  501. if (mobjinfo[i].flags & MF_SPAWNCEILING)
  502. z = ONCEILINGZ;
  503. else
  504. z = ONFLOORZ;
  505. mo = P_SpawnMobj (x,y,z, i);
  506. mo->spawnpoint = *mthing;
  507. mo->angle = ANG45 * (mthing->angle/45);
  508. // pull it from the que
  509. iquetail = (iquetail+1)&(ITEMQUESIZE-1);
  510. }
  511. //
  512. // P_SpawnPlayer
  513. // Called when a player is spawned on the level.
  514. // Most of the player structure stays unchanged
  515. // between levels.
  516. //
  517. void P_SpawnPlayer (mapthing_t* mthing)
  518. {
  519. player_t* p;
  520. fixed_t x;
  521. fixed_t y;
  522. fixed_t z;
  523. mobj_t* mobj;
  524. int i;
  525. // not playing?
  526. if (!playeringame[mthing->type-1])
  527. return;
  528. p = &players[mthing->type-1];
  529. if (p->playerstate == PST_REBORN)
  530. G_PlayerReborn (mthing->type-1);
  531. x = mthing->x << FRACBITS;
  532. y = mthing->y << FRACBITS;
  533. z = ONFLOORZ;
  534. mobj = P_SpawnMobj (x,y,z, MT_PLAYER);
  535. // set color translations for player sprites
  536. if (mthing->type > 1)
  537. mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
  538. mobj->angle = ANG45 * (mthing->angle/45);
  539. mobj->player = p;
  540. mobj->health = p->health;
  541. p->mo = mobj;
  542. p->playerstate = PST_LIVE;
  543. p->refire = 0;
  544. p->message = NULL;
  545. p->damagecount = 0;
  546. p->bonuscount = 0;
  547. p->extralight = 0;
  548. p->fixedcolormap = 0;
  549. p->viewheight = VIEWHEIGHT;
  550. // setup gun psprite
  551. P_SetupPsprites (p);
  552. // give all cards in death match mode
  553. if (deathmatch)
  554. for (i=0 ; i<NUMCARDS ; i++)
  555. p->cards[i] = true;
  556. if (mthing->type-1 == consoleplayer)
  557. {
  558. // wake up the status bar
  559. ST_Start ();
  560. // wake up the heads up text
  561. HU_Start ();
  562. }
  563. }
  564. //
  565. // P_SpawnMapThing
  566. // The fields of the mapthing should
  567. // already be in host byte order.
  568. //
  569. void P_SpawnMapThing (mapthing_t* mthing)
  570. {
  571. int i;
  572. int bit;
  573. mobj_t* mobj;
  574. fixed_t x;
  575. fixed_t y;
  576. fixed_t z;
  577. // count deathmatch start positions
  578. if (mthing->type == 11)
  579. {
  580. if (deathmatch_p < &deathmatchstarts[10])
  581. {
  582. memcpy (deathmatch_p, mthing, sizeof(*mthing));
  583. deathmatch_p++;
  584. }
  585. return;
  586. }
  587. // check for players specially
  588. if (mthing->type <= 4)
  589. {
  590. // save spots for respawning in network games
  591. playerstarts[mthing->type-1] = *mthing;
  592. if (!deathmatch)
  593. P_SpawnPlayer (mthing);
  594. return;
  595. }
  596. // check for apropriate skill level
  597. if (!netgame && (mthing->options & 16) )
  598. return;
  599. if (gameskill == sk_baby)
  600. bit = 1;
  601. else if (gameskill == sk_nightmare)
  602. bit = 4;
  603. else
  604. bit = 1<<(gameskill-1);
  605. if (!(mthing->options & bit) )
  606. return;
  607. // find which type to spawn
  608. for (i=0 ; i< NUMMOBJTYPES ; i++)
  609. if (mthing->type == mobjinfo[i].doomednum)
  610. break;
  611. if (i==NUMMOBJTYPES)
  612. I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",
  613. mthing->type,
  614. mthing->x, mthing->y);
  615. // don't spawn keycards and players in deathmatch
  616. if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
  617. return;
  618. // don't spawn any monsters if -nomonsters
  619. if (nomonsters
  620. && ( i == MT_SKULL
  621. || (mobjinfo[i].flags & MF_COUNTKILL)) )
  622. {
  623. return;
  624. }
  625. // spawn it
  626. x = mthing->x << FRACBITS;
  627. y = mthing->y << FRACBITS;
  628. if (mobjinfo[i].flags & MF_SPAWNCEILING)
  629. z = ONCEILINGZ;
  630. else
  631. z = ONFLOORZ;
  632. mobj = P_SpawnMobj (x,y,z, i);
  633. mobj->spawnpoint = *mthing;
  634. if (mobj->tics > 0)
  635. mobj->tics = 1 + (P_Random () % mobj->tics);
  636. if (mobj->flags & MF_COUNTKILL)
  637. totalkills++;
  638. if (mobj->flags & MF_COUNTITEM)
  639. totalitems++;
  640. mobj->angle = ANG45 * (mthing->angle/45);
  641. if (mthing->options & MTF_AMBUSH)
  642. mobj->flags |= MF_AMBUSH;
  643. }
  644. //
  645. // GAME SPAWN FUNCTIONS
  646. //
  647. //
  648. // P_SpawnPuff
  649. //
  650. extern fixed_t attackrange;
  651. void
  652. P_SpawnPuff
  653. ( fixed_t x,
  654. fixed_t y,
  655. fixed_t z )
  656. {
  657. mobj_t* th;
  658. z += ((P_Random()-P_Random())<<10);
  659. th = P_SpawnMobj (x,y,z, MT_PUFF);
  660. th->momz = FRACUNIT;
  661. th->tics -= P_Random()&3;
  662. if (th->tics < 1)
  663. th->tics = 1;
  664. // don't make punches spark on the wall
  665. if (attackrange == MELEERANGE)
  666. P_SetMobjState (th, S_PUFF3);
  667. }
  668. //
  669. // P_SpawnBlood
  670. //
  671. void
  672. P_SpawnBlood
  673. ( fixed_t x,
  674. fixed_t y,
  675. fixed_t z,
  676. int damage )
  677. {
  678. mobj_t* th;
  679. z += ((P_Random()-P_Random())<<10);
  680. th = P_SpawnMobj (x,y,z, MT_BLOOD);
  681. th->momz = FRACUNIT*2;
  682. th->tics -= P_Random()&3;
  683. if (th->tics < 1)
  684. th->tics = 1;
  685. if (damage <= 12 && damage >= 9)
  686. P_SetMobjState (th,S_BLOOD2);
  687. else if (damage < 9)
  688. P_SetMobjState (th,S_BLOOD3);
  689. }
  690. //
  691. // P_CheckMissileSpawn
  692. // Moves the missile forward a bit
  693. // and possibly explodes it right there.
  694. //
  695. void P_CheckMissileSpawn (mobj_t* th)
  696. {
  697. th->tics -= P_Random()&3;
  698. if (th->tics < 1)
  699. th->tics = 1;
  700. // move a little forward so an angle can
  701. // be computed if it immediately explodes
  702. th->x += (th->momx>>1);
  703. th->y += (th->momy>>1);
  704. th->z += (th->momz>>1);
  705. if (!P_TryMove (th, th->x, th->y))
  706. P_ExplodeMissile (th);
  707. }
  708. //
  709. // P_SpawnMissile
  710. //
  711. mobj_t*
  712. P_SpawnMissile
  713. ( mobj_t* source,
  714. mobj_t* dest,
  715. mobjtype_t type )
  716. {
  717. mobj_t* th;
  718. angle_t an;
  719. int dist;
  720. th = P_SpawnMobj (source->x,
  721. source->y,
  722. source->z + 4*8*FRACUNIT, type);
  723. if (th->info->seesound)
  724. S_StartSound (th, th->info->seesound);
  725. th->target = source; // where it came from
  726. an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);
  727. // fuzzy player
  728. if (dest->flags & MF_SHADOW)
  729. an += (P_Random()-P_Random())<<20;
  730. th->angle = an;
  731. an >>= ANGLETOFINESHIFT;
  732. th->momx = FixedMul (th->info->speed, finecosine[an]);
  733. th->momy = FixedMul (th->info->speed, finesine[an]);
  734. dist = P_AproxDistance (dest->x - source->x, dest->y - source->y);
  735. dist = dist / th->info->speed;
  736. if (dist < 1)
  737. dist = 1;
  738. th->momz = (dest->z - source->z) / dist;
  739. P_CheckMissileSpawn (th);
  740. return th;
  741. }
  742. //
  743. // P_SpawnPlayerMissile
  744. // Tries to aim at a nearby monster
  745. //
  746. void
  747. P_SpawnPlayerMissile
  748. ( mobj_t* source,
  749. mobjtype_t type )
  750. {
  751. mobj_t* th;
  752. angle_t an;
  753. fixed_t x;
  754. fixed_t y;
  755. fixed_t z;
  756. fixed_t slope;
  757. // see which target is to be aimed at
  758. an = source->angle;
  759. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  760. if (!linetarget)
  761. {
  762. an += 1<<26;
  763. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  764. if (!linetarget)
  765. {
  766. an -= 2<<26;
  767. slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  768. }
  769. if (!linetarget)
  770. {
  771. an = source->angle;
  772. slope = 0;
  773. }
  774. }
  775. x = source->x;
  776. y = source->y;
  777. z = source->z + 4*8*FRACUNIT;
  778. th = P_SpawnMobj (x,y,z, type);
  779. if (th->info->seesound)
  780. S_StartSound (th, th->info->seesound);
  781. th->target = source;
  782. th->angle = an;
  783. th->momx = FixedMul( th->info->speed,
  784. finecosine[an>>ANGLETOFINESHIFT]);
  785. th->momy = FixedMul( th->info->speed,
  786. finesine[an>>ANGLETOFINESHIFT]);
  787. th->momz = FixedMul( th->info->speed, slope);
  788. P_CheckMissileSpawn (th);
  789. }