p_mobj.cpp 19 KB

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