ref: 0df2cb80cf03d7259746834220d209b306a8c503
dir: /src/heretic/in_lude.c/
/* ======================== = = IN_lude.c = ======================== */ #include "DoomDef.h" #include "soundst.h" typedef enum { SINGLE, COOPERATIVE, DEATHMATCH } gametype_t; // Public functions void IN_Start(void); void IN_Ticker(void); void IN_Drawer(void); boolean intermission; // Private functions void IN_WaitStop(void); void IN_Stop(void); void IN_LoadPics(void); void IN_UnloadPics(void); void IN_CheckForSkip(void); void IN_InitStats(void); void IN_InitDeathmatchStats(void); void IN_InitNetgameStats(void); void IN_DrawOldLevel(void); void IN_DrawYAH(void); void IN_DrawStatBack(void); void IN_DrawSingleStats(void); void IN_DrawCoopStats(void); void IN_DrawDMStats(void); void IN_DrawNumber(int val, int x, int y, int digits); void IN_DrawTime(int x, int y, int h, int m, int s); void IN_DrTextB(char *text, int x, int y); static boolean skipintermission; static int interstate = 0; static int intertime = -1; static int oldintertime = 0; static gametype_t gametype; static int cnt; static int time; static int hours; static int minutes; static int seconds; static int slaughterboy; // in DM, the player with the most kills static int killPercent[MAXPLAYERS]; static int bonusPercent[MAXPLAYERS]; static int secretPercent[MAXPLAYERS]; static patch_t *patchINTERPIC; static patch_t *patchBEENTHERE; static patch_t *patchGOINGTHERE; static patch_t *FontBNumbers[10]; static patch_t *FontBNegative; static patch_t *FontBSlash; static patch_t *FontBPercent; static int FontBLump; static int FontBLumpBase; static int patchFaceOkayBase; static int patchFaceDeadBase; static signed int totalFrags[MAXPLAYERS]; static fixed_t dSlideX[MAXPLAYERS]; static fixed_t dSlideY[MAXPLAYERS]; static char *KillersText[] = { "K", "I", "L", "L", "E", "R", "S" }; extern char *LevelNames[]; typedef struct { int x; int y; } yahpt_t; static yahpt_t YAHspot[3][9] = { { { 172, 78 }, { 86, 90 }, { 73, 66 }, { 159, 95 }, { 148, 126 }, { 132, 54 }, { 131, 74 }, { 208, 138 }, { 52, 101 } }, { { 218, 57 }, { 137, 81 }, { 155, 124 }, { 171, 68 }, { 250, 86 }, { 136, 98 }, { 203, 90 }, { 220, 140 }, { 279, 106 } }, { { 86, 99 }, { 124, 103 }, { 154, 79 }, { 202, 83 }, { 178, 59 }, { 142, 58 }, { 219, 66 }, { 247, 57 }, { 107, 80 } } }; //======================================================================== // // IN_Start // //======================================================================== extern void AM_Stop (void); void IN_Start(void) { I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); IN_LoadPics(); IN_InitStats(); intermission = true; interstate = -1; skipintermission = false; intertime = 0; oldintertime = 0; AM_Stop(); S_StartSong(mus_intr, true); } //======================================================================== // // IN_WaitStop // //======================================================================== void IN_WaitStop(void) { if(!--cnt) { IN_Stop(); G_WorldDone(); } } //======================================================================== // // IN_Stop // //======================================================================== void IN_Stop(void) { intermission = false; IN_UnloadPics(); SB_state = -1; BorderNeedRefresh = true; } //======================================================================== // // IN_InitStats // // Initializes the stats for single player mode //======================================================================== void IN_InitStats(void) { int i; int j; signed int slaughterfrags; int posnum; int slaughtercount; int playercount; if(!netgame) { gametype = SINGLE; time = leveltime/35; hours = time/3600; time -= hours*3600; minutes = time/60; time -= minutes*60; seconds = time; } else if(netgame && !deathmatch) { gametype = COOPERATIVE; memset(killPercent, 0, MAXPLAYERS*sizeof(int)); memset(bonusPercent, 0, MAXPLAYERS*sizeof(int)); memset(secretPercent, 0, MAXPLAYERS*sizeof(int)); for(i=0; i<MAXPLAYERS; i++) { if(playeringame[i]) { if(totalkills) { killPercent[i] = players[i].killcount*100/totalkills; } if(totalitems) { bonusPercent[i] = players[i].itemcount*100/totalitems; } if(totalsecret) { secretPercent[i] = players[i].secretcount*100/totalsecret; } } } } else { gametype = DEATHMATCH; slaughterboy = 0; slaughterfrags = -9999; posnum = 0; playercount = 0; slaughtercount = 0; for(i=0; i<MAXPLAYERS; i++) { totalFrags[i] = 0; if(playeringame[i]) { playercount++; for(j=0; j<MAXPLAYERS; j++) { if(playeringame[j]) { totalFrags[i] += players[i].frags[j]; } } dSlideX[i] = (43*posnum*FRACUNIT)/20; dSlideY[i] = (36*posnum*FRACUNIT)/20; posnum++; } if(totalFrags[i] > slaughterfrags) { slaughterboy = 1<<i; slaughterfrags = totalFrags[i]; slaughtercount = 1; } else if(totalFrags[i] == slaughterfrags) { slaughterboy |= 1<<i; slaughtercount++; } } if(playercount == slaughtercount) { // don't do the slaughter stuff if everyone is equal slaughterboy = 0; } } } //======================================================================== // // IN_LoadPics // //======================================================================== void IN_LoadPics(void) { int i; switch(gameepisode) { case 1: patchINTERPIC = W_CacheLumpName("MAPE1", PU_STATIC); break; case 2: patchINTERPIC = W_CacheLumpName("MAPE2", PU_STATIC); break; case 3: patchINTERPIC = W_CacheLumpName("MAPE3", PU_STATIC); break; default: break; } patchBEENTHERE = W_CacheLumpName("IN_X", PU_STATIC); patchGOINGTHERE = W_CacheLumpName("IN_YAH", PU_STATIC); FontBLumpBase = W_GetNumForName("FONTB16"); for(i=0; i<10; i++) { FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase+i, PU_STATIC); } FontBLump = W_GetNumForName("FONTB_S")+1; FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC); FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC); FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC); patchFaceOkayBase = W_GetNumForName("FACEA0"); patchFaceDeadBase = W_GetNumForName("FACEB0"); } //======================================================================== // // IN_UnloadPics // //======================================================================== void IN_UnloadPics(void) { int i; if(patchINTERPIC) { Z_ChangeTag(patchINTERPIC, PU_CACHE); } Z_ChangeTag(patchBEENTHERE, PU_CACHE); Z_ChangeTag(patchGOINGTHERE, PU_CACHE); for(i=0; i<10; i++) { Z_ChangeTag(FontBNumbers[i], PU_CACHE); } Z_ChangeTag(FontBNegative, PU_CACHE); Z_ChangeTag(FontBSlash, PU_CACHE); Z_ChangeTag(FontBPercent, PU_CACHE); } //======================================================================== // // IN_Ticker // //======================================================================== void IN_Ticker(void) { if(!intermission) { return; } if(interstate == 3) { IN_WaitStop(); return; } IN_CheckForSkip(); intertime++; if(oldintertime < intertime) { interstate++; if(gameepisode > 3 && interstate >= 1) { // Extended Wad levels: skip directly to the next level interstate = 3; } switch(interstate) { case 0: oldintertime = intertime+300; if(gameepisode > 3) { oldintertime = intertime+1200; } break; case 1: oldintertime = intertime+200; break; case 2: oldintertime = MAXINT; break; case 3: cnt = 10; break; default: break; } } if(skipintermission) { if(interstate == 0 && intertime < 150) { intertime = 150; skipintermission = false; return; } else if(interstate < 2 && gameepisode < 4) { interstate = 2; skipintermission = false; S_StartSound(NULL, sfx_dorcls); return; } interstate = 3; cnt = 10; skipintermission = false; S_StartSound(NULL, sfx_dorcls); } } //======================================================================== // // IN_CheckForSkip // // Check to see if any player hit a key //======================================================================== void IN_CheckForSkip(void) { int i; player_t *player; for (i=0, player = players ; i<MAXPLAYERS ; i++, player++) { if (playeringame[i]) { if (player->cmd.buttons&BT_ATTACK) { if (!player->attackdown) { skipintermission = 1; } player->attackdown = true; } else { player->attackdown = false; } if (player->cmd.buttons&BT_USE) { if (!player->usedown) { skipintermission = 1; } player->usedown = true; } else { player->usedown = false; } } } } //======================================================================== // // IN_Drawer // //======================================================================== void IN_Drawer(void) { static int oldinterstate; if(!intermission) { return; } if(interstate == 3) { return; } UpdateState |= I_FULLSCRN; if(oldinterstate != 2 && interstate == 2) { S_StartSound(NULL, sfx_pstop); } oldinterstate = interstate; switch(interstate) { case 0: // draw stats IN_DrawStatBack(); switch(gametype) { case SINGLE: IN_DrawSingleStats(); break; case COOPERATIVE: IN_DrawCoopStats(); break; case DEATHMATCH: IN_DrawDMStats(); break; } break; case 1: // leaving old level if(gameepisode < 4) { V_DrawPatch(0, 0, patchINTERPIC); IN_DrawOldLevel(); } break; case 2: // going to the next level if(gameepisode < 4) { V_DrawPatch(0, 0, patchINTERPIC); IN_DrawYAH(); } break; case 3: // waiting before going to the next level if(gameepisode < 4) { V_DrawPatch(0, 0, patchINTERPIC); } break; default: I_Error("IN_lude: Intermission state out of range.\n"); break; } } //======================================================================== // // IN_DrawStatBack // //======================================================================== void IN_DrawStatBack(void) { int x; int y; byte *src; byte *dest; src = W_CacheLumpName ("FLOOR16", PU_CACHE); dest = screen; for (y=0 ; y<SCREENHEIGHT ; y++) { for (x=0 ; x<SCREENWIDTH/64 ; x++) { memcpy (dest, src+((y&63)<<6), 64); dest += 64; } if (SCREENWIDTH&63) { memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); dest += (SCREENWIDTH&63); } } } //======================================================================== // // IN_DrawOldLevel // //======================================================================== void IN_DrawOldLevel(void) { int i; int x; x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2; IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3); x = 160-MN_TextAWidth("FINISHED")/2; MN_DrTextA("FINISHED", x, 25); if(prevmap == 9) { for(i=0; i<gamemap-1; i++) { V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y, patchBEENTHERE); } if(!(intertime&16)) { V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y, patchBEENTHERE); } } else { for(i=0; i<prevmap-1; i++) { V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y, patchBEENTHERE); } if(players[consoleplayer].didsecret) { V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y, patchBEENTHERE); } if(!(intertime&16)) { V_DrawPatch(YAHspot[gameepisode-1][prevmap-1].x, YAHspot[gameepisode-1][prevmap-1].y, patchBEENTHERE); } } } //======================================================================== // // IN_DrawYAH // //======================================================================== void IN_DrawYAH(void) { int i; int x; x = 160-MN_TextAWidth("NOW ENTERING:")/2; MN_DrTextA("NOW ENTERING:", x, 10); x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2; IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 20); if(prevmap == 9) { prevmap = gamemap-1; } for(i=0; i<prevmap; i++) { V_DrawPatch(YAHspot[gameepisode-1][i].x, YAHspot[gameepisode-1][i].y, patchBEENTHERE); } if(players[consoleplayer].didsecret) { V_DrawPatch(YAHspot[gameepisode-1][8].x, YAHspot[gameepisode-1][8].y, patchBEENTHERE); } if(!(intertime&16) || interstate == 3) { // draw the destination 'X' V_DrawPatch(YAHspot[gameepisode-1][gamemap-1].x, YAHspot[gameepisode-1][gamemap-1].y, patchGOINGTHERE); } } //======================================================================== // // IN_DrawSingleStats // //======================================================================== void IN_DrawSingleStats(void) { int x; static int sounds; IN_DrTextB("KILLS", 50, 65); IN_DrTextB("ITEMS", 50, 90); IN_DrTextB("SECRETS", 50, 115); x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2; IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3); x = 160-MN_TextAWidth("FINISHED")/2; MN_DrTextA("FINISHED", x, 25); if(intertime < 30) { sounds = 0; return; } if(sounds < 1 && intertime >= 30) { S_StartSound(NULL, sfx_dorcls); sounds++; } IN_DrawNumber(players[consoleplayer].killcount, 200, 65, 3); V_DrawShadowedPatch(237, 65, FontBSlash); IN_DrawNumber(totalkills, 248, 65, 3); if(intertime < 60) { return; } if(sounds < 2 && intertime >= 60) { S_StartSound(NULL, sfx_dorcls); sounds++; } IN_DrawNumber(players[consoleplayer].itemcount, 200, 90, 3); V_DrawShadowedPatch(237, 90, FontBSlash); IN_DrawNumber(totalitems, 248, 90, 3); if(intertime < 90) { return; } if(sounds < 3 && intertime >= 90) { S_StartSound(NULL, sfx_dorcls); sounds++; } IN_DrawNumber(players[consoleplayer].secretcount, 200, 115, 3); V_DrawShadowedPatch(237, 115, FontBSlash); IN_DrawNumber(totalsecret, 248, 115, 3); if(intertime < 150) { return; } if(sounds < 4 && intertime >= 150) { S_StartSound(NULL, sfx_dorcls); sounds++; } if(!ExtendedWAD || gameepisode < 4) { IN_DrTextB("TIME", 85, 160); IN_DrawTime(155, 160, hours, minutes, seconds); } else { x = 160-MN_TextAWidth("NOW ENTERING:")/2; MN_DrTextA("NOW ENTERING:", x, 160); x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+gamemap-1]+7)/2; IN_DrTextB(LevelNames[(gameepisode-1)*9+gamemap-1]+7, x, 170); skipintermission = false; } } //======================================================================== // // IN_DrawCoopStats // //======================================================================== void IN_DrawCoopStats(void) { int i; int x; int ypos; static int sounds; IN_DrTextB("KILLS", 95, 35); IN_DrTextB("BONUS", 155, 35); IN_DrTextB("SECRET", 232, 35); x = 160-MN_TextBWidth(LevelNames[(gameepisode-1)*9+prevmap-1]+7)/2; IN_DrTextB(LevelNames[(gameepisode-1)*9+prevmap-1]+7, x, 3); x = 160-MN_TextAWidth("FINISHED")/2; MN_DrTextA("FINISHED", x, 25); ypos = 50; for(i=0; i<MAXPLAYERS; i++) { if(playeringame[i]) { V_DrawShadowedPatch(25, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE)); if(intertime < 40) { sounds = 0; ypos += 37; continue; } else if(intertime >= 40 && sounds < 1) { S_StartSound(NULL, sfx_dorcls); sounds++; } IN_DrawNumber(killPercent[i], 85, ypos+10, 3); V_DrawShadowedPatch(121, ypos+10, FontBPercent); IN_DrawNumber(bonusPercent[i], 160, ypos+10, 3); V_DrawShadowedPatch(196, ypos+10, FontBPercent); IN_DrawNumber(secretPercent[i], 237, ypos+10, 3); V_DrawShadowedPatch(273, ypos+10, FontBPercent); ypos += 37; } } } //======================================================================== // // IN_DrawDMStats // //======================================================================== void IN_DrawDMStats(void) { int i; int j; int ypos; int xpos; int kpos; int x; static int sounds; xpos = 90; ypos = 55; IN_DrTextB("TOTAL", 265, 30); MN_DrTextA("VICTIMS", 140, 8); for(i=0; i<7; i++) { MN_DrTextA(KillersText[i], 10, 80+9*i); } if(intertime < 20) { for(i=0; i<MAXPLAYERS; i++) { if(playeringame[i]) { V_DrawShadowedPatch(40, ((ypos<<FRACBITS)+dSlideY[i]*intertime) >>FRACBITS, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE)); V_DrawShadowedPatch(((xpos<<FRACBITS)+dSlideX[i]*intertime) >>FRACBITS, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE)); } } sounds = 0; return; } if(intertime >= 20 && sounds < 1) { S_StartSound(NULL, sfx_dorcls); sounds++; } if(intertime >= 100 && slaughterboy && sounds < 2) { S_StartSound(NULL, sfx_wpnup); sounds++; } for(i=0; i<MAXPLAYERS; i++) { if(playeringame[i]) { if(intertime < 100 || i == consoleplayer) { V_DrawShadowedPatch(40, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE)); V_DrawShadowedPatch(xpos, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE)); } else { V_DrawFuzzPatch(40, ypos, W_CacheLumpNum(patchFaceOkayBase+i, PU_CACHE)); V_DrawFuzzPatch(xpos, 18, W_CacheLumpNum(patchFaceDeadBase+i, PU_CACHE)); } kpos = 86; for(j=0; j<MAXPLAYERS; j++) { if(playeringame[j]) { IN_DrawNumber(players[i].frags[j], kpos, ypos+10, 3); kpos += 43; } } if(slaughterboy&(1<<i)) { if(!(intertime&16)) { IN_DrawNumber(totalFrags[i], 263, ypos+10, 3); } } else { IN_DrawNumber(totalFrags[i], 263, ypos+10, 3); } ypos += 36; xpos += 43; } } } //======================================================================== // // IN_DrawTime // //======================================================================== void IN_DrawTime(int x, int y, int h, int m, int s) { if(h) { IN_DrawNumber(h, x, y, 2); IN_DrTextB(":", x+26, y); } x += 34; if(m || h) { IN_DrawNumber(m, x, y, 2); } x += 34; if(s) { IN_DrTextB(":", x-8, y); IN_DrawNumber(s, x, y, 2); } } //======================================================================== // // IN_DrawNumber // //======================================================================== void IN_DrawNumber(int val, int x, int y, int digits) { patch_t *patch; int xpos; int oldval; int realdigits; boolean neg; oldval = val; xpos = x; neg = false; realdigits = 1; if(val < 0) { //...this should reflect negative frags val = -val; neg = true; if(val > 99) { val = 99; } } if(val > 9) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 9; } } if(val > 99) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 99; } } if(val > 999) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 999; } } if(digits == 4) { patch = FontBNumbers[val/1000]; V_DrawShadowedPatch(xpos+6-patch->width/2-12, y, patch); } if(digits > 2) { if(realdigits > 2) { patch = FontBNumbers[val/100]; V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch); } xpos += 12; } val = val%100; if(digits > 1) { if(val > 9) { patch = FontBNumbers[val/10]; V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch); } else if(digits == 2 || oldval > 99) { V_DrawShadowedPatch(xpos, y, FontBNumbers[0]); } xpos += 12; } val = val%10; patch = FontBNumbers[val]; V_DrawShadowedPatch(xpos+6-patch->width/2, y, patch); if(neg) { patch = FontBNegative; V_DrawShadowedPatch(xpos+6-patch->width/2-12*(realdigits), y, patch); } } //======================================================================== // // IN_DrTextB // //======================================================================== void IN_DrTextB(char *text, int x, int y) { char c; patch_t *p; while((c = *text++) != 0) { if(c < 33) { x += 8; } else { p = W_CacheLumpNum(FontBLump+c-33, PU_CACHE); V_DrawShadowedPatch(x, y, p); x += p->width-1; } } }