+++ /dev/null
-// 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