+++ /dev/null
-/* Catacomb Armageddon 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_PLAY.C\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define POINTTICS 6\r
-#define PAUSE 300\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte bcolor;\r
-short skytimer=-1,skytimer_reset;\r
-short groundtimer=-1,groundtimer_reset;\r
-\r
-unsigned scolor,gcolor;\r
-unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;\r
-\r
-unsigned nocolorchange=0xFFFF;\r
-byte BGFLAGS, // global that holds all current flags\r
- bgflag; // used by BG changer, this flag is set when done\r
-\r
-\r
-unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};\r
-//unsigned gnd_daytonight[]={0x0202,0xFFFF};\r
-\r
-unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};\r
-\r
-unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,\r
- 0x0404,0x0000,0x0000,0x0000,0x0000,\r
- 0x0000,0x0000,0x0000,0x0000,0x0606,\r
- 0x0000,0x0000,0x0000,0x0000,0x0000,\r
- 0x0000};\r
-unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,\r
- 0x0505,0x0808,0x0606,0x0101,0x0808,\r
- 0x0606,0x0404,0x0808,0x0c0c,0x0e0e,\r
- 0x0808,0x0808,0x0c0c,0x0000,0x0707,\r
- 0x0808};\r
-\r
-\r
-ControlInfo control;\r
-boolean running=false; //,slowturn;\r
-\r
-int bordertime;\r
-objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;\r
-\r
-#if USE_INERT_LIST\r
-inertobjtype inertobjlist[MAXINERTOBJ],*inert;\r
-#endif\r
-\r
-unsigned farmapylookup[MAPSIZE];\r
-byte *nearmapylookup[MAPSIZE];\r
-\r
-boolean singlestep,godmode;\r
-int extravbls;\r
-status_flags status_flag;\r
-int status_delay;\r
-\r
-//\r
-// replacing refresh manager\r
-//\r
-unsigned mapwidth,mapheight,tics,realtics;\r
-boolean compatability;\r
-byte *updateptr;\r
-unsigned mapwidthtable[64];\r
-unsigned uwidthtable[UPDATEHIGH];\r
-unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-byte update[UPDATESIZE];\r
-\r
-int mousexmove,mouseymove;\r
-int pointcount,pointsleft;\r
-\r
-short BeepTime = 0;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void CalcBounds (objtype *ob);\r
-void DrawPlayScreen (void);\r
-void PreFullDisplay(void);\r
-void PostFullDisplay(boolean draw_view);\r
-\r
-\r
-//\r
-// near data map array (wall values only, get text number from far data)\r
-//\r
-byte tilemap[MAPSIZE][MAPSIZE];\r
-byte spotvis[MAPSIZE][MAPSIZE];\r
-objtype *actorat[MAPSIZE][MAPSIZE];\r
-\r
-objtype dummyobj;\r
-\r
-int bordertime;\r
-int objectcount;\r
-\r
-void StopMusic(void);\r
-void StartMusic(void);\r
-\r
-void CalibrateJoystick(short joynum);\r
-\r
-//==========================================================================\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// CenterWindow() - Generates a window of a given width & height in the\r
-// middle of the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-\r
-#define MAXX 320\r
-#define MAXY 120\r
-\r
-void CenterWindow(word w,word h)\r
-{\r
- US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= CheckKeys\r
-=\r
-=====================\r
-*/\r
-\r
-void CheckKeys (void)\r
-{\r
- extern boolean autofire;\r
-\r
- if (screenfaded) // don't do anything with a faded screen\r
- return;\r
-\r
-#if 0\r
-//\r
-// pause key wierdness can't be checked as a scan code\r
-//\r
- if (Paused)\r
- {\r
- CenterWindow (8,3);\r
- US_PrintCentered ("PAUSED");\r
- VW_UpdateScreen ();\r
-// SD_MusicOff();\r
- IN_Ack();\r
-// SD_MusicOn();\r
- Paused = false;\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
- else\r
- if (Keyboard[sc_Enter]) // P = pause with no screen disruptioon\r
- {\r
-// SD_MusicOff();\r
- DisplaySMsg("PAUSED",NULL);\r
- IN_Ack();\r
-// SD_MusicOn();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
- else\r
- if (Keyboard[sc_S])\r
- {\r
- char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};\r
-\r
- SlowMode ^= 1;\r
- extravbls = SlowMode << 3;\r
- CenterWindow (8,3);\r
- US_PrintCentered (Text[SlowMode]);\r
- VW_UpdateScreen ();\r
-// SD_MusicOff();\r
- IN_Ack();\r
-// SD_MusicOn();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
-#endif\r
-\r
-\r
-// F2 - SOUND OPTIONS\r
-//\r
- if (Keyboard[sc_F2])\r
- {\r
- int height=7;\r
- boolean ChoiceMade = false;\r
-\r
- if (AdLibPresent)\r
- height++;\r
-\r
- VW_FixRefreshBuffer();\r
- CenterWindow(22,height);\r
- US_Print( "\n 1 ) NO SOUND \n");\r
- US_Print( " 2 ) PC AUDIO \n");\r
-\r
- if (AdLibPresent)\r
- US_Print(" 3 ) ADLIB AUDIO\n");\r
-\r
- US_Print( "\n ESC) EXIT ");\r
- VW_UpdateScreen();\r
-\r
- // Switch audio device ON/OFF & load sounds if there\r
- // was a change in the device.\r
-\r
- do {\r
-\r
- if (Keyboard[1]) // ESC - Exit\r
- ChoiceMade = true;\r
- else\r
- if (Keyboard[2]) // 1 - No Sound\r
- {\r
- SD_SetSoundMode(sdm_Off);\r
- ChoiceMade = true;\r
- }\r
- else\r
- if (Keyboard[3]) // 2 - PC Audio\r
- {\r
- SD_SetSoundMode(sdm_PC);\r
-// if (oldsoundmode != sdm_PC)\r
- CA_LoadAllSounds();\r
- ChoiceMade = true;\r
- }\r
- else\r
- if ((Keyboard[4]) && AdLibPresent) // 3 - AdLib Audio\r
- {\r
- SD_SetSoundMode(sdm_AdLib);\r
-// if (oldsoundmode != sdm_AdLib)\r
- CA_LoadAllSounds();\r
- ChoiceMade = true;\r
- }\r
-\r
- } while (!ChoiceMade);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F5 - CALIBRATE JOYSTICK\r
-//\r
- if (Keyboard[sc_F5])\r
- {\r
- CalibrateJoystick(0);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-deadloop:;\r
-// ESCAPE - quits game\r
-//\r
- if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))\r
- {\r
- char ch;\r
-\r
- DisplaySMsg("Options", NULL);\r
- status_flag = S_NONE;\r
-\r
-\r
- if (Flags & FL_DEAD)\r
- {\r
- char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};\r
- ch = DisplayMsg("Restore New Quit",choices);\r
- }\r
- else\r
- {\r
- char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};\r
- ch = DisplayMsg("Save Restore New Quit",choices);\r
- }\r
- DrawText(true);\r
-\r
- switch (ch)\r
- {\r
- case sc_S:\r
- if (!(Flags & FL_DEAD))\r
- Keyboard[sc_F3] = true;\r
- break;\r
-\r
- case sc_R:\r
- Keyboard[sc_F4] = true;\r
- break;\r
-\r
- case sc_N:\r
- DisplaySMsg("Starting anew", NULL);\r
- VW_WaitVBL(60);\r
- playstate = ex_resetgame;\r
- Flags &= ~FL_DEAD;\r
- break;\r
-\r
- case sc_Q:\r
- DisplaySMsg("FARE THEE WELL!", NULL);\r
- VW_WaitVBL(120);\r
- if (!Flags & FL_QUICK)\r
- VW_FadeOut();\r
- NormalScreen();\r
- FreeUpMemory();\r
- Quit(NULL);\r
- break;\r
- }\r
- tics = realtics = 1;\r
- }\r
-\r
-// F1 - DISPLAY HELP\r
-//\r
- if (Keyboard[sc_F1])\r
- {\r
- PrintHelp();\r
-\r
-#ifdef TEXT_PRESENTER\r
-\r
- extern PresenterInfo MainHelpText;\r
-\r
- VW_FadeOut();\r
-\r
- FreeUpMemory();\r
- if (!LoadPresenterScript("HELP.TXT",&MainHelpText))\r
- {\r
- VW_FadeIn();\r
- CenterWindow(30,5);\r
- US_CPrint("\nError loading HELP file.\n");\r
- US_CPrint("Press any key.");\r
- IN_Ack();\r
- VW_FadeOut();\r
- }\r
- else\r
- {\r
- VW_SetSplitScreen(200);\r
- bufferofs = displayofs = screenloc[0];\r
- VW_Bar(0,0,320,200,0);\r
-\r
- Display640();\r
- Presenter(&MainHelpText);\r
- Display320();\r
- }\r
- FreePresenterScript(&MainHelpText);\r
-#endif\r
- VW_SetSplitScreen(120);\r
- VW_SetScreen(screenloc[0],0);\r
- screenpage = 0;\r
- CacheScaleds();\r
-\r
- bufferofs = 0;\r
- RedrawStatusWindow();\r
- ThreeDRefresh();\r
- VW_FadeIn();\r
- Keyboard[sc_F1] = false;\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F3 - SAVE GAME\r
-//\r
- if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))\r
- {\r
- PreFullDisplay();\r
- GE_SaveGame();\r
- PostFullDisplay(true);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F4 - LOAD GAME\r
-//\r
- if (Keyboard[sc_F4])\r
- {\r
- PreFullDisplay();\r
- if (GE_LoadGame())\r
- {\r
- loadedgame = true;\r
- playstate = ex_loadedgame;\r
- Flags &= ~FL_DEAD;\r
- lasttext = -1;\r
- PostFullDisplay(false);\r
- }\r
- else\r
- if (playstate == ex_victorious)\r
- {\r
- PostFullDisplay(false);\r
- Victory(false);\r
- IN_Ack();\r
-// gamestate.mapon++;\r
- }\r
- else\r
- PostFullDisplay(true);\r
- Keyboard[sc_F5] = false;\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
- if (Flags & FL_DEAD)\r
- goto deadloop;\r
-\r
-//\r
-// F10-? debug keys\r
-//\r
- if (Keyboard[sc_BackSpace])\r
- {\r
- DebugKeys();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- lasttimecount = TimeCount;\r
- }\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// PreFullDisplay()\r
-//-------------------------------------------------------------------------\r
-void PreFullDisplay()\r
-{\r
- VW_FadeOut();\r
- VW_SetSplitScreen(200);\r
- bufferofs = displayofs = screenloc[0];\r
- VW_Bar(0,0,320,200,0);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// PostFullDisplay()\r
-//-------------------------------------------------------------------------\r
-void PostFullDisplay(boolean draw_view)\r
-{\r
- VW_SetSplitScreen(120);\r
- bufferofs = 0;\r
- RedrawStatusWindow();\r
- if (draw_view)\r
- {\r
- ThreeDRefresh();\r
- VW_FadeIn();\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-#############################################################################\r
-\r
- The objlist data structure\r
-\r
-#############################################################################\r
-\r
-objlist containt structures for every actor currently playing. The structure\r
-is accessed as a linked list starting at *player, ending when ob->next ==\r
-NULL. GetNewObj inserts a new object at the end of the list, meaning that\r
-if an actor spawn another actor, the new one WILL get to think and react the\r
-same frame. RemoveObj unlinks the given object and returns it to the free\r
-list, but does not damage the objects ->next pointer, so if the current object\r
-removes itself, a linked list following loop can still safely get to the\r
-next element.\r
-\r
-<backwardly linked free list>\r
-\r
-#############################################################################\r
-*/\r
-\r
-\r
-/*\r
-=========================\r
-=\r
-= InitObjList\r
-=\r
-= Call to clear out the entire object list, returning them all to the free\r
-= list. Allocates a special spot for the player.\r
-=\r
-=========================\r
-*/\r
-\r
-void InitObjList (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<MAXACTORS;i++)\r
- {\r
- objlist[i].prev = &objlist[i+1];\r
- objlist[i].next = NULL;\r
- }\r
-\r
- objlist[MAXACTORS-1].prev = NULL;\r
-\r
- objfreelist = &objlist[0];\r
- lastobj = NULL;\r
-\r
- objectcount = 0;\r
-\r
-//\r
-// give the player and score the first free spots\r
-//\r
- GetNewObj (false);\r
- player = new;\r
-\r
-#if USE_INERT_LIST\r
- inert = inertobjlist;\r
-#endif\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= GetNewObj\r
-=\r
-= Sets the global variable new to point to a free spot in objlist.\r
-= The free spot is inserted at the end of the liked list\r
-=\r
-= When the object list is full, the caller can either have it bomb out ot\r
-= return a dummy object pointer that will never get used\r
-=\r
-=========================\r
-*/\r
-\r
-void GetNewObj (boolean usedummy)\r
-{\r
- if (!objfreelist)\r
- {\r
- if (usedummy)\r
- {\r
- new = &dummyobj;\r
- return;\r
- }\r
- Quit ("GetNewObj: No free spots in objlist!");\r
- }\r
-\r
- new = objfreelist;\r
- objfreelist = new->prev;\r
- memset (new,0,sizeof(*new));\r
-\r
- if (lastobj)\r
- lastobj->next = new;\r
- new->prev = lastobj; // new->next is allready NULL from memset\r
-\r
- new->active = false;\r
- lastobj = new;\r
-\r
- objectcount++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= RemoveObj\r
-=\r
-= Add the given object back into the free list, and unlink it from it's\r
-= neighbors\r
-=\r
-=========================\r
-*/\r
-\r
-void RemoveObj (objtype *gone)\r
-{\r
- objtype **spotat;\r
-\r
- if (gone == player)\r
- Quit ("RemoveObj: Tried to remove the player!");\r
-\r
-//\r
-// fix the next object's back link\r
-//\r
- if (gone == lastobj)\r
- lastobj = (objtype *)gone->prev;\r
- else\r
- gone->next->prev = gone->prev;\r
-\r
-//\r
-// fix the previous object's forward link\r
-//\r
- gone->prev->next = gone->next;\r
-\r
-//\r
-// add it back in to the free list\r
-//\r
- gone->prev = objfreelist;\r
- objfreelist = gone;\r
-\r
- objectcount--;\r
-}\r
-\r
-#if USE_INERT_LIST\r
-\r
-//--------------------------------------------------------------------------\r
-// MoveObjToInert()\r
-//--------------------------------------------------------------------------\r
-void MoveObjToInert(objtype *obj)\r
-{\r
-\r
- if (inert == &inertobjlist[MAXINERTOBJ])\r
- return;\r
-\r
-// Transfer info needed by inert objtype\r
-//\r
- inert->x = obj->x;\r
- inert->y = obj->y;\r
- inert->size = obj->size;\r
- inert->viewx = obj->viewx;\r
- inert->tilex = obj->tilex;\r
- inert->tiley = obj->tiley;\r
- inert->state = obj->state;\r
- inert->ticcount = obj->ticcount;\r
-\r
-// Setup links between inert objects\r
-//\r
- if (inert != inertobjlist)\r
- (inert-1)->next = inert;\r
- inert->next = NULL;\r
- inert++;\r
-\r
-// Free 'real' object from list.\r
-//\r
- RemoveObj(obj);\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= PollControls\r
-=\r
-===================\r
-*/\r
-\r
-void PollControls (void)\r
-{\r
- unsigned buttons;\r
-\r
- IN_ReadControl(0,&control);\r
-\r
- if (MousePresent)\r
- {\r
- Mouse(MButtons);\r
- buttons = _BX;\r
- Mouse(MDelta);\r
- mousexmove = _CX;\r
- mouseymove = _DX;\r
-\r
- if (buttons&1)\r
- control.button0 = 1;\r
- if (buttons&2)\r
- control.button1 = 1;\r
-\r
- }\r
-\r
- if (Keyboard[sc_V] || Keyboard[sc_Tab])\r
- running = true;\r
- else\r
- running = false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-=================\r
-=\r
-= StopMusic\r
-=\r
-=================\r
-*/\r
-\r
-void StopMusic(void)\r
-{\r
- int i;\r
-\r
- SD_MusicOff();\r
- for (i = 0;i < LASTMUSIC;i++)\r
- if (audiosegs[STARTMUSIC + i])\r
- {\r
- MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);\r
- MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= StartMusic\r
-=\r
-=================\r
-*/\r
-\r
-// JAB - Cache & start the appropriate music for this level\r
-void StartMusic(void)\r
-{\r
- musicnames chunk;\r
-\r
- SD_MusicOff();\r
- chunk = TOOHOT_MUS;\r
-// if ((chunk == -1) || (MusicMode != smm_AdLib))\r
-//DEBUG control panel return;\r
-\r
- MM_BombOnError (false);\r
- CA_CacheAudioChunk(STARTMUSIC + chunk);\r
- MM_BombOnError (true);\r
- if (mmerror)\r
- mmerror = false;\r
- else\r
- {\r
- MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
- SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
- }\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= PlayLoop\r
-=\r
-===================\r
-*/\r
-\r
-void PlayLoop (void)\r
-{\r
- char shot_color[3] = {4,9,14};\r
-\r
- int allgems[5]={GEM_DELAY_TIME, // used for Q & D comparison\r
- GEM_DELAY_TIME, // for having all gems...\r
- GEM_DELAY_TIME, // the "allgems" declaration MUST\r
- GEM_DELAY_TIME, // match the "gems" declaration in\r
- GEM_DELAY_TIME // the gametype structure!\r
- };\r
-\r
-// int originx=0;\r
-// int i=100;\r
- signed long dx,dy,radius,psin,pcos,newx,newy;\r
- int give;\r
- short objnum;\r
- signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;\r
- short o_radius;\r
-\r
- void (*think)();\r
-\r
- ingame = true;\r
- playstate = TimeCount = 0;\r
- gamestate.shotpower = handheight = 0;\r
- pointcount = pointsleft = 0;\r
-\r
- status_flag = S_NONE;\r
-\r
-#if 0\r
- // setup sky/ground colors and effects (based on level)\r
- //\r
- switch (gamestate.mapon)\r
- {\r
- case 255:\r
- if (!(BGFLAGS & BGF_NIGHT))\r
- {\r
- InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);\r
- groundcolor = &gnd_colors[0];\r
- }\r
- else\r
- {\r
- skycolor = &sky_colors[0];\r
- groundcolor = &gnd_colors[0];\r
- }\r
- break;\r
-\r
- default:\r
- skycolor = &sky_colors[gamestate.mapon];\r
- groundcolor = &gnd_colors[gamestate.mapon];\r
- skytimer = groundtimer = -1;\r
- break;\r
- }\r
-#endif\r
-\r
- BGFLAGS |= BGF_NOT_LIGHTNING;\r
- skytimer = groundtimer = -1;\r
-\r
- debug_gnd = *groundcolor;\r
- debug_sky = *skycolor;\r
- RedrawStatusWindow();\r
- ThreeDRefresh();\r
- if (screenfaded)\r
- VW_FadeIn();\r
-\r
-#ifndef PROFILE\r
- fizzlein = true; // fizzle fade in the first refresh\r
-#endif\r
- TimeCount = lasttimecount = lastnuke = 0;\r
-\r
- PollControls (); // center mouse\r
-// StartMusic ();\r
- do\r
- {\r
-#ifndef PROFILE\r
- PollControls();\r
-#else\r
- control.xaxis = 1;\r
- if (++TimeCount == 300)\r
- return;\r
-#endif\r
- DisplayStatus(&status_flag);\r
-\r
- objnum=0;\r
- for (obj = player;obj;obj = obj->next)\r
- {\r
- if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))\r
- {\r
- if (obj->ticcount)\r
- {\r
- obj->ticcount-=realtics;\r
- while ( obj->ticcount <= 0)\r
- {\r
- think = obj->state->think;\r
- if (think)\r
- {\r
- statetype *oldstate=obj->state;\r
-\r
- think (obj);\r
- if (!obj->state)\r
- {\r
- RemoveObj (obj);\r
- goto nextactor;\r
- }\r
- if (obj->state != oldstate)\r
- break;\r
- }\r
-\r
- obj->state = obj->state->next;\r
- if (!obj->state)\r
- {\r
- RemoveObj (obj);\r
- goto nextactor;\r
- }\r
- if (!obj->state->tictime)\r
- {\r
- obj->ticcount = 0;\r
- goto nextactor;\r
- }\r
- if (obj->state->tictime>0)\r
- obj->ticcount += obj->state->tictime;\r
- }\r
- }\r
-\r
- think = obj->state->think;\r
- if (think)\r
- {\r
- think (obj);\r
- if (!obj->state)\r
- RemoveObj (obj);\r
- }\r
-nextactor:;\r
- }\r
-\r
- // keep a list of objects around the player for radar updates\r
- //\r
- if (obj == player)\r
- {\r
- px = player->x;\r
- py = player->y;\r
- psin = sintable[player->angle];\r
- pcos = costable[player->angle];\r
- xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;\r
- xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;\r
- yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- }\r
-\r
- if (objnum > MAX_RADAR_BLIPS-2)\r
- objnum = MAX_RADAR_BLIPS-2;\r
-\r
- ox = obj->x;\r
- oy = obj->y;\r
-\r
-\r
- if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))\r
- {\r
- norm_dx = (dx = px-ox)>>TILESHIFT;\r
- norm_dy = (dy = oy-py)>>TILESHIFT;\r
-\r
- o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));\r
-\r
- if (o_radius < RADAR_RADIUS)\r
- {\r
- newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);\r
- newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);\r
-\r
- RadarXY[objnum][0]=newx>>TILESHIFT;\r
- RadarXY[objnum][1]=newy>>TILESHIFT;\r
-\r
- // Define color to use for this object...\r
- //\r
-\r
- switch (obj->obclass)\r
- {\r
- // NO GEM NEEDED\r
- //\r
- // THE WIZARD! (YOU)\r
- //\r
- case playerobj:\r
- RadarXY[objnum++][2]=15;\r
- break;\r
-\r
- // WIZARD'S SHOTS\r
- //\r
- case pshotobj:\r
- case bigpshotobj:\r
- RadarXY[objnum++][2]=shot_color[screenpage];\r
- break;\r
-\r
- // BATS (DK GRAY)\r
- //\r
- case batobj:\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=8;\r
- break;\r
-\r
- // RABBITS (LT GRAY)\r
- //\r
- case bunnyobj:\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=7;\r
- break;\r
-\r
- // RED GEM\r
- //\r
- // EYE, RED DEMON (DK RED)\r
- //\r
- case eyeobj:\r
- case reddemonobj:\r
- if (gamestate.gems[B_RGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=4;\r
- break;\r
-\r
- // RED MAGE (LT RED)\r
- //\r
- case mageobj:\r
- if (gamestate.gems[B_RGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=12;\r
- break;\r
-\r
- // BLUE GEM\r
- //\r
- // SUCCUBUS (LT BLUE)\r
- //\r
- case succubusobj:\r
- if (gamestate.gems[B_BGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=9;\r
- break;\r
-\r
- // WATER DRAGON (DK BLUE)\r
- //\r
- case wetobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=1;\r
- break;\r
-\r
-\r
-\r
- // GREEN GEM\r
- //\r
- // GREEN TROLL (LT GREEN)\r
- //\r
- case fatdemonobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=10;\r
- break;\r
-\r
- // GODESS (DK GREEN)\r
- //\r
- case godessobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=2;\r
- break;\r
-\r
- // YELLOW GEM\r
- //\r
- // ANT (BROWN)\r
- //\r
- case antobj:\r
- case treeobj:\r
- if (gamestate.gems[B_YGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=6;\r
- break;\r
-\r
- // SKELETON (YELLOW)\r
- //\r
- case skeletonobj:\r
- if (gamestate.gems[B_YGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=14;\r
- break;\r
-\r
- // PURPLE GEM\r
- //\r
- // ZOMBIE\r
- //\r
- case zombieobj:\r
- if (gamestate.gems[B_PGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=13;\r
- break;\r
-\r
- // ALL GEMS NEEDED\r
- //\r
- // NEMESIS\r
- //\r
- case grelmobj:\r
- if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=15;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- RadarXY[objnum][2]=-1; // Signals end of RadarXY list...\r
-\r
-#if USE_INERT_LIST\r
- if (inert != inertobjlist)\r
- for (obj=(objtype *)inertobjlist;obj;obj=obj->next)\r
- if (obj->ticcount)\r
- {\r
- obj->ticcount-=realtics;\r
- while ( obj->ticcount <= 0)\r
- {\r
- obj->state = obj->state->next;\r
- if (!obj->state)\r
- Quit("Removable object in INERT list.");\r
-\r
- if (!obj->state->tictime)\r
- {\r
- obj->ticcount = 0;\r
- goto nextactor;\r
- }\r
-\r
- if (obj->state->tictime>0)\r
- obj->ticcount += obj->state->tictime;\r
- }\r
- }\r
-#endif\r
-\r
- if (bordertime)\r
- {\r
- bordertime -= realtics;\r
- if (bordertime<=0)\r
- {\r
- bordertime = 0;\r
- VW_ColorBorder(0);\r
- }\r
- }\r
-\r
-#if 1\r
-// random lightning?\r
-//\r
- if (BGFLAGS & (BGF_NOT_LIGHTNING))\r
- {\r
- if ((scolor & 0xe0) && (!(random(20-realtics))))\r
- {\r
- BGFLAGS &= ~BGF_NOT_LIGHTNING;\r
- InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);\r
- }\r
- }\r
-\r
-// handle sky/ground color changes\r
-//\r
- if (skytimer != -1)\r
- {\r
- skytimer -= realtics;\r
- if (skytimer < 0)\r
- {\r
- skycolor++;\r
- if (*skycolor == 0xffff)\r
- {\r
- skytimer = -1;\r
-// skycolor--;\r
- skycolor = &scolor;\r
- if (groundtimer == -1)\r
- BGFLAGS |= bgflag;\r
- }\r
- else\r
- skytimer = skytimer_reset;\r
- }\r
- }\r
-\r
- if (groundtimer != -1)\r
- {\r
- groundtimer -= realtics;\r
- if (groundtimer < 0)\r
- {\r
- groundcolor++;\r
- if (*groundcolor == 0xffff)\r
- {\r
- groundtimer = -1;\r
-// groundcolor--;\r
- groundcolor = &gcolor;\r
- if (skytimer == -1)\r
- BGFLAGS |= bgflag;\r
- }\r
- else\r
- groundtimer = groundtimer_reset;\r
- }\r
- }\r
-#endif\r
-\r
-\r
-//\r
-// Handle FreezeTime counter..\r
-//\r
- if (FreezeTime)\r
- {\r
- if (FreezeTime<20*30)\r
- if ((BeepTime+=realtics)>=60)\r
- {\r
- BeepTime -= 60;\r
- SD_PlaySound(TICKSND);\r
- }\r
-\r
- if ((FreezeTime-=realtics)<=0)\r
- {\r
- FreezeTime=0;\r
- SD_PlaySound(TIMERETURNSND);\r
- DisplaySMsg(NULL,NULL);\r
- status_flag = S_NONE;\r
- }\r
- }\r
-\r
-\r
-// refresh all\r
-//\r
- ThreeDRefresh ();\r
-\r
- if (Flags & FL_DEAD)\r
- {\r
- SD_PlaySound (GAMEOVERSND);\r
- DisplaySMsg("DEAD",NULL);\r
- DrawHealth();\r
- if (gamestate.potions)\r
- {\r
- bufferofs = displayofs = screenloc[screenpage];\r
- CenterWindow(35,3);\r
- US_CPrint("\nYou should use your Cure Potions wisely\n");\r
- IN_Ack();\r
- }\r
- }\r
-\r
-// check for win\r
-//\r
- if (playstate == ex_victorious)\r
- {\r
- Victory(true);\r
-// Flags |= FL_DEAD;\r
- IN_Ack();\r
-// gamestate.mapon++;\r
- }\r
-\r
- CheckKeys();\r
-\r
- }while (!playstate);\r
-// StopMusic ();\r
-\r
- ingame = false;\r
- if (bordertime)\r
- {\r
- bordertime = 0;\r
- VW_ColorBorder(0);\r
- }\r
-\r
- if (abortgame)\r
- abortgame = false;\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// IntSqrt() - by Master Programmer, George Leritte!\r
-//--------------------------------------------------------------------------\r
-int IntSqrt(long va)\r
-{\r
-asm mov AX, word ptr va\r
-asm mov DX, word ptr va+2\r
-asm mov bx,dx // {bx = integer square root of dx:ax}\r
-asm or bx,ax // {if dx:ax=0 then return}\r
-asm jz isq01\r
-asm mov bx,dx\r
-asm shl bx,1\r
-asm or bl,ah\r
-asm or bl,al\r
-asm dec bx\r
-asm add bx,dx // { initial guess}\r
-asm jg isq10\r
-asm inc bx // { don't return zero}\r
-asm jg isq10\r
-asm mov bx,7fffh\r
-isq01:;\r
- goto exitrout;\r
-\r
-isq10:;\r
-asm push ax\r
-asm push dx\r
-asm div bx\r
-asm sub ax,bx\r
-asm cmp ax,1\r
-asm jbe isq90\r
-asm cmp ax,-1\r
-asm jae isq90\r
-asm sar ax,1\r
-asm add bx,ax\r
-asm pop dx\r
-asm pop ax\r
-asm jmp isq10\r
-isq90:;\r
-asm pop dx\r
-asm pop ax\r
-exitrout:;\r
-asm mov ax,bx\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// InitBgChange()\r
-//-------------------------------------------------------------------------\r
-void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)\r
-{\r
- skytimer_reset = skytimer = stimer;\r
- if (scolors)\r
- skycolor = scolors;\r
-\r
- groundtimer_reset = groundtimer = gtimer;\r
- if (gcolors)\r
- groundcolor = gcolors;\r
-\r
- bgflag = flag;\r
-}\r
-\r
-////////////////////////////////////////////////////////\r
-//\r
-// DisplayStatus\r
-//\r
-// Stat_Flag - contains the type of status displayed\r
-// -- also uses status_delay (global variable) will not\r
-// change display until this variable is zero.\r
-// -- heirarchy is determined by the series of if statements,\r
-// to change it, rearrange th if statements.\r
-//\r
-////////////////////////////////////////////////////////\r
-\r
-#define MESSAGEDELAY 25\r
-void DisplayStatus (status_flags *stat_flag)\r
-{\r
- status_flags temp_status;\r
-\r
-\r
- if (*stat_flag == S_TIMESTOP)\r
- return;\r
-\r
- if (status_delay > 0)\r
- {\r
- status_delay -= realtics;\r
- return;\r
- }\r
- else\r
- status_delay = 0;\r
-\r
- // check for a change in status from previous call\r
-\r
- temp_status = S_VIEWING; //precaution\r
-\r
- if (Keyboard[sc_Control] || control.button0)\r
- temp_status = S_MISSLE;\r
-\r
- if (Keyboard[sc_Z] && !Keyboard[sc_F10])\r
- temp_status = S_ZAPPER;\r
-\r
- if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])\r
- temp_status = S_XTER;\r
-\r
- if (control.x)\r
- temp_status = S_TURN;\r
-\r
- if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)\r
- temp_status = S_QTURN;\r
-\r
- if (Keyboard[sc_Alt] && control.x)\r
- temp_status = S_SIDESTEP;\r
-\r
- if (control.y < 0)\r
- temp_status = S_ADVANCE;\r
-\r
- if (control.y > 0)\r
- temp_status = S_RETREAT;\r
-\r
- if (Keyboard[sc_F5])\r
- temp_status = S_JOYSTICK;\r
-\r
- if (Keyboard[sc_F4])\r
- temp_status = S_RESTORING;\r
-\r
- if (Keyboard[sc_F3])\r
- temp_status = S_SAVING;\r
-\r
- if (Keyboard[sc_F2])\r
- temp_status = S_SND;\r
-\r
- if (Keyboard[sc_F1])\r
- temp_status = S_HELP;\r
-\r
- if (temp_status != *stat_flag)\r
- {\r
- *stat_flag = temp_status;\r
-\r
-\r
- switch (*stat_flag)\r
- {\r
- case S_MISSLE:\r
- DisplaySMsg("Magick Missile", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_ZAPPER:\r
- if (gamestate.bolts)\r
- {\r
- DisplaySMsg("Zapper", NULL);\r
- status_delay = MESSAGEDELAY+10;\r
- }\r
- break;\r
-\r
- case S_XTER:\r
- if (gamestate.nukes)\r
- {\r
- DisplaySMsg("Xterminator", NULL);\r
- status_delay = MESSAGEDELAY+5;\r
- }\r
- break;\r
-\r
- case S_TURN:\r
- DisplaySMsg("Turning", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_QTURN:\r
- DisplaySMsg("Quick Turning", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_SIDESTEP:\r
- DisplaySMsg("Sidestepping", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_ADVANCE:\r
- DisplaySMsg("Advancing", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_RETREAT:\r
- DisplaySMsg("Retreating", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_JOYSTICK:\r
- DisplaySMsg("Adjusting Joystick", NULL);\r
- break;\r
-\r
- case S_RESTORING:\r
- DisplaySMsg("Restoring", NULL);\r
- break;\r
-\r
- case S_SAVING:\r
- DisplaySMsg("Saving", NULL);\r
- break;\r
-\r
- case S_SND:\r
- DisplaySMsg("Select Sound", NULL);\r
- break;\r
-\r
- case S_HELP:\r
- DisplaySMsg("Getting Help", NULL);\r
- break;\r
-\r
- case S_VIEWING:\r
- DisplaySMsg("Viewing", NULL);\r
- break;\r
- }\r
- bufferofs = displayofs = screenloc[screenpage];\r
-\r
- }\r
-}\r