+++ /dev/null
-/* Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_STATE.C\r
-\r
-#include "C3_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
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-dirtype opposite[9] =\r
- {south,west,north,east,southwest,northwest,northeast,southeast,nodir};\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= SpawnNewObj\r
-=\r
-===================\r
-*/\r
-\r
-void SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size)\r
-{\r
- GetNewObj (false);\r
- new->size = size;\r
- new->state = state;\r
- new->ticcount = random (state->tictime)+1;\r
-\r
- new->tilex = x;\r
- new->tiley = y;\r
- new->x = ((long)x<<TILESHIFT)+TILEGLOBAL/2;\r
- new->y = ((long)y<<TILESHIFT)+TILEGLOBAL/2;\r
- CalcBounds(new);\r
- new->dir = nodir;\r
-\r
- actorat[new->tilex][new->tiley] = new;\r
-}\r
-\r
-void SpawnNewObjFrac (long x, long y, statetype *state, unsigned size)\r
-{\r
- GetNewObj (false);\r
- new->size = size;\r
- new->state = state;\r
- new->ticcount = random (state->tictime)+1;\r
- new->active = true;\r
-\r
- new->x = x;\r
- new->y = y;\r
- new->tilex = x>>TILESHIFT;\r
- new->tiley = y>>TILESHIFT;\r
- CalcBounds(new);\r
- new->distance = 100;\r
- new->dir = nodir;\r
-}\r
-\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= CheckHandAttack\r
-=\r
-= If the object can move next to the player, it will return true\r
-=\r
-===================\r
-*/\r
-\r
-boolean CheckHandAttack (objtype *ob)\r
-{\r
- long deltax,deltay,size;\r
-\r
- size = (long)ob->size + player->size + ob->speed*tics;\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax > size || deltax < -size || deltay > size || deltay < -size)\r
- return false;\r
-\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= T_DoDamage\r
-=\r
-= Attacks the player if still nearby, then immediately changes to next state\r
-=\r
-===================\r
-*/\r
-\r
-void T_DoDamage (objtype *ob)\r
-{\r
- int points;\r
-\r
-\r
- if (!CheckHandAttack (ob))\r
- {\r
- SD_PlaySound (MONSTERMISSSND);\r
- }\r
- else\r
- {\r
- points = 0;\r
-\r
- switch (ob->obclass)\r
- {\r
- case orcobj:\r
- points = 4;\r
- break;\r
- case trollobj:\r
- points = 8;\r
- break;\r
- case demonobj:\r
- points = 15;\r
- break;\r
- }\r
- TakeDamage (points);\r
- }\r
-\r
- ob->state = ob->state->next;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================================\r
-=\r
-= Walk\r
-=\r
-==================================\r
-*/\r
-\r
-boolean Walk (objtype *ob)\r
-{\r
- switch (ob->dir)\r
- {\r
- case north:\r
- if (actorat[ob->tilex][ob->tiley-1])\r
- return false;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case northeast:\r
- if (actorat[ob->tilex+1][ob->tiley-1])\r
- return false;\r
- ob->tilex++;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case east:\r
- if (actorat[ob->tilex+1][ob->tiley])\r
- return false;\r
- ob->tilex++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case southeast:\r
- if (actorat[ob->tilex+1][ob->tiley+1])\r
- return false;\r
- ob->tilex++;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case south:\r
- if (actorat[ob->tilex][ob->tiley+1])\r
- return false;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case southwest:\r
- if (actorat[ob->tilex-1][ob->tiley+1])\r
- return false;\r
- ob->tilex--;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case west:\r
- if (actorat[ob->tilex-1][ob->tiley])\r
- return false;\r
- ob->tilex--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case northwest:\r
- if (actorat[ob->tilex-1][ob->tiley-1])\r
- return false;\r
- ob->tilex--;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case nodir:\r
- return false;\r
- }\r
-\r
- Quit ("Walk: Bad dir");\r
- return false;\r
-}\r
-\r
-\r
-\r
-/*\r
-==================================\r
-=\r
-= ChaseThink\r
-= have the current monster go after the player,\r
-= either diagonally or straight on\r
-=\r
-==================================\r
-*/\r
-\r
-void ChaseThink (objtype *obj, boolean diagonal)\r
-{\r
- int deltax,deltay,i;\r
- dirtype d[3];\r
- dirtype tdir, olddir, turnaround;\r
-\r
-\r
- olddir=obj->dir;\r
- turnaround=opposite[olddir];\r
-\r
- deltax=player->tilex - obj->tilex;\r
- deltay=player->tiley - obj->tiley;\r
-\r
- d[1]=nodir;\r
- d[2]=nodir;\r
-\r
- if (deltax>0)\r
- d[1]= east;\r
- if (deltax<0)\r
- d[1]= west;\r
- if (deltay>0)\r
- d[2]=south;\r
- 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 (diagonal)\r
- { /*ramdiagonals try the best dir first*/\r
- if (d[1]!=nodir)\r
- {\r
- obj->dir=d[1];\r
- if (Walk(obj))\r
- return; /*either moved forward or attacked*/\r
- }\r
-\r
- if (d[2]!=nodir)\r
- {\r
- obj->dir=d[2];\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- else\r
- { /*ramstraights try the second best dir first*/\r
-\r
- if (d[2]!=nodir)\r
- {\r
- obj->dir=d[2];\r
- if (Walk(obj))\r
- return;\r
- }\r
-\r
- if (d[1]!=nodir)\r
- {\r
- obj->dir=d[1];\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
-\r
-/* there is no direct path to the player, so pick another direction */\r
-\r
- obj->dir=olddir;\r
- if (Walk(obj))\r
- return;\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
- obj->dir=tdir;\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- for (tdir=west;tdir>=north;tdir--)\r
- {\r
- if (tdir!=turnaround)\r
- {\r
- obj->dir=tdir;\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- }\r
-\r
- obj->dir=turnaround;\r
- Walk(obj); /*last chance, don't worry about returned value*/\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= MoveObj\r
-=\r
-=================\r
-*/\r
-\r
-void MoveObj (objtype *ob, long move)\r
-{\r
- ob->distance -=move;\r
-\r
- switch (ob->dir)\r
- {\r
- case north:\r
- ob->y -= move;\r
- return;\r
- case northeast:\r
- ob->x += move;\r
- ob->y -= move;\r
- return;\r
- case east:\r
- ob->x += move;\r
- return;\r
- case southeast:\r
- ob->x += move;\r
- ob->y += move;\r
- return;\r
- case south:\r
- ob->y += move;\r
- return;\r
- case southwest:\r
- ob->x -= move;\r
- ob->y += move;\r
- return;\r
- case west:\r
- ob->x -= move;\r
- return;\r
- case northwest:\r
- ob->x -= move;\r
- ob->y -= move;\r
- return;\r
-\r
- case nodir:\r
- return;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= Chase\r
-=\r
-= returns true if hand attack range\r
-=\r
-=================\r
-*/\r
-\r
-boolean Chase (objtype *ob, boolean diagonal)\r
-{\r
- long move;\r
- long deltax,deltay,size;\r
-\r
- move = ob->speed*tics;\r
- size = (long)ob->size + player->size + move;\r
-\r
- while (move)\r
- {\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax <= size && deltax >= -size\r
- && deltay <= size && deltay >= -size)\r
- {\r
- CalcBounds (ob);\r
- return true;\r
- }\r
-\r
- if (move < ob->distance)\r
- {\r
- MoveObj (ob,move);\r
- break;\r
- }\r
- actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal\r
- if (ob->dir == nodir)\r
- ob->dir = north;\r
-\r
- ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- move -= ob->distance;\r
-\r
- ChaseThink (ob,diagonal);\r
- if (!ob->distance)\r
- break; // no possible move\r
- actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker\r
- }\r
- CalcBounds (ob);\r
- return false;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= ShootActor\r
-=\r
-===================\r
-*/\r
-\r
-void ShootActor (objtype *ob, unsigned damage)\r
-{\r
- ob->hitpoints -= damage;\r
- if (ob->hitpoints<=0)\r
- {\r
- switch (ob->obclass)\r
- {\r
- case orcobj:\r
- ob->state = &s_orcdie1;\r
- GivePoints (100);\r
- break;\r
- case trollobj:\r
- ob->state = &s_trolldie1;\r
- GivePoints (400);\r
- break;\r
- case demonobj:\r
- ob->state = &s_demondie1;\r
- GivePoints (1000);\r
- break;\r
- case mageobj:\r
- ob->state = &s_magedie1;\r
- GivePoints (600);\r
- break;\r
- case batobj:\r
- ob->state = &s_batdie1;\r
- GivePoints (100);\r
- break;\r
- case grelmobj:\r
- ob->state = &s_greldie1;\r
- GivePoints (10000);\r
- break;\r
-\r
- }\r
- ob->obclass = inertobj;\r
- ob->shootable = false;\r
- actorat[ob->tilex][ob->tiley] = NULL;\r
- }\r
- else\r
- {\r
- switch (ob->obclass)\r
- {\r
- case orcobj:\r
- ob->state = &s_orcouch;\r
- break;\r
- case trollobj:\r
- ob->state = &s_trollouch;\r
- break;\r
- case demonobj:\r
- ob->state = &s_demonouch;\r
- break;\r
- case mageobj:\r
- ob->state = &s_mageouch;\r
- break;\r
- case grelmobj:\r
- ob->state = &s_grelouch;\r
- break;\r
-\r
- }\r
- }\r
- ob->ticcount = ob->state->tictime;\r
-}\r
-\r