diff options
Diffstat (limited to 'src/heretic/in_lude.c')
-rw-r--r-- | src/heretic/in_lude.c | 1007 |
1 files changed, 1007 insertions, 0 deletions
diff --git a/src/heretic/in_lude.c b/src/heretic/in_lude.c new file mode 100644 index 00000000..bdf7fa6e --- /dev/null +++ b/src/heretic/in_lude.c @@ -0,0 +1,1007 @@ +/* +======================== += += 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; + } + } +} |