home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -screenplay- / otherstuff / adoomppc_src / p_mobj.c < prev    next >
C/C++ Source or Header  |  1998-04-23  |  19KB  |  993 lines

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