ref: 2c0d5e026f50ae4f2a069b882a598e9a8a4d553b
dir: /play.c/
// WL_PLAY.C #include "WL_DEF.H" #pragma hdrstop /* ============================================================================= LOCAL CONSTANTS ============================================================================= */ #define sc_Question 0x35 /* ============================================================================= GLOBAL VARIABLES ============================================================================= */ int madenoise; // true when shooting or screaming exit_t playstate; s16int DebugOk; objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj, *objfreelist,*killerobj; u16int farmapylookup[MAPSIZE]; u8int *nearmapylookup[MAPSIZE]; int singlestep,godmode,noclip; s16int extravbls; u8int tilemap[MAPSIZE][MAPSIZE]; // wall values only u8int spotvis[MAPSIZE][MAPSIZE]; objtype *actorat[MAPSIZE][MAPSIZE]; // // replacing refresh manager // u16int mapwidth,mapheight,tics; int compatability; u8int *updateptr; u16int mapwidthtable[64]; u16int uwidthtable[UPDATEHIGH]; u16int blockstarts[UPDATEWIDE*UPDATEHIGH]; u8int update[UPDATESIZE]; // // control info // int mouseenabled,joystickenabled,joypadenabled,joystickprogressive; s16int joystickport; s16int dirscan[4] = {sc_UpArrow,sc_RightArrow,sc_DownArrow,sc_LeftArrow}; s16int buttonscan[NUMBUTTONS] = {sc_Control,sc_Alt,sc_RShift,sc_Space,sc_1,sc_2,sc_3,sc_4}; s16int buttonmouse[4]={bt_attack,bt_strafe,bt_use,bt_nobutton}; s16int buttonjoy[4]={bt_attack,bt_strafe,bt_use,bt_run}; s16int viewsize; int buttonheld[NUMBUTTONS]; int demorecord,demoplayback; char far *demoptr, far *lastdemoptr; uchar *demobuffer; // // curent user input // s16int controlx,controly; // range from -100 to 100 per tic int buttonstate[NUMBUTTONS]; //=========================================================================== void CenterWindow(u16int w,u16int h); void InitObjList (void); void RemoveObj (objtype *gone); void PollControls (void); void StopMusic(void); void StartMusic(void); void PlayLoop (void); /* ============================================================================= LOCAL VARIABLES ============================================================================= */ objtype dummyobj; // // LIST OF SONGS FOR EACH VERSION // s16int songs[]= { #ifndef SPEAR // // Episode One // GETTHEM_MUS, SEARCHN_MUS, POW_MUS, SUSPENSE_MUS, GETTHEM_MUS, SEARCHN_MUS, POW_MUS, SUSPENSE_MUS, WARMARCH_MUS, // Boss level CORNER_MUS, // Secret level // // Episode Two // NAZI_OMI_MUS, PREGNANT_MUS, GOINGAFT_MUS, HEADACHE_MUS, NAZI_OMI_MUS, PREGNANT_MUS, HEADACHE_MUS, GOINGAFT_MUS, WARMARCH_MUS, // Boss level DUNGEON_MUS, // Secret level // // Episode Three // INTROCW3_MUS, NAZI_RAP_MUS, TWELFTH_MUS, ZEROHOUR_MUS, INTROCW3_MUS, NAZI_RAP_MUS, TWELFTH_MUS, ZEROHOUR_MUS, ULTIMATE_MUS, // Boss level PACMAN_MUS, // Secret level // // Episode Four // GETTHEM_MUS, SEARCHN_MUS, POW_MUS, SUSPENSE_MUS, GETTHEM_MUS, SEARCHN_MUS, POW_MUS, SUSPENSE_MUS, WARMARCH_MUS, // Boss level CORNER_MUS, // Secret level // // Episode Five // NAZI_OMI_MUS, PREGNANT_MUS, GOINGAFT_MUS, HEADACHE_MUS, NAZI_OMI_MUS, PREGNANT_MUS, HEADACHE_MUS, GOINGAFT_MUS, WARMARCH_MUS, // Boss level DUNGEON_MUS, // Secret level // // Episode Six // INTROCW3_MUS, NAZI_RAP_MUS, TWELFTH_MUS, ZEROHOUR_MUS, INTROCW3_MUS, NAZI_RAP_MUS, TWELFTH_MUS, ZEROHOUR_MUS, ULTIMATE_MUS, // Boss level FUNKYOU_MUS // Secret level #else ////////////////////////////////////////////////////////////// // // SPEAR OF DESTINY TRACKS // ////////////////////////////////////////////////////////////// XTIPTOE_MUS, XFUNKIE_MUS, XDEATH_MUS, XGETYOU_MUS, // DON'T KNOW ULTIMATE_MUS, // Trans Gr�sse DUNGEON_MUS, GOINGAFT_MUS, POW_MUS, TWELFTH_MUS, ULTIMATE_MUS, // Barnacle Wilhelm BOSS NAZI_OMI_MUS, GETTHEM_MUS, SUSPENSE_MUS, SEARCHN_MUS, ZEROHOUR_MUS, ULTIMATE_MUS, // Super Mutant BOSS XPUTIT_MUS, ULTIMATE_MUS, // Death Knight BOSS XJAZNAZI_MUS, // Secret level XFUNKIE_MUS, // Secret level (DON'T KNOW) XEVIL_MUS // Angel of Death BOSS #endif }; /* ============================================================================= USER CONTROL ============================================================================= */ #define BASEMOVE 35 #define RUNMOVE 70 #define BASETURN 35 #define RUNTURN 70 #define JOYSCALE 2 /* =================== = = PollKeyboardButtons = =================== */ void PollKeyboardButtons (void) { s16int i; for (i=0;i<NUMBUTTONS;i++) if (Keyboard[buttonscan[i]]) buttonstate[i] = true; } /* =================== = = PollMouseButtons = =================== */ void PollMouseButtons (void) { s16int buttons; buttons = IN_MouseButtons (); if (buttons&1) buttonstate[buttonmouse[0]] = true; if (buttons&2) buttonstate[buttonmouse[1]] = true; if (buttons&4) buttonstate[buttonmouse[2]] = true; } /* =================== = = PollJoystickButtons = =================== */ void PollJoystickButtons (void) { s16int buttons; buttons = IN_JoyButtons (); if (joystickport && !joypadenabled) { if (buttons&4) buttonstate[buttonjoy[0]] = true; if (buttons&8) buttonstate[buttonjoy[1]] = true; } else { if (buttons&1) buttonstate[buttonjoy[0]] = true; if (buttons&2) buttonstate[buttonjoy[1]] = true; if (joypadenabled) { if (buttons&4) buttonstate[buttonjoy[2]] = true; if (buttons&8) buttonstate[buttonjoy[3]] = true; } } } /* =================== = = PollKeyboardMove = =================== */ void PollKeyboardMove (void) { if (buttonstate[bt_run]) { if (Keyboard[dirscan[di_north]]) controly -= RUNMOVE*tics; if (Keyboard[dirscan[di_south]]) controly += RUNMOVE*tics; if (Keyboard[dirscan[di_west]]) controlx -= RUNMOVE*tics; if (Keyboard[dirscan[di_east]]) controlx += RUNMOVE*tics; } else { if (Keyboard[dirscan[di_north]]) controly -= BASEMOVE*tics; if (Keyboard[dirscan[di_south]]) controly += BASEMOVE*tics; if (Keyboard[dirscan[di_west]]) controlx -= BASEMOVE*tics; if (Keyboard[dirscan[di_east]]) controlx += BASEMOVE*tics; } } /* =================== = = PollMouseMove = =================== */ void PollMouseMove (void) { s16int mousexmove,mouseymove; Mouse(MDelta); mousexmove = _CX; mouseymove = _DX; controlx += mousexmove*10/(13-mouseadjustment); controly += mouseymove*20/(13-mouseadjustment); } /* =================== = = PollJoystickMove = =================== */ void PollJoystickMove (void) { s16int joyx,joyy; INL_GetJoyDelta(joystickport,&joyx,&joyy); if (joystickprogressive) { if (joyx > 64) controlx += (joyx-64)*JOYSCALE*tics; else if (joyx < -64) controlx -= (-joyx-64)*JOYSCALE*tics; if (joyy > 64) controlx += (joyy-64)*JOYSCALE*tics; else if (joyy < -64) controly -= (-joyy-64)*JOYSCALE*tics; } else if (buttonstate[bt_run]) { if (joyx > 64) controlx += RUNMOVE*tics; else if (joyx < -64) controlx -= RUNMOVE*tics; if (joyy > 64) controly += RUNMOVE*tics; else if (joyy < -64) controly -= RUNMOVE*tics; } else { if (joyx > 64) controlx += BASEMOVE*tics; else if (joyx < -64) controlx -= BASEMOVE*tics; if (joyy > 64) controly += BASEMOVE*tics; else if (joyy < -64) controly -= BASEMOVE*tics; } } /* =================== = = PollControls = = Gets user or demo input, call once each frame = = controlx set between -100 and 100 per tic = controly = buttonheld[] the state of the buttons LAST frame = buttonstate[] the state of the buttons THIS frame = =================== */ void PollControls (void) { s16int max,min,i; u8int buttonbits; // // get timing info for last frame // if (demoplayback) { while (TimeCount<lasttimecount+DEMOTICS) ; TimeCount = lasttimecount + DEMOTICS; lasttimecount += DEMOTICS; tics = DEMOTICS; } else if (demorecord) // demo recording and playback needs { // to be constant // // take DEMOTICS or more tics, and modify Timecount to reflect time taken // while (TimeCount<lasttimecount+DEMOTICS) ; TimeCount = lasttimecount + DEMOTICS; lasttimecount += DEMOTICS; tics = DEMOTICS; } else CalcTics (); controlx = 0; controly = 0; memcpy (buttonheld,buttonstate,sizeof(buttonstate)); memset (buttonstate,0,sizeof(buttonstate)); if (demoplayback) { // // read commands from demo buffer // buttonbits = *demoptr++; for (i=0;i<NUMBUTTONS;i++) { buttonstate[i] = buttonbits&1; buttonbits >>= 1; } controlx = *demoptr++; controly = *demoptr++; if (demoptr == lastdemoptr) playstate = ex_completed; // demo is done controlx *= (s16int)tics; controly *= (s16int)tics; return; } // // get button states // PollKeyboardButtons (); if (mouseenabled) PollMouseButtons (); if (joystickenabled) PollJoystickButtons (); // // get movements // PollKeyboardMove (); if (mouseenabled) PollMouseMove (); if (joystickenabled) PollJoystickMove (); // // bound movement to a maximum // max = 100*tics; min = -max; if (controlx > max) controlx = max; else if (controlx < min) controlx = min; if (controly > max) controly = max; else if (controly < min) controly = min; if (demorecord) { // // save info out to demo buffer // controlx /= (s16int)tics; controly /= (s16int)tics; buttonbits = 0; for (i=NUMBUTTONS-1;i>=0;i--) { buttonbits <<= 1; if (buttonstate[i]) buttonbits |= 1; } *demoptr++ = buttonbits; *demoptr++ = controlx; *demoptr++ = controly; if (demoptr >= lastdemoptr) Quit ("Demo buffer overflowed!"); controlx *= (s16int)tics; controly *= (s16int)tics; } } //========================================================================== /////////////////////////////////////////////////////////////////////////// // // CenterWindow() - Generates a window of a given width & height in the // middle of the screen // /////////////////////////////////////////////////////////////////////////// #define MAXX 320 #define MAXY 160 void CenterWindow(u16int w,u16int h) { FixOfs (); US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h); } //=========================================================================== /* ===================== = = CheckKeys = ===================== */ void CheckKeys (void) { s16int i; u8int scan; u16int temp; if (screenfaded || demoplayback) // don't do anything with a faded screen return; scan = LastScan; #ifdef SPEAR // // SECRET CHEAT CODE: TAB-G-F10 // if (Keyboard[sc_Tab] && Keyboard[sc_G] && Keyboard[sc_F10]) { WindowH = 160; if (godmode) { Message ("God mode OFF"); SD_PlaySound (NOBONUSSND); } else { Message ("God mode ON"); SD_PlaySound (ENDBONUS2SND); } IN_Ack(); godmode ^= 1; DrawAllPlayBorderSides (); IN_ClearKeysDown(); return; } #endif // // SECRET CHEAT CODE: 'MLI' // if (Keyboard[sc_M] && Keyboard[sc_L] && Keyboard[sc_I]) { gamestate.health = 100; gamestate.ammo = 99; gamestate.keys = 3; gamestate.score = 0; gamestate.TimeCount += 42000L; GiveWeapon (wp_chaingun); DrawWeapon(); DrawHealth(); DrawKeys(); DrawAmmo(); DrawScore(); ClearMemory (); CA_CacheGrChunk (STARTFONT+1); ClearSplitVWB (); VW_ScreenToScreen (displayofs,bufferofs,80,160); Message(STR_CHEATER1"\n" STR_CHEATER2"\n\n" STR_CHEATER3"\n" STR_CHEATER4"\n" STR_CHEATER5); UNCACHEGRCHUNK(STARTFONT+1); PM_CheckMainMem (); IN_ClearKeysDown(); IN_Ack(); DrawAllPlayBorder (); } // // OPEN UP DEBUG KEYS // #ifndef SPEAR if (Keyboard[sc_BackSpace] && Keyboard[sc_LShift] && Keyboard[sc_Alt] && MS_CheckParm("goobers")) #else if (Keyboard[sc_BackSpace] && Keyboard[sc_LShift] && Keyboard[sc_Alt] && MS_CheckParm("debugmode")) #endif { ClearMemory (); CA_CacheGrChunk (STARTFONT+1); ClearSplitVWB (); VW_ScreenToScreen (displayofs,bufferofs,80,160); Message("Debugging keys are\nnow available!"); UNCACHEGRCHUNK(STARTFONT+1); PM_CheckMainMem (); IN_ClearKeysDown(); IN_Ack(); DrawAllPlayBorderSides (); DebugOk=1; } // // TRYING THE KEEN CHEAT CODE! // if (Keyboard[sc_B] && Keyboard[sc_A] && Keyboard[sc_T]) { ClearMemory (); CA_CacheGrChunk (STARTFONT+1); ClearSplitVWB (); VW_ScreenToScreen (displayofs,bufferofs,80,160); Message("Commander Keen is also\n" "available from Apogee, but\n" "then, you already know\n" "that - right, Cheatmeister?!"); UNCACHEGRCHUNK(STARTFONT+1); PM_CheckMainMem (); IN_ClearKeysDown(); IN_Ack(); DrawAllPlayBorder (); } // // pause key weirdness can't be checked as a scan code // if (Paused) { bufferofs = displayofs; LatchDrawPic (20-4,80-2*8,PAUSEDPIC); SD_MusicOff(); IN_Ack(); IN_ClearKeysDown (); SD_MusicOn(); Paused = false; if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement return; } // // F1-F7/ESC to enter control panel // if ( scan == sc_F10 || scan == sc_F9 || scan == sc_F7 || scan == sc_F8) // pop up quit dialog { ClearMemory (); ClearSplitVWB (); VW_ScreenToScreen (displayofs,bufferofs,80,160); US_ControlPanel(scan); DrawAllPlayBorderSides (); if (scan == sc_F9) StartMusic (); PM_CheckMainMem (); SETFONTCOLOR(0,15); IN_ClearKeysDown(); return; } if ( (scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape) { StopMusic (); ClearMemory (); VW_FadeOut (); US_ControlPanel(scan); SETFONTCOLOR(0,15); IN_ClearKeysDown(); DrawPlayScreen (); if (!startgame && !loadedgame) { VW_FadeIn (); StartMusic (); } if (loadedgame) playstate = ex_abort; lasttimecount = TimeCount; if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement PM_CheckMainMem (); return; } // // TAB-? debug keys // if (Keyboard[sc_Tab] && DebugOk) { CA_CacheGrChunk (STARTFONT); fontnumber=0; SETFONTCOLOR(0,15); DebugKeys(); if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement lasttimecount = TimeCount; return; } } //=========================================================================== /* ############################################################################# The objlist data structure ############################################################################# objlist containt structures for every actor currently playing. The structure is accessed as a linked list starting at *player, ending when ob->next == NULL. GetNewObj inserts a new object at the end of the list, meaning that if an actor spawn another actor, the new one WILL get to think and react the same frame. RemoveObj unlinks the given object and returns it to the free list, but does not damage the objects ->next pointer, so if the current object removes itself, a linked list following loop can still safely get to the next element. <backwardly linked free list> ############################################################################# */ /* ========================= = = InitActorList = = Call to clear out the actor object lists returning them all to the free = list. Allocates a special spot for the player. = ========================= */ s16int objcount; void InitActorList (void) { s16int i; // // init the actor lists // for (i=0;i<MAXACTORS;i++) { objlist[i].prev = &objlist[i+1]; objlist[i].next = NULL; } objlist[MAXACTORS-1].prev = NULL; objfreelist = &objlist[0]; lastobj = NULL; objcount = 0; // // give the player the first free spots // GetNewActor (); player = new; } //=========================================================================== /* ========================= = = GetNewActor = = Sets the global variable new to point to a free spot in objlist. = The free spot is inserted at the end of the liked list = = When the object list is full, the caller can either have it bomb out ot = return a dummy object pointer that will never get used = ========================= */ void GetNewActor (void) { if (!objfreelist) Quit ("GetNewActor: No free spots in objlist!"); new = objfreelist; objfreelist = new->prev; memset (new,0,sizeof(*new)); if (lastobj) lastobj->next = new; new->prev = lastobj; // new->next is allready NULL from memset new->active = false; lastobj = new; objcount++; } //=========================================================================== /* ========================= = = RemoveObj = = Add the given object back into the free list, and unlink it from it's = neighbors = ========================= */ void RemoveObj (objtype *gone) { objtype **spotat; if (gone == player) Quit ("RemoveObj: Tried to remove the player!"); gone->state = NULL; // // fix the next object's back link // if (gone == lastobj) lastobj = (objtype *)gone->prev; else gone->next->prev = gone->prev; // // fix the previous object's forward link // gone->prev->next = gone->next; // // add it back in to the free list // gone->prev = objfreelist; objfreelist = gone; objcount--; } /* ============================================================================= MUSIC STUFF ============================================================================= */ /* ================= = = StopMusic = ================= */ void StopMusic(void) { s16int i; SD_MusicOff(); for (i = 0;i < LASTMUSIC;i++) if (audiosegs[STARTMUSIC + i]) { MM_SetPurge(&((uchar *)audiosegs[STARTMUSIC + i]),3); MM_SetLock(&((uchar *)audiosegs[STARTMUSIC + i]),false); } } //========================================================================== /* ================= = = StartMusic = ================= */ void StartMusic(void) { musicnames chunk; SD_MusicOff(); chunk = songs[gamestate.mapon+gamestate.episode*10]; // if ((chunk == -1) || (MusicMode != smm_AdLib)) //DEBUG control panel return; MM_BombOnError (false); CA_CacheAudioChunk(STARTMUSIC + chunk); MM_BombOnError (true); if (mmerror) mmerror = false; else { MM_SetLock(&((uchar *)audiosegs[STARTMUSIC + chunk]),true); SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]); } } /* ============================================================================= PALETTE SHIFTING STUFF ============================================================================= */ #define NUMREDSHIFTS 6 #define REDSTEPS 8 #define NUMWHITESHIFTS 3 #define WHITESTEPS 20 #define WHITETICS 6 u8int far redshifts[NUMREDSHIFTS][768]; u8int far whiteshifts[NUMREDSHIFTS][768]; s16int damagecount,bonuscount; int palshifted; extern u8int far gamepal; /* ===================== = = InitRedShifts = ===================== */ void InitRedShifts (void) { u8int far *workptr, far *baseptr; s16int i,j,delta; // // fade through intermediate frames // for (i=1;i<=NUMREDSHIFTS;i++) { workptr = (u8int far *)&redshifts[i-1][0]; baseptr = &gamepal; for (j=0;j<=255;j++) { delta = 64-*baseptr; *workptr++ = *baseptr++ + delta * i / REDSTEPS; delta = -*baseptr; *workptr++ = *baseptr++ + delta * i / REDSTEPS; delta = -*baseptr; *workptr++ = *baseptr++ + delta * i / REDSTEPS; } } for (i=1;i<=NUMWHITESHIFTS;i++) { workptr = (u8int far *)&whiteshifts[i-1][0]; baseptr = &gamepal; for (j=0;j<=255;j++) { delta = 64-*baseptr; *workptr++ = *baseptr++ + delta * i / WHITESTEPS; delta = 62-*baseptr; *workptr++ = *baseptr++ + delta * i / WHITESTEPS; delta = 0-*baseptr; *workptr++ = *baseptr++ + delta * i / WHITESTEPS; } } } /* ===================== = = ClearPaletteShifts = ===================== */ void ClearPaletteShifts (void) { bonuscount = damagecount = 0; } /* ===================== = = StartBonusFlash = ===================== */ void StartBonusFlash (void) { bonuscount = NUMWHITESHIFTS*WHITETICS; // white shift palette } /* ===================== = = StartDamageFlash = ===================== */ void StartDamageFlash (s16int damage) { damagecount += damage; } /* ===================== = = UpdatePaletteShifts = ===================== */ void UpdatePaletteShifts (void) { s16int red,white; if (bonuscount) { white = bonuscount/WHITETICS +1; if (white>NUMWHITESHIFTS) white = NUMWHITESHIFTS; bonuscount -= tics; if (bonuscount < 0) bonuscount = 0; } else white = 0; if (damagecount) { red = damagecount/10 +1; if (red>NUMREDSHIFTS) red = NUMREDSHIFTS; damagecount -= tics; if (damagecount < 0) damagecount = 0; } else red = 0; if (red) { VW_WaitVBL(1); VL_SetPalette (redshifts[red-1]); palshifted = true; } else if (white) { VW_WaitVBL(1); VL_SetPalette (whiteshifts[white-1]); palshifted = true; } else if (palshifted) { VW_WaitVBL(1); VL_SetPalette (&gamepal); // back to normal palshifted = false; } } /* ===================== = = FinishPaletteShifts = = Resets palette to normal if needed = ===================== */ void FinishPaletteShifts (void) { if (palshifted) { palshifted = 0; VW_WaitVBL(1); VL_SetPalette (&gamepal); } } /* ============================================================================= CORE PLAYLOOP ============================================================================= */ /* ===================== = = DoActor = ===================== */ void DoActor (objtype *ob) { void (*think)(objtype *); if (!ob->active && !areabyplayer[ob->areanumber]) return; if (!(ob->flags&(FL_NONMARK|FL_NEVERMARK)) ) actorat[ob->tilex][ob->tiley] = NULL; // // non transitional object // if (!ob->ticcount) { think = ob->state->think; if (think) { think (ob); if (!ob->state) { RemoveObj (ob); return; } } if (ob->flags&FL_NEVERMARK) return; if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley]) return; actorat[ob->tilex][ob->tiley] = ob; return; } // // transitional object // ob->ticcount-=tics; while ( ob->ticcount <= 0) { think = ob->state->action; // end of state action if (think) { think (ob); if (!ob->state) { RemoveObj (ob); return; } } ob->state = ob->state->next; if (!ob->state) { RemoveObj (ob); return; } if (!ob->state->tictime) { ob->ticcount = 0; goto think; } ob->ticcount += ob->state->tictime; } think: // // think // think = ob->state->think; if (think) { think (ob); if (!ob->state) { RemoveObj (ob); return; } } if (ob->flags&FL_NEVERMARK) return; if ( (ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley]) return; actorat[ob->tilex][ob->tiley] = ob; } //========================================================================== /* =================== = = PlayLoop = =================== */ s32int funnyticount; void PlayLoop (void) { s16int give; s16int helmetangle; playstate = TimeCount = lasttimecount = 0; frameon = 0; running = false; anglefrac = 0; facecount = 0; funnyticount = 0; memset (buttonstate,0,sizeof(buttonstate)); ClearPaletteShifts (); if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement if (demoplayback) IN_StartAck (); do { if (virtualreality) { helmetangle = peek (0x40,0xf0); player->angle += helmetangle; if (player->angle >= ANGLES) player->angle -= ANGLES; } PollControls(); // // actor thinking // madenoise = false; MoveDoors (); MovePWalls (); for (obj = player;obj;obj = obj->next) DoActor (obj); UpdatePaletteShifts (); ThreeDRefresh (); // // MAKE FUNNY FACE IF BJ DOESN'T MOVE FOR AWHILE // #ifdef SPEAR funnyticount += tics; if (funnyticount > 30l*70) { funnyticount = 0; StatusDrawPic (17,4,BJWAITING1PIC+(US_RndT()&1)); facecount = 0; } #endif gamestate.TimeCount+=tics; SD_Poll (); UpdateSoundLoc(); // JAB if (screenfaded) VW_FadeIn (); CheckKeys(); // // debug aids // if (singlestep) { VW_WaitVBL(14); lasttimecount = TimeCount; } if (extravbls) VW_WaitVBL(extravbls); if (demoplayback) { if (IN_CheckAck ()) { IN_ClearKeysDown (); playstate = ex_abort; } } if (virtualreality) { player->angle -= helmetangle; if (player->angle < 0) player->angle += ANGLES; } }while (!playstate && !startgame); if (playstate != ex_died) FinishPaletteShifts (); }