Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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