home *** CD-ROM | disk | FTP | other *** search
/ 100 af Verdens Bedste Spil / 100Spil.iso / dos / wolf3d / source / wolfsrc.1 / WL_STATE.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  27KB  |  1,481 lines

  1. // WL_STATE.C
  2.  
  3. #include "WL_DEF.H"
  4. #pragma hdrstop
  5.  
  6. /*
  7. =============================================================================
  8.  
  9.                          LOCAL CONSTANTS
  10.  
  11. =============================================================================
  12. */
  13.  
  14.  
  15. /*
  16. =============================================================================
  17.  
  18.                          GLOBAL VARIABLES
  19.  
  20. =============================================================================
  21. */
  22.  
  23.  
  24. dirtype opposite[9] =
  25.     {west,southwest,south,southeast,east,northeast,north,northwest,nodir};
  26.  
  27. dirtype diagonal[9][9] =
  28. {
  29. /* east */    {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
  30.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  31. /* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
  32.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  33. /* west */  {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
  34.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  35. /* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
  36.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
  37.             {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
  38. };
  39.  
  40.  
  41.  
  42. void    SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);
  43. void    NewState (objtype *ob, statetype *state);
  44.  
  45. boolean TryWalk (objtype *ob);
  46. void    MoveObj (objtype *ob, long move);
  47.  
  48. void    KillActor (objtype *ob);
  49. void    DamageActor (objtype *ob, unsigned damage);
  50.  
  51. boolean CheckLine (objtype *ob);
  52. void FirstSighting (objtype *ob);
  53. boolean    CheckSight (objtype *ob);
  54.  
  55. /*
  56. =============================================================================
  57.  
  58.                          LOCAL VARIABLES
  59.  
  60. =============================================================================
  61. */
  62.  
  63.  
  64.  
  65. //===========================================================================
  66.  
  67.  
  68. /*
  69. ===================
  70. =
  71. = SpawnNewObj
  72. =
  73. = Spaws a new actor at the given TILE coordinates, with the given state, and
  74. = the given size in GLOBAL units.
  75. =
  76. = new            = a pointer to an initialized new actor
  77. =
  78. ===================
  79. */
  80.  
  81. void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)
  82. {
  83.     GetNewActor ();
  84.     new->state = state;
  85.     if (state->tictime)
  86.         new->ticcount = US_RndT () % state->tictime;
  87.     else
  88.         new->ticcount = 0;
  89.  
  90.     new->tilex = tilex;
  91.     new->tiley = tiley;
  92.     new->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;
  93.     new->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;
  94.     new->dir = nodir;
  95.  
  96.     actorat[tilex][tiley] = new;
  97.     new->areanumber =
  98.         *(mapsegs[0] + farmapylookup[new->tiley]+new->tilex) - AREATILE;
  99. }
  100.  
  101.  
  102.  
  103. /*
  104. ===================
  105. =
  106. = NewState
  107. =
  108. = Changes ob to a new state, setting ticcount to the max for that state
  109. =
  110. ===================
  111. */
  112.  
  113. void NewState (objtype *ob, statetype *state)
  114. {
  115.     ob->state = state;
  116.     ob->ticcount = state->tictime;
  117. }
  118.  
  119.  
  120.  
  121. /*
  122. =============================================================================
  123.  
  124.                 ENEMY TILE WORLD MOVEMENT CODE
  125.  
  126. =============================================================================
  127. */
  128.  
  129.  
  130. /*
  131. ==================================
  132. =
  133. = TryWalk
  134. =
  135. = Attempts to move ob in its current (ob->dir) direction.
  136. =
  137. = If blocked by either a wall or an actor returns FALSE
  138. =
  139. = If move is either clear or blocked only by a door, returns TRUE and sets
  140. =
  141. = ob->tilex            = new destination
  142. = ob->tiley
  143. = ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination
  144. = ob->distance      = TILEGLOBAl, or -doornumber if a door is blocking the way
  145. =
  146. = If a door is in the way, an OpenDoor call is made to start it opening.
  147. = The actor code should wait until
  148. =     doorobjlist[-ob->distance].action = dr_open, meaning the door has been
  149. =    fully opened
  150. =
  151. ==================================
  152. */
  153.  
  154. #define CHECKDIAG(x,y)                                \
  155. {                                                   \
  156.     temp=(unsigned)actorat[x][y];                   \
  157.     if (temp)                                       \
  158.     {                                               \
  159.         if (temp<256)                               \
  160.             return false;                           \
  161.         if (((objtype *)temp)->flags&FL_SHOOTABLE)  \
  162.             return false;                           \
  163.     }                                               \
  164. }
  165.  
  166. #define CHECKSIDE(x,y)                                \
  167. {                                                   \
  168.     temp=(unsigned)actorat[x][y];                   \
  169.     if (temp)                                       \
  170.     {                                               \
  171.         if (temp<128)                               \
  172.             return false;                           \
  173.         if (temp<256)                               \
  174.             doornum = temp&63;                      \
  175.         else if (((objtype *)temp)->flags&FL_SHOOTABLE)\
  176.             return false;                           \
  177.     }                                               \
  178. }
  179.  
  180.  
  181. boolean TryWalk (objtype *ob)
  182. {
  183.     int            doornum;
  184.     unsigned    temp;
  185.  
  186.     doornum = -1;
  187.  
  188.     if (ob->obclass == inertobj)
  189.     {
  190.         switch (ob->dir)
  191.         {
  192.         case north:
  193.             ob->tiley--;
  194.             break;
  195.  
  196.         case northeast:
  197.             ob->tilex++;
  198.             ob->tiley--;
  199.             break;
  200.  
  201.         case east:
  202.             ob->tilex++;
  203.             break;
  204.  
  205.         case southeast:
  206.             ob->tilex++;
  207.             ob->tiley++;
  208.             break;
  209.  
  210.         case south:
  211.             ob->tiley++;
  212.             break;
  213.  
  214.         case southwest:
  215.             ob->tilex--;
  216.             ob->tiley++;
  217.             break;
  218.  
  219.         case west:
  220.             ob->tilex--;
  221.             break;
  222.  
  223.         case northwest:
  224.             ob->tilex--;
  225.             ob->tiley--;
  226.             break;
  227.         }
  228.     }
  229.     else
  230.         switch (ob->dir)
  231.         {
  232.         case north:
  233.             if (ob->obclass == dogobj || ob->obclass == fakeobj)
  234.             {
  235.                 CHECKDIAG(ob->tilex,ob->tiley-1);
  236.             }
  237.             else
  238.             {
  239.                 CHECKSIDE(ob->tilex,ob->tiley-1);
  240.             }
  241.             ob->tiley--;
  242.             break;
  243.  
  244.         case northeast:
  245.             CHECKDIAG(ob->tilex+1,ob->tiley-1);
  246.             CHECKDIAG(ob->tilex+1,ob->tiley);
  247.             CHECKDIAG(ob->tilex,ob->tiley-1);
  248.             ob->tilex++;
  249.             ob->tiley--;
  250.             break;
  251.  
  252.         case east:
  253.             if (ob->obclass == dogobj || ob->obclass == fakeobj)
  254.             {
  255.                 CHECKDIAG(ob->tilex+1,ob->tiley);
  256.             }
  257.             else
  258.             {
  259.                 CHECKSIDE(ob->tilex+1,ob->tiley);
  260.             }
  261.             ob->tilex++;
  262.             break;
  263.  
  264.         case southeast:
  265.             CHECKDIAG(ob->tilex+1,ob->tiley+1);
  266.             CHECKDIAG(ob->tilex+1,ob->tiley);
  267.             CHECKDIAG(ob->tilex,ob->tiley+1);
  268.             ob->tilex++;
  269.             ob->tiley++;
  270.             break;
  271.  
  272.         case south:
  273.             if (ob->obclass == dogobj || ob->obclass == fakeobj)
  274.             {
  275.                 CHECKDIAG(ob->tilex,ob->tiley+1);
  276.             }
  277.             else
  278.             {
  279.                 CHECKSIDE(ob->tilex,ob->tiley+1);
  280.             }
  281.             ob->tiley++;
  282.             break;
  283.  
  284.         case southwest:
  285.             CHECKDIAG(ob->tilex-1,ob->tiley+1);
  286.             CHECKDIAG(ob->tilex-1,ob->tiley);
  287.             CHECKDIAG(ob->tilex,ob->tiley+1);
  288.             ob->tilex--;
  289.             ob->tiley++;
  290.             break;
  291.  
  292.         case west:
  293.             if (ob->obclass == dogobj || ob->obclass == fakeobj)
  294.             {
  295.                 CHECKDIAG(ob->tilex-1,ob->tiley);
  296.             }
  297.             else
  298.             {
  299.                 CHECKSIDE(ob->tilex-1,ob->tiley);
  300.             }
  301.             ob->tilex--;
  302.             break;
  303.  
  304.         case northwest:
  305.             CHECKDIAG(ob->tilex-1,ob->tiley-1);
  306.             CHECKDIAG(ob->tilex-1,ob->tiley);
  307.             CHECKDIAG(ob->tilex,ob->tiley-1);
  308.             ob->tilex--;
  309.             ob->tiley--;
  310.             break;
  311.  
  312.         case nodir:
  313.             return false;
  314.  
  315.         default:
  316.             Quit ("Walk: Bad dir");
  317.         }
  318.  
  319.     if (doornum != -1)
  320.     {
  321.         OpenDoor (doornum);
  322.         ob->distance = -doornum-1;
  323.         return true;
  324.     }
  325.  
  326.  
  327.     ob->areanumber =
  328.         *(mapsegs[0] + farmapylookup[ob->tiley]+ob->tilex) - AREATILE;
  329.  
  330.     ob->distance = TILEGLOBAL;
  331.     return true;
  332. }
  333.  
  334.  
  335.  
  336. /*
  337. ==================================
  338. =
  339. = SelectDodgeDir
  340. =
  341. = Attempts to choose and initiate a movement for ob that sends it towards
  342. = the player while dodging
  343. =
  344. = If there is no possible move (ob is totally surrounded)
  345. =
  346. = ob->dir            =    nodir
  347. =
  348. = Otherwise
  349. =
  350. = ob->dir            = new direction to follow
  351. = ob->distance        = TILEGLOBAL or -doornumber
  352. = ob->tilex            = new destination
  353. = ob->tiley
  354. = ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination
  355. =
  356. ==================================
  357. */
  358.  
  359. void SelectDodgeDir (objtype *ob)
  360. {
  361.     int         deltax,deltay,i;
  362.     unsigned    absdx,absdy;
  363.     dirtype     dirtry[5];
  364.     dirtype     turnaround,tdir;
  365.  
  366.     if (ob->flags & FL_FIRSTATTACK)
  367.     {
  368.     //
  369.     // turning around is only ok the very first time after noticing the
  370.     // player
  371.     //
  372.         turnaround = nodir;
  373.         ob->flags &= ~FL_FIRSTATTACK;
  374.     }
  375.     else
  376.         turnaround=opposite[ob->dir];
  377.  
  378.     deltax = player->tilex - ob->tilex;
  379.     deltay = player->tiley - ob->tiley;
  380.  
  381. //
  382. // arange 5 direction choices in order of preference
  383. // the four cardinal directions plus the diagonal straight towards
  384. // the player
  385. //
  386.  
  387.     if (deltax>0)
  388.     {
  389.         dirtry[1]= east;
  390.         dirtry[3]= west;
  391.     }
  392.     else
  393.     {
  394.         dirtry[1]= west;
  395.         dirtry[3]= east;
  396.     }
  397.  
  398.     if (deltay>0)
  399.     {
  400.         dirtry[2]= south;
  401.         dirtry[4]= north;
  402.     }
  403.     else
  404.     {
  405.         dirtry[2]= north;
  406.         dirtry[4]= south;
  407.     }
  408.  
  409. //
  410. // randomize a bit for dodging
  411. //
  412.     absdx = abs(deltax);
  413.     absdy = abs(deltay);
  414.  
  415.     if (absdx > absdy)
  416.     {
  417.         tdir = dirtry[1];
  418.         dirtry[1] = dirtry[2];
  419.         dirtry[2] = tdir;
  420.         tdir = dirtry[3];
  421.         dirtry[3] = dirtry[4];
  422.         dirtry[4] = tdir;
  423.     }
  424.  
  425.     if (US_RndT() < 128)
  426.     {
  427.         tdir = dirtry[1];
  428.         dirtry[1] = dirtry[2];
  429.         dirtry[2] = tdir;
  430.         tdir = dirtry[3];
  431.         dirtry[3] = dirtry[4];
  432.         dirtry[4] = tdir;
  433.     }
  434.  
  435.     dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];
  436.  
  437. //
  438. // try the directions util one works
  439. //
  440.     for (i=0;i<5;i++)
  441.     {
  442.         if ( dirtry[i] == nodir || dirtry[i] == turnaround)
  443.             continue;
  444.  
  445.         ob->dir = dirtry[i];
  446.         if (TryWalk(ob))
  447.             return;
  448.     }
  449.  
  450. //
  451. // turn around only as a last resort
  452. //
  453.     if (turnaround != nodir)
  454.     {
  455.         ob->dir = turnaround;
  456.  
  457.         if (TryWalk(ob))
  458.             return;
  459.     }
  460.  
  461.     ob->dir = nodir;
  462. }
  463.  
  464.  
  465. /*
  466. ============================
  467. =
  468. = SelectChaseDir
  469. =
  470. = As SelectDodgeDir, but doesn't try to dodge
  471. =
  472. ============================
  473. */
  474.  
  475. void SelectChaseDir (objtype *ob)
  476. {
  477.     int deltax,deltay,i;
  478.     dirtype d[3];
  479.     dirtype tdir, olddir, turnaround;
  480.  
  481.  
  482.     olddir=ob->dir;
  483.     turnaround=opposite[olddir];
  484.  
  485.     deltax=player->tilex - ob->tilex;
  486.     deltay=player->tiley - ob->tiley;
  487.  
  488.     d[1]=nodir;
  489.     d[2]=nodir;
  490.  
  491.     if (deltax>0)
  492.         d[1]= east;
  493.     else if (deltax<0)
  494.         d[1]= west;
  495.     if (deltay>0)
  496.         d[2]=south;
  497.     else if (deltay<0)
  498.         d[2]=north;
  499.  
  500.     if (abs(deltay)>abs(deltax))
  501.     {
  502.         tdir=d[1];
  503.         d[1]=d[2];
  504.         d[2]=tdir;
  505.     }
  506.  
  507.     if (d[1]==turnaround)
  508.         d[1]=nodir;
  509.     if (d[2]==turnaround)
  510.         d[2]=nodir;
  511.  
  512.  
  513.     if (d[1]!=nodir)
  514.     {
  515.         ob->dir=d[1];
  516.         if (TryWalk(ob))
  517.             return;     /*either moved forward or attacked*/
  518.     }
  519.  
  520.     if (d[2]!=nodir)
  521.     {
  522.         ob->dir=d[2];
  523.         if (TryWalk(ob))
  524.             return;
  525.     }
  526.  
  527. /* there is no direct path to the player, so pick another direction */
  528.  
  529.     if (olddir!=nodir)
  530.     {
  531.         ob->dir=olddir;
  532.         if (TryWalk(ob))
  533.             return;
  534.     }
  535.  
  536.     if (US_RndT()>128)     /*randomly determine direction of search*/
  537.     {
  538.         for (tdir=north;tdir<=west;tdir++)
  539.         {
  540.             if (tdir!=turnaround)
  541.             {
  542.                 ob->dir=tdir;
  543.                 if ( TryWalk(ob) )
  544.                     return;
  545.             }
  546.         }
  547.     }
  548.     else
  549.     {
  550.         for (tdir=west;tdir>=north;tdir--)
  551.         {
  552.             if (tdir!=turnaround)
  553.             {
  554.               ob->dir=tdir;
  555.               if ( TryWalk(ob) )
  556.                 return;
  557.             }
  558.         }
  559.     }
  560.  
  561.     if (turnaround !=  nodir)
  562.     {
  563.         ob->dir=turnaround;
  564.         if (ob->dir != nodir)
  565.         {
  566.             if ( TryWalk(ob) )
  567.                 return;
  568.         }
  569.     }
  570.  
  571.     ob->dir = nodir;        // can't move
  572. }
  573.  
  574.  
  575. /*
  576. ============================
  577. =
  578. = SelectRunDir
  579. =
  580. = Run Away from player
  581. =
  582. ============================
  583. */
  584.  
  585. void SelectRunDir (objtype *ob)
  586. {
  587.     int deltax,deltay,i;
  588.     dirtype d[3];
  589.     dirtype tdir, olddir, turnaround;
  590.  
  591.  
  592.     deltax=player->tilex - ob->tilex;
  593.     deltay=player->tiley - ob->tiley;
  594.  
  595.     if (deltax<0)
  596.         d[1]= east;
  597.     else
  598.         d[1]= west;
  599.     if (deltay<0)
  600.         d[2]=south;
  601.     else
  602.         d[2]=north;
  603.  
  604.     if (abs(deltay)>abs(deltax))
  605.     {
  606.         tdir=d[1];
  607.         d[1]=d[2];
  608.         d[2]=tdir;
  609.     }
  610.  
  611.     ob->dir=d[1];
  612.     if (TryWalk(ob))
  613.         return;     /*either moved forward or attacked*/
  614.  
  615.     ob->dir=d[2];
  616.     if (TryWalk(ob))
  617.         return;
  618.  
  619. /* there is no direct path to the player, so pick another direction */
  620.  
  621.     if (US_RndT()>128)     /*randomly determine direction of search*/
  622.     {
  623.         for (tdir=north;tdir<=west;tdir++)
  624.         {
  625.             ob->dir=tdir;
  626.             if ( TryWalk(ob) )
  627.                 return;
  628.         }
  629.     }
  630.     else
  631.     {
  632.         for (tdir=west;tdir>=north;tdir--)
  633.         {
  634.             ob->dir=tdir;
  635.             if ( TryWalk(ob) )
  636.               return;
  637.         }
  638.     }
  639.  
  640.     ob->dir = nodir;        // can't move
  641. }
  642.  
  643.  
  644. /*
  645. =================
  646. =
  647. = MoveObj
  648. =
  649. = Moves ob be move global units in ob->dir direction
  650. = Actors are not allowed to move inside the player
  651. = Does NOT check to see if the move is tile map valid
  652. =
  653. = ob->x            = adjusted for new position
  654. = ob->y
  655. =
  656. =================
  657. */
  658.  
  659. void MoveObj (objtype *ob, long move)
  660. {
  661.     long    deltax,deltay;
  662.  
  663.     switch (ob->dir)
  664.     {
  665.     case north:
  666.         ob->y -= move;
  667.         break;
  668.     case northeast:
  669.         ob->x += move;
  670.         ob->y -= move;
  671.         break;
  672.     case east:
  673.         ob->x += move;
  674.         break;
  675.     case southeast:
  676.         ob->x += move;
  677.         ob->y += move;
  678.         break;
  679.     case south:
  680.         ob->y += move;
  681.         break;
  682.     case southwest:
  683.         ob->x -= move;
  684.         ob->y += move;
  685.         break;
  686.     case west:
  687.         ob->x -= move;
  688.         break;
  689.     case northwest:
  690.         ob->x -= move;
  691.         ob->y -= move;
  692.         break;
  693.  
  694.     case nodir:
  695.         return;
  696.  
  697.     default:
  698.         Quit ("MoveObj: bad dir!");
  699.     }
  700.  
  701. //
  702. // check to make sure it's not on top of player
  703. //
  704.     if (areabyplayer[ob->areanumber])
  705.     {
  706.         deltax = ob->x - player->x;
  707.         if (deltax < -MINACTORDIST || deltax > MINACTORDIST)
  708.             goto moveok;
  709.         deltay = ob->y - player->y;
  710.         if (deltay < -MINACTORDIST || deltay > MINACTORDIST)
  711.             goto moveok;
  712.  
  713.         if (ob->obclass == ghostobj || ob->obclass == spectreobj)
  714.             TakeDamage (tics*2,ob);
  715.  
  716.     //
  717.     // back up
  718.     //
  719.         switch (ob->dir)
  720.         {
  721.         case north:
  722.             ob->y += move;
  723.             break;
  724.         case northeast:
  725.             ob->x -= move;
  726.             ob->y += move;
  727.             break;
  728.         case east:
  729.             ob->x -= move;
  730.             break;
  731.         case southeast:
  732.             ob->x -= move;
  733.             ob->y -= move;
  734.             break;
  735.         case south:
  736.             ob->y -= move;
  737.             break;
  738.         case southwest:
  739.             ob->x += move;
  740.             ob->y -= move;
  741.             break;
  742.         case west:
  743.             ob->x += move;
  744.             break;
  745.         case northwest:
  746.             ob->x += move;
  747.             ob->y += move;
  748.             break;
  749.  
  750.         case nodir:
  751.             return;
  752.         }
  753.         return;
  754.     }
  755. moveok:
  756.     ob->distance -=move;
  757. }
  758.  
  759. /*
  760. =============================================================================
  761.  
  762.                             STUFF
  763.  
  764. =============================================================================
  765. */
  766.  
  767. /*
  768. ===============
  769. =
  770. = DropItem
  771. =
  772. = Tries to drop a bonus item somewhere in the tiles surrounding the
  773. = given tilex/tiley
  774. =
  775. ===============
  776. */
  777.  
  778. void DropItem (stat_t itemtype, int tilex, int tiley)
  779. {
  780.     int    x,y,xl,xh,yl,yh;
  781.  
  782. //
  783. // find a free spot to put it in
  784. //
  785.     if (!actorat[tilex][tiley])
  786.     {
  787.         PlaceItemType (itemtype, tilex,tiley);
  788.         return;
  789.     }
  790.  
  791.     xl = tilex-1;
  792.     xh = tilex+1;
  793.     yl = tiley-1;
  794.     yh = tiley+1;
  795.  
  796.     for (x=xl ; x<= xh ; x++)
  797.         for (y=yl ; y<= yh ; y++)
  798.             if (!actorat[x][y])
  799.             {
  800.                 PlaceItemType (itemtype, x,y);
  801.                 return;
  802.             }
  803. }
  804.  
  805.  
  806.  
  807. /*
  808. ===============
  809. =
  810. = KillActor
  811. =
  812. ===============
  813. */
  814.  
  815. void KillActor (objtype *ob)
  816. {
  817.     int    tilex,tiley;
  818.  
  819.     tilex = ob->tilex = ob->x >> TILESHIFT;        // drop item on center
  820.     tiley = ob->tiley = ob->y >> TILESHIFT;
  821.  
  822.     switch (ob->obclass)
  823.     {
  824.     case guardobj:
  825.         GivePoints (100);
  826.         NewState (ob,&s_grddie1);
  827.         PlaceItemType (bo_clip2,tilex,tiley);
  828.         break;
  829.  
  830.     case officerobj:
  831.         GivePoints (400);
  832.         NewState (ob,&s_ofcdie1);
  833.         PlaceItemType (bo_clip2,tilex,tiley);
  834.         break;
  835.  
  836.     case mutantobj:
  837.         GivePoints (700);
  838.         NewState (ob,&s_mutdie1);
  839.         PlaceItemType (bo_clip2,tilex,tiley);
  840.         break;
  841.  
  842.     case ssobj:
  843.         GivePoints (500);
  844.         NewState (ob,&s_ssdie1);
  845.         if (gamestate.bestweapon < wp_machinegun)
  846.             PlaceItemType (bo_machinegun,tilex,tiley);
  847.         else
  848.             PlaceItemType (bo_clip2,tilex,tiley);
  849.         break;
  850.  
  851.     case dogobj:
  852.         GivePoints (200);
  853.         NewState (ob,&s_dogdie1);
  854.         break;
  855.  
  856. #ifndef SPEAR
  857.     case bossobj:
  858.         GivePoints (5000);
  859.         NewState (ob,&s_bossdie1);
  860.         PlaceItemType (bo_key1,tilex,tiley);
  861.         break;
  862.  
  863.     case gretelobj:
  864.         GivePoints (5000);
  865.         NewState (ob,&s_greteldie1);
  866.         PlaceItemType (bo_key1,tilex,tiley);
  867.         break;
  868.  
  869.     case giftobj:
  870.         GivePoints (5000);
  871.         gamestate.killx = player->x;
  872.         gamestate.killy = player->y;
  873.         NewState (ob,&s_giftdie1);
  874.         break;
  875.  
  876.     case fatobj:
  877.         GivePoints (5000);
  878.         gamestate.killx = player->x;
  879.         gamestate.killy = player->y;
  880.         NewState (ob,&s_fatdie1);
  881.         break;
  882.  
  883.     case schabbobj:
  884.         GivePoints (5000);
  885.         gamestate.killx = player->x;
  886.         gamestate.killy = player->y;
  887.         NewState (ob,&s_schabbdie1);
  888.         A_DeathScream(ob);
  889.         break;
  890.     case fakeobj:
  891.         GivePoints (2000);
  892.         NewState (ob,&s_fakedie1);
  893.         break;
  894.  
  895.     case mechahitlerobj:
  896.         GivePoints (5000);
  897.         NewState (ob,&s_mechadie1);
  898.         break;
  899.     case realhitlerobj:
  900.         GivePoints (5000);
  901.         gamestate.killx = player->x;
  902.         gamestate.killy = player->y;
  903.         NewState (ob,&s_hitlerdie1);
  904.         A_DeathScream(ob);
  905.         break;
  906. #else
  907.     case spectreobj:
  908.         GivePoints (200);
  909.         NewState (ob,&s_spectredie1);
  910.         break;
  911.  
  912.     case angelobj:
  913.         GivePoints (5000);
  914.         NewState (ob,&s_angeldie1);
  915.         break;
  916.  
  917.     case transobj:
  918.         GivePoints (5000);
  919.         NewState (ob,&s_transdie0);
  920.         PlaceItemType (bo_key1,tilex,tiley);
  921.         break;
  922.  
  923.     case uberobj:
  924.         GivePoints (5000);
  925.         NewState (ob,&s_uberdie0);
  926.         PlaceItemType (bo_key1,tilex,tiley);
  927.         break;
  928.  
  929.     case willobj:
  930.         GivePoints (5000);
  931.         NewState (ob,&s_willdie1);
  932.         PlaceItemType (bo_key1,tilex,tiley);
  933.         break;
  934.  
  935.     case deathobj:
  936.         GivePoints (5000);
  937.         NewState (ob,&s_deathdie1);
  938.         PlaceItemType (bo_key1,tilex,tiley);
  939.         break;
  940. #endif
  941.     }
  942.  
  943.     gamestate.killcount++;
  944.     ob->flags &= ~FL_SHOOTABLE;
  945.     actorat[ob->tilex][ob->tiley] = NULL;
  946.     ob->flags |= FL_NONMARK;
  947. }
  948.  
  949.  
  950.  
  951. /*
  952. ===================
  953. =
  954. = DamageActor
  955. =
  956. = Called when the player succesfully hits an enemy.
  957. =
  958. = Does damage points to enemy ob, either putting it into a stun frame or
  959. = killing it.
  960. =
  961. ===================
  962. */
  963.  
  964. void DamageActor (objtype *ob, unsigned damage)
  965. {
  966.     madenoise = true;
  967.  
  968. //
  969. // do double damage if shooting a non attack mode actor
  970. //
  971.     if ( !(ob->flags & FL_ATTACKMODE) )
  972.         damage <<= 1;
  973.  
  974.     ob->hitpoints -= damage;
  975.  
  976.     if (ob->hitpoints<=0)
  977.         KillActor (ob);
  978.     else
  979.     {
  980.         if (! (ob->flags & FL_ATTACKMODE) )
  981.             FirstSighting (ob);        // put into combat mode
  982.  
  983.         switch (ob->obclass)        // dogs only have one hit point
  984.         {
  985.         case guardobj:
  986.             if (ob->hitpoints&1)
  987.                 NewState (ob,&s_grdpain);
  988.             else
  989.                 NewState (ob,&s_grdpain1);
  990.             break;
  991.  
  992.         case officerobj:
  993.             if (ob->hitpoints&1)
  994.                 NewState (ob,&s_ofcpain);
  995.             else
  996.                 NewState (ob,&s_ofcpain1);
  997.             break;
  998.  
  999.         case mutantobj:
  1000.             if (ob->hitpoints&1)
  1001.                 NewState (ob,&s_mutpain);
  1002.             else
  1003.                 NewState (ob,&s_mutpain1);
  1004.             break;
  1005.  
  1006.         case ssobj:
  1007.             if (ob->hitpoints&1)
  1008.                 NewState (ob,&s_sspain);
  1009.             else
  1010.                 NewState (ob,&s_sspain1);
  1011.  
  1012.             break;
  1013.  
  1014.         }
  1015.     }
  1016. }
  1017.  
  1018. /*
  1019. =============================================================================
  1020.  
  1021.                             CHECKSIGHT
  1022.  
  1023. =============================================================================
  1024. */
  1025.  
  1026.  
  1027. /*
  1028. =====================
  1029. =
  1030. = CheckLine
  1031. =
  1032. = Returns true if a straight line between the player and ob is unobstructed
  1033. =
  1034. =====================
  1035. */
  1036.  
  1037. boolean CheckLine (objtype *ob)
  1038. {
  1039.     int    x1,y1,xt1,yt1,x2,y2,xt2,yt2;
  1040.     int    x,y;
  1041.     int    xdist,ydist,xstep,ystep;
  1042.     int    temp;
  1043.     int    partial,delta;
  1044.     long    ltemp;
  1045.     int    xfrac,yfrac,deltafrac;
  1046.     unsigned    value,intercept;
  1047.  
  1048.     x1 = ob->x >> UNSIGNEDSHIFT;        // 1/256 tile precision
  1049.     y1 = ob->y >> UNSIGNEDSHIFT;
  1050.     xt1 = x1 >> 8;
  1051.     yt1 = y1 >> 8;
  1052.  
  1053.     x2 = plux;
  1054.     y2 = pluy;
  1055.     xt2 = player->tilex;
  1056.     yt2 = player->tiley;
  1057.  
  1058.  
  1059.     xdist = abs(xt2-xt1);
  1060.  
  1061.     if (xdist > 0)
  1062.     {
  1063.         if (xt2 > xt1)
  1064.         {
  1065.             partial = 256-(x1&0xff);
  1066.             xstep = 1;
  1067.         }
  1068.         else
  1069.         {
  1070.             partial = x1&0xff;
  1071.             xstep = -1;
  1072.         }
  1073.  
  1074.         deltafrac = abs(x2-x1);
  1075.         delta = y2-y1;
  1076.         ltemp = ((long)delta<<8)/deltafrac;
  1077.         if (ltemp > 0x7fffl)
  1078.             ystep = 0x7fff;
  1079.         else if (ltemp < -0x7fffl)
  1080.             ystep = -0x7fff;
  1081.         else
  1082.             ystep = ltemp;
  1083.         yfrac = y1 + (((long)ystep*partial) >>8);
  1084.  
  1085.         x = xt1+xstep;
  1086.         xt2 += xstep;
  1087.         do
  1088.         {
  1089.             y = yfrac>>8;
  1090.             yfrac += ystep;
  1091.  
  1092.             value = (unsigned)tilemap[x][y];
  1093.             x += xstep;
  1094.  
  1095.             if (!value)
  1096.                 continue;
  1097.  
  1098.             if (value<128 || value>256)
  1099.                 return false;
  1100.  
  1101.             //
  1102.             // see if the door is open enough
  1103.             //
  1104.             value &= ~0x80;
  1105.             intercept = yfrac-ystep/2;
  1106.  
  1107.             if (intercept>doorposition[value])
  1108.                 return false;
  1109.  
  1110.         } while (x != xt2);
  1111.     }
  1112.  
  1113.     ydist = abs(yt2-yt1);
  1114.  
  1115.     if (ydist > 0)
  1116.     {
  1117.         if (yt2 > yt1)
  1118.         {
  1119.             partial = 256-(y1&0xff);
  1120.             ystep = 1;
  1121.         }
  1122.         else
  1123.         {
  1124.             partial = y1&0xff;
  1125.             ystep = -1;
  1126.         }
  1127.  
  1128.         deltafrac = abs(y2-y1);
  1129.         delta = x2-x1;
  1130.         ltemp = ((long)delta<<8)/deltafrac;
  1131.         if (ltemp > 0x7fffl)
  1132.             xstep = 0x7fff;
  1133.         else if (ltemp < -0x7fffl)
  1134.             xstep = -0x7fff;
  1135.         else
  1136.             xstep = ltemp;
  1137.         xfrac = x1 + (((long)xstep*partial) >>8);
  1138.  
  1139.         y = yt1 + ystep;
  1140.         yt2 += ystep;
  1141.         do
  1142.         {
  1143.             x = xfrac>>8;
  1144.             xfrac += xstep;
  1145.  
  1146.             value = (unsigned)tilemap[x][y];
  1147.             y += ystep;
  1148.  
  1149.             if (!value)
  1150.                 continue;
  1151.  
  1152.             if (value<128 || value>256)
  1153.                 return false;
  1154.  
  1155.             //
  1156.             // see if the door is open enough
  1157.             //
  1158.             value &= ~0x80;
  1159.             intercept = xfrac-xstep/2;
  1160.  
  1161.             if (intercept>doorposition[value])
  1162.                 return false;
  1163.         } while (y != yt2);
  1164.     }
  1165.  
  1166.     return true;
  1167. }
  1168.  
  1169.  
  1170.  
  1171. /*
  1172. ================
  1173. =
  1174. = CheckSight
  1175. =
  1176. = Checks a straight line between player and current object
  1177. =
  1178. = If the sight is ok, check alertness and angle to see if they notice
  1179. =
  1180. = returns true if the player has been spoted
  1181. =
  1182. ================
  1183. */
  1184.  
  1185. #define MINSIGHT    0x18000l
  1186.  
  1187. boolean CheckSight (objtype *ob)
  1188. {
  1189.     long        deltax,deltay;
  1190.  
  1191. //
  1192. // don't bother tracing a line if the area isn't connected to the player's
  1193. //
  1194.     if (!areabyplayer[ob->areanumber])
  1195.         return false;
  1196.  
  1197. //
  1198. // if the player is real close, sight is automatic
  1199. //
  1200.     deltax = player->x - ob->x;
  1201.     deltay = player->y - ob->y;
  1202.  
  1203.     if (deltax > -MINSIGHT && deltax < MINSIGHT
  1204.     && deltay > -MINSIGHT && deltay < MINSIGHT)
  1205.         return true;
  1206.  
  1207. //
  1208. // see if they are looking in the right direction
  1209. //
  1210.     switch (ob->dir)
  1211.     {
  1212.     case north:
  1213.         if (deltay > 0)
  1214.             return false;
  1215.         break;
  1216.  
  1217.     case east:
  1218.         if (deltax < 0)
  1219.             return false;
  1220.         break;
  1221.  
  1222.     case south:
  1223.         if (deltay < 0)
  1224.             return false;
  1225.         break;
  1226.  
  1227.     case west:
  1228.         if (deltax > 0)
  1229.             return false;
  1230.         break;
  1231.     }
  1232.  
  1233. //
  1234. // trace a line to check for blocking tiles (corners)
  1235. //
  1236.     return CheckLine (ob);
  1237.  
  1238. }
  1239.  
  1240.  
  1241.  
  1242. /*
  1243. ===============
  1244. =
  1245. = FirstSighting
  1246. =
  1247. = Puts an actor into attack mode and possibly reverses the direction
  1248. = if the player is behind it
  1249. =
  1250. ===============
  1251. */
  1252.  
  1253. void FirstSighting (objtype *ob)
  1254. {
  1255. //
  1256. // react to the player
  1257. //
  1258.     switch (ob->obclass)
  1259.     {
  1260.     case guardobj:
  1261.         PlaySoundLocActor(HALTSND,ob);
  1262.         NewState (ob,&s_grdchase1);
  1263.         ob->speed *= 3;            // go faster when chasing player
  1264.         break;
  1265.  
  1266.     case officerobj:
  1267.         PlaySoundLocActor(SPIONSND,ob);
  1268.         NewState (ob,&s_ofcchase1);
  1269.         ob->speed *= 5;            // go faster when chasing player
  1270.         break;
  1271.  
  1272.     case mutantobj:
  1273.         NewState (ob,&s_mutchase1);
  1274.         ob->speed *= 3;            // go faster when chasing player
  1275.         break;
  1276.  
  1277.     case ssobj:
  1278.         PlaySoundLocActor(SCHUTZADSND,ob);
  1279.         NewState (ob,&s_sschase1);
  1280.         ob->speed *= 4;            // go faster when chasing player
  1281.         break;
  1282.  
  1283.     case dogobj:
  1284.         PlaySoundLocActor(DOGBARKSND,ob);
  1285.         NewState (ob,&s_dogchase1);
  1286.         ob->speed *= 2;            // go faster when chasing player
  1287.         break;
  1288.  
  1289. #ifndef SPEAR
  1290.     case bossobj:
  1291.         SD_PlaySound(GUTENTAGSND);
  1292.         NewState (ob,&s_bosschase1);
  1293.         ob->speed = SPDPATROL*3;    // go faster when chasing player
  1294.         break;
  1295.  
  1296.     case gretelobj:
  1297.         SD_PlaySound(KEINSND);
  1298.         NewState (ob,&s_gretelchase1);
  1299.         ob->speed *= 3;            // go faster when chasing player
  1300.         break;
  1301.  
  1302.     case giftobj:
  1303.         SD_PlaySound(EINESND);
  1304.         NewState (ob,&s_giftchase1);
  1305.         ob->speed *= 3;            // go faster when chasing player
  1306.         break;
  1307.  
  1308.     case fatobj:
  1309.         SD_PlaySound(ERLAUBENSND);
  1310.         NewState (ob,&s_fatchase1);
  1311.         ob->speed *= 3;            // go faster when chasing player
  1312.         break;
  1313.  
  1314.     case schabbobj:
  1315.         SD_PlaySound(SCHABBSHASND);
  1316.         NewState (ob,&s_schabbchase1);
  1317.         ob->speed *= 3;            // go faster when chasing player
  1318.         break;
  1319.  
  1320.     case fakeobj:
  1321.         SD_PlaySound(TOT_HUNDSND);
  1322.         NewState (ob,&s_fakechase1);
  1323.         ob->speed *= 3;            // go faster when chasing player
  1324.         break;
  1325.  
  1326.     case mechahitlerobj:
  1327.         SD_PlaySound(DIESND);
  1328.         NewState (ob,&s_mechachase1);
  1329.         ob->speed *= 3;            // go faster when chasing player
  1330.         break;
  1331.  
  1332.     case realhitlerobj:
  1333.         SD_PlaySound(DIESND);
  1334.         NewState (ob,&s_hitlerchase1);
  1335.         ob->speed *= 5;            // go faster when chasing player
  1336.         break;
  1337.  
  1338.     case ghostobj:
  1339.         NewState (ob,&s_blinkychase1);
  1340.         ob->speed *= 2;            // go faster when chasing player
  1341.         break;
  1342. #else
  1343.  
  1344.     case spectreobj:
  1345.         SD_PlaySound(GHOSTSIGHTSND);
  1346.         NewState (ob,&s_spectrechase1);
  1347.         ob->speed = 800;            // go faster when chasing player
  1348.         break;
  1349.  
  1350.     case angelobj:
  1351.         SD_PlaySound(ANGELSIGHTSND);
  1352.         NewState (ob,&s_angelchase1);
  1353.         ob->speed = 1536;            // go faster when chasing player
  1354.         break;
  1355.  
  1356.     case transobj:
  1357.         SD_PlaySound(TRANSSIGHTSND);
  1358.         NewState (ob,&s_transchase1);
  1359.         ob->speed = 1536;            // go faster when chasing player
  1360.         break;
  1361.  
  1362.     case uberobj:
  1363.         NewState (ob,&s_uberchase1);
  1364.         ob->speed = 3000;            // go faster when chasing player
  1365.         break;
  1366.  
  1367.     case willobj:
  1368.         SD_PlaySound(WILHELMSIGHTSND);
  1369.         NewState (ob,&s_willchase1);
  1370.         ob->speed = 2048;            // go faster when chasing player
  1371.         break;
  1372.  
  1373.     case deathobj:
  1374.         SD_PlaySound(KNIGHTSIGHTSND);
  1375.         NewState (ob,&s_deathchase1);
  1376.         ob->speed = 2048;            // go faster when chasing player
  1377.         break;
  1378.  
  1379. #endif
  1380.     }
  1381.  
  1382.     if (ob->distance < 0)
  1383.         ob->distance = 0;    // ignore the door opening command
  1384.  
  1385.     ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;
  1386. }
  1387.  
  1388.  
  1389.  
  1390. /*
  1391. ===============
  1392. =
  1393. = SightPlayer
  1394. =
  1395. = Called by actors that ARE NOT chasing the player.  If the player
  1396. = is detected (by sight, noise, or proximity), the actor is put into
  1397. = it's combat frame and true is returned.
  1398. =
  1399. = Incorporates a random reaction delay
  1400. =
  1401. ===============
  1402. */
  1403.  
  1404. boolean SightPlayer (objtype *ob)
  1405. {
  1406.     if (ob->flags & FL_ATTACKMODE)
  1407.         Quit ("An actor in ATTACKMODE called SightPlayer!");
  1408.  
  1409.     if (ob->temp2)
  1410.     {
  1411.     //
  1412.     // count down reaction time
  1413.     //
  1414.         ob->temp2 -= tics;
  1415.         if (ob->temp2 > 0)
  1416.             return false;
  1417.         ob->temp2 = 0;                    // time to react
  1418.     }
  1419.     else
  1420.     {
  1421.         if (!areabyplayer[ob->areanumber])
  1422.             return false;
  1423.  
  1424.         if (ob->flags & FL_AMBUSH)
  1425.         {
  1426.             if (!CheckSight (ob))
  1427.                 return false;
  1428.             ob->flags &= ~FL_AMBUSH;
  1429.         }
  1430.         else
  1431.         {
  1432.             if (!madenoise && !CheckSight (ob))
  1433.                 return false;
  1434.         }
  1435.  
  1436.  
  1437.         switch (ob->obclass)
  1438.         {
  1439.         case guardobj:
  1440.             ob->temp2 = 1+US_RndT()/4;
  1441.             break;
  1442.         case officerobj:
  1443.             ob->temp2 = 2;
  1444.             break;
  1445.         case mutantobj:
  1446.             ob->temp2 = 1+US_RndT()/6;
  1447.             break;
  1448.         case ssobj:
  1449.             ob->temp2 = 1+US_RndT()/6;
  1450.             break;
  1451.         case dogobj:
  1452.             ob->temp2 = 1+US_RndT()/8;
  1453.             break;
  1454.  
  1455.         case bossobj:
  1456.         case schabbobj:
  1457.         case fakeobj:
  1458.         case mechahitlerobj:
  1459.         case realhitlerobj:
  1460.         case gretelobj:
  1461.         case giftobj:
  1462.         case fatobj:
  1463.         case spectreobj:
  1464.         case angelobj:
  1465.         case transobj:
  1466.         case uberobj:
  1467.         case willobj:
  1468.         case deathobj:
  1469.             ob->temp2 = 1;
  1470.             break;
  1471.         }
  1472.         return false;
  1473.     }
  1474.  
  1475.     FirstSighting (ob);
  1476.  
  1477.     return true;
  1478. }
  1479.  
  1480.  
  1481.