diff options
Diffstat (limited to 'src/hexen/in_lude.c')
-rw-r--r-- | src/hexen/in_lude.c | 618 |
1 files changed, 618 insertions, 0 deletions
diff --git a/src/hexen/in_lude.c b/src/hexen/in_lude.c new file mode 100644 index 00000000..8e95596d --- /dev/null +++ b/src/hexen/in_lude.c @@ -0,0 +1,618 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 1993-2008 Raven Software +// Copyright(C) 2008 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +//----------------------------------------------------------------------------- + + +#include "h2def.h" +#include "s_sound.h" +#include "i_system.h" +#include "i_video.h" +#include <ctype.h> +#include "v_video.h" + +// MACROS ------------------------------------------------------------------ + +#define TEXTSPEED 3 +#define TEXTWAIT 140 + +// TYPES ------------------------------------------------------------------- + +typedef enum +{ + SINGLE, + COOPERATIVE, + DEATHMATCH +} gametype_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +void IN_Start(void); +void IN_Ticker(void); +void IN_Drawer(void); + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +static void WaitStop(void); +static void Stop(void); +static void LoadPics(void); +static void UnloadPics(void); +static void CheckForSkip(void); +static void InitStats(void); +static void DrDeathTally(void); +static void DrNumber(int val, int x, int y, int wrapThresh); +static void DrNumberBold(int val, int x, int y, int wrapThresh); +static void DrawHubText(void); + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DECLARATIONS ------------------------------------------------ + +boolean intermission; +char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE]; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static boolean skipintermission; +static int interstate = 0; +static int intertime = -1; +static gametype_t gametype; +static int cnt; +static int slaughterboy; // in DM, the player with the most kills +static patch_t *patchINTERPIC; +static patch_t *FontBNumbers[10]; +static patch_t *FontBNegative; +static patch_t *FontBSlash; +static patch_t *FontBPercent; +static int FontABaseLump; +static int FontBLump; +static int FontBLumpBase; + +static signed int totalFrags[MAXPLAYERS]; + +static int HubCount; +static char *HubText; + +// CODE -------------------------------------------------------------------- + +//======================================================================== +// +// IN_Start +// +//======================================================================== + +extern void AM_Stop(void); + +void IN_Start(void) +{ + int i; + I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE)); + InitStats(); + LoadPics(); + intermission = true; + interstate = 0; + skipintermission = false; + intertime = 0; + AM_Stop(); + for (i = 0; i < MAXPLAYERS; i++) + { + players[i].messageTics = 0; + players[i].message[0] = 0; + } + SN_StopAllSequences(); +} + +//======================================================================== +// +// WaitStop +// +//======================================================================== + +void WaitStop(void) +{ + if (!--cnt) + { + Stop(); +// gamestate = GS_LEVEL; +// G_DoLoadLevel(); + gameaction = ga_leavemap; +// G_WorldDone(); + } +} + +//======================================================================== +// +// Stop +// +//======================================================================== + +static void Stop(void) +{ + intermission = false; + UnloadPics(); + SB_state = -1; + BorderNeedRefresh = true; +} + +//======================================================================== +// +// InitStats +// +// Initializes the stats for single player mode +//======================================================================== + +static char *ClusMsgLumpNames[] = { + "clus1msg", + "clus2msg", + "clus3msg", + "clus4msg", + "clus5msg" +}; + +static void InitStats(void) +{ + int i; + int j; + int oldCluster; + signed int slaughterfrags; + int posnum; + int slaughtercount; + int playercount; + char *msgLumpName; + int msgSize; + int msgLump; + + extern int LeaveMap; + + if (!deathmatch) + { + gametype = SINGLE; + HubCount = 0; + oldCluster = P_GetMapCluster(gamemap); + if (oldCluster != P_GetMapCluster(LeaveMap)) + { + if (oldCluster >= 1 && oldCluster <= 5) + { + msgLumpName = ClusMsgLumpNames[oldCluster - 1]; + msgLump = W_GetNumForName(msgLumpName); + msgSize = W_LumpLength(msgLump); + if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE) + { + I_Error("Cluster message too long (%s)", msgLumpName); + } + W_ReadLump(msgLump, ClusterMessage); + ClusterMessage[msgSize] = 0; // Append terminator + HubText = ClusterMessage; + HubCount = strlen(HubText) * TEXTSPEED + TEXTWAIT; + S_StartSongName("hub", true); + } + } + } + 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]; + } + } + 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; + } + S_StartSongName("hub", true); + } +} + +//======================================================================== +// +// LoadPics +// +//======================================================================== + +static void LoadPics(void) +{ + int i; + + if (HubCount || gametype == DEATHMATCH) + { + patchINTERPIC = W_CacheLumpName("INTERPIC", 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); + FontABaseLump = W_GetNumForName("FONTA_S") + 1; + + FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC); + FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC); + } +} + +//======================================================================== +// +// UnloadPics +// +//======================================================================== + +static void UnloadPics(void) +{ + int i; + + if (HubCount || gametype == DEATHMATCH) + { + W_ReleaseLumpName("INTERPIC"); + + patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC); + FontBLumpBase = W_GetNumForName("FONTB16"); + for (i = 0; i < 10; i++) + { + W_ReleaseLumpNum(FontBLumpBase + i); + } + W_ReleaseLumpName("FONTB13"); + W_ReleaseLumpName("FONTB15"); + W_ReleaseLumpName("FONTB05"); + } +} + +//======================================================================== +// +// IN_Ticker +// +//======================================================================== + +void IN_Ticker(void) +{ + if (!intermission) + { + return; + } + if (interstate) + { + WaitStop(); + return; + } + skipintermission = false; + CheckForSkip(); + intertime++; + if (skipintermission || (gametype == SINGLE && !HubCount)) + { + interstate = 1; + cnt = 10; + skipintermission = false; + //S_StartSound(NULL, sfx_dorcls); + } +} + +//======================================================================== +// +// CheckForSkip +// +// Check to see if any player hit a key +//======================================================================== + +static void CheckForSkip(void) +{ + int i; + player_t *player; + static boolean triedToSkip; + + 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; + } + } + } + if (deathmatch && intertime < 140) + { // wait for 4 seconds before allowing a skip + if (skipintermission == 1) + { + triedToSkip = true; + skipintermission = 0; + } + } + else + { + if (triedToSkip) + { + skipintermission = 1; + triedToSkip = false; + } + } +} + +//======================================================================== +// +// IN_Drawer +// +//======================================================================== + +void IN_Drawer(void) +{ + if (!intermission) + { + return; + } + if (interstate) + { + return; + } + UpdateState |= I_FULLSCRN; + memcpy(I_VideoBuffer, (byte *) patchINTERPIC, SCREENWIDTH * SCREENHEIGHT); + + if (gametype == SINGLE) + { + if (HubCount) + { + DrawHubText(); + } + } + else + { + DrDeathTally(); + } +} + +//======================================================================== +// +// DrDeathTally +// +//======================================================================== + +#define TALLY_EFFECT_TICKS 20 +#define TALLY_FINAL_X_DELTA (23*FRACUNIT) +#define TALLY_FINAL_Y_DELTA (13*FRACUNIT) +#define TALLY_START_XPOS (178*FRACUNIT) +#define TALLY_STOP_XPOS (90*FRACUNIT) +#define TALLY_START_YPOS (132*FRACUNIT) +#define TALLY_STOP_YPOS (83*FRACUNIT) +#define TALLY_TOP_X 85 +#define TALLY_TOP_Y 9 +#define TALLY_LEFT_X 7 +#define TALLY_LEFT_Y 71 +#define TALLY_TOTALS_X 291 + +static void DrDeathTally(void) +{ + int i, j; + fixed_t xPos, yPos; + fixed_t xDelta, yDelta; + fixed_t xStart, scale; + int x, y; + boolean bold; + static boolean showTotals; + int temp; + + V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y, + W_CacheLumpName("tallytop", PU_CACHE)); + V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y, + W_CacheLumpName("tallylft", PU_CACHE)); + if (intertime < TALLY_EFFECT_TICKS) + { + showTotals = false; + scale = (intertime * FRACUNIT) / TALLY_EFFECT_TICKS; + xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA); + yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA); + xStart = TALLY_START_XPOS - FixedMul(scale, + TALLY_START_XPOS - + TALLY_STOP_XPOS); + yPos = + TALLY_START_YPOS - FixedMul(scale, + TALLY_START_YPOS - TALLY_STOP_YPOS); + } + else + { + xDelta = TALLY_FINAL_X_DELTA; + yDelta = TALLY_FINAL_Y_DELTA; + xStart = TALLY_STOP_XPOS; + yPos = TALLY_STOP_YPOS; + } + if (intertime >= TALLY_EFFECT_TICKS && showTotals == false) + { + showTotals = true; + S_StartSound(NULL, SFX_PLATFORM_STOP); + } + y = yPos >> FRACBITS; + for (i = 0; i < MAXPLAYERS; i++) + { + xPos = xStart; + for (j = 0; j < MAXPLAYERS; j++, xPos += xDelta) + { + x = xPos >> FRACBITS; + bold = (i == consoleplayer || j == consoleplayer); + if (playeringame[i] && playeringame[j]) + { + if (bold) + { + DrNumberBold(players[i].frags[j], x, y, 100); + } + else + { + DrNumber(players[i].frags[j], x, y, 100); + } + } + else + { + temp = MN_TextAWidth("--") / 2; + if (bold) + { + MN_DrTextAYellow("--", x - temp, y); + } + else + { + MN_DrTextA("--", x - temp, y); + } + } + } + if (showTotals && playeringame[i] + && !((slaughterboy & (1 << i)) && !(intertime & 16))) + { + DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000); + } + yPos += yDelta; + y = yPos >> FRACBITS; + } +} + +//========================================================================== +// +// DrNumber +// +//========================================================================== + +static void DrNumber(int val, int x, int y, int wrapThresh) +{ + char buff[8] = "XX"; + + if (!(val < -9 && wrapThresh < 1000)) + { + sprintf(buff, "%d", val >= wrapThresh ? val % wrapThresh : val); + } + MN_DrTextA(buff, x - MN_TextAWidth(buff) / 2, y); +} + +//========================================================================== +// +// DrNumberBold +// +//========================================================================== + +static void DrNumberBold(int val, int x, int y, int wrapThresh) +{ + char buff[8] = "XX"; + + if (!(val < -9 && wrapThresh < 1000)) + { + sprintf(buff, "%d", val >= wrapThresh ? val % wrapThresh : val); + } + MN_DrTextAYellow(buff, x - MN_TextAWidth(buff) / 2, y); +} + +//=========================================================================== +// +// DrawHubText +// +//=========================================================================== + +static void DrawHubText(void) +{ + int count; + char *ch; + int c; + int cx, cy; + patch_t *w; + + cy = 5; + cx = 10; + ch = HubText; + count = (intertime - 10) / TEXTSPEED; + if (count < 0) + { + count = 0; + } + for (; count; count--) + { + c = *ch++; + if (!c) + { + break; + } + if (c == '\n') + { + cx = 10; + cy += 9; + continue; + } + if (c < 32) + { + continue; + } + c = toupper(c); + if (c == 32) + { + cx += 5; + continue; + } + w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE); + if (cx + w->width > SCREENWIDTH) + { + break; + } + V_DrawPatch(cx, cy, w); + cx += w->width; + } +} |