]> 4ch.mooo.com Git - 16.git/blobdiff - 16/sod8086/wl_state.c
got 8086 port of wolf3d to work and sod to work
[16.git] / 16 / sod8086 / wl_state.c
diff --git a/16/sod8086/wl_state.c b/16/sod8086/wl_state.c
new file mode 100755 (executable)
index 0000000..ad534ba
--- /dev/null
@@ -0,0 +1,1480 @@
+// WL_STATE.C\r
+\r
+#include "WL_DEF.H"\r
+#pragma hdrstop\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL CONSTANTS\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+dirtype opposite[9] =\r
+       {west,southwest,south,southeast,east,northeast,north,northwest,nodir};\r
+\r
+dirtype diagonal[9][9] =\r
+{\r
+/* east */     {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},\r
+                       {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},\r
+                       {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* west */  {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},\r
+                       {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+/* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},\r
+                       {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},\r
+                       {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}\r
+};\r
+\r
+\r
+\r
+void   SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);\r
+void   NewState (objtype *ob, statetype *state);\r
+\r
+boolean TryWalk (objtype *ob);\r
+void   MoveObj (objtype *ob, long move);\r
+\r
+void   KillActor (objtype *ob);\r
+void   DamageActor (objtype *ob, unsigned damage);\r
+\r
+boolean CheckLine (objtype *ob);\r
+void FirstSighting (objtype *ob);\r
+boolean        CheckSight (objtype *ob);\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+\r
+//===========================================================================\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= SpawnNewObj\r
+=\r
+= Spaws a new actor at the given TILE coordinates, with the given state, and\r
+= the given size in GLOBAL units.\r
+=\r
+= new                  = a pointer to an initialized new actor\r
+=\r
+===================\r
+*/\r
+\r
+void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)\r
+{\r
+       GetNewActor ();\r
+       new->state = state;\r
+       if (state->tictime)\r
+               new->ticcount = US_RndT () % state->tictime;\r
+       else\r
+               new->ticcount = 0;\r
+\r
+       new->tilex = tilex;\r
+       new->tiley = tiley;\r
+       new->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;\r
+       new->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;\r
+       new->dir = nodir;\r
+\r
+       actorat[tilex][tiley] = new;\r
+       new->areanumber =\r
+               *(mapsegs[0] + farmapylookup[new->tiley]+new->tilex) - AREATILE;\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= NewState\r
+=\r
+= Changes ob to a new state, setting ticcount to the max for that state\r
+=\r
+===================\r
+*/\r
+\r
+void NewState (objtype *ob, statetype *state)\r
+{\r
+       ob->state = state;\r
+       ob->ticcount = state->tictime;\r
+}\r
+\r
+\r
+\r
+/*\r
+=============================================================================\r
+\r
+                               ENEMY TILE WORLD MOVEMENT CODE\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+==================================\r
+=\r
+= TryWalk\r
+=\r
+= Attempts to move ob in its current (ob->dir) direction.\r
+=\r
+= If blocked by either a wall or an actor returns FALSE\r
+=\r
+= If move is either clear or blocked only by a door, returns TRUE and sets\r
+=\r
+= ob->tilex                    = new destination\r
+= ob->tiley\r
+= ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination\r
+= ob->distance         = TILEGLOBAl, or -doornumber if a door is blocking the way\r
+=\r
+= If a door is in the way, an OpenDoor call is made to start it opening.\r
+= The actor code should wait until\r
+=      doorobjlist[-ob->distance].action = dr_open, meaning the door has been\r
+=      fully opened\r
+=\r
+==================================\r
+*/\r
+\r
+#define CHECKDIAG(x,y)                                                         \\r
+{                                                   \\r
+       temp=(unsigned)actorat[x][y];                   \\r
+       if (temp)                                       \\r
+       {                                               \\r
+               if (temp<256)                               \\r
+                       return false;                           \\r
+               if (((objtype *)temp)->flags&FL_SHOOTABLE)  \\r
+                       return false;                           \\r
+       }                                               \\r
+}\r
+\r
+#define CHECKSIDE(x,y)                                                         \\r
+{                                                   \\r
+       temp=(unsigned)actorat[x][y];                   \\r
+       if (temp)                                       \\r
+       {                                               \\r
+               if (temp<128)                               \\r
+                       return false;                           \\r
+               if (temp<256)                               \\r
+                       doornum = temp&63;                      \\r
+               else if (((objtype *)temp)->flags&FL_SHOOTABLE)\\r
+                       return false;                           \\r
+       }                                               \\r
+}\r
+\r
+\r
+boolean TryWalk (objtype *ob)\r
+{\r
+       int                     doornum;\r
+       unsigned        temp;\r
+\r
+       doornum = -1;\r
+\r
+       if (ob->obclass == inertobj)\r
+       {\r
+               switch (ob->dir)\r
+               {\r
+               case north:\r
+                       ob->tiley--;\r
+                       break;\r
+\r
+               case northeast:\r
+                       ob->tilex++;\r
+                       ob->tiley--;\r
+                       break;\r
+\r
+               case east:\r
+                       ob->tilex++;\r
+                       break;\r
+\r
+               case southeast:\r
+                       ob->tilex++;\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case south:\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case southwest:\r
+                       ob->tilex--;\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case west:\r
+                       ob->tilex--;\r
+                       break;\r
+\r
+               case northwest:\r
+                       ob->tilex--;\r
+                       ob->tiley--;\r
+                       break;\r
+               }\r
+       }\r
+       else\r
+               switch (ob->dir)\r
+               {\r
+               case north:\r
+                       if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+                       {\r
+                               CHECKDIAG(ob->tilex,ob->tiley-1);\r
+                       }\r
+                       else\r
+                       {\r
+                               CHECKSIDE(ob->tilex,ob->tiley-1);\r
+                       }\r
+                       ob->tiley--;\r
+                       break;\r
+\r
+               case northeast:\r
+                       CHECKDIAG(ob->tilex+1,ob->tiley-1);\r
+                       CHECKDIAG(ob->tilex+1,ob->tiley);\r
+                       CHECKDIAG(ob->tilex,ob->tiley-1);\r
+                       ob->tilex++;\r
+                       ob->tiley--;\r
+                       break;\r
+\r
+               case east:\r
+                       if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+                       {\r
+                               CHECKDIAG(ob->tilex+1,ob->tiley);\r
+                       }\r
+                       else\r
+                       {\r
+                               CHECKSIDE(ob->tilex+1,ob->tiley);\r
+                       }\r
+                       ob->tilex++;\r
+                       break;\r
+\r
+               case southeast:\r
+                       CHECKDIAG(ob->tilex+1,ob->tiley+1);\r
+                       CHECKDIAG(ob->tilex+1,ob->tiley);\r
+                       CHECKDIAG(ob->tilex,ob->tiley+1);\r
+                       ob->tilex++;\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case south:\r
+                       if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+                       {\r
+                               CHECKDIAG(ob->tilex,ob->tiley+1);\r
+                       }\r
+                       else\r
+                       {\r
+                               CHECKSIDE(ob->tilex,ob->tiley+1);\r
+                       }\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case southwest:\r
+                       CHECKDIAG(ob->tilex-1,ob->tiley+1);\r
+                       CHECKDIAG(ob->tilex-1,ob->tiley);\r
+                       CHECKDIAG(ob->tilex,ob->tiley+1);\r
+                       ob->tilex--;\r
+                       ob->tiley++;\r
+                       break;\r
+\r
+               case west:\r
+                       if (ob->obclass == dogobj || ob->obclass == fakeobj)\r
+                       {\r
+                               CHECKDIAG(ob->tilex-1,ob->tiley);\r
+                       }\r
+                       else\r
+                       {\r
+                               CHECKSIDE(ob->tilex-1,ob->tiley);\r
+                       }\r
+                       ob->tilex--;\r
+                       break;\r
+\r
+               case northwest:\r
+                       CHECKDIAG(ob->tilex-1,ob->tiley-1);\r
+                       CHECKDIAG(ob->tilex-1,ob->tiley);\r
+                       CHECKDIAG(ob->tilex,ob->tiley-1);\r
+                       ob->tilex--;\r
+                       ob->tiley--;\r
+                       break;\r
+\r
+               case nodir:\r
+                       return false;\r
+\r
+               default:\r
+                       Quit ("Walk: Bad dir");\r
+               }\r
+\r
+       if (doornum != -1)\r
+       {\r
+               OpenDoor (doornum);\r
+               ob->distance = -doornum-1;\r
+               return true;\r
+       }\r
+\r
+\r
+       ob->areanumber =\r
+               *(mapsegs[0] + farmapylookup[ob->tiley]+ob->tilex) - AREATILE;\r
+\r
+       ob->distance = TILEGLOBAL;\r
+       return true;\r
+}\r
+\r
+\r
+\r
+/*\r
+==================================\r
+=\r
+= SelectDodgeDir\r
+=\r
+= Attempts to choose and initiate a movement for ob that sends it towards\r
+= the player while dodging\r
+=\r
+= If there is no possible move (ob is totally surrounded)\r
+=\r
+= ob->dir                      =       nodir\r
+=\r
+= Otherwise\r
+=\r
+= ob->dir                      = new direction to follow\r
+= ob->distance         = TILEGLOBAL or -doornumber\r
+= ob->tilex                    = new destination\r
+= ob->tiley\r
+= ob->areanumber    = the floor tile number (0-(NUMAREAS-1)) of destination\r
+=\r
+==================================\r
+*/\r
+\r
+void SelectDodgeDir (objtype *ob)\r
+{\r
+       int             deltax,deltay,i;\r
+       unsigned        absdx,absdy;\r
+       dirtype         dirtry[5];\r
+       dirtype         turnaround,tdir;\r
+\r
+       if (ob->flags & FL_FIRSTATTACK)\r
+       {\r
+       //\r
+       // turning around is only ok the very first time after noticing the\r
+       // player\r
+       //\r
+               turnaround = nodir;\r
+               ob->flags &= ~FL_FIRSTATTACK;\r
+       }\r
+       else\r
+               turnaround=opposite[ob->dir];\r
+\r
+       deltax = player->tilex - ob->tilex;\r
+       deltay = player->tiley - ob->tiley;\r
+\r
+//\r
+// arange 5 direction choices in order of preference\r
+// the four cardinal directions plus the diagonal straight towards\r
+// the player\r
+//\r
+\r
+       if (deltax>0)\r
+       {\r
+               dirtry[1]= east;\r
+               dirtry[3]= west;\r
+       }\r
+       else\r
+       {\r
+               dirtry[1]= west;\r
+               dirtry[3]= east;\r
+       }\r
+\r
+       if (deltay>0)\r
+       {\r
+               dirtry[2]= south;\r
+               dirtry[4]= north;\r
+       }\r
+       else\r
+       {\r
+               dirtry[2]= north;\r
+               dirtry[4]= south;\r
+       }\r
+\r
+//\r
+// randomize a bit for dodging\r
+//\r
+       absdx = abs(deltax);\r
+       absdy = abs(deltay);\r
+\r
+       if (absdx > absdy)\r
+       {\r
+               tdir = dirtry[1];\r
+               dirtry[1] = dirtry[2];\r
+               dirtry[2] = tdir;\r
+               tdir = dirtry[3];\r
+               dirtry[3] = dirtry[4];\r
+               dirtry[4] = tdir;\r
+       }\r
+\r
+       if (US_RndT() < 128)\r
+       {\r
+               tdir = dirtry[1];\r
+               dirtry[1] = dirtry[2];\r
+               dirtry[2] = tdir;\r
+               tdir = dirtry[3];\r
+               dirtry[3] = dirtry[4];\r
+               dirtry[4] = tdir;\r
+       }\r
+\r
+       dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];\r
+\r
+//\r
+// try the directions util one works\r
+//\r
+       for (i=0;i<5;i++)\r
+       {\r
+               if ( dirtry[i] == nodir || dirtry[i] == turnaround)\r
+                       continue;\r
+\r
+               ob->dir = dirtry[i];\r
+               if (TryWalk(ob))\r
+                       return;\r
+       }\r
+\r
+//\r
+// turn around only as a last resort\r
+//\r
+       if (turnaround != nodir)\r
+       {\r
+               ob->dir = turnaround;\r
+\r
+               if (TryWalk(ob))\r
+                       return;\r
+       }\r
+\r
+       ob->dir = nodir;\r
+}\r
+\r
+\r
+/*\r
+============================\r
+=\r
+= SelectChaseDir\r
+=\r
+= As SelectDodgeDir, but doesn't try to dodge\r
+=\r
+============================\r
+*/\r
+\r
+void SelectChaseDir (objtype *ob)\r
+{\r
+       int deltax,deltay,i;\r
+       dirtype d[3];\r
+       dirtype tdir, olddir, turnaround;\r
+\r
+\r
+       olddir=ob->dir;\r
+       turnaround=opposite[olddir];\r
+\r
+       deltax=player->tilex - ob->tilex;\r
+       deltay=player->tiley - ob->tiley;\r
+\r
+       d[1]=nodir;\r
+       d[2]=nodir;\r
+\r
+       if (deltax>0)\r
+               d[1]= east;\r
+       else if (deltax<0)\r
+               d[1]= west;\r
+       if (deltay>0)\r
+               d[2]=south;\r
+       else if (deltay<0)\r
+               d[2]=north;\r
+\r
+       if (abs(deltay)>abs(deltax))\r
+       {\r
+               tdir=d[1];\r
+               d[1]=d[2];\r
+               d[2]=tdir;\r
+       }\r
+\r
+       if (d[1]==turnaround)\r
+               d[1]=nodir;\r
+       if (d[2]==turnaround)\r
+               d[2]=nodir;\r
+\r
+\r
+       if (d[1]!=nodir)\r
+       {\r
+               ob->dir=d[1];\r
+               if (TryWalk(ob))\r
+                       return;     /*either moved forward or attacked*/\r
+       }\r
+\r
+       if (d[2]!=nodir)\r
+       {\r
+               ob->dir=d[2];\r
+               if (TryWalk(ob))\r
+                       return;\r
+       }\r
+\r
+/* there is no direct path to the player, so pick another direction */\r
+\r
+       if (olddir!=nodir)\r
+       {\r
+               ob->dir=olddir;\r
+               if (TryWalk(ob))\r
+                       return;\r
+       }\r
+\r
+       if (US_RndT()>128)      /*randomly determine direction of search*/\r
+       {\r
+               for (tdir=north;tdir<=west;tdir++)\r
+               {\r
+                       if (tdir!=turnaround)\r
+                       {\r
+                               ob->dir=tdir;\r
+                               if ( TryWalk(ob) )\r
+                                       return;\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               for (tdir=west;tdir>=north;tdir--)\r
+               {\r
+                       if (tdir!=turnaround)\r
+                       {\r
+                         ob->dir=tdir;\r
+                         if ( TryWalk(ob) )\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (turnaround !=  nodir)\r
+       {\r
+               ob->dir=turnaround;\r
+               if (ob->dir != nodir)\r
+               {\r
+                       if ( TryWalk(ob) )\r
+                               return;\r
+               }\r
+       }\r
+\r
+       ob->dir = nodir;                // can't move\r
+}\r
+\r
+\r
+/*\r
+============================\r
+=\r
+= SelectRunDir\r
+=\r
+= Run Away from player\r
+=\r
+============================\r
+*/\r
+\r
+void SelectRunDir (objtype *ob)\r
+{\r
+       int deltax,deltay,i;\r
+       dirtype d[3];\r
+       dirtype tdir, olddir, turnaround;\r
+\r
+\r
+       deltax=player->tilex - ob->tilex;\r
+       deltay=player->tiley - ob->tiley;\r
+\r
+       if (deltax<0)\r
+               d[1]= east;\r
+       else\r
+               d[1]= west;\r
+       if (deltay<0)\r
+               d[2]=south;\r
+       else\r
+               d[2]=north;\r
+\r
+       if (abs(deltay)>abs(deltax))\r
+       {\r
+               tdir=d[1];\r
+               d[1]=d[2];\r
+               d[2]=tdir;\r
+       }\r
+\r
+       ob->dir=d[1];\r
+       if (TryWalk(ob))\r
+               return;     /*either moved forward or attacked*/\r
+\r
+       ob->dir=d[2];\r
+       if (TryWalk(ob))\r
+               return;\r
+\r
+/* there is no direct path to the player, so pick another direction */\r
+\r
+       if (US_RndT()>128)      /*randomly determine direction of search*/\r
+       {\r
+               for (tdir=north;tdir<=west;tdir++)\r
+               {\r
+                       ob->dir=tdir;\r
+                       if ( TryWalk(ob) )\r
+                               return;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               for (tdir=west;tdir>=north;tdir--)\r
+               {\r
+                       ob->dir=tdir;\r
+                       if ( TryWalk(ob) )\r
+                         return;\r
+               }\r
+       }\r
+\r
+       ob->dir = nodir;                // can't move\r
+}\r
+\r
+\r
+/*\r
+=================\r
+=\r
+= MoveObj\r
+=\r
+= Moves ob be move global units in ob->dir direction\r
+= Actors are not allowed to move inside the player\r
+= Does NOT check to see if the move is tile map valid\r
+=\r
+= ob->x                        = adjusted for new position\r
+= ob->y\r
+=\r
+=================\r
+*/\r
+\r
+void MoveObj (objtype *ob, long move)\r
+{\r
+       long    deltax,deltay;\r
+\r
+       switch (ob->dir)\r
+       {\r
+       case north:\r
+               ob->y -= move;\r
+               break;\r
+       case northeast:\r
+               ob->x += move;\r
+               ob->y -= move;\r
+               break;\r
+       case east:\r
+               ob->x += move;\r
+               break;\r
+       case southeast:\r
+               ob->x += move;\r
+               ob->y += move;\r
+               break;\r
+       case south:\r
+               ob->y += move;\r
+               break;\r
+       case southwest:\r
+               ob->x -= move;\r
+               ob->y += move;\r
+               break;\r
+       case west:\r
+               ob->x -= move;\r
+               break;\r
+       case northwest:\r
+               ob->x -= move;\r
+               ob->y -= move;\r
+               break;\r
+\r
+       case nodir:\r
+               return;\r
+\r
+       default:\r
+               Quit ("MoveObj: bad dir!");\r
+       }\r
+\r
+//\r
+// check to make sure it's not on top of player\r
+//\r
+       if (areabyplayer[ob->areanumber])\r
+       {\r
+               deltax = ob->x - player->x;\r
+               if (deltax < -MINACTORDIST || deltax > MINACTORDIST)\r
+                       goto moveok;\r
+               deltay = ob->y - player->y;\r
+               if (deltay < -MINACTORDIST || deltay > MINACTORDIST)\r
+                       goto moveok;\r
+\r
+               if (ob->obclass == ghostobj || ob->obclass == spectreobj)\r
+                       TakeDamage (tics*2,ob);\r
+\r
+       //\r
+       // back up\r
+       //\r
+               switch (ob->dir)\r
+               {\r
+               case north:\r
+                       ob->y += move;\r
+                       break;\r
+               case northeast:\r
+                       ob->x -= move;\r
+                       ob->y += move;\r
+                       break;\r
+               case east:\r
+                       ob->x -= move;\r
+                       break;\r
+               case southeast:\r
+                       ob->x -= move;\r
+                       ob->y -= move;\r
+                       break;\r
+               case south:\r
+                       ob->y -= move;\r
+                       break;\r
+               case southwest:\r
+                       ob->x += move;\r
+                       ob->y -= move;\r
+                       break;\r
+               case west:\r
+                       ob->x += move;\r
+                       break;\r
+               case northwest:\r
+                       ob->x += move;\r
+                       ob->y += move;\r
+                       break;\r
+\r
+               case nodir:\r
+                       return;\r
+               }\r
+               return;\r
+       }\r
+moveok:\r
+       ob->distance -=move;\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       STUFF\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+===============\r
+=\r
+= DropItem\r
+=\r
+= Tries to drop a bonus item somewhere in the tiles surrounding the\r
+= given tilex/tiley\r
+=\r
+===============\r
+*/\r
+\r
+void DropItem (stat_t itemtype, int tilex, int tiley)\r
+{\r
+       int     x,y,xl,xh,yl,yh;\r
+\r
+//\r
+// find a free spot to put it in\r
+//\r
+       if (!actorat[tilex][tiley])\r
+       {\r
+               PlaceItemType (itemtype, tilex,tiley);\r
+               return;\r
+       }\r
+\r
+       xl = tilex-1;\r
+       xh = tilex+1;\r
+       yl = tiley-1;\r
+       yh = tiley+1;\r
+\r
+       for (x=xl ; x<= xh ; x++)\r
+               for (y=yl ; y<= yh ; y++)\r
+                       if (!actorat[x][y])\r
+                       {\r
+                               PlaceItemType (itemtype, x,y);\r
+                               return;\r
+                       }\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= KillActor\r
+=\r
+===============\r
+*/\r
+\r
+void KillActor (objtype *ob)\r
+{\r
+       int     tilex,tiley;\r
+\r
+       tilex = ob->tilex = ob->x >> TILESHIFT;         // drop item on center\r
+       tiley = ob->tiley = ob->y >> TILESHIFT;\r
+\r
+       switch (ob->obclass)\r
+       {\r
+       case guardobj:\r
+               GivePoints (100);\r
+               NewState (ob,&s_grddie1);\r
+               PlaceItemType (bo_clip2,tilex,tiley);\r
+               break;\r
+\r
+       case officerobj:\r
+               GivePoints (400);\r
+               NewState (ob,&s_ofcdie1);\r
+               PlaceItemType (bo_clip2,tilex,tiley);\r
+               break;\r
+\r
+       case mutantobj:\r
+               GivePoints (700);\r
+               NewState (ob,&s_mutdie1);\r
+               PlaceItemType (bo_clip2,tilex,tiley);\r
+               break;\r
+\r
+       case ssobj:\r
+               GivePoints (500);\r
+               NewState (ob,&s_ssdie1);\r
+               if (gamestate.bestweapon < wp_machinegun)\r
+                       PlaceItemType (bo_machinegun,tilex,tiley);\r
+               else\r
+                       PlaceItemType (bo_clip2,tilex,tiley);\r
+               break;\r
+\r
+       case dogobj:\r
+               GivePoints (200);\r
+               NewState (ob,&s_dogdie1);\r
+               break;\r
+\r
+#ifndef SPEAR\r
+       case bossobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_bossdie1);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+\r
+       case gretelobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_greteldie1);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+\r
+       case giftobj:\r
+               GivePoints (5000);\r
+               gamestate.killx = player->x;\r
+               gamestate.killy = player->y;\r
+               NewState (ob,&s_giftdie1);\r
+               break;\r
+\r
+       case fatobj:\r
+               GivePoints (5000);\r
+               gamestate.killx = player->x;\r
+               gamestate.killy = player->y;\r
+               NewState (ob,&s_fatdie1);\r
+               break;\r
+\r
+       case schabbobj:\r
+               GivePoints (5000);\r
+               gamestate.killx = player->x;\r
+               gamestate.killy = player->y;\r
+               NewState (ob,&s_schabbdie1);\r
+               A_DeathScream(ob);\r
+               break;\r
+       case fakeobj:\r
+               GivePoints (2000);\r
+               NewState (ob,&s_fakedie1);\r
+               break;\r
+\r
+       case mechahitlerobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_mechadie1);\r
+               break;\r
+       case realhitlerobj:\r
+               GivePoints (5000);\r
+               gamestate.killx = player->x;\r
+               gamestate.killy = player->y;\r
+               NewState (ob,&s_hitlerdie1);\r
+               A_DeathScream(ob);\r
+               break;\r
+#else\r
+       case spectreobj:\r
+               GivePoints (200);\r
+               NewState (ob,&s_spectredie1);\r
+               break;\r
+\r
+       case angelobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_angeldie1);\r
+               break;\r
+\r
+       case transobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_transdie0);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+\r
+       case uberobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_uberdie0);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+\r
+       case willobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_willdie1);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+\r
+       case deathobj:\r
+               GivePoints (5000);\r
+               NewState (ob,&s_deathdie1);\r
+               PlaceItemType (bo_key1,tilex,tiley);\r
+               break;\r
+#endif\r
+       }\r
+\r
+       gamestate.killcount++;\r
+       ob->flags &= ~FL_SHOOTABLE;\r
+       actorat[ob->tilex][ob->tiley] = NULL;\r
+       ob->flags |= FL_NONMARK;\r
+}\r
+\r
+\r
+\r
+/*\r
+===================\r
+=\r
+= DamageActor\r
+=\r
+= Called when the player succesfully hits an enemy.\r
+=\r
+= Does damage points to enemy ob, either putting it into a stun frame or\r
+= killing it.\r
+=\r
+===================\r
+*/\r
+\r
+void DamageActor (objtype *ob, unsigned damage)\r
+{\r
+       madenoise = true;\r
+\r
+//\r
+// do double damage if shooting a non attack mode actor\r
+//\r
+       if ( !(ob->flags & FL_ATTACKMODE) )\r
+               damage <<= 1;\r
+\r
+       ob->hitpoints -= damage;\r
+\r
+       if (ob->hitpoints<=0)\r
+               KillActor (ob);\r
+       else\r
+       {\r
+               if (! (ob->flags & FL_ATTACKMODE) )\r
+                       FirstSighting (ob);             // put into combat mode\r
+\r
+               switch (ob->obclass)            // dogs only have one hit point\r
+               {\r
+               case guardobj:\r
+                       if (ob->hitpoints&1)\r
+                               NewState (ob,&s_grdpain);\r
+                       else\r
+                               NewState (ob,&s_grdpain1);\r
+                       break;\r
+\r
+               case officerobj:\r
+                       if (ob->hitpoints&1)\r
+                               NewState (ob,&s_ofcpain);\r
+                       else\r
+                               NewState (ob,&s_ofcpain1);\r
+                       break;\r
+\r
+               case mutantobj:\r
+                       if (ob->hitpoints&1)\r
+                               NewState (ob,&s_mutpain);\r
+                       else\r
+                               NewState (ob,&s_mutpain1);\r
+                       break;\r
+\r
+               case ssobj:\r
+                       if (ob->hitpoints&1)\r
+                               NewState (ob,&s_sspain);\r
+                       else\r
+                               NewState (ob,&s_sspain1);\r
+\r
+                       break;\r
+\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                       CHECKSIGHT\r
+\r
+=============================================================================\r
+*/\r
+\r
+\r
+/*\r
+=====================\r
+=\r
+= CheckLine\r
+=\r
+= Returns true if a straight line between the player and ob is unobstructed\r
+=\r
+=====================\r
+*/\r
+\r
+boolean CheckLine (objtype *ob)\r
+{\r
+       int     x1,y1,xt1,yt1,x2,y2,xt2,yt2;\r
+       int     x,y;\r
+       int     xdist,ydist,xstep,ystep;\r
+       int     temp;\r
+       int     partial,delta;\r
+       long    ltemp;\r
+       int     xfrac,yfrac,deltafrac;\r
+       unsigned        value,intercept;\r
+\r
+       x1 = ob->x >> UNSIGNEDSHIFT;            // 1/256 tile precision\r
+       y1 = ob->y >> UNSIGNEDSHIFT;\r
+       xt1 = x1 >> 8;\r
+       yt1 = y1 >> 8;\r
+\r
+       x2 = plux;\r
+       y2 = pluy;\r
+       xt2 = player->tilex;\r
+       yt2 = player->tiley;\r
+\r
+\r
+       xdist = abs(xt2-xt1);\r
+\r
+       if (xdist > 0)\r
+       {\r
+               if (xt2 > xt1)\r
+               {\r
+                       partial = 256-(x1&0xff);\r
+                       xstep = 1;\r
+               }\r
+               else\r
+               {\r
+                       partial = x1&0xff;\r
+                       xstep = -1;\r
+               }\r
+\r
+               deltafrac = abs(x2-x1);\r
+               delta = y2-y1;\r
+               ltemp = ((long)delta<<8)/deltafrac;\r
+               if (ltemp > 0x7fffl)\r
+                       ystep = 0x7fff;\r
+               else if (ltemp < -0x7fffl)\r
+                       ystep = -0x7fff;\r
+               else\r
+                       ystep = ltemp;\r
+               yfrac = y1 + (((long)ystep*partial) >>8);\r
+\r
+               x = xt1+xstep;\r
+               xt2 += xstep;\r
+               do\r
+               {\r
+                       y = yfrac>>8;\r
+                       yfrac += ystep;\r
+\r
+                       value = (unsigned)tilemap[x][y];\r
+                       x += xstep;\r
+\r
+                       if (!value)\r
+                               continue;\r
+\r
+                       if (value<128 || value>256)\r
+                               return false;\r
+\r
+                       //\r
+                       // see if the door is open enough\r
+                       //\r
+                       value &= ~0x80;\r
+                       intercept = yfrac-ystep/2;\r
+\r
+                       if (intercept>doorposition[value])\r
+                               return false;\r
+\r
+               } while (x != xt2);\r
+       }\r
+\r
+       ydist = abs(yt2-yt1);\r
+\r
+       if (ydist > 0)\r
+       {\r
+               if (yt2 > yt1)\r
+               {\r
+                       partial = 256-(y1&0xff);\r
+                       ystep = 1;\r
+               }\r
+               else\r
+               {\r
+                       partial = y1&0xff;\r
+                       ystep = -1;\r
+               }\r
+\r
+               deltafrac = abs(y2-y1);\r
+               delta = x2-x1;\r
+               ltemp = ((long)delta<<8)/deltafrac;\r
+               if (ltemp > 0x7fffl)\r
+                       xstep = 0x7fff;\r
+               else if (ltemp < -0x7fffl)\r
+                       xstep = -0x7fff;\r
+               else\r
+                       xstep = ltemp;\r
+               xfrac = x1 + (((long)xstep*partial) >>8);\r
+\r
+               y = yt1 + ystep;\r
+               yt2 += ystep;\r
+               do\r
+               {\r
+                       x = xfrac>>8;\r
+                       xfrac += xstep;\r
+\r
+                       value = (unsigned)tilemap[x][y];\r
+                       y += ystep;\r
+\r
+                       if (!value)\r
+                               continue;\r
+\r
+                       if (value<128 || value>256)\r
+                               return false;\r
+\r
+                       //\r
+                       // see if the door is open enough\r
+                       //\r
+                       value &= ~0x80;\r
+                       intercept = xfrac-xstep/2;\r
+\r
+                       if (intercept>doorposition[value])\r
+                               return false;\r
+               } while (y != yt2);\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+\r
+\r
+/*\r
+================\r
+=\r
+= CheckSight\r
+=\r
+= Checks a straight line between player and current object\r
+=\r
+= If the sight is ok, check alertness and angle to see if they notice\r
+=\r
+= returns true if the player has been spoted\r
+=\r
+================\r
+*/\r
+\r
+#define MINSIGHT       0x18000l\r
+\r
+boolean CheckSight (objtype *ob)\r
+{\r
+       long            deltax,deltay;\r
+\r
+//\r
+// don't bother tracing a line if the area isn't connected to the player's\r
+//\r
+       if (!areabyplayer[ob->areanumber])\r
+               return false;\r
+\r
+//\r
+// if the player is real close, sight is automatic\r
+//\r
+       deltax = player->x - ob->x;\r
+       deltay = player->y - ob->y;\r
+\r
+       if (deltax > -MINSIGHT && deltax < MINSIGHT\r
+       && deltay > -MINSIGHT && deltay < MINSIGHT)\r
+               return true;\r
+\r
+//\r
+// see if they are looking in the right direction\r
+//\r
+       switch (ob->dir)\r
+       {\r
+       case north:\r
+               if (deltay > 0)\r
+                       return false;\r
+               break;\r
+\r
+       case east:\r
+               if (deltax < 0)\r
+                       return false;\r
+               break;\r
+\r
+       case south:\r
+               if (deltay < 0)\r
+                       return false;\r
+               break;\r
+\r
+       case west:\r
+               if (deltax > 0)\r
+                       return false;\r
+               break;\r
+       }\r
+\r
+//\r
+// trace a line to check for blocking tiles (corners)\r
+//\r
+       return CheckLine (ob);\r
+\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= FirstSighting\r
+=\r
+= Puts an actor into attack mode and possibly reverses the direction\r
+= if the player is behind it\r
+=\r
+===============\r
+*/\r
+\r
+void FirstSighting (objtype *ob)\r
+{\r
+//\r
+// react to the player\r
+//\r
+       switch (ob->obclass)\r
+       {\r
+       case guardobj:\r
+               PlaySoundLocActor(HALTSND,ob);\r
+               NewState (ob,&s_grdchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case officerobj:\r
+               PlaySoundLocActor(SPIONSND,ob);\r
+               NewState (ob,&s_ofcchase1);\r
+               ob->speed *= 5;                 // go faster when chasing player\r
+               break;\r
+\r
+       case mutantobj:\r
+               NewState (ob,&s_mutchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case ssobj:\r
+               PlaySoundLocActor(SCHUTZADSND,ob);\r
+               NewState (ob,&s_sschase1);\r
+               ob->speed *= 4;                 // go faster when chasing player\r
+               break;\r
+\r
+       case dogobj:\r
+               PlaySoundLocActor(DOGBARKSND,ob);\r
+               NewState (ob,&s_dogchase1);\r
+               ob->speed *= 2;                 // go faster when chasing player\r
+               break;\r
+\r
+#ifndef SPEAR\r
+       case bossobj:\r
+               SD_PlaySound(GUTENTAGSND);\r
+               NewState (ob,&s_bosschase1);\r
+               ob->speed = SPDPATROL*3;        // go faster when chasing player\r
+               break;\r
+\r
+       case gretelobj:\r
+               SD_PlaySound(KEINSND);\r
+               NewState (ob,&s_gretelchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case giftobj:\r
+               SD_PlaySound(EINESND);\r
+               NewState (ob,&s_giftchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case fatobj:\r
+               SD_PlaySound(ERLAUBENSND);\r
+               NewState (ob,&s_fatchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case schabbobj:\r
+               SD_PlaySound(SCHABBSHASND);\r
+               NewState (ob,&s_schabbchase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case fakeobj:\r
+               SD_PlaySound(TOT_HUNDSND);\r
+               NewState (ob,&s_fakechase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case mechahitlerobj:\r
+               SD_PlaySound(DIESND);\r
+               NewState (ob,&s_mechachase1);\r
+               ob->speed *= 3;                 // go faster when chasing player\r
+               break;\r
+\r
+       case realhitlerobj:\r
+               SD_PlaySound(DIESND);\r
+               NewState (ob,&s_hitlerchase1);\r
+               ob->speed *= 5;                 // go faster when chasing player\r
+               break;\r
+\r
+       case ghostobj:\r
+               NewState (ob,&s_blinkychase1);\r
+               ob->speed *= 2;                 // go faster when chasing player\r
+               break;\r
+#else\r
+\r
+       case spectreobj:\r
+               SD_PlaySound(GHOSTSIGHTSND);\r
+               NewState (ob,&s_spectrechase1);\r
+               ob->speed = 800;                        // go faster when chasing player\r
+               break;\r
+\r
+       case angelobj:\r
+               SD_PlaySound(ANGELSIGHTSND);\r
+               NewState (ob,&s_angelchase1);\r
+               ob->speed = 1536;                       // go faster when chasing player\r
+               break;\r
+\r
+       case transobj:\r
+               SD_PlaySound(TRANSSIGHTSND);\r
+               NewState (ob,&s_transchase1);\r
+               ob->speed = 1536;                       // go faster when chasing player\r
+               break;\r
+\r
+       case uberobj:\r
+               NewState (ob,&s_uberchase1);\r
+               ob->speed = 3000;                       // go faster when chasing player\r
+               break;\r
+\r
+       case willobj:\r
+               SD_PlaySound(WILHELMSIGHTSND);\r
+               NewState (ob,&s_willchase1);\r
+               ob->speed = 2048;                       // go faster when chasing player\r
+               break;\r
+\r
+       case deathobj:\r
+               SD_PlaySound(KNIGHTSIGHTSND);\r
+               NewState (ob,&s_deathchase1);\r
+               ob->speed = 2048;                       // go faster when chasing player\r
+               break;\r
+\r
+#endif\r
+       }\r
+\r
+       if (ob->distance < 0)\r
+               ob->distance = 0;       // ignore the door opening command\r
+\r
+       ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;\r
+}\r
+\r
+\r
+\r
+/*\r
+===============\r
+=\r
+= SightPlayer\r
+=\r
+= Called by actors that ARE NOT chasing the player.  If the player\r
+= is detected (by sight, noise, or proximity), the actor is put into\r
+= it's combat frame and true is returned.\r
+=\r
+= Incorporates a random reaction delay\r
+=\r
+===============\r
+*/\r
+\r
+boolean SightPlayer (objtype *ob)\r
+{\r
+       if (ob->flags & FL_ATTACKMODE)\r
+               Quit ("An actor in ATTACKMODE called SightPlayer!");\r
+\r
+       if (ob->temp2)\r
+       {\r
+       //\r
+       // count down reaction time\r
+       //\r
+               ob->temp2 -= tics;\r
+               if (ob->temp2 > 0)\r
+                       return false;\r
+               ob->temp2 = 0;                                  // time to react\r
+       }\r
+       else\r
+       {\r
+               if (!areabyplayer[ob->areanumber])\r
+                       return false;\r
+\r
+               if (ob->flags & FL_AMBUSH)\r
+               {\r
+                       if (!CheckSight (ob))\r
+                               return false;\r
+                       ob->flags &= ~FL_AMBUSH;\r
+               }\r
+               else\r
+               {\r
+                       if (!madenoise && !CheckSight (ob))\r
+                               return false;\r
+               }\r
+\r
+\r
+               switch (ob->obclass)\r
+               {\r
+               case guardobj:\r
+                       ob->temp2 = 1+US_RndT()/4;\r
+                       break;\r
+               case officerobj:\r
+                       ob->temp2 = 2;\r
+                       break;\r
+               case mutantobj:\r
+                       ob->temp2 = 1+US_RndT()/6;\r
+                       break;\r
+               case ssobj:\r
+                       ob->temp2 = 1+US_RndT()/6;\r
+                       break;\r
+               case dogobj:\r
+                       ob->temp2 = 1+US_RndT()/8;\r
+                       break;\r
+\r
+               case bossobj:\r
+               case schabbobj:\r
+               case fakeobj:\r
+               case mechahitlerobj:\r
+               case realhitlerobj:\r
+               case gretelobj:\r
+               case giftobj:\r
+               case fatobj:\r
+               case spectreobj:\r
+               case angelobj:\r
+               case transobj:\r
+               case uberobj:\r
+               case willobj:\r
+               case deathobj:\r
+                       ob->temp2 = 1;\r
+                       break;\r
+               }\r
+               return false;\r
+       }\r
+\r
+       FirstSighting (ob);\r
+\r
+       return true;\r
+}\r
+\r
+\r