1 /* Catacomb Armageddon 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
301 char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};
\r
302 ch = DisplayMsg("Save Restore New Quit",choices);
\r
309 if (!(Flags & FL_DEAD))
\r
310 Keyboard[sc_F3] = true;
\r
314 Keyboard[sc_F4] = true;
\r
318 DisplaySMsg("Starting anew", NULL);
\r
320 playstate = ex_resetgame;
\r
325 DisplaySMsg("FARE THEE WELL!", NULL);
\r
327 if (!Flags & FL_QUICK)
\r
334 tics = realtics = 1;
\r
337 // F1 - DISPLAY HELP
\r
339 if (Keyboard[sc_F1])
\r
343 #ifdef TEXT_PRESENTER
\r
345 extern PresenterInfo MainHelpText;
\r
350 if (!LoadPresenterScript("HELP.TXT",&MainHelpText))
\r
353 CenterWindow(30,5);
\r
354 US_CPrint("\nError loading HELP file.\n");
\r
355 US_CPrint("Press any key.");
\r
361 VW_SetSplitScreen(200);
\r
362 bufferofs = displayofs = screenloc[0];
\r
363 VW_Bar(0,0,320,200,0);
\r
366 Presenter(&MainHelpText);
\r
369 FreePresenterScript(&MainHelpText);
\r
371 VW_SetSplitScreen(120);
\r
372 VW_SetScreen(screenloc[0],0);
\r
377 RedrawStatusWindow();
\r
380 Keyboard[sc_F1] = false;
\r
381 tics = realtics = 1;
\r
382 IN_ClearKeysDown();
\r
387 if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))
\r
391 PostFullDisplay(true);
\r
392 tics = realtics = 1;
\r
393 IN_ClearKeysDown();
\r
398 if (Keyboard[sc_F4])
\r
404 playstate = ex_loadedgame;
\r
407 PostFullDisplay(false);
\r
410 if (playstate == ex_victorious)
\r
412 PostFullDisplay(false);
\r
415 // gamestate.mapon++;
\r
418 PostFullDisplay(true);
\r
419 Keyboard[sc_F5] = false;
\r
420 tics = realtics = 1;
\r
421 IN_ClearKeysDown();
\r
424 if (Flags & FL_DEAD)
\r
428 // F10-? debug keys
\r
430 if (Keyboard[sc_BackSpace])
\r
433 if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
\r
434 lasttimecount = TimeCount;
\r
438 //-------------------------------------------------------------------------
\r
439 // PreFullDisplay()
\r
440 //-------------------------------------------------------------------------
\r
441 void PreFullDisplay()
\r
444 VW_SetSplitScreen(200);
\r
445 bufferofs = displayofs = screenloc[0];
\r
446 VW_Bar(0,0,320,200,0);
\r
449 //-------------------------------------------------------------------------
\r
450 // PostFullDisplay()
\r
451 //-------------------------------------------------------------------------
\r
452 void PostFullDisplay(boolean draw_view)
\r
454 VW_SetSplitScreen(120);
\r
456 RedrawStatusWindow();
\r
465 //===========================================================================
\r
468 #############################################################################
\r
470 The objlist data structure
\r
472 #############################################################################
\r
474 objlist containt structures for every actor currently playing. The structure
\r
475 is accessed as a linked list starting at *player, ending when ob->next ==
\r
476 NULL. GetNewObj inserts a new object at the end of the list, meaning that
\r
477 if an actor spawn another actor, the new one WILL get to think and react the
\r
478 same frame. RemoveObj unlinks the given object and returns it to the free
\r
479 list, but does not damage the objects ->next pointer, so if the current object
\r
480 removes itself, a linked list following loop can still safely get to the
\r
483 <backwardly linked free list>
\r
485 #############################################################################
\r
490 =========================
\r
494 = Call to clear out the entire object list, returning them all to the free
\r
495 = list. Allocates a special spot for the player.
\r
497 =========================
\r
500 void InitObjList (void)
\r
504 for (i=0;i<MAXACTORS;i++)
\r
506 objlist[i].prev = &objlist[i+1];
\r
507 objlist[i].next = NULL;
\r
510 objlist[MAXACTORS-1].prev = NULL;
\r
512 objfreelist = &objlist[0];
\r
518 // give the player and score the first free spots
\r
524 inert = inertobjlist;
\r
529 //===========================================================================
\r
532 =========================
\r
536 = Sets the global variable new to point to a free spot in objlist.
\r
537 = The free spot is inserted at the end of the liked list
\r
539 = When the object list is full, the caller can either have it bomb out ot
\r
540 = return a dummy object pointer that will never get used
\r
542 =========================
\r
545 void GetNewObj (boolean usedummy)
\r
554 Quit ("GetNewObj: No free spots in objlist!");
\r
558 objfreelist = new->prev;
\r
559 memset (new,0,sizeof(*new));
\r
562 lastobj->next = new;
\r
563 new->prev = lastobj; // new->next is allready NULL from memset
\r
565 new->active = false;
\r
571 //===========================================================================
\r
574 =========================
\r
578 = Add the given object back into the free list, and unlink it from it's
\r
581 =========================
\r
584 void RemoveObj (objtype *gone)
\r
588 if (gone == player)
\r
589 Quit ("RemoveObj: Tried to remove the player!");
\r
592 // fix the next object's back link
\r
594 if (gone == lastobj)
\r
595 lastobj = (objtype *)gone->prev;
\r
597 gone->next->prev = gone->prev;
\r
600 // fix the previous object's forward link
\r
602 gone->prev->next = gone->next;
\r
605 // add it back in to the free list
\r
607 gone->prev = objfreelist;
\r
608 objfreelist = gone;
\r
615 //--------------------------------------------------------------------------
\r
616 // MoveObjToInert()
\r
617 //--------------------------------------------------------------------------
\r
618 void MoveObjToInert(objtype *obj)
\r
621 if (inert == &inertobjlist[MAXINERTOBJ])
\r
624 // Transfer info needed by inert objtype
\r
628 inert->size = obj->size;
\r
629 inert->viewx = obj->viewx;
\r
630 inert->tilex = obj->tilex;
\r
631 inert->tiley = obj->tiley;
\r
632 inert->state = obj->state;
\r
633 inert->ticcount = obj->ticcount;
\r
635 // Setup links between inert objects
\r
637 if (inert != inertobjlist)
\r
638 (inert-1)->next = inert;
\r
639 inert->next = NULL;
\r
642 // Free 'real' object from list.
\r
649 //==========================================================================
\r
652 ===================
\r
656 ===================
\r
659 void PollControls (void)
\r
663 IN_ReadControl(0,&control);
\r
674 control.button0 = 1;
\r
676 control.button1 = 1;
\r
680 if (Keyboard[sc_V] || Keyboard[sc_Tab])
\r
686 //==========================================================================
\r
697 void StopMusic(void)
\r
702 for (i = 0;i < LASTMUSIC;i++)
\r
703 if (audiosegs[STARTMUSIC + i])
\r
705 MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);
\r
706 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);
\r
710 //==========================================================================
\r
721 // JAB - Cache & start the appropriate music for this level
\r
722 void StartMusic(void)
\r
727 chunk = TOOHOT_MUS;
\r
728 // if ((chunk == -1) || (MusicMode != smm_AdLib))
\r
729 //DEBUG control panel return;
\r
731 MM_BombOnError (false);
\r
732 CA_CacheAudioChunk(STARTMUSIC + chunk);
\r
733 MM_BombOnError (true);
\r
738 MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);
\r
739 SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);
\r
744 //==========================================================================
\r
748 ===================
\r
752 ===================
\r
755 void PlayLoop (void)
\r
757 char shot_color[3] = {4,9,14};
\r
759 int allgems[5]={GEM_DELAY_TIME, // used for Q & D comparison
\r
760 GEM_DELAY_TIME, // for having all gems...
\r
761 GEM_DELAY_TIME, // the "allgems" declaration MUST
\r
762 GEM_DELAY_TIME, // match the "gems" declaration in
\r
763 GEM_DELAY_TIME // the gametype structure!
\r
768 signed long dx,dy,radius,psin,pcos,newx,newy;
\r
771 signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;
\r
777 playstate = TimeCount = 0;
\r
778 gamestate.shotpower = handheight = 0;
\r
779 pointcount = pointsleft = 0;
\r
781 status_flag = S_NONE;
\r
784 // setup sky/ground colors and effects (based on level)
\r
786 switch (gamestate.mapon)
\r
789 if (!(BGFLAGS & BGF_NIGHT))
\r
791 InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);
\r
792 groundcolor = &gnd_colors[0];
\r
796 skycolor = &sky_colors[0];
\r
797 groundcolor = &gnd_colors[0];
\r
802 skycolor = &sky_colors[gamestate.mapon];
\r
803 groundcolor = &gnd_colors[gamestate.mapon];
\r
804 skytimer = groundtimer = -1;
\r
809 BGFLAGS |= BGF_NOT_LIGHTNING;
\r
810 skytimer = groundtimer = -1;
\r
812 debug_gnd = *groundcolor;
\r
813 debug_sky = *skycolor;
\r
814 RedrawStatusWindow();
\r
820 fizzlein = true; // fizzle fade in the first refresh
\r
822 TimeCount = lasttimecount = lastnuke = 0;
\r
824 PollControls (); // center mouse
\r
832 if (++TimeCount == 300)
\r
835 DisplayStatus(&status_flag);
\r
838 for (obj = player;obj;obj = obj->next)
\r
840 if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))
\r
844 obj->ticcount-=realtics;
\r
845 while ( obj->ticcount <= 0)
\r
847 think = obj->state->think;
\r
850 statetype *oldstate=obj->state;
\r
858 if (obj->state != oldstate)
\r
862 obj->state = obj->state->next;
\r
868 if (!obj->state->tictime)
\r
873 if (obj->state->tictime>0)
\r
874 obj->ticcount += obj->state->tictime;
\r
878 think = obj->state->think;
\r
888 // keep a list of objects around the player for radar updates
\r
894 psin = sintable[player->angle];
\r
895 pcos = costable[player->angle];
\r
896 xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;
\r
897 xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;
\r
898 yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;
\r
899 yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;
\r
902 if (objnum > MAX_RADAR_BLIPS-2)
\r
903 objnum = MAX_RADAR_BLIPS-2;
\r
909 if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))
\r
911 norm_dx = (dx = px-ox)>>TILESHIFT;
\r
912 norm_dy = (dy = oy-py)>>TILESHIFT;
\r
914 o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));
\r
916 if (o_radius < RADAR_RADIUS)
\r
918 newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);
\r
919 newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);
\r
921 RadarXY[objnum][0]=newx>>TILESHIFT;
\r
922 RadarXY[objnum][1]=newy>>TILESHIFT;
\r
924 // Define color to use for this object...
\r
927 switch (obj->obclass)
\r
931 // THE WIZARD! (YOU)
\r
934 RadarXY[objnum++][2]=15;
\r
941 RadarXY[objnum++][2]=shot_color[screenpage];
\r
947 if (obj->active == always)
\r
948 RadarXY[objnum++][2]=8;
\r
951 // RABBITS (LT GRAY)
\r
954 if (obj->active == always)
\r
955 RadarXY[objnum++][2]=7;
\r
960 // EYE, RED DEMON (DK RED)
\r
964 if (gamestate.gems[B_RGEM-B_RGEM])
\r
965 if (obj->active == always)
\r
966 RadarXY[objnum++][2]=4;
\r
969 // RED MAGE (LT RED)
\r
972 if (gamestate.gems[B_RGEM-B_RGEM])
\r
973 if (obj->active == always)
\r
974 RadarXY[objnum++][2]=12;
\r
979 // SUCCUBUS (LT BLUE)
\r
982 if (gamestate.gems[B_BGEM-B_RGEM])
\r
983 if (obj->active == always)
\r
984 RadarXY[objnum++][2]=9;
\r
987 // WATER DRAGON (DK BLUE)
\r
990 if (gamestate.gems[B_GGEM-B_RGEM])
\r
991 if (obj->active == always)
\r
992 RadarXY[objnum++][2]=1;
\r
999 // GREEN TROLL (LT GREEN)
\r
1002 if (gamestate.gems[B_GGEM-B_RGEM])
\r
1003 if (obj->active == always)
\r
1004 RadarXY[objnum++][2]=10;
\r
1007 // GODESS (DK GREEN)
\r
1010 if (gamestate.gems[B_GGEM-B_RGEM])
\r
1011 if (obj->active == always)
\r
1012 RadarXY[objnum++][2]=2;
\r
1021 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1022 if (obj->active == always)
\r
1023 RadarXY[objnum++][2]=6;
\r
1026 // SKELETON (YELLOW)
\r
1029 if (gamestate.gems[B_YGEM-B_RGEM])
\r
1030 if (obj->active == always)
\r
1031 RadarXY[objnum++][2]=14;
\r
1039 if (gamestate.gems[B_PGEM-B_RGEM])
\r
1040 if (obj->active == always)
\r
1041 RadarXY[objnum++][2]=13;
\r
1044 // ALL GEMS NEEDED
\r
1049 if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))
\r
1050 if (obj->active == always)
\r
1051 RadarXY[objnum++][2]=15;
\r
1057 RadarXY[objnum][2]=-1; // Signals end of RadarXY list...
\r
1059 #if USE_INERT_LIST
\r
1060 if (inert != inertobjlist)
\r
1061 for (obj=(objtype *)inertobjlist;obj;obj=obj->next)
\r
1062 if (obj->ticcount)
\r
1064 obj->ticcount-=realtics;
\r
1065 while ( obj->ticcount <= 0)
\r
1067 obj->state = obj->state->next;
\r
1069 Quit("Removable object in INERT list.");
\r
1071 if (!obj->state->tictime)
\r
1073 obj->ticcount = 0;
\r
1077 if (obj->state->tictime>0)
\r
1078 obj->ticcount += obj->state->tictime;
\r
1085 bordertime -= realtics;
\r
1086 if (bordertime<=0)
\r
1089 VW_ColorBorder(0);
\r
1094 // random lightning?
\r
1096 if (BGFLAGS & (BGF_NOT_LIGHTNING))
\r
1098 if ((scolor & 0xe0) && (!(random(20-realtics))))
\r
1100 BGFLAGS &= ~BGF_NOT_LIGHTNING;
\r
1101 InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);
\r
1105 // handle sky/ground color changes
\r
1107 if (skytimer != -1)
\r
1109 skytimer -= realtics;
\r
1113 if (*skycolor == 0xffff)
\r
1117 skycolor = &scolor;
\r
1118 if (groundtimer == -1)
\r
1119 BGFLAGS |= bgflag;
\r
1122 skytimer = skytimer_reset;
\r
1126 if (groundtimer != -1)
\r
1128 groundtimer -= realtics;
\r
1129 if (groundtimer < 0)
\r
1132 if (*groundcolor == 0xffff)
\r
1136 groundcolor = &gcolor;
\r
1137 if (skytimer == -1)
\r
1138 BGFLAGS |= bgflag;
\r
1141 groundtimer = groundtimer_reset;
\r
1148 // Handle FreezeTime counter..
\r
1152 if (FreezeTime<20*30)
\r
1153 if ((BeepTime+=realtics)>=60)
\r
1156 SD_PlaySound(TICKSND);
\r
1159 if ((FreezeTime-=realtics)<=0)
\r
1162 SD_PlaySound(TIMERETURNSND);
\r
1163 DisplaySMsg(NULL,NULL);
\r
1164 status_flag = S_NONE;
\r
1173 if (Flags & FL_DEAD)
\r
1175 SD_PlaySound (GAMEOVERSND);
\r
1176 DisplaySMsg("DEAD",NULL);
\r
1178 if (gamestate.potions)
\r
1180 bufferofs = displayofs = screenloc[screenpage];
\r
1181 CenterWindow(35,3);
\r
1182 US_CPrint("\nYou should use your Cure Potions wisely\n");
\r
1189 if (playstate == ex_victorious)
\r
1192 // Flags |= FL_DEAD;
\r
1194 // gamestate.mapon++;
\r
1199 }while (!playstate);
\r
1206 VW_ColorBorder(0);
\r
1210 abortgame = false;
\r
1213 //--------------------------------------------------------------------------
\r
1214 // IntSqrt() - by Master Programmer, George Leritte!
\r
1215 //--------------------------------------------------------------------------
\r
1216 int IntSqrt(long va)
\r
1218 asm mov AX, word ptr va
\r
1219 asm mov DX, word ptr va+2
\r
1220 asm mov bx,dx // {bx = integer square root of dx:ax}
\r
1221 asm or bx,ax // {if dx:ax=0 then return}
\r
1228 asm add bx,dx // { initial guess}
\r
1230 asm inc bx // { don't return zero}
\r
1257 //-------------------------------------------------------------------------
\r
1259 //-------------------------------------------------------------------------
\r
1260 void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)
\r
1262 skytimer_reset = skytimer = stimer;
\r
1264 skycolor = scolors;
\r
1266 groundtimer_reset = groundtimer = gtimer;
\r
1268 groundcolor = gcolors;
\r
1273 ////////////////////////////////////////////////////////
\r
1277 // Stat_Flag - contains the type of status displayed
\r
1278 // -- also uses status_delay (global variable) will not
\r
1279 // change display until this variable is zero.
\r
1280 // -- heirarchy is determined by the series of if statements,
\r
1281 // to change it, rearrange th if statements.
\r
1283 ////////////////////////////////////////////////////////
\r
1285 #define MESSAGEDELAY 25
\r
1286 void DisplayStatus (status_flags *stat_flag)
\r
1288 status_flags temp_status;
\r
1291 if (*stat_flag == S_TIMESTOP)
\r
1294 if (status_delay > 0)
\r
1296 status_delay -= realtics;
\r
1302 // check for a change in status from previous call
\r
1304 temp_status = S_VIEWING; //precaution
\r
1306 if (Keyboard[sc_Control] || control.button0)
\r
1307 temp_status = S_MISSLE;
\r
1309 if (Keyboard[sc_Z] && !Keyboard[sc_F10])
\r
1310 temp_status = S_ZAPPER;
\r
1312 if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])
\r
1313 temp_status = S_XTER;
\r
1316 temp_status = S_TURN;
\r
1318 if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)
\r
1319 temp_status = S_QTURN;
\r
1321 if (Keyboard[sc_Alt] && control.x)
\r
1322 temp_status = S_SIDESTEP;
\r
1324 if (control.y < 0)
\r
1325 temp_status = S_ADVANCE;
\r
1327 if (control.y > 0)
\r
1328 temp_status = S_RETREAT;
\r
1330 if (Keyboard[sc_F5])
\r
1331 temp_status = S_JOYSTICK;
\r
1333 if (Keyboard[sc_F4])
\r
1334 temp_status = S_RESTORING;
\r
1336 if (Keyboard[sc_F3])
\r
1337 temp_status = S_SAVING;
\r
1339 if (Keyboard[sc_F2])
\r
1340 temp_status = S_SND;
\r
1342 if (Keyboard[sc_F1])
\r
1343 temp_status = S_HELP;
\r
1345 if (temp_status != *stat_flag)
\r
1347 *stat_flag = temp_status;
\r
1350 switch (*stat_flag)
\r
1353 DisplaySMsg("Magick Missile", NULL);
\r
1354 status_delay = MESSAGEDELAY;
\r
1358 if (gamestate.bolts)
\r
1360 DisplaySMsg("Zapper", NULL);
\r
1361 status_delay = MESSAGEDELAY+10;
\r
1366 if (gamestate.nukes)
\r
1368 DisplaySMsg("Xterminator", NULL);
\r
1369 status_delay = MESSAGEDELAY+5;
\r
1374 DisplaySMsg("Turning", NULL);
\r
1375 status_delay = MESSAGEDELAY;
\r
1379 DisplaySMsg("Quick Turning", NULL);
\r
1380 status_delay = MESSAGEDELAY;
\r
1384 DisplaySMsg("Sidestepping", NULL);
\r
1385 status_delay = MESSAGEDELAY;
\r
1389 DisplaySMsg("Advancing", NULL);
\r
1390 status_delay = MESSAGEDELAY;
\r
1394 DisplaySMsg("Retreating", NULL);
\r
1395 status_delay = MESSAGEDELAY;
\r
1399 DisplaySMsg("Adjusting Joystick", NULL);
\r
1403 DisplaySMsg("Restoring", NULL);
\r
1407 DisplaySMsg("Saving", NULL);
\r
1411 DisplaySMsg("Select Sound", NULL);
\r
1415 DisplaySMsg("Getting Help", NULL);
\r
1419 DisplaySMsg("Viewing", NULL);
\r
1422 bufferofs = displayofs = screenloc[screenpage];
\r