home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / source / linuxdoom-1.10 / p_mobj.c < prev    next >
C/C++ Source or Header  |  1997-12-22  |  19KB  |  989 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. void P_MobjThinker (mobj_t* mobj)
  415. {
  416.     // momentum movement
  417.     if (mobj->momx
  418.     || mobj->momy
  419.     || (mobj->flags&MF_SKULLFLY) )
  420.     {
  421.     P_XYMovement (mobj);
  422.  
  423.     // FIXME: decent NOP/NULL/Nil function pointer please.
  424.     if (mobj->thinker.function.acv == (actionf_v) (-1))
  425.         return;        // mobj was removed
  426.     }
  427.     if ( (mobj->z != mobj->floorz)
  428.      || mobj->momz )
  429.     {
  430.     P_ZMovement (mobj);
  431.     
  432.     // FIXME: decent NOP/NULL/Nil function pointer please.
  433.     if (mobj->thinker.function.acv == (actionf_v) (-1))
  434.         return;        // mobj was removed
  435.     }
  436.  
  437.     
  438.     // cycle through states,
  439.     // calling action functions at transitions
  440.     if (mobj->tics != -1)
  441.     {
  442.     mobj->tics--;
  443.         
  444.     // you can cycle through multiple states in a tic
  445.     if (!mobj->tics)
  446.         if (!P_SetMobjState (mobj, mobj->state->nextstate) )
  447.         return;        // freed itself
  448.     }
  449.     else
  450.     {
  451.     // check for nightmare respawn
  452.     if (! (mobj->flags & MF_COUNTKILL) )
  453.         return;
  454.  
  455.     if (!respawnmonsters)
  456.         return;
  457.  
  458.     mobj->movecount++;
  459.  
  460.     if (mobj->movecount < 12*35)
  461.         return;
  462.  
  463.     if ( leveltime&31 )
  464.         return;
  465.  
  466.     if (P_Random () > 4)
  467.         return;
  468.  
  469.     P_NightmareRespawn (mobj);
  470.     }
  471.  
  472. }
  473.  
  474.  
  475. //
  476. // P_SpawnMobj
  477. //
  478. mobj_t*
  479. P_SpawnMobj
  480. ( fixed_t    x,
  481.   fixed_t    y,
  482.   fixed_t    z,
  483.   mobjtype_t    type )
  484. {
  485.     mobj_t*    mobj;
  486.     state_t*    st;
  487.     mobjinfo_t*    info;
  488.     
  489.     mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
  490.     memset (mobj, 0, sizeof (*mobj));
  491.     info = &mobjinfo[type];
  492.     
  493.     mobj->type = type;
  494.     mobj->info = info;
  495.     mobj->x = x;
  496.     mobj->y = y;
  497.     mobj->radius = info->radius;
  498.     mobj->height = info->height;
  499.     mobj->flags = info->flags;
  500.     mobj->health = info->spawnhealth;
  501.  
  502.     if (gameskill != sk_nightmare)
  503.     mobj->reactiontime = info->reactiontime;
  504.     
  505.     mobj->lastlook = P_Random () % MAXPLAYERS;
  506.     // do not set the state with P_SetMobjState,
  507.     // because action routines can not be called yet
  508.     st = &states[info->spawnstate];
  509.  
  510.     mobj->state = st;
  511.     mobj->tics = st->tics;
  512.     mobj->sprite = st->sprite;
  513.     mobj->frame = st->frame;
  514.  
  515.     // set subsector and/or block links
  516.     P_SetThingPosition (mobj);
  517.     
  518.     mobj->floorz = mobj->subsector->sector->floorheight;
  519.     mobj->ceilingz = mobj->subsector->sector->ceilingheight;
  520.  
  521.     if (z == ONFLOORZ)
  522.     mobj->z = mobj->floorz;
  523.     else if (z == ONCEILINGZ)
  524.     mobj->z = mobj->ceilingz - mobj->info->height;
  525.     else 
  526.     mobj->z = z;
  527.  
  528.     mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
  529.     
  530.     P_AddThinker (&mobj->thinker);
  531.  
  532.     return mobj;
  533. }
  534.  
  535.  
  536. //
  537. // P_RemoveMobj
  538. //
  539. mapthing_t    itemrespawnque[ITEMQUESIZE];
  540. int        itemrespawntime[ITEMQUESIZE];
  541. int        iquehead;
  542. int        iquetail;
  543.  
  544.  
  545. void P_RemoveMobj (mobj_t* mobj)
  546. {
  547.     if ((mobj->flags & MF_SPECIAL)
  548.     && !(mobj->flags & MF_DROPPED)
  549.     && (mobj->type != MT_INV)
  550.     && (mobj->type != MT_INS))
  551.     {
  552.     itemrespawnque[iquehead] = mobj->spawnpoint;
  553.     itemrespawntime[iquehead] = leveltime;
  554.     iquehead = (iquehead+1)&(ITEMQUESIZE-1);
  555.  
  556.     // lose one off the end?
  557.     if (iquehead == iquetail)
  558.         iquetail = (iquetail+1)&(ITEMQUESIZE-1);
  559.     }
  560.     
  561.     // unlink from sector and block lists
  562.     P_UnsetThingPosition (mobj);
  563.     
  564.     // stop any playing sound
  565.     S_StopSound (mobj);
  566.     
  567.     // free block
  568.     P_RemoveThinker ((thinker_t*)mobj);
  569. }
  570.  
  571.  
  572.  
  573.  
  574. //
  575. // P_RespawnSpecials
  576. //
  577. void P_RespawnSpecials (void)
  578. {
  579.     fixed_t        x;
  580.     fixed_t        y;
  581.     fixed_t        z;
  582.     
  583.     subsector_t*    ss; 
  584.     mobj_t*        mo;
  585.     mapthing_t*        mthing;
  586.     
  587.     int            i;
  588.  
  589.     // only respawn items in deathmatch
  590.     if (deathmatch != 2)
  591.     return;    // 
  592.  
  593.     // nothing left to respawn?
  594.     if (iquehead == iquetail)
  595.     return;        
  596.  
  597.     // wait at least 30 seconds
  598.     if (leveltime - itemrespawntime[iquetail] < 30*35)
  599.     return;            
  600.  
  601.     mthing = &itemrespawnque[iquetail];
  602.     
  603.     x = mthing->x << FRACBITS; 
  604.     y = mthing->y << FRACBITS; 
  605.       
  606.     // spawn a teleport fog at the new spot
  607.     ss = R_PointInSubsector (x,y); 
  608.     mo = P_SpawnMobj (x, y, ss->sector->floorheight , MT_IFOG); 
  609.     S_StartSound (mo, sfx_itmbk);
  610.  
  611.     // find which type to spawn
  612.     for (i=0 ; i< NUMMOBJTYPES ; i++)
  613.     {
  614.     if (mthing->type == mobjinfo[i].doomednum)
  615.         break;
  616.     }
  617.     
  618.     // spawn it
  619.     if (mobjinfo[i].flags & MF_SPAWNCEILING)
  620.     z = ONCEILINGZ;
  621.     else
  622.     z = ONFLOORZ;
  623.  
  624.     mo = P_SpawnMobj (x,y,z, i);
  625.     mo->spawnpoint = *mthing;    
  626.     mo->angle = ANG45 * (mthing->angle/45);
  627.  
  628.     // pull it from the que
  629.     iquetail = (iquetail+1)&(ITEMQUESIZE-1);
  630. }
  631.  
  632.  
  633.  
  634.  
  635. //
  636. // P_SpawnPlayer
  637. // Called when a player is spawned on the level.
  638. // Most of the player structure stays unchanged
  639. //  between levels.
  640. //
  641. void P_SpawnPlayer (mapthing_t* mthing)
  642. {
  643.     player_t*        p;
  644.     fixed_t        x;
  645.     fixed_t        y;
  646.     fixed_t        z;
  647.  
  648.     mobj_t*        mobj;
  649.  
  650.     int            i;
  651.  
  652.     // not playing?
  653.     if (!playeringame[mthing->type-1])
  654.     return;                    
  655.         
  656.     p = &players[mthing->type-1];
  657.  
  658.     if (p->playerstate == PST_REBORN)
  659.     G_PlayerReborn (mthing->type-1);
  660.  
  661.     x         = mthing->x << FRACBITS;
  662.     y         = mthing->y << FRACBITS;
  663.     z        = ONFLOORZ;
  664.     mobj    = P_SpawnMobj (x,y,z, MT_PLAYER);
  665.  
  666.     // set color translations for player sprites
  667.     if (mthing->type > 1)        
  668.     mobj->flags |= (mthing->type-1)<<MF_TRANSSHIFT;
  669.         
  670.     mobj->angle    = ANG45 * (mthing->angle/45);
  671.     mobj->player = p;
  672.     mobj->health = p->health;
  673.  
  674.     p->mo = mobj;
  675.     p->playerstate = PST_LIVE;    
  676.     p->refire = 0;
  677.     p->message = NULL;
  678.     p->damagecount = 0;
  679.     p->bonuscount = 0;
  680.     p->extralight = 0;
  681.     p->fixedcolormap = 0;
  682.     p->viewheight = VIEWHEIGHT;
  683.  
  684.     // setup gun psprite
  685.     P_SetupPsprites (p);
  686.     
  687.     // give all cards in death match mode
  688.     if (deathmatch)
  689.     for (i=0 ; i<NUMCARDS ; i++)
  690.         p->cards[i] = true;
  691.             
  692.     if (mthing->type-1 == consoleplayer)
  693.     {
  694.     // wake up the status bar
  695.     ST_Start ();
  696.     // wake up the heads up text
  697.     HU_Start ();        
  698.     }
  699. }
  700.  
  701.  
  702. //
  703. // P_SpawnMapThing
  704. // The fields of the mapthing should
  705. // already be in host byte order.
  706. //
  707. void P_SpawnMapThing (mapthing_t* mthing)
  708. {
  709.     int            i;
  710.     int            bit;
  711.     mobj_t*        mobj;
  712.     fixed_t        x;
  713.     fixed_t        y;
  714.     fixed_t        z;
  715.         
  716.     // count deathmatch start positions
  717.     if (mthing->type == 11)
  718.     {
  719.     if (deathmatch_p < &deathmatchstarts[10])
  720.     {
  721.         memcpy (deathmatch_p, mthing, sizeof(*mthing));
  722.         deathmatch_p++;
  723.     }
  724.     return;
  725.     }
  726.     
  727.     // check for players specially
  728.     if (mthing->type <= 4)
  729.     {
  730.     // save spots for respawning in network games
  731.     playerstarts[mthing->type-1] = *mthing;
  732.     if (!deathmatch)
  733.         P_SpawnPlayer (mthing);
  734.  
  735.     return;
  736.     }
  737.  
  738.     // check for apropriate skill level
  739.     if (!netgame && (mthing->options & 16) )
  740.     return;
  741.         
  742.     if (gameskill == sk_baby)
  743.     bit = 1;
  744.     else if (gameskill == sk_nightmare)
  745.     bit = 4;
  746.     else
  747.     bit = 1<<(gameskill-1);
  748.  
  749.     if (!(mthing->options & bit) )
  750.     return;
  751.     
  752.     // find which type to spawn
  753.     for (i=0 ; i< NUMMOBJTYPES ; i++)
  754.     if (mthing->type == mobjinfo[i].doomednum)
  755.         break;
  756.     
  757.     if (i==NUMMOBJTYPES)
  758.     I_Error ("P_SpawnMapThing: Unknown type %i at (%i, %i)",
  759.          mthing->type,
  760.          mthing->x, mthing->y);
  761.         
  762.     // don't spawn keycards and players in deathmatch
  763.     if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH)
  764.     return;
  765.         
  766.     // don't spawn any monsters if -nomonsters
  767.     if (nomonsters
  768.     && ( i == MT_SKULL
  769.          || (mobjinfo[i].flags & MF_COUNTKILL)) )
  770.     {
  771.     return;
  772.     }
  773.     
  774.     // spawn it
  775.     x = mthing->x << FRACBITS;
  776.     y = mthing->y << FRACBITS;
  777.  
  778.     if (mobjinfo[i].flags & MF_SPAWNCEILING)
  779.     z = ONCEILINGZ;
  780.     else
  781.     z = ONFLOORZ;
  782.     
  783.     mobj = P_SpawnMobj (x,y,z, i);
  784.     mobj->spawnpoint = *mthing;
  785.  
  786.     if (mobj->tics > 0)
  787.     mobj->tics = 1 + (P_Random () % mobj->tics);
  788.     if (mobj->flags & MF_COUNTKILL)
  789.     totalkills++;
  790.     if (mobj->flags & MF_COUNTITEM)
  791.     totalitems++;
  792.         
  793.     mobj->angle = ANG45 * (mthing->angle/45);
  794.     if (mthing->options & MTF_AMBUSH)
  795.     mobj->flags |= MF_AMBUSH;
  796. }
  797.  
  798.  
  799.  
  800. //
  801. // GAME SPAWN FUNCTIONS
  802. //
  803.  
  804.  
  805. //
  806. // P_SpawnPuff
  807. //
  808. extern fixed_t attackrange;
  809.  
  810. void
  811. P_SpawnPuff
  812. ( fixed_t    x,
  813.   fixed_t    y,
  814.   fixed_t    z )
  815. {
  816.     mobj_t*    th;
  817.     
  818.     z += ((P_Random()-P_Random())<<10);
  819.  
  820.     th = P_SpawnMobj (x,y,z, MT_PUFF);
  821.     th->momz = FRACUNIT;
  822.     th->tics -= P_Random()&3;
  823.  
  824.     if (th->tics < 1)
  825.     th->tics = 1;
  826.     
  827.     // don't make punches spark on the wall
  828.     if (attackrange == MELEERANGE)
  829.     P_SetMobjState (th, S_PUFF3);
  830. }
  831.  
  832.  
  833.  
  834. //
  835. // P_SpawnBlood
  836. // 
  837. void
  838. P_SpawnBlood
  839. ( fixed_t    x,
  840.   fixed_t    y,
  841.   fixed_t    z,
  842.   int        damage )
  843. {
  844.     mobj_t*    th;
  845.     
  846.     z += ((P_Random()-P_Random())<<10);
  847.     th = P_SpawnMobj (x,y,z, MT_BLOOD);
  848.     th->momz = FRACUNIT*2;
  849.     th->tics -= P_Random()&3;
  850.  
  851.     if (th->tics < 1)
  852.     th->tics = 1;
  853.         
  854.     if (damage <= 12 && damage >= 9)
  855.     P_SetMobjState (th,S_BLOOD2);
  856.     else if (damage < 9)
  857.     P_SetMobjState (th,S_BLOOD3);
  858. }
  859.  
  860.  
  861.  
  862. //
  863. // P_CheckMissileSpawn
  864. // Moves the missile forward a bit
  865. //  and possibly explodes it right there.
  866. //
  867. void P_CheckMissileSpawn (mobj_t* th)
  868. {
  869.     th->tics -= P_Random()&3;
  870.     if (th->tics < 1)
  871.     th->tics = 1;
  872.     
  873.     // move a little forward so an angle can
  874.     // be computed if it immediately explodes
  875.     th->x += (th->momx>>1);
  876.     th->y += (th->momy>>1);
  877.     th->z += (th->momz>>1);
  878.  
  879.     if (!P_TryMove (th, th->x, th->y))
  880.     P_ExplodeMissile (th);
  881. }
  882.  
  883.  
  884. //
  885. // P_SpawnMissile
  886. //
  887. mobj_t*
  888. P_SpawnMissile
  889. ( mobj_t*    source,
  890.   mobj_t*    dest,
  891.   mobjtype_t    type )
  892. {
  893.     mobj_t*    th;
  894.     angle_t    an;
  895.     int        dist;
  896.  
  897.     th = P_SpawnMobj (source->x,
  898.               source->y,
  899.               source->z + 4*8*FRACUNIT, type);
  900.     
  901.     if (th->info->seesound)
  902.     S_StartSound (th, th->info->seesound);
  903.  
  904.     th->target = source;    // where it came from
  905.     an = R_PointToAngle2 (source->x, source->y, dest->x, dest->y);    
  906.  
  907.     // fuzzy player
  908.     if (dest->flags & MF_SHADOW)
  909.     an += (P_Random()-P_Random())<<20;    
  910.  
  911.     th->angle = an;
  912.     an >>= ANGLETOFINESHIFT;
  913.     th->momx = FixedMul (th->info->speed, finecosine[an]);
  914.     th->momy = FixedMul (th->info->speed, finesine[an]);
  915.     
  916.     dist = P_AproxDistance (dest->x - source->x, dest->y - source->y);
  917.     dist = dist / th->info->speed;
  918.  
  919.     if (dist < 1)
  920.     dist = 1;
  921.  
  922.     th->momz = (dest->z - source->z) / dist;
  923.     P_CheckMissileSpawn (th);
  924.     
  925.     return th;
  926. }
  927.  
  928.  
  929. //
  930. // P_SpawnPlayerMissile
  931. // Tries to aim at a nearby monster
  932. //
  933. void
  934. P_SpawnPlayerMissile
  935. ( mobj_t*    source,
  936.   mobjtype_t    type )
  937. {
  938.     mobj_t*    th;
  939.     angle_t    an;
  940.     
  941.     fixed_t    x;
  942.     fixed_t    y;
  943.     fixed_t    z;
  944.     fixed_t    slope;
  945.     
  946.     // see which target is to be aimed at
  947.     an = source->angle;
  948.     slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  949.     
  950.     if (!linetarget)
  951.     {
  952.     an += 1<<26;
  953.     slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  954.  
  955.     if (!linetarget)
  956.     {
  957.         an -= 2<<26;
  958.         slope = P_AimLineAttack (source, an, 16*64*FRACUNIT);
  959.     }
  960.  
  961.     if (!linetarget)
  962.     {
  963.         an = source->angle;
  964.         slope = 0;
  965.     }
  966.     }
  967.         
  968.     x = source->x;
  969.     y = source->y;
  970.     z = source->z + 4*8*FRACUNIT;
  971.     
  972.     th = P_SpawnMobj (x,y,z, type);
  973.  
  974.     if (th->info->seesound)
  975.     S_StartSound (th, th->info->seesound);
  976.  
  977.     th->target = source;
  978.     th->angle = an;
  979.     th->momx = FixedMul( th->info->speed,
  980.              finecosine[an>>ANGLETOFINESHIFT]);
  981.     th->momy = FixedMul( th->info->speed,
  982.              finesine[an>>ANGLETOFINESHIFT]);
  983.     th->momz = FixedMul( th->info->speed, slope);
  984.  
  985.     P_CheckMissileSpawn (th);
  986. }
  987.  
  988.