1 /* Catacomb Apocalypse Source Code
\r
2 * Copyright (C) 1993-2014 Flat Rock Software
\r
4 * This program is free software; you can redistribute it and/or modify
\r
5 * it under the terms of the GNU General Public License as published by
\r
6 * the Free Software Foundation; either version 2 of the License, or
\r
7 * (at your option) any later version.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
14 * You should have received a copy of the GNU General Public License along
\r
15 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
26 =============================================================================
\r
30 =============================================================================
\r
37 =============================================================================
\r
41 =============================================================================
\r
45 short skytimer=-1,skytimer_reset;
\r
46 short groundtimer=-1,groundtimer_reset;
\r
48 unsigned scolor,gcolor;
\r
49 unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;
\r
51 unsigned nocolorchange=0xFFFF;
\r
52 byte BGFLAGS, // global that holds all current flags
\r
53 bgflag; // used by BG changer, this flag is set when done
\r
56 unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};
\r
57 //unsigned gnd_daytonight[]={0x0202,0xFFFF};
\r
59 unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};
\r
61 unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,
\r
62 0x0404,0x0000,0x0000,0x0000,0x0000,
\r
63 0x0000,0x0000,0x0000,0x0000,0x0606,
\r
64 0x0000,0x0000,0x0000,0x0000,0x0000,
\r
66 unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,
\r
67 0x0505,0x0808,0x0606,0x0101,0x0808,
\r
68 0x0606,0x0404,0x0808,0x0c0c,0x0e0e,
\r
69 0x0808,0x0808,0x0c0c,0x0000,0x0707,
\r
73 ControlInfo control;
\r
74 boolean running=false; //,slowturn;
\r
77 objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;
\r
80 inertobjtype inertobjlist[MAXINERTOBJ],*inert;
\r
83 unsigned farmapylookup[MAPSIZE];
\r
84 byte *nearmapylookup[MAPSIZE];
\r
86 boolean singlestep,godmode;
\r
88 status_flags status_flag;
\r
92 // replacing refresh manager
\r
94 unsigned mapwidth,mapheight,tics,realtics;
\r
95 boolean compatability;
\r
97 unsigned mapwidthtable[64];
\r
98 unsigned uwidthtable[UPDATEHIGH];
\r
99 unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];
\r
100 #define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)
\r
101 #define UPDATESPARESIZE (UPDATEWIDE*2+4)
\r
102 #define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)
\r
103 byte update[UPDATESIZE];
\r
105 int mousexmove,mouseymove;
\r
106 int pointcount,pointsleft;
\r
108 short BeepTime = 0;
\r
111 =============================================================================
\r
115 =============================================================================
\r
118 void CalcBounds (objtype *ob);
\r
119 void DrawPlayScreen (void);
\r
120 void PreFullDisplay(void);
\r
121 void PostFullDisplay(boolean draw_view);
\r
125 // near data map array (wall values only, get text number from far data)
\r
127 byte tilemap[MAPSIZE][MAPSIZE];
\r
128 byte spotvis[MAPSIZE][MAPSIZE];
\r
129 objtype *actorat[MAPSIZE][MAPSIZE];
\r
136 void StopMusic(void);
\r
137 void StartMusic(void);
\r
139 void CalibrateJoystick(short joynum);
\r
141 //==========================================================================
\r
143 ///////////////////////////////////////////////////////////////////////////
\r
145 // CenterWindow() - Generates a window of a given width & height in the
\r
146 // middle of the screen
\r
148 ///////////////////////////////////////////////////////////////////////////
\r
153 void CenterWindow(word w,word h)
\r
155 US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);
\r
158 //===========================================================================
\r
162 =====================
\r
166 =====================
\r
169 void CheckKeys (void)
\r
171 extern boolean autofire;
\r
173 if (screenfaded) // don't do anything with a faded screen
\r
178 // pause key wierdness can't be checked as a scan code
\r
182 CenterWindow (8,3);
\r
183 US_PrintCentered ("PAUSED");
\r
184 VW_UpdateScreen ();
\r
189 if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
\r
192 if (Keyboard[sc_Enter]) // P = pause with no screen disruptioon
\r
195 DisplaySMsg("PAUSED",NULL);
\r
198 if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
\r
201 if (Keyboard[sc_S])
\r
203 char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};
\r
206 extravbls = SlowMode << 3;
\r
207 CenterWindow (8,3);
\r
208 US_PrintCentered (Text[SlowMode]);
\r
209 VW_UpdateScreen ();
\r
213 if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
\r
218 // F2 - SOUND OPTIONS
\r
220 if (Keyboard[sc_F2])
\r
223 boolean ChoiceMade = false;
\r
228 VW_FixRefreshBuffer();
\r
229 CenterWindow(22,height);
\r
230 US_Print( "\n 1 ) NO SOUND \n");
\r
231 US_Print( " 2 ) PC AUDIO \n");
\r
234 US_Print(" 3 ) ADLIB AUDIO\n");
\r
236 US_Print( "\n ESC) EXIT ");
\r
239 // Switch audio device ON/OFF & load sounds if there
\r
240 // was a change in the device.
\r
244 if (Keyboard[1]) // ESC - Exit
\r
247 if (Keyboard[2]) // 1 - No Sound
\r
249 SD_SetSoundMode(sdm_Off);
\r
253 if (Keyboard[3]) // 2 - PC Audio
\r
255 SD_SetSoundMode(sdm_PC);
\r
256 // if (oldsoundmode != sdm_PC)
\r
257 CA_LoadAllSounds();
\r
261 if ((Keyboard[4]) && AdLibPresent) // 3 - AdLib Audio
\r
263 SD_SetSoundMode(sdm_AdLib);
\r
264 // if (oldsoundmode != sdm_AdLib)
\r
265 CA_LoadAllSounds();
\r
269 } while (!ChoiceMade);
\r
270 tics = realtics = 1;
\r
271 IN_ClearKeysDown();
\r
274 // F5 - CALIBRATE JOYSTICK
\r
276 if (Keyboard[sc_F5])
\r
278 CalibrateJoystick(0);
\r
279 tics = realtics = 1;
\r
280 IN_ClearKeysDown();
\r
284 // ESCAPE - quits game
\r
286 if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))
\r
290 DisplaySMsg("Options", NULL);
\r
291 status_flag = S_NONE;
\r
294 if (Flags & FL_DEAD)
\r
296 char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};
\r
297 ch = DisplayMsg("Restore New Quit",choices);
\r
298 DisplayMsg(" ", NULL);
\r
302 char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};
\r
303 ch = DisplayMsg("Save Restore New Quit",choices);
\r
310 if (!(Flags & FL_DEAD))
\r
311 Keyboard[sc_F3] = true;
\r
315 Keyboard[sc_F4] = true;
\r
319 DisplaySMsg("Starting anew", NULL);
\r
321 playstate = ex_resetgame;
\r
326 DisplaySMsg("FARE THEE WELL!", NULL);
\r
328 if (!Flags & FL_QUICK)
\r
335 tics = realtics = 1;
\r
338 // F1 - DISPLAY HELP
\r
340 if (Keyboard[sc_F1])
\r
344 #ifdef TEXT_PRESENTER
\r
346 extern PresenterInfo MainHelpText;
\r
351 if (!LoadPresenterScript("HELP.TXT",&MainHelpText))
\r
354 CenterWindow(30,5);
\r
355 US_CPrint("\nError loading HELP file.\n");
\r
356 US_CPrint("Press any key.");
\r
362 VW_SetSplitScreen(200);
\r
363 bufferofs = displayofs = screenloc[0];
\r
364 VW_Bar(0,0,320,200,0);
\r
367 Presenter(&MainHelpText);
\r
370 FreePresenterScript(&MainHelpText);
\r
372 VW_SetSplitScreen(120);
\r
373 VW_SetScreen(screenloc[0],0);
\r
378 RedrawStatusWindow();
\r
381 Keyboard[sc_F1] = false;
\r
382 tics = realtics = 1;
\r
383 IN_ClearKeysDown();
\r
388 if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))
\r
392 PostFullDisplay(true);
\r
393 tics = realtics = 1;
\r
394 IN_ClearKeysDown();
\r
399 if (Keyboard[sc_F4])
\r
405 playstate = ex_loadedgame;
\r
408 PostFullDisplay(false);
\r
411 if (playstate == ex_victorious)
\r
413 PostFullDisplay(false);
\r
419 PostFullDisplay(true);
\r
420 Keyboard[sc_F5] = false;
\r
421 tics = realtics = 1;
\r
422 IN_ClearKeysDown();
\r
425 if (Flags & FL_DEAD)
\r
429 // F10-? debug keys
\r
431 if (Keyboard[sc_BackSpace])
\r
434 if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
\r
435 lasttimecount = TimeCount;
\r
439 //-------------------------------------------------------------------------
\r
440 // PreFullDisplay()
\r
441 //-------------------------------------------------------------------------
\r
442 void PreFullDisplay()
\r
445 VW_SetSplitScreen(200);
\r
446 bufferofs = displayofs = screenloc[0];
\r
447 VW_Bar(0,0,320,200,0);
\r
450 //-------------------------------------------------------------------------
\r
451 // PostFullDisplay()
\r
452 //-------------------------------------------------------------------------
\r
453 void PostFullDisplay(boolean draw_view)
\r
455 VW_SetSplitScreen(120);
\r
457 RedrawStatusWindow();
\r
466 //===========================================================================
\r
469 #############################################################################
\r
471 The objlist data structure
\r
473 #############################################################################
\r
475 objlist containt structures for every actor currently playing. The structure
\r
476 is accessed as a linked list starting at *player, ending when ob->next ==
\r
477 NULL. GetNewObj inserts a new object at the end of the list, meaning that
\r
478 if an actor spawn another actor, the new one WILL get to think and react the
\r
479 same frame. RemoveObj unlinks the given object and returns it to the free
\r
480 list, but does not damage the objects ->next pointer, so if the current object
\r
481 removes itself, a linked list following loop can still safely get to the
\r
484 <backwardly linked free list>
\r
486 #############################################################################
\r
491 =========================
\r
495 = Call to clear out the entire object list, returning them all to the free
\r
496 = list. Allocates a special spot for the player.
\r
498 =========================
\r
501 void InitObjList (void)
\r
505 for (i=0;i<MAXACTORS;i++)
\r
507 objlist[i].prev = &objlist[i+1];
\r
508 objlist[i].next = NULL;
\r
511 objlist[MAXACTORS-1].prev = NULL;
\r
513 objfreelist = &objlist[0];
\r
519 // give the player and score the first free spots
\r
525 inert = inertobjlist;
\r
530 //===========================================================================
\r
533 =========================
\r
537 = Sets the global variable new to point to a free spot in objlist.
\r
538 = The free spot is inserted at the end of the liked list
\r
540 = When the object list is full, the caller can either have it bomb out ot
\r
541 = return a dummy object pointer that will never get used
\r
543 =========================
\r
546 void GetNewObj (boolean usedummy)
\r
555 Quit ("GetNewObj: No free spots in objlist!");
\r
559 objfreelist = new->prev;
\r
560 memset (new,0,sizeof(*new));
\r
563 lastobj->next = new;
\r
564 new->prev = lastobj; // new->next is allready NULL from memset
\r
566 new->active = false;
\r
572 //===========================================================================
\r
575 =========================
\r
579 = Add the given object back into the free list, and unlink it from it's
\r
582 =========================
\r
585 void RemoveObj (objtype *gone)
\r
589 if (gone == player)
\r
590 Quit ("RemoveObj: Tried to remove the player!");
\r
593 // fix the next object's back link
\r
595 if (gone == lastobj)
\r
596 lastobj = (objtype *)gone->prev;
\r
598 gone->next->prev = gone->prev;
\r
601 // fix the previous object's forward link
\r
603 gone->prev->next = gone->next;
\r
606 // add it back in to the free list
\r
608 gone->prev = objfreelist;
\r
609 objfreelist = gone;
\r
616 //--------------------------------------------------------------------------
\r
617 // MoveObjToInert()
\r
618 //--------------------------------------------------------------------------
\r
619 void MoveObjToInert(objtype *obj)
\r
622 if (inert == &inertobjlist[MAXINERTOBJ])
\r
625 // Transfer info needed by inert objtype
\r
629 inert->size = obj->size;
\r
630 inert->viewx = obj->viewx;
\r
631 inert->tilex = obj->tilex;
\r
632 inert->tiley = obj->tiley;
\r
633 inert->state = obj->state;
\r
634 inert->ticcount = obj->ticcount;
\r
636 // Setup links between inert objects
\r
638 if (inert != inertobjlist)
\r
639 (inert-1)->next = inert;
\r
640 inert->next = NULL;
\r
643 // Free 'real' object from list.
\r
650 //==========================================================================
\r
653 ===================
\r
657 ===================
\r
660 void PollControls (void)
\r
664 IN_ReadControl(0,&control);
\r
675 control.button0 = 1;
\r
677 control.button1 = 1;
\r
681 if (Keyboard[sc_V] || Keyboard[sc_Tab])
\r
687 //==========================================================================
\r
698 void StopMusic(void)
\r
703 for (i = 0;i < LASTMUSIC;i++)
\r
704 if (audiosegs[STARTMUSIC + i])
\r
706 MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);
\r
707 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);
\r
711 //==========================================================================
\r
722 // JAB - Cache & start the appropriate music for this level
\r
723 void StartMusic(void)
\r
728 chunk = TOOHOT_MUS;
\r
729 // if ((chunk == -1) || (MusicMode != smm_AdLib))
\r
730 //DEBUG control panel return;
\r
732 MM_BombOnError (false);
\r
733 CA_CacheAudioChunk(STARTMUSIC + chunk);
\r
734 MM_BombOnError (true);
\r
739 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);
\r
740 SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);
\r
745 //==========================================================================
\r
749 ===================
\r
753 ===================
\r
756 void PlayLoop (void)
\r
758 char shot_color[3] = {4,9,14};
\r
760 int allgems[5]={GEM_DELAY_TIME, // used for Q & D comparison
\r
761 GEM_DELAY_TIME, // for having all gems...
\r
762 GEM_DELAY_TIME, // the "allgems" declaration MUST
\r
763 GEM_DELAY_TIME, // match the "gems" declaration in
\r
764 GEM_DELAY_TIME // the gametype structure!
\r
769 signed long dx,dy,radius,psin,pcos,newx,newy;
\r
772 signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;
\r
778 playstate = TimeCount = 0;
\r
779 gamestate.shotpower = handheight = 0;
\r
780 pointcount = pointsleft = 0;
\r
782 status_flag = S_NONE;
\r
785 // setup sky/ground colors and effects (based on level)
\r
787 switch (gamestate.mapon)
\r
790 if (!(BGFLAGS & BGF_NIGHT))
\r
792 InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);
\r
793 groundcolor = &gnd_colors[0];
\r
797 skycolor = &sky_colors[0];
\r
798 groundcolor = &gnd_colors[0];
\r
803 skycolor = &sky_colors[gamestate.mapon];
\r
804 groundcolor = &gnd_colors[gamestate.mapon];
\r
805 skytimer = groundtimer = -1;
\r
810 BGFLAGS |= BGF_NOT_LIGHTNING;
\r
811 skytimer = groundtimer = -1;
\r
813 debug_gnd = *groundcolor;
\r
814 debug_sky = *skycolor;
\r
815 RedrawStatusWindow();
\r
821 fizzlein = true; // fizzle fade in the first refresh
\r
823 TimeCount = lasttimecount = lastnuke = 0;
\r
825 PollControls (); // center mouse
\r
833 if (++TimeCount == 300)
\r
836 DisplayStatus(&status_flag);
\r
839 for (obj = player;obj;obj = obj->next)
\r
841 if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))
\r
845 obj->ticcount-=realtics;
\r
846 while ( obj->ticcount <= 0)
\r
848 think = obj->state->think;
\r
851 statetype *oldstate=obj->state;
\r
859 if (obj->state != oldstate)
\r
863 obj->state = obj->state->next;
\r
869 if (!obj->state->tictime)
\r
874 if (obj->state->tictime>0)
\r
875 obj->ticcount += obj->state->tictime;
\r
879 think = obj->state->think;
\r
889 // keep a list of objects around the player for radar updates
\r
895 psin = sintable[player->angle];
\r
896 pcos = costable[player->angle];
\r
897 xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;
\r
898 xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;
\r
899 yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;
\r
900 yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;
\r
903 if (objnum > MAX_RADAR_BLIPS-2)
\r
904 objnum = MAX_RADAR_BLIPS-2;
\r
910 if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))
\r
912 norm_dx = (dx = px-ox)>>TILESHIFT;
\r
913 norm_dy = (dy = oy-py)>>TILESHIFT;
\r
915 o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));
\r
917 if (o_radius < RADAR_RADIUS)
\r
919 newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);
\r
920 newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);
\r
922 RadarXY[objnum][0]=newx>>TILESHIFT;
\r
923 RadarXY[objnum][1]=newy>>TILESHIFT;
\r
925 // Define color to use for this object...
\r
928 switch (obj->obclass)
\r
932 // THE WIZARD! (YOU)
\r
935 RadarXY[objnum++][2]=15;
\r
943 RadarXY[objnum++][2]=shot_color[screenpage];
\r
952 if (gamestate.gems[B_RGEM-B_RGEM])
\r
953 if (obj->active == always)
\r
954 RadarXY[objnum++][2]=4;
\r
960 if (gamestate.gems[B_RGEM-B_RGEM])
\r
961 if (obj->active == always)
\r
962 RadarXY[objnum++][2]=12;
\r
967 // ROBOTANK (LT BLUE)
\r
971 if (gamestate.gems[B_BGEM-B_RGEM])
\r
972 if (obj->active == always)
\r
973 RadarXY[objnum++][2]=9;
\r
977 // BLUE DEMON (DK BLUE)
\r
980 if (gamestate.gems[B_GGEM-B_RGEM])
\r
981 if (obj->active == always)
\r
982 RadarXY[objnum++][2]=1;
\r
988 // WIZARD (LT GREEN)
\r
991 if (gamestate.gems[B_GGEM-B_RGEM])
\r
992 if (obj->active == always)
\r
993 RadarXY[objnum++][2]=10;
\r
996 // AQUA MAN (DK GREEN)
\r
999 if (gamestate.gems[B_GGEM-B_RGEM])
\r
1000 if (obj->active == always)
\r
1001 RadarXY[objnum++][2]=2;
\r
1006 // EQYPTIAN HEAD (BROWN)
\r
1009 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1010 if (obj->active == always)
\r
1011 RadarXY[objnum++][2]=6;
\r
1014 // RAMBONE (YELLOW)
\r
1018 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1019 if (obj->active == always)
\r
1020 RadarXY[objnum++][2]=14;
\r
1023 // BUG (LIGHT GRAY)
\r
1025 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1026 if (obj->active == always)
\r
1027 RadarXY[objnum++][2]=7;
\r
1030 // RAY (DARK GRAY)
\r
1032 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1033 if (obj->active == always)
\r
1034 RadarXY[objnum++][2]=8;
\r
1039 // MEC DEMON (PURPLE)
\r
1041 case cyborgdemonobj:
\r
1042 if (gamestate.gems[B_PGEM-B_RGEM])
\r
1043 if (obj->active == always)
\r
1044 RadarXY[objnum++][2]=5;
\r
1047 // EYE (LT PURPLE)
\r
1051 if (gamestate.gems[B_PGEM-B_RGEM])
\r
1052 if (obj->active == always)
\r
1053 RadarXY[objnum++][2]=13;
\r
1056 // ALL GEMS NEEDED
\r
1061 if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))
\r
1062 if (obj->active == always)
\r
1063 RadarXY[objnum++][2]=15;
\r
1069 RadarXY[objnum][2]=-1; // Signals end of RadarXY list...
\r
1071 #if USE_INERT_LIST
\r
1072 if (inert != inertobjlist)
\r
1073 for (obj=(objtype *)inertobjlist;obj;obj=obj->next)
\r
1074 if (obj->ticcount)
\r
1076 obj->ticcount-=realtics;
\r
1077 while ( obj->ticcount <= 0)
\r
1079 obj->state = obj->state->next;
\r
1081 Quit("Removable object in INERT list.");
\r
1083 if (!obj->state->tictime)
\r
1085 obj->ticcount = 0;
\r
1089 if (obj->state->tictime>0)
\r
1090 obj->ticcount += obj->state->tictime;
\r
1097 bordertime -= realtics;
\r
1098 if (bordertime<=0)
\r
1101 VW_ColorBorder(0);
\r
1106 // random lightning?
\r
1108 if (BGFLAGS & (BGF_NOT_LIGHTNING))
\r
1110 if ((scolor & 0xe0) && (!(random(20-realtics))))
\r
1112 BGFLAGS &= ~BGF_NOT_LIGHTNING;
\r
1113 InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);
\r
1117 // handle sky/ground color changes
\r
1119 if (skytimer != -1)
\r
1121 skytimer -= realtics;
\r
1125 if (*skycolor == 0xffff)
\r
1129 skycolor = &scolor;
\r
1130 if (groundtimer == -1)
\r
1131 BGFLAGS |= bgflag;
\r
1134 skytimer = skytimer_reset;
\r
1138 if (groundtimer != -1)
\r
1140 groundtimer -= realtics;
\r
1141 if (groundtimer < 0)
\r
1144 if (*groundcolor == 0xffff)
\r
1148 groundcolor = &gcolor;
\r
1149 if (skytimer == -1)
\r
1150 BGFLAGS |= bgflag;
\r
1153 groundtimer = groundtimer_reset;
\r
1160 // Handle FreezeTime counter..
\r
1164 if (FreezeTime<20*30)
\r
1165 if ((BeepTime+=realtics)>=60)
\r
1168 SD_PlaySound(TICKSND);
\r
1171 if ((FreezeTime-=realtics)<=0)
\r
1174 SD_PlaySound(TIMERETURNSND);
\r
1175 DisplaySMsg(NULL,NULL);
\r
1176 status_flag = S_NONE;
\r
1185 if (Flags & FL_DEAD)
\r
1187 SD_PlaySound (GAMEOVERSND);
\r
1188 DisplaySMsg("DEAD",NULL);
\r
1194 if (playstate == ex_victorious)
\r
1203 }while (!playstate);
\r
1210 VW_ColorBorder(0);
\r
1214 abortgame = false;
\r
1217 //--------------------------------------------------------------------------
\r
1218 // IntSqrt() - by Master Programmer, George Leritte!
\r
1219 //--------------------------------------------------------------------------
\r
1220 int IntSqrt(long va)
\r
1222 asm mov AX, word ptr va
\r
1223 asm mov DX, word ptr va+2
\r
1224 asm mov bx,dx // {bx = integer square root of dx:ax}
\r
1225 asm or bx,ax // {if dx:ax=0 then return}
\r
1232 asm add bx,dx // { initial guess}
\r
1234 asm inc bx // { don't return zero}
\r
1261 //-------------------------------------------------------------------------
\r
1263 //-------------------------------------------------------------------------
\r
1264 void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)
\r
1266 skytimer_reset = skytimer = stimer;
\r
1268 skycolor = scolors;
\r
1270 groundtimer_reset = groundtimer = gtimer;
\r
1272 groundcolor = gcolors;
\r
1277 ////////////////////////////////////////////////////////
\r
1281 // Stat_Flag - contains the type of status displayed
\r
1282 // -- also uses status_delay (global variable) will not
\r
1283 // change display until this variable is zero.
\r
1284 // -- heirarchy is determined by the series of if statements,
\r
1285 // to change it, rearrange th if statements.
\r
1287 ////////////////////////////////////////////////////////
\r
1289 #define MESSAGEDELAY 25
\r
1290 void DisplayStatus (status_flags *stat_flag)
\r
1292 status_flags temp_status;
\r
1295 if (*stat_flag == S_TIMESTOP)
\r
1298 if (status_delay > 0)
\r
1300 status_delay -= realtics;
\r
1306 // check for a change in status from previous call
\r
1308 temp_status = S_VIEWING; //precaution
\r
1310 if (Keyboard[sc_Control] || control.button0)
\r
1311 temp_status = S_MISSLE;
\r
1313 if (Keyboard[sc_Z] && !Keyboard[sc_F10])
\r
1314 temp_status = S_ZAPPER;
\r
1316 if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])
\r
1317 temp_status = S_XTER;
\r
1320 temp_status = S_TURN;
\r
1322 if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)
\r
1323 temp_status = S_QTURN;
\r
1325 if (Keyboard[sc_Alt] && control.x)
\r
1326 temp_status = S_SIDESTEP;
\r
1328 if (control.y < 0)
\r
1329 temp_status = S_ADVANCE;
\r
1331 if (control.y > 0)
\r
1332 temp_status = S_RETREAT;
\r
1334 if (Keyboard[sc_F5])
\r
1335 temp_status = S_JOYSTICK;
\r
1337 if (Keyboard[sc_F4])
\r
1338 temp_status = S_RESTORING;
\r
1340 if (Keyboard[sc_F3])
\r
1341 temp_status = S_SAVING;
\r
1343 if (Keyboard[sc_F2])
\r
1344 temp_status = S_SND;
\r
1346 if (Keyboard[sc_F1])
\r
1347 temp_status = S_HELP;
\r
1349 if (temp_status != *stat_flag)
\r
1351 *stat_flag = temp_status;
\r
1354 switch (*stat_flag)
\r
1357 DisplaySMsg("Magick Missile", NULL);
\r
1358 status_delay = MESSAGEDELAY;
\r
1362 if (gamestate.bolts)
\r
1364 DisplaySMsg("Zapper", NULL);
\r
1365 status_delay = MESSAGEDELAY+10;
\r
1370 if (gamestate.nukes)
\r
1372 DisplaySMsg("Xterminator", NULL);
\r
1373 status_delay = MESSAGEDELAY+5;
\r
1378 DisplaySMsg("Turning", NULL);
\r
1379 status_delay = MESSAGEDELAY;
\r
1383 DisplaySMsg("Quick Turning", NULL);
\r
1384 status_delay = MESSAGEDELAY;
\r
1388 DisplaySMsg("Sidestepping", NULL);
\r
1389 status_delay = MESSAGEDELAY;
\r
1393 DisplaySMsg("Advancing", NULL);
\r
1394 status_delay = MESSAGEDELAY;
\r
1398 DisplaySMsg("Retreating", NULL);
\r
1399 status_delay = MESSAGEDELAY;
\r
1403 DisplaySMsg("Adjusting Joystick", NULL);
\r
1407 DisplaySMsg("Restoring", NULL);
\r
1411 DisplaySMsg("Saving", NULL);
\r
1415 DisplaySMsg("Select Sound", NULL);
\r
1419 DisplaySMsg("Getting Help", NULL);
\r
1423 DisplaySMsg("Viewing", NULL);
\r
1426 bufferofs = displayofs = screenloc[screenpage];
\r