p_mobj.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:20k
源码类别:

射击游戏

开发平台:

Visual C++

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