+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is loosely based on:\r
- * Keen Dreams Source Code\r
- * Copyright (C) 2014 Javier M. Chavez\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
-#include "CK_DEF.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Sint16 wallclip[8][16] = { // the height of a given point in a tile\r
-{ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256},\r
-{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},\r
-{ 0,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78},\r
-{0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0xe0,0xe8,0xf0,0xf8},\r
-{ 0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0},\r
-{0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x18,0x10,0x08, 0},\r
-{0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x98,0x90,0x88,0x80},\r
-{0xf0,0xe0,0xd0,0xc0,0xb0,0xa0,0x90,0x80,0x70,0x60,0x50,0x40,0x30,0x20,0x10, 0}\r
-};\r
-\r
-Sint16 xtry, ytry;\r
-boolean playerkludgeclipcancel;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-Uint16 oldtileleft, oldtiletop, oldtileright, oldtilebottom, oldtilemidx;\r
-Uint16 oldleft, oldtop, oldright, oldbottom, oldmidx;\r
-Sint16 leftmoved, topmoved, rightmoved, bottommoved, midxmoved;\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MoveObjVert\r
-=\r
-====================\r
-*/\r
-\r
-void MoveObjVert(objtype *ob, Sint16 ymove)\r
-{\r
- ob->y += ymove;\r
- ob->top += ymove;\r
- ob->bottom += ymove;\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MoveObjHoriz\r
-=\r
-====================\r
-*/\r
-\r
-void MoveObjHoriz(objtype *ob, Sint16 xmove)\r
-{\r
- //BUG? ob->midx is not adjusted in Keen 4 & 5\r
- ob->x += xmove;\r
- ob->left += xmove;\r
- ob->right += xmove;\r
-#ifdef KEEN6\r
- ob->midx += xmove; //BUG? ob->tilemidx is not updated\r
-#endif\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= PlayerBottomKludge\r
-=\r
-====================\r
-*/\r
-\r
-void PlayerBottomKludge(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 wall, clip, xpix;\r
- Sint16 xmove, ymove;\r
-\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tilebottom-1]/2;\r
- if (ob->xdir == 1)\r
- {\r
- xpix = 0;\r
- map += ob->tileright;\r
- xmove = ob->right - ob->midx;\r
- if (tinf[*(map-mapwidth)+WESTWALL] || tinf[*map+WESTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- xpix = 15;\r
- map += ob->tileleft;\r
- xmove = ob->left - ob->midx;\r
- if (tinf[*(map-mapwidth)+EASTWALL] || tinf[*map+EASTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- if ((_AX = tinf[*map+NORTHWALL]) != 0) // the _AX = ... part is just to recreate the original code's quirks, feel free to delete this\r
- {\r
- return;\r
- }\r
- map += mapwidth;\r
- if ((wall = tinf[*map+NORTHWALL]) != 1)\r
- {\r
- return;\r
- }\r
- clip = wallclip[wall&7][xpix];\r
- ymove = CONVERT_TILE_TO_GLOBAL(ob->tilebottom) + clip - 1 -ob->bottom;\r
- if (ymove <= 0 && ymove >= -bottommoved)\r
- {\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, ymove);\r
- MoveObjHoriz(ob, xmove);\r
- }\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= PlayerTopKludge\r
-=\r
-====================\r
-*/\r
-\r
-void PlayerTopKludge(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 xpix, wall, clip;\r
- Sint16 move;\r
-\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop+1]/2;\r
- if (ob->xdir == 1)\r
- {\r
- xpix = 0;\r
- map += ob->tileright;\r
- if (tinf[*(map+mapwidth)+WESTWALL] || tinf[*(map+2*mapwidth)+WESTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- xpix = 15;\r
- map += ob->tileleft;\r
- if (tinf[*(map+mapwidth)+EASTWALL] || tinf[*(map+2*mapwidth)+EASTWALL])\r
- {\r
- return;\r
- }\r
- }\r
- if ((_AX = tinf[*map+SOUTHWALL]) != 0) // the _AX = ... part is just to recreate the original code's quirks, feel free to delete this\r
- {\r
- return;\r
- }\r
- map -= mapwidth;\r
- if ((wall = tinf[*map+SOUTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][xpix];\r
- move = CONVERT_TILE_TO_GLOBAL(ob->tiletop+1) - clip - ob->top;\r
- if (move >= 0 && move <= -topmoved)\r
- {\r
- ob->hitsouth = wall;\r
- MoveObjVert(ob, move);\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= ClipToEnds\r
-=\r
-===========================\r
-*/\r
-\r
-void ClipToEnds(objtype *ob)\r
-{\r
- Uint16 far *map;\r
- Uint16 wall, y, clip;\r
- Sint16 totalmove, maxmove, move;\r
- Uint16 midxpix;\r
- \r
- midxpix = CONVERT_GLOBAL_TO_PIXEL(ob->midx & 0xF0);\r
- maxmove = -abs(midxmoved)-bottommoved-16;\r
- map = (Uint16 far *)mapsegs[1] + (mapbwidthtable-1)[oldtilebottom]/2 + ob->tilemidx;\r
- for (y=oldtilebottom-1; y <= ob->tilebottom; y++,map+=mapwidth)\r
- {\r
- if ((wall = tinf[*map + NORTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][midxpix];\r
- move = (CONVERT_TILE_TO_GLOBAL(y) + clip)-1-ob->bottom;\r
- if (move < 0 && move >= maxmove)\r
- {\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, move);\r
- return;\r
- }\r
- }\r
- }\r
- maxmove = abs(midxmoved)-topmoved+16;\r
- map = (Uint16 far *)mapsegs[1] + (mapbwidthtable+1)[oldtiletop]/2 + ob->tilemidx;\r
- for (y=oldtiletop+1; y >= ob->tiletop; y--,map-=mapwidth) // BUG: unsigned comparison - loop never ends if ob->tiletop is 0\r
- {\r
- if ((wall = tinf[*map + SOUTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall&7][midxpix];\r
- move = CONVERT_TILE_TO_GLOBAL(y+1) - clip - ob->top;\r
- if (move > 0 && move <= maxmove)\r
- {\r
- totalmove = ytry+move;\r
- if (totalmove < 0x100 && totalmove > -0x100)\r
- {\r
- ob->hitsouth = wall;\r
- MoveObjVert(ob, move);\r
- //BUG? no return here\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= ClipToSides\r
-=\r
-===========================\r
-*/\r
-\r
-void ClipToSides(objtype *ob)\r
-{\r
- Sint16 move, y, top, bottom;\r
- Uint16 far *map;\r
- \r
- top = ob->tiletop;\r
- if (ob->hitsouth > 1)\r
- {\r
- top++;\r
- }\r
- bottom = ob->tilebottom;\r
- if (ob->hitnorth > 1)\r
- {\r
- bottom--;\r
- }\r
- for (y=top; y<=bottom; y++)\r
- {\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[y]/2 + ob->tileleft;\r
- if ((ob->hiteast = tinf[*map+EASTWALL]) != 0)\r
- {\r
- move = CONVERT_TILE_TO_GLOBAL(ob->tileleft+1) - ob->left;\r
- MoveObjHoriz(ob, move);\r
- return;\r
- }\r
- }\r
- for (y=top; y<=bottom; y++)\r
- {\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[y]/2 + ob->tileright;\r
- if ((ob->hitwest = tinf[*map+WESTWALL]) != 0)\r
- {\r
- move = (CONVERT_TILE_TO_GLOBAL(ob->tileright)-1)-ob->right;\r
- MoveObjHoriz(ob, move);\r
- return;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= CheckPosition\r
-=\r
-===========================\r
-*/\r
-\r
-boolean CheckPosition(objtype *ob)\r
-{\r
-#ifdef KEEN6Ev15\r
- // This version is pretty much a compiler-optimized version of the other\r
- // version below, but I simply could not get the compiler to optimize it\r
- // in exactly the same way.\r
-\r
- Uint16 tile, x, tileright;\r
- Uint16 far *map;\r
- Uint16 rowdiff;\r
- Uint16 tileleft, y, tilebottom;\r
- \r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdiff = mapwidth-(ob->tileright-ob->tileleft+1);\r
-\r
- y = ob->tiletop;\r
- tileleft = ob->tileleft;\r
- tileright = _AX = ob->tileright;\r
- tilebottom = ob->tilebottom;\r
-\r
- for (; tilebottom>=y; y++,map+=rowdiff)\r
- {\r
- for (x=tileleft; tileright>=x; x++)\r
- {\r
- tile = *(map++);\r
- if (tinf[tile+NORTHWALL] || tinf[tile+EASTWALL] || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- {\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
-#else\r
- Uint16 tile, x, y;\r
- Uint16 far *map;\r
- Uint16 rowdiff;\r
- \r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[ob->tiletop]/2 + ob->tileleft;\r
- rowdiff = mapwidth-(ob->tileright-ob->tileleft+1);\r
- for (y=ob->tiletop; y<=ob->tilebottom; y++,map+=rowdiff)\r
- {\r
- for (x=ob->tileleft; x<=ob->tileright; x++)\r
- {\r
- tile = *(map++);\r
- if (tinf[tile+NORTHWALL] || tinf[tile+EASTWALL] || tinf[tile+SOUTHWALL] || tinf[tile+WESTWALL])\r
- {\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
-#endif\r
-}\r
-\r
-/*\r
-===========================\r
-=\r
-= StatePositionOk\r
-=\r
-===========================\r
-*/\r
-\r
-boolean StatePositionOk(objtype *ob, statetype *state)\r
-{\r
- spritetabletype far *shape;\r
-\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
- return CheckPosition(ob);\r
-}\r
-\r
-#ifdef KEEN5\r
-/*\r
-===========================\r
-=\r
-= CalcBounds\r
-=\r
-===========================\r
-*/\r
-\r
-void CalcBounds(objtype *ob) //not present in Keen 4 & 6\r
-{\r
- spritetabletype far *shape;\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-================\r
-=\r
-= ClipToWalls\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void ClipToWalls(objtype *ob)\r
-{\r
- Uint16 oldx, oldy;\r
-#ifdef KEEN6\r
- Uint16 y;\r
-#endif\r
- spritetabletype far *shape;\r
- boolean pushed;\r
-\r
- oldx = ob->x;\r
- oldy = ob->y;\r
- pushed = false;\r
-\r
-//\r
-// make sure it stays in contact with a 45 degree slope\r
-//\r
- if (ob->state->pushtofloor)\r
- {\r
- if (ob->hitnorth == 25)\r
- {\r
- ytry = 145;\r
- }\r
- else\r
- {\r
- if (xtry > 0)\r
- {\r
- ytry = xtry+16;\r
- }\r
- else\r
- {\r
- ytry = -xtry+16;\r
- }\r
- pushed = true;\r
- }\r
- }\r
-\r
-//\r
-// move the shape\r
-//\r
- if (xtry > 239)\r
- {\r
- xtry = 239;\r
- }\r
- else if (xtry < -239)\r
- {\r
- xtry = -239;\r
- }\r
- if (ytry > 255) // +16 for push to floor\r
- {\r
- ytry = 255;\r
- }\r
- else if (ytry < -239)\r
- {\r
- ytry = -239;\r
- }\r
-\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- if (!ob->shapenum) // can't get a hit rect with no shape!\r
- {\r
- return;\r
- }\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- oldtileright = ob->tileright;\r
- oldtiletop = ob->tiletop;\r
- oldtileleft = ob->tileleft;\r
- oldtilebottom = ob->tilebottom;\r
- oldtilemidx = ob->tilemidx;\r
-\r
- oldright = ob->right;\r
- oldtop = ob->top;\r
- oldleft = ob->left;\r
- oldbottom = ob->bottom;\r
- oldmidx = ob->midx;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
-\r
- ob->hitnorth=ob->hiteast=ob->hitsouth=ob->hitwest=0;\r
-\r
- if (ob->needtoclip)\r
- {\r
- leftmoved = ob->left - oldleft;\r
- rightmoved = ob->right - oldright;\r
- topmoved = ob->top - oldtop;\r
- bottommoved = ob->bottom - oldbottom;\r
- midxmoved = ob->midx - oldmidx;\r
-\r
- //\r
- // clip it\r
- //\r
- ClipToEnds(ob);\r
-\r
- if (ob == player && !playerkludgeclipcancel) // zero tolerance near the edge when player gets pushed!\r
- {\r
- if (!ob->hitnorth && bottommoved > 0)\r
- {\r
- PlayerBottomKludge(ob);\r
- }\r
- if (!ob->hitsouth && topmoved < 0)\r
- {\r
- PlayerTopKludge(ob);\r
- }\r
- }\r
- ClipToSides(ob);\r
-\r
-#ifdef KEEN6\r
- //\r
- // special hack to prevent player from getting stuck on slopes?\r
- //\r
- if (ob == player && (ob->hitnorth & 7) > 1 && (ob->hiteast || ob->hitwest))\r
- {\r
- Uint16 far *map;\r
- Uint16 pixx, clip, move;\r
- Uint16 wall;\r
-\r
- pixx = CONVERT_GLOBAL_TO_PIXEL(ob->midx & (15*PIXGLOBAL));\r
- map = (Uint16 far *)mapsegs[1] + mapbwidthtable[oldtilebottom]/2 + ob->tilemidx;\r
-\r
- for (y=oldtilebottom; ob->tilebottom+1 >= y; y++, map+=mapwidth)\r
- {\r
- if ((wall = tinf[*map + NORTHWALL]) != 0)\r
- {\r
- clip = wallclip[wall & 7][pixx];\r
- move = CONVERT_TILE_TO_GLOBAL(y) + clip - 1 - ob->bottom;\r
- ob->hitnorth = wall;\r
- MoveObjVert(ob, move);\r
- return;\r
- }\r
- }\r
- }\r
-#endif\r
- }\r
- if (pushed && !ob->hitnorth)\r
- {\r
- ob->y = oldy;\r
- ob->x = oldx + xtry;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-}\r
-\r
-/*\r
-================\r
-=\r
-= FullClipToWalls\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void FullClipToWalls(objtype *ob)\r
-{\r
- Uint16 oldx, oldy, w, h;\r
- spritetabletype far *shape;\r
-\r
- oldx = ob->x;\r
- oldy = ob->y;\r
-\r
-//\r
-// move the shape\r
-//\r
- if (xtry > 239)\r
- {\r
- xtry = 239;\r
- }\r
- else if (xtry < -239)\r
- {\r
- xtry = -239;\r
- }\r
- if (ytry > 239)\r
- {\r
- ytry = 239;\r
- }\r
- else if (ytry < -239)\r
- {\r
- ytry = -239;\r
- }\r
-\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- switch (ob->obclass)\r
- {\r
-#if defined KEEN4\r
- case keenobj:\r
- w = 40*PIXGLOBAL;\r
- h = 24*PIXGLOBAL;\r
- break;\r
- case eggbirdobj:\r
- w = 64*PIXGLOBAL;\r
- h = 32*PIXGLOBAL;\r
- break;\r
- case dopefishobj:\r
- w = 88*PIXGLOBAL;\r
- h = 64*PIXGLOBAL;\r
- break;\r
- case schoolfishobj:\r
- w = 16*PIXGLOBAL;\r
- h = 8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN5\r
- case slicestarobj:\r
- case spherefulobj:\r
- w = h = 32*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN6\r
- case blorbobj:\r
- w = h = 32*PIXGLOBAL;\r
- break;\r
-#endif\r
-\r
- default:\r
- Quit("FullClipToWalls: Bad obclass");\r
- break;\r
- }\r
-\r
- ob->right = ob->x + w;\r
- ob->left = ob->x;\r
- ob->top = ob->y;\r
- ob->bottom = ob->y + h;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
-\r
- ob->hitnorth=ob->hiteast=ob->hitsouth=ob->hitwest=0;\r
-\r
-//\r
-// clip it\r
-//\r
- if (!CheckPosition(ob))\r
- {\r
- MoveObjHoriz(ob, -xtry); //undo x movement\r
- if (CheckPosition(ob))\r
- {\r
- if (xtry > 0)\r
- {\r
- ob->hitwest = 1;\r
- }\r
- else\r
- {\r
- ob->hiteast = 1;\r
- }\r
- }\r
- else\r
- {\r
- if (ytry > 0)\r
- {\r
- ob->hitnorth = 1;\r
- }\r
- else\r
- {\r
- ob->hitsouth = 1;\r
- }\r
- MoveObjHoriz(ob, xtry); //redo x movement\r
- MoveObjVert(ob, -ytry); //undo y movement\r
- if (!CheckPosition(ob))\r
- {\r
- MoveObjHoriz(ob, -xtry); //undo x movement\r
- if (xtry > 0)\r
- {\r
- ob->hitwest = 1;\r
- }\r
- else\r
- {\r
- ob->hiteast = 1;\r
- }\r
- }\r
- }\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-}\r
-\r
-/*\r
-================\r
-=\r
-= PushObj\r
-=\r
-= Moves the current object xtry/ytry units, clipping to walls\r
-=\r
-================\r
-*/\r
-\r
-void PushObj(objtype *ob)\r
-{\r
- Uint16 oldx, oldy;\r
- spritetabletype far *shape;\r
- \r
- oldx = ob->x;\r
- oldy = ob->y;\r
-\r
-//\r
-// move the shape\r
-//\r
- ob->x += xtry;\r
- ob->y += ytry;\r
-\r
- ob->needtoreact = true;\r
-\r
- if (!ob->shapenum) // can't get a hit rect with no shape!\r
- {\r
- return;\r
- }\r
-\r
- shape = &spritetable[ob->shapenum-STARTSPRITES];\r
-\r
- oldtileright = ob->tileright;\r
- oldtiletop = ob->tiletop;\r
- oldtileleft = ob->tileleft;\r
- oldtilebottom = ob->tilebottom;\r
- oldtilemidx = ob->tilemidx;\r
-\r
- oldright = ob->right;\r
- oldtop = ob->top;\r
- oldleft = ob->left;\r
- oldbottom = ob->bottom;\r
- oldmidx = ob->midx;\r
-\r
- ob->left = ob->x + shape->xl;\r
- ob->right = ob->x + shape->xh;\r
- ob->top = ob->y + shape->yl;\r
- ob->bottom = ob->y + shape->yh;\r
- ob->midx = ob->left + (ob->right-ob->left)/2;\r
-\r
- ob->tileleft = CONVERT_GLOBAL_TO_TILE(ob->left);\r
- ob->tileright = CONVERT_GLOBAL_TO_TILE(ob->right);\r
- ob->tiletop = CONVERT_GLOBAL_TO_TILE(ob->top);\r
- ob->tilebottom = CONVERT_GLOBAL_TO_TILE(ob->bottom);\r
- ob->tilemidx = CONVERT_GLOBAL_TO_TILE(ob->midx);\r
-\r
- if (ob->needtoclip)\r
- {\r
- leftmoved = ob->left - oldleft;\r
- rightmoved = ob->right - oldright;\r
- topmoved = ob->top - oldtop;\r
- bottommoved = ob->bottom - oldbottom;\r
- midxmoved = ob->midx - oldmidx;\r
-\r
- ClipToEnds(ob);\r
- ClipToSides(ob);\r
- }\r
-\r
- ob->xmove = ob->xmove + (ob->x - oldx);\r
- ob->ymove = ob->ymove + (ob->y - oldy);\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSpriteSide\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSpriteSide(objtype *push, objtype *solid)\r
-{\r
- Sint16 xmove, leftinto, rightinto;\r
-\r
- //\r
- // amount the push shape can be pushed\r
- //\r
- xmove = solid->xmove - push->xmove;\r
-\r
- //\r
- // amount it is inside\r
- //\r
- leftinto = solid->right - push->left;\r
- rightinto = push->right - solid->left;\r
-\r
- if (leftinto > 0 && leftinto <= xmove)\r
- {\r
- xtry = leftinto;\r
- if (push->state->pushtofloor)\r
- {\r
- ytry = leftinto+16;\r
- }\r
- ClipToWalls(push);\r
- push->hiteast = 1;\r
- }\r
- else if (rightinto > 0 && rightinto <= -xmove)\r
- {\r
- xtry = -rightinto;\r
- if (push->state->pushtofloor)\r
- {\r
- ytry = rightinto+16;\r
- }\r
- ClipToWalls(push);\r
- push->hitwest = 1;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSpriteTop\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSpriteTop(objtype *push, objtype *solid)\r
-{\r
- Sint16 temp, ymove, bottominto;\r
-\r
- //\r
- // amount the push shape can be pushed\r
- //\r
- ymove = push->ymove - solid->ymove;\r
-\r
- //\r
- // amount it is inside\r
- //\r
- bottominto = push->bottom - solid->top;\r
-\r
- if (bottominto >= 0 && bottominto <= ymove)\r
- {\r
- if (push == player)\r
- {\r
- gamestate.riding = solid;\r
- }\r
- ytry = -bottominto;\r
- temp = push->state->pushtofloor;\r
- push->state->pushtofloor = false;\r
- ClipToWalls(push);\r
- push->state->pushtofloor = temp;\r
- if (!push->hitsouth)\r
- {\r
- push->hitnorth = 25;\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= ClipToSprite\r
-=\r
-= Clips push to solid\r
-=\r
-==================\r
-*/\r
-\r
-void ClipToSprite(objtype *push, objtype *solid, boolean squish)\r
-{\r
- Sint16 xmove, ymove, leftinto, rightinto, topinto, bottominto;\r
- \r
- xmove = solid->xmove - push->xmove;\r
- xtry = ytry = 0;\r
-\r
- //\r
- // left / right\r
- //\r
- leftinto = solid->right - push->left;\r
- rightinto = push->right - solid->left;\r
-\r
- if (leftinto > 0 && xmove+1 >= leftinto)\r
- {\r
- xtry = leftinto;\r
- push->xspeed = 0;\r
- PushObj(push);\r
- if (squish && push->hitwest)\r
- {\r
- KillKeen();\r
- }\r
- push->hiteast = 1;\r
- return;\r
- }\r
- else if (rightinto > 0 && -xmove+1 >= rightinto)\r
- {\r
- xtry = -rightinto;\r
- push->xspeed = 0;\r
- PushObj(push);\r
- if (squish && push->hiteast)\r
- {\r
- KillKeen();\r
- }\r
- push->hitwest = 1;\r
- return;\r
- }\r
-\r
- //\r
- // top / bottom\r
- //\r
- ymove = push->ymove - solid->ymove;\r
- topinto = solid->bottom - push->top;\r
- bottominto = push->bottom - solid->top;\r
- if (bottominto >= 0 && bottominto <= ymove)\r
- {\r
- if (push == player)\r
- {\r
- gamestate.riding = solid;\r
- }\r
- ytry = -bottominto;\r
- PushObj(push);\r
- if (squish && push->hitsouth)\r
- {\r
- KillKeen();\r
- }\r
- if (!push->hitsouth)\r
- {\r
- push->hitnorth = 25;\r
- }\r
- return;\r
- }\r
- else if (topinto >= 0 && topinto <= ymove) // BUG: should be 'topinto <= -ymove'\r
- {\r
- ytry = topinto;\r
- ClipToWalls(push);\r
- if (squish && push->hitnorth)\r
- {\r
- KillKeen();\r
- }\r
- push->hitsouth = 25;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= DoActor\r
-=\r
-= Moves an actor in its current state by a given number of tics.\r
-= If that time takes it into the next state, it changes the state\r
-= and returns the number of excess tics after the state change\r
-=\r
-==================\r
-*/\r
-\r
-Sint16 DoActor(objtype *ob, Sint16 numtics)\r
-{\r
- Sint16 ticcount, usedtics, excesstics;\r
- statetype *state;\r
- \r
- state = ob->state;\r
-\r
- if (state->progress == think)\r
- {\r
- if (state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
- return 0;\r
- }\r
-\r
- ticcount = ob->ticcount + numtics;\r
-\r
- if (state->tictime > ticcount || state->tictime == 0)\r
- {\r
- ob->ticcount = ticcount;\r
- if (state->progress == slide || state->progress == slidethink)\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? numtics*state->xmove : -numtics*state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? numtics*state->ymove : -numtics*state->ymove;\r
- }\r
- }\r
- if ((state->progress == slidethink || state->progress == stepthink) && state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
- return 0;\r
- }\r
- else\r
- {\r
- usedtics = state->tictime - ob->ticcount;\r
- excesstics = ticcount - state->tictime;\r
- ob->ticcount = 0;\r
- if (state->progress == slide || state->progress == slidethink)\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? usedtics*state->xmove : -usedtics*state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? usedtics*state->ymove : -usedtics*state->ymove;\r
- }\r
- }\r
- else\r
- {\r
- if (ob->xdir)\r
- {\r
- xtry += ob->xdir == 1? state->xmove : -state->xmove;\r
- }\r
- if (ob->ydir)\r
- {\r
- ytry += ob->ydir == 1? state->ymove : -state->ymove;\r
- }\r
- }\r
-\r
- if (state->think)\r
- {\r
- if (ob->nothink)\r
- {\r
- ob->nothink--;\r
- }\r
- else\r
- {\r
- state->think(ob);\r
- }\r
- }\r
-\r
- if (state == ob->state)\r
- {\r
- ob->state = state->nextstate; // go to next state\r
- }\r
- else if (!ob->state)\r
- {\r
- return 0; // object removed itself\r
- }\r
- return excesstics;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= StateMachine\r
-=\r
-= Change state and give directions\r
-=\r
-====================\r
-*/\r
-\r
-void StateMachine(objtype *ob)\r
-{\r
- Sint16 excesstics, oldshapenum;\r
- statetype *state;\r
- \r
- ob->xmove=ob->ymove=xtry=ytry=0;\r
- oldshapenum = ob->shapenum;\r
-\r
- state = ob->state;\r
-\r
- excesstics = DoActor(ob, tics);\r
- if (ob->state != state)\r
- {\r
- ob->ticcount = 0; // start the new state at 0, then use excess\r
- state = ob->state;\r
- }\r
-\r
- while (excesstics)\r
- {\r
- //\r
- // passed through to next state\r
- //\r
- if (!state->skippable && state->tictime <= excesstics)\r
- {\r
- excesstics = DoActor(ob, state->tictime-1);\r
- }\r
- else\r
- {\r
- excesstics = DoActor(ob, excesstics);\r
- }\r
- if (ob->state != state)\r
- {\r
- ob->ticcount = 0; // start the new state at 0, then use excess\r
- state = ob->state;\r
- }\r
- }\r
-\r
- if (!state) // object removed itself\r
- {\r
- RemoveObj(ob);\r
- return;\r
- }\r
-\r
- //\r
- // if state->rightshapenum == NULL, the state does not have a standard\r
- // shape (the think routine should have set it)\r
- //\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0; // make it invisable this time\r
- }\r
-\r
- if (xtry || ytry || ob->shapenum != oldshapenum || ob->hitnorth == 25)\r
- {\r
- //\r
- // actor moved or changed shape\r
- // make sure the movement is within limits (one tile)\r
- //\r
- if (ob->needtoclip == cl_fullclip)\r
- {\r
- FullClipToWalls(ob);\r
- }\r
- else\r
- {\r
- ClipToWalls(ob);\r
- }\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= NewState\r
-=\r
-====================\r
-*/\r
-\r
-void NewState(objtype *ob, statetype *state)\r
-{\r
- Sint16 temp;\r
- \r
- ob->state = state;\r
-\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
-\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0;\r
- }\r
-\r
- temp = ob->needtoclip;\r
- ob->needtoclip = cl_noclip;\r
-\r
- xtry = ytry = 0; // no movement\r
- ClipToWalls(ob); // just calculate values\r
-\r
- ob->needtoclip = temp;\r
-\r
- if (ob->needtoclip == cl_fullclip)\r
- {\r
- FullClipToWalls(ob);\r
- }\r
- else if (ob->needtoclip == cl_midclip)\r
- {\r
- ClipToWalls(ob);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= ChangeState\r
-=\r
-====================\r
-*/\r
-\r
-void ChangeState(objtype *ob, statetype *state)\r
-{\r
- ob->state = state;\r
- ob->ticcount = 0;\r
- if (state->rightshapenum)\r
- {\r
- if (ob->xdir > 0)\r
- {\r
- ob->shapenum = state->rightshapenum;\r
- }\r
- else\r
- {\r
- ob->shapenum = state->leftshapenum;\r
- }\r
- }\r
-\r
- if ((Sint16)ob->shapenum == -1)\r
- {\r
- ob->shapenum = 0;\r
- }\r
-\r
- ob->needtoreact = true; // it will need to be redrawn this frame\r
-\r
- xtry = ytry = 0; // no movement\r
-\r
- if (ob->hitnorth != 25)\r
- {\r
- ClipToWalls(ob);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= OnScreen\r
-=\r
-====================\r
-*/\r
-\r
-boolean OnScreen(objtype *ob)\r
-{\r
- if (ob->tileright < originxtile || ob->tilebottom < originytile\r
- || ob->tileleft > originxtilemax || ob->tiletop > originytilemax)\r
- {\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i&1)\r
- {\r
- if (ob->yspeed < 0 && ob->yspeed >= -4)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- ob->yspeed += 4;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoWeakGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoWeakGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i&1)\r
- {\r
- if (ob->yspeed < 0 && ob->yspeed >= -3)\r
- {\r
- ytry += ob->yspeed;\r
- ob->yspeed = 0;\r
- return;\r
- }\r
- ob->yspeed += 3;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= DoTinyGravity\r
-=\r
-====================\r
-*/\r
-\r
-void DoTinyGravity(objtype *ob)\r
-{\r
- Sint32 i;\r
-//\r
-// only accelerate every 4 tics, because of limited precision\r
-//\r
- for (i = lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (!i & 3) //BUG: this is equal to ((!i) & 3), not (!(i & 3))\r
- {\r
- ob->yspeed++;\r
- if (ob->yspeed > 70)\r
- {\r
- ob->yspeed = 70;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateX\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateX(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
- Uint16 oldsign;\r
- \r
- oldsign = ob->xspeed & 0x8000;\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += dir;\r
- if ((ob->xspeed & 0x8000) != oldsign)\r
- {\r
- oldsign = ob->xspeed & 0x8000;\r
- ob->xdir = oldsign? -1 : 1;\r
- }\r
- if (ob->xspeed > maxspeed)\r
- {\r
- ob->xspeed = maxspeed;\r
- }\r
- else if (ob->xspeed < -maxspeed)\r
- {\r
- ob->xspeed = -maxspeed;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateXv\r
-=\r
-= Doesn't change object's xdir\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateXv(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
-\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += dir;\r
- if (ob->xspeed > maxspeed)\r
- {\r
- ob->xspeed = maxspeed;\r
- }\r
- else if (ob->xspeed < -maxspeed)\r
- {\r
- ob->xspeed = -maxspeed;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= AccelerateY\r
-=\r
-===============\r
-*/\r
-\r
-void AccelerateY(objtype *ob, Sint16 dir, Sint16 maxspeed)\r
-{\r
- Sint32 i;\r
-\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->yspeed += dir;\r
- if (ob->yspeed > maxspeed)\r
- {\r
- ob->yspeed = maxspeed;\r
- }\r
- else if (ob->yspeed < -maxspeed)\r
- {\r
- ob->yspeed = -maxspeed;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= FrictionX\r
-=\r
-===============\r
-*/\r
-\r
-void FrictionX(objtype *ob)\r
-{\r
- Sint16 friction, oldsign;\r
- Sint32 i;\r
-\r
- oldsign = ob->xspeed & 0x8000;\r
- if (ob->xspeed > 0)\r
- {\r
- friction = -1;\r
- }\r
- else if (ob->xspeed < 0)\r
- {\r
- friction = 1;\r
- }\r
- else\r
- {\r
- friction = 0;\r
- }\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
-\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->xspeed += friction;\r
- if ((ob->xspeed & 0x8000) != oldsign)\r
- {\r
- ob->xspeed = 0;\r
- }\r
- }\r
- xtry += ob->xspeed;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= FrictionY\r
-=\r
-===============\r
-*/\r
-\r
-void FrictionY(objtype *ob)\r
-{\r
- Sint16 friction, oldsign;\r
- Sint32 i;\r
-\r
- if (ob->yspeed > 0)\r
- {\r
- friction = -1;\r
- }\r
- else if (ob->yspeed < 0)\r
- {\r
- friction = 1;\r
- }\r
- else\r
- {\r
- friction = 0;\r
- }\r
-//\r
-// only accelerate on odd tics, because of limited precision\r
-//\r
- for (i=lasttimecount-tics; i<lasttimecount; i++)\r
- {\r
- if (i & 1)\r
- {\r
- ob->yspeed += friction;\r
- if ((ob->yspeed & 0x8000) != oldsign) //BUG: oldsign is not initialized!\r
- {\r
- ob->yspeed = 0;\r
- }\r
- }\r
- ytry += ob->yspeed;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= StunObj\r
-=\r
-===============\r
-*/\r
-\r
-void StunObj(objtype *ob, objtype *shot, statetype *stunstate)\r
-{\r
- ExplodeShot(shot);\r
- ob->temp1 = ob->temp2 = ob->temp3 = 0; // Note: ob->nothink should also be set to 0\r
- ob->temp4 = ob->obclass;\r
- ChangeState(ob, stunstate);\r
- ob->obclass = stunnedobj;\r
-#ifndef KEEN4\r
- ob->yspeed -= 24;\r
- if (ob->yspeed < -48)\r
- ob->yspeed = -48;\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= T_Projectile\r
-=\r
-===============\r
-*/\r
-\r
-void T_Projectile(objtype *ob)\r
-{\r
- DoGravity(ob);\r
- xtry = ob->xspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_WeakProjectile\r
-=\r
-===============\r
-*/\r
-\r
-void T_WeakProjectile(objtype *ob)\r
-{\r
- DoWeakGravity(ob);\r
- xtry = ob->xspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Velocity\r
-=\r
-===============\r
-*/\r
-\r
-void T_Velocity(objtype *ob)\r
-{\r
- xtry = ob->xspeed*tics;\r
- ytry = ob->yspeed*tics;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SetReactThink\r
-=\r
-===============\r
-*/\r
-\r
-void SetReactThink(objtype *ob)\r
-{\r
- ob->needtoreact = true;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Stunned\r
-=\r
-===============\r
-*/\r
-\r
-void T_Stunned(objtype *ob)\r
-{\r
- ob->temp1 = 0;\r
- ob->needtoreact = true;\r
- if (++ob->temp2 == 3)\r
- ob->temp2 = 0;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= C_Lethal\r
-=\r
-===============\r
-*/\r
-\r
-void C_Lethal(objtype *ob, objtype *hit)\r
-{\r
- ob++; // shut up compiler\r
- if (hit->obclass == keenobj)\r
- {\r
- KillKeen();\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Draw\r
-=\r
-===============\r
-*/\r
-\r
-void R_Draw(objtype *ob)\r
-{\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Walk\r
-=\r
-===============\r
-*/\r
-\r
-void R_Walk(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_WalkNormal\r
-=\r
-= Actor will not walk onto tiles with special (e.g. deadly) north walls\r
-=\r
-===============\r
-*/\r
-\r
-void R_WalkNormal(objtype *ob)\r
-{\r
- if (ob->xdir == 1 && ob->hitwest)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = -1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (ob->xdir == -1 && ob->hiteast)\r
- {\r
- ob->x -= ob->xmove;\r
- ob->xdir = 1;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- else if (!ob->hitnorth || (ob->hitnorth & ~7))\r
- {\r
- ob->x -= ob->xmove*2;\r
- ob->xdir = -ob->xdir;\r
- ob->nothink = US_RndT() >> 5;\r
- ChangeState(ob, ob->state);\r
- }\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= BadState\r
-=\r
-===============\r
-*/\r
-\r
-void BadState(void)\r
-{\r
- Quit("Object with bad state!");\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= R_Stunned\r
-=\r
-===============\r
-*/\r
-\r
-void R_Stunned(objtype *ob)\r
-{\r
- Sint16 starx, stary;\r
-\r
- if (ob->hitwest || ob->hiteast)\r
- ob->xspeed = 0;\r
-\r
- if (ob->hitsouth)\r
- ob->yspeed = 0;\r
-\r
- if (ob->hitnorth)\r
- {\r
- ob->xspeed = ob->yspeed = 0;\r
- if (ob->state->nextstate)\r
- ChangeState(ob, ob->state->nextstate);\r
- }\r
-\r
- RF_PlaceSprite(&ob->sprite, ob->x, ob->y, ob->shapenum, spritedraw, ob->priority);\r
-\r
- starx = stary = 0;\r
- switch (ob->temp4)\r
- {\r
-#if defined KEEN4\r
- case mimrockobj:\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case eggobj:\r
- starx = 8*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case treasureeaterobj:\r
- starx = 8*PIXGLOBAL;\r
- break;\r
- case bounderobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case wormouthobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -350; // -21.875 pixels (this one is a bit strange)\r
- break;\r
- case lickobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case inchwormobj:\r
- starx = -4*PIXGLOBAL;\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case slugobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN5\r
- case sparkyobj:\r
- starx += 4*PIXGLOBAL;\r
- break;\r
- case amptonobj:\r
- stary -= 8*PIXGLOBAL;\r
- asm jmp done; // just to recreate the original code's quirks, feel free to delete this\r
- break;\r
- case scottieobj:\r
- stary -= 8*PIXGLOBAL;\r
- break;\r
-#elif defined KEEN6\r
- case blooguardobj:\r
- starx = 16*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case flectobj:\r
- starx = 4*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case bloogobj:\r
- case nospikeobj:\r
- starx = 8*PIXGLOBAL;\r
- stary = -4*PIXGLOBAL;\r
- break;\r
- case bloogletobj:\r
- case babobbaobj:\r
- stary = -8*PIXGLOBAL;\r
- break;\r
- case fleexobj:\r
- starx = 16*PIXGLOBAL;\r
- stary = 8*PIXGLOBAL;\r
- break;\r
- case ceilickobj:\r
- stary = 12*PIXGLOBAL;\r
- break;\r
- default:\r
- Quit("No star spec for object!");\r
-#endif\r
- }\r
-done:\r
-\r
- ob->temp1 = ob->temp1 + tics;\r
- if (ob->temp1 > 10)\r
- {\r
- ob->temp1 -= 10;\r
- if (++ob->temp2 == 3)\r
- ob->temp2 = 0;\r
- }\r
-\r
- RF_PlaceSprite((void **)&ob->temp3, ob->x+starx, ob->y+stary, ob->temp2+STUNSTARS1SPR, spritedraw, 3);\r
-}\r
-\r
-//==========================================================================\r
-\r
-statetype sc_deadstate = {0, 0, think, false, false, 0, 0, 0, NULL, NULL, NULL, NULL};\r
-#pragma warn -sus //BadState is not a valid think/contact/react function. Nobody cares.\r
-statetype sc_badstate = {0, 0, think, false, false, 0, 0, 0, &BadState, &BadState, &BadState, NULL};\r
-#pragma warn +sus
\ No newline at end of file