/* Copyright (C) 1994-1995 Apogee Software, Ltd. 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. */ #ifdef DOS #include #include #include #endif #include #include #include #include #include "rt_def.h" #include "rt_main.h" #include "rt_game.h" #include "_rt_game.h" #include "rt_menu.h" #include "z_zone.h" #include "w_wad.h" #include "lumpy.h" #include "rt_playr.h" #include "rt_util.h" #include "rt_ted.h" #include "rt_draw.h" #include "rt_view.h" #include "rt_vid.h" #include "rt_door.h" #include "rt_in.h" #include "rt_str.h" #include "isr.h" #include "rt_build.h" #include "rt_rand.h" #include "rt_cfg.h" #include "rt_sound.h" #include "version.h" #include "rt_crc.h" #include "modexlib.h" #include "engine.h" #include "gmove.h" #include "rt_com.h" #include "rt_net.h" #include "watcom.h" #include "rt_floor.h" #include "rt_msg.h" #include "rt_scale.h" #include "develop.h" //MED #include "memcheck.h" #if (SHAREWARE == 1) #define NUMAMMOGRAPHICS 10 #else #define NUMAMMOGRAPHICS 20 #endif //****************************************************************************** // // GLOBALS // //****************************************************************************** int PlayerSnds[5] = {SD_PLAYERTCSND, SD_PLAYERTBSND, SD_PLAYERDWSND, SD_PLAYERLNSND, SD_PLAYERIPFSND}; unsigned short SHAKETICS = 0xFFFF;//bna++ //int SHAKETICS = 0xFFFF; int damagecount = 0; HighScore Scores[MaxScores] = { {"Tom",70000,7,1}, {"Chuck",60000,6,1}, {"Mark",50000,5,1}, {"The Joes",40000,4,1}, {"William",30000,3,1}, {"Jim",20000,2,1}, {"Steve",10000,1,1}, }; //****************************************************************************** // // LOCALS // //****************************************************************************** static int KeyX[4] = {KEY1_X, KEY2_X, KEY3_X, KEY4_X}; static const char *Names[ 5 ] = { "Taradino", "Thi", "Doug", "Lorelei", "Ian Paul" }; static const char *LastNames[ 5 ] = { "Cassatt", "Barrett", "Wendt", "Ni", "Freeley" }; static STR ScoreStr; static STR LivesStr; static STR TriadStr; static STR KillStr; static pic_t *lifeptnums[10]; static pic_t *lifenums[10]; static pic_t *timenums[10]; static pic_t *scorenums[10]; static pic_t *keys[4]; static pic_t *men[5]; static pic_t *health[6]; static pic_t *ammo[26]; static pic_t *erase; static pic_t *eraseb; static pic_t *fragpic[ 5 ]; static pic_t *frag100pic[ 5 ]; static pic_t *negfragpic[ 5 ]; static pic_t *menneg[ 5 ]; static pic_t *blankfragpic; static int powerpics; static int poweradjust; static int poweruptime; static int powerupheight; static int protectiontime; static int protectionheight; static boolean EndLevelStuff = false; static boolean borderset = false; static int oldsec = -1; static pic_t *BkPic; int SaveTime = 0; int oldhealth; static int oldplayerhealth; static int oldpercenthealth; static int playeruniformcolor; #define NUMBONUSES 11 #define BONUSBONUS 100000 extern void VL_MemToScreenClipped (byte *source, int width, int height, int x, int y); void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly); extern void MoveScreenUpLeft(); extern void MoveScreenUpRight(); extern void MoveScreenDownLeft(); extern void MoveScreenDownRight(); //****************************************************************************** // // V_ReDrawBkgnd () // //****************************************************************************** void V_ReDrawBkgnd (int x, int y, int width, int height, boolean shade) { byte *src; byte *dest; byte *origdest; int j, k, planes, mask, m; m = (x&3); mask = (1 << m); #ifdef DOS origdest = (byte *)(bufferofs+ylookup[y]+(x>>2)); #else origdest = (byte *)(bufferofs+ylookup[y]+x); #endif if (VW_MarkUpdateBlock (x, y, x+width-1, y+height-1)) { for (planes = 0; planes < 4; planes++) { src = (&(BkPic->data)+((80*200)*m)+(80*y)+(x>>2)); dest = origdest; #ifdef DOS VGAMAPMASK (mask); #else dest += planes; #endif for (j = 0; j < height; j++) { for (k = 0; k < (width/4); k++) { if (shade) { *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src++); } else { *dest = *src++; } #ifdef DOS dest++; #else dest += 4; #endif } #ifndef DOS // draw the remainder. did the DOS version even bother? - SBF if ((width & 3) > planes) { if (shade) { *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src); } else { *dest = *src; } } #endif src += (80-(width/4)); #ifdef DOS dest += (linewidth-(width/4)); #else dest += (linewidth-(width&~3)); #endif } m++; mask <<= 1; if (mask == 16) { x+=4; mask = 1; m = 0; #ifdef DOS origdest++; #endif } } } } //****************************************************************************** // // CacheLumpGroup () // //****************************************************************************** void CacheLumpGroup ( char *startlump, pic_t **lumparray, int numberoflumps ) { int lumpnum; int i; lumpnum = W_GetNumForName( startlump ); for( i = 0; i < numberoflumps; i++ ) { lumparray[ i ] = ( pic_t * )W_CacheLumpNum( lumpnum + i, PU_LEVEL, Cvt_pic_t, 1 ); } } //****************************************************************************** // // SetupPlayScreen () // //****************************************************************************** void SetupPlayScreen ( void ) { int i; int j; int num; erase = ( pic_t * )W_CacheLumpName( "erase", PU_LEVEL, Cvt_pic_t, 1 ); eraseb = ( pic_t * )W_CacheLumpName( "eraseb", PU_LEVEL, Cvt_pic_t, 1 ); CacheLumpGroup( "tmnum0", timenums, 10 ); CacheLumpGroup( "lfnum0", lifeptnums, 10 ); CacheLumpGroup( "lvnum0", lifenums, 10 ); CacheLumpGroup( "health1b", health, 6 ); CacheLumpGroup( "key1", keys, 4 ); if ( !BATTLEMODE ) { CacheLumpGroup( "scnum0", scorenums, 10 ); num = locplayerstate->player; men[ num ] = ( pic_t * )W_CacheLumpNum( W_GetNumForName( "MAN1" ) + num, PU_LEVEL, Cvt_pic_t, 1 ); } else { int man; int num100; int negnum; int negman; CacheLumpGroup( "kilnum0", scorenums, 10 ); negnum = W_GetNumForName( "botnpic1" ); num = W_GetNumForName( "botpic0" ); num100 = W_GetNumForName( "botopic1" ); negman = W_GetNumForName( "negman1" ); man = W_GetNumForName( "man1" ); blankfragpic = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 ); num++; for( i = 0; i < numplayers; i++ ) { j = PLAYERSTATE[ i ].player; if ( !gamestate.teamplay ) { fragpic[ j ] = ( pic_t * )W_CacheLumpNum( num + j, PU_LEVEL, Cvt_pic_t, 1 ); frag100pic[ j ] = ( pic_t * )W_CacheLumpNum( num100 + j, PU_LEVEL, Cvt_pic_t, 1 ); negfragpic[ j ] = ( pic_t * )W_CacheLumpNum( negnum + j, PU_LEVEL, Cvt_pic_t, 1 ); } else { negfragpic[ j ] = ( pic_t * )W_CacheLumpName( "teamnpic", PU_LEVEL, Cvt_pic_t, 1 ); fragpic[ j ] = ( pic_t * )W_CacheLumpName( "teampic", PU_LEVEL, Cvt_pic_t, 1 ); frag100pic[ j ] = fragpic[ j ]; } menneg[ j ] = ( pic_t * )W_CacheLumpNum( negman + j, PU_LEVEL, Cvt_pic_t, 1 ); men[ j ] = ( pic_t * )W_CacheLumpNum( man + j, PU_LEVEL, Cvt_pic_t, 1 ); } } powerpics = W_GetNumForName( "GDMODEP" ); poweradjust = POWERUPTICS / 16; num = W_GetNumForName( "INF_B" ); // bullet weapons ammo[0] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 ); ammo[1] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 ); ammo[2] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 ); for(i=3;i < 13; i++ ) { ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 ); } ammo[13] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 ); ammo[14] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 ); ammo[15] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 ); for(i=16;i < 26; i++ ) { ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 ); } oldplayerhealth = -1; oldpercenthealth = -1; } //****************************************************************************** // // GameMemToScreen() // //****************************************************************************** void GameMemToScreen ( pic_t *source, int x, int y, int bufferofsonly ) { if ( bufferofsonly ) { VL_MemToScreen( ( byte * )&source->data, source->width, source->height, x, y ); } else { GM_MemToScreen( ( byte * )&source->data, source->width, source->height, x, y ); } } //****************************************************************************** // // DrawPlayScreen () // //****************************************************************************** void DrawPlayScreen (boolean bufferofsonly) { pic_t *shape; int shapenum; int ShowKillsYoffset = 0;//bna++ //return; if ( SHOW_TOP_STATUS_BAR() ) { if (iGLOBAL_SCREENWIDTH == 640) { //use this as dummy pic to fill out missing bar shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 ); //GameMemToScreen( shape, 0, 0, bufferofsonly ); GameMemToScreen( shape, 320, 0, bufferofsonly ); // delete hart in middle of topbar DrawPPic( 323,1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); // delete bullet in end of topbar DrawPPic( 620,1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( shape, 0, 0, bufferofsonly ); }else if (iGLOBAL_SCREENWIDTH == 800) { //use this as dummy pic to fill out missing bar shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( shape, 0, 0, bufferofsonly ); GameMemToScreen( shape, 260, 0, bufferofsonly ); GameMemToScreen( shape, 800-320, 0, bufferofsonly ); // delete hart in middle of topbar DrawPPic( 480+3,1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); // delete bullet in end of topbar DrawPPic( 780,1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( shape, 0, 0, bufferofsonly ); }else if (iGLOBAL_SCREENWIDTH == 320) { //SetTextMode ( ); shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( shape, 0, 0, bufferofsonly ); } } if ( BATTLEMODE ) { DrawKills( bufferofsonly ); } if ( SHOW_BOTTOM_STATUS_BAR() ) { shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 ); if ( SHOW_KILLS() ) { ShowKillsYoffset = KILLS_HEIGHT; //shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 ); //DrawTiledRegion( 0, 584, iGLOBAL_SCREENWIDTH, 32-16, 0, 16, shape );//bna++ // health_y = iGLOBAL_HEALTH_Y; // if ( SHOW_KILLS() ) // { // health_y -= KILLS_HEIGHT; //GameMemToScreen( shape, 0, (iGLOBAL_SCREENHEIGHT-40)+16, bufferofsonly ); //GameMemToScreen( shape, 0, 160, bufferofsonly );bna++ } //else { if (iGLOBAL_SCREENWIDTH == 640) { //bna fix - not to good? but no one has 286 any more //statusbar dosent cover hole screen, because its a lump picture width max 320 //first write dummy shape and next over it GameMemToScreen( shape, 320, (224*2)+16-ShowKillsYoffset, bufferofsonly ); //copy next shape to mem GameMemToScreen( shape, 0, (224*2)+16-ShowKillsYoffset, bufferofsonly ); // delete bullet in middle of shape picture DrawPPic( 310, (224*2)+17-ShowKillsYoffset, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); // delete hart in middle of shape picture DrawPPic( 324, (224*2)+17-ShowKillsYoffset, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); }else if (iGLOBAL_SCREENWIDTH == 800) { GameMemToScreen( shape, 800-320, 584-ShowKillsYoffset, bufferofsonly ); //copy next shape to mem GameMemToScreen( shape, 300, 584-ShowKillsYoffset, bufferofsonly ); //copy next shape to mem GameMemToScreen( shape, 0, 584-ShowKillsYoffset, bufferofsonly ); // delete 2 bullets in middle of shape picture DrawPPic( 305, 584+1-ShowKillsYoffset, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); // delete hart in middle of shape picture DrawPPic( 610, 584+1-ShowKillsYoffset, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); }else{ GameMemToScreen( shape, 0, 184, bufferofsonly ); } } DrawBarAmmo( bufferofsonly ); DrawBarHealth( bufferofsonly ); if ( demoplayback ) { shape = ( pic_t * )W_CacheLumpName( "demo", PU_CACHE, Cvt_pic_t, 1 ); if (iGLOBAL_SCREENWIDTH == 640) { //DrawPPic( 148, 185, shape->width, shape->height, // ( byte * )&shape->data, 1, true, bufferofsonly );bna DrawPPic( 148*2, 465, shape->width, shape->height, ( byte * )&shape->data, 1, true, bufferofsonly ); }else if (iGLOBAL_SCREENWIDTH == 800) { DrawPPic( 380, 585, shape->width, shape->height, ( byte * )&shape->data, 1, true, bufferofsonly ); }else{ DrawPPic( 148, 185, shape->width, shape->height, ( byte * )&shape->data, 1, true, bufferofsonly ); } } } if ( !SHOW_TOP_STATUS_BAR() ) { return; } //draws small player picture and name in topbar oldsec = -1; DrawTime( bufferofsonly ); if ( !BATTLEMODE ) { int character; int width; int height; character = locplayerstate->player; GameMemToScreen( men[ character ], MEN_X, MEN_Y,bufferofsonly ); CurrentFont = tinyfont; // Draw player's name DrawGameString ( MEN_X + 3, MEN_Y + 2, Names[ character ], bufferofsonly ); VW_MeasurePropString( LastNames[ character ], &width, &height ); DrawGameString ( MEN_X + 44 - width, MEN_Y + 8, LastNames[ character ], bufferofsonly ); UpdateLives( locplayerstate->lives ); UpdateScore( gamestate.score ); DrawTriads( bufferofsonly ); DrawLives( bufferofsonly ); DrawScore( bufferofsonly ); } DrawKeys( bufferofsonly ); if ( locplayerstate->poweruptime ) { if ( player->flags & FL_GODMODE ) { shapenum = powerpics; } else if ( player->flags & FL_DOGMODE ) { shapenum = powerpics + 1; } else if ( player->flags & FL_FLEET ) { shapenum = powerpics + 2; } else if ( player->flags & FL_ELASTO ) { shapenum = powerpics + 3; } else if ( player->flags & FL_SHROOMS ) { shapenum = powerpics + 4; } shape = ( pic_t * )W_CacheLumpNum ( shapenum, PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( eraseb, POWERUP1X, POWERUPY, bufferofsonly ); DrawMPPic( POWERUP1X, POWERUPY + powerupheight, shape->width, shape->height - powerupheight, powerupheight, ( byte * )&shape->data, bufferofsonly ); } if ( locplayerstate->protectiontime ) { if ( player->flags & FL_BPV ) { shapenum = powerpics + 6; } else if ( player->flags & FL_GASMASK ) { shapenum = powerpics + 5; } else if ( player->flags & FL_AV ) { shapenum = powerpics + 7; } shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 ); GameMemToScreen( eraseb, POWERUP2X, POWERUPY, bufferofsonly ); DrawMPPic( POWERUP2X, POWERUPY + protectionheight, shape->width, shape->height - protectionheight, protectionheight, ( byte * )&shape->data, bufferofsonly ); } } //****************************************************************************** // // ShortenCodeName() // //****************************************************************************** void GetShortCodeName ( char *dest, char *source, int maxwidth ) { int width; int height; int length; strcpy( dest, source ); // Shorten name to fit length = strlen( dest ); VW_MeasurePropString( dest, &width, &height ); while( width > maxwidth ) { dest[ length ] = 0; length--; VW_MeasurePropString( dest, &width, &height ); } } //****************************************************************************** // // DrawKills () // //****************************************************************************** void DrawKills ( boolean bufferofsonly ) { int rank; int xpos; char codename[ MAXCODENAMELENGTH ]; int width; int playernum; int playerimage; int temp; int iKILLS_Y; pic_t *pic; CurrentFont = tinyfont; if ( SHOW_TOP_STATUS_BAR() ) { playernum = BATTLE_Team[ consoleplayer ]; playerimage = BATTLE_TeamLeader[ playernum ]; // Set uniformcolor playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor; // Draw player's point box pic = men[ PLAYERSTATE[ playerimage ].player ]; if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) ) { pic = menneg[ PLAYERSTATE[ playerimage ].player ]; } DrawPPic( MEN_X, MEN_Y, pic->width, pic->height, ( byte * )&pic->data, 1, true, bufferofsonly ); // Draw player's name if ( gamestate.teamplay ) { GetShortCodeName( codename, colorname[ playeruniformcolor ], 42 ); } else { GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename, 42 ); } DrawGameString ( MEN_X + 2, MEN_Y + 2, codename, bufferofsonly ); // Draw "It" if player is 'it' if ( ( ( gamestate.battlemode == battle_Tag ) || ( gamestate.battlemode == battle_Hunter ) ) && ( BATTLE_It == BATTLE_Team[ consoleplayer ] ) ) { DrawGameString ( MEN_X + 22, MEN_Y + 8, "It", bufferofsonly); } // Draw triad if player is 'it' or has caught a triad if ( PLAYER[ consoleplayer ]->flags & FL_DESIGNATED ) { pic = W_CacheLumpName( "smalltri", PU_CACHE, Cvt_pic_t, 1 ); DrawPPic( TRIAD_X - 1, TRIAD_Y - 2, pic->width, pic->height, ( byte * )&pic->data, 1, true, bufferofsonly ); } else if ( ( gamestate.ShowScores ) && ( DisplayPoints != bo_kills_infinite ) ) { // Draw Kill goal if ( ( gamestate.battlemode == battle_Collector ) || ( gamestate.battlemode == battle_StandAloneGame ) ) { temp = BATTLE_NumCollectorItems; } else { temp = DisplayPoints; } ltoa ( temp % 1000, KillStr.str, 10); KillStr.length = strlen (KillStr.str); DrawNumber (TRIAD_X - 6, TRIAD_Y, 3, 5, bufferofsonly); } // Set uniformcolor playeruniformcolor = PLAYERSTATE[ consoleplayer ].uniformcolor; if ( gamestate.ShowScores ) { // Draw local player's points temp = BATTLE_Points[ playernum ] % 1000; if ( temp < 0 ) { temp = -temp; } ltoa ( temp, KillStr.str, 10); KillStr.length = strlen (KillStr.str); DrawNumber( LIVES_X - 12, LIVES_Y, 3, 4, bufferofsonly); } else { pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 ); StatusDrawColoredPic( LIVES_X - 12, LIVES_Y, pic, bufferofsonly, playeruniformcolor ); StatusDrawColoredPic( LIVES_X - 4, LIVES_Y, pic, bufferofsonly, playeruniformcolor ); } // Draw whoever is 'It' playernum = BATTLE_It; playerimage = BATTLE_TeamLeader[ playernum ]; // Set uniformcolor playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor; // Draw player's point box pic = men[ PLAYERSTATE[ playerimage ].player ]; if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) ) { pic = menneg[ PLAYERSTATE[ playerimage ].player ]; } DrawPPic( LEADER_X, LEADER_Y, pic->width, pic->height, (byte *)&pic->data, 1, true, bufferofsonly ); if ( ( gamestate.battlemode == battle_Tag ) || ( gamestate.battlemode == battle_Hunter ) ) { DrawGameString ( LEADER_X + 22, LEADER_Y + 8, "It", bufferofsonly); } if ( gamestate.ShowScores ) { // Draw number of points temp = BATTLE_Points[ playernum ] % 1000; if ( temp < 0 ) { temp = -temp; } ltoa ( temp, KillStr.str, 10); KillStr.length = strlen (KillStr.str); DrawNumber ( LEADER_NUM_X, LEADER_NUM_Y, 3, 4, bufferofsonly); } else { pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 ); StatusDrawColoredPic( LEADER_NUM_X, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor ); StatusDrawColoredPic( LEADER_NUM_X + 8, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor ); } // Draw name if ( gamestate.teamplay ) { DrawGameString ( LEADER_NAME_X, LEADER_NAME_Y - 1, colorname[ playeruniformcolor ], bufferofsonly); } else { GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename, 42 ); DrawGameString ( LEADER_NAME_X - 1, LEADER_NAME_Y, codename, bufferofsonly); } } // Only draw the rest of the rifraff when the kill count is selected if ( !SHOW_KILLS() ) { return; } // SetTextMode ( ); // Draw all the other losers //#define KILLS_Y 176 iKILLS_Y = iGLOBAL_SCREENHEIGHT - 24; //draw blank status pic->width = 8;pic->height = 24 pic = blankfragpic; for (temp = iGLOBAL_SCREENWIDTH-pic->width-24;temp > pic->width; temp -= pic->width){ DrawPPic( temp, iKILLS_Y, pic->width, pic->height, (byte *)&pic->data, 1, true, bufferofsonly ); } xpos = KILLS_X; for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ ) { playernum = BATTLE_PlayerOrder[ rank ]; playerimage = BATTLE_TeamLeader[ playernum ]; if ( ( playernum == BATTLE_It ) && SHOW_TOP_STATUS_BAR() ) { continue; } // Set uniformcolor playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor; // Draw player's point box pic = fragpic[ PLAYERSTATE[ playerimage ].player ]; if ( gamestate.ShowScores ) { if ( BATTLE_Points[ playernum ] < 0 ) { pic = negfragpic[ PLAYERSTATE[ playerimage ].player ]; } else if ( BATTLE_Points[ playernum ] >= 100 ) { pic = frag100pic[ PLAYERSTATE[ playerimage ].player ]; } } DrawPPic( xpos, iKILLS_Y, pic->width, pic->height, (byte *)&pic->data, 1, true, bufferofsonly ); // Draw number of points if ( gamestate.ShowScores ) { temp = BATTLE_Points[ playernum ] % 1000; if ( temp < 0 ) { temp = -temp; } ltoa ( temp, KillStr.str, 10); KillStr.length = strlen (KillStr.str); width = 2; if ( temp > 99 ) { width = 3; } DrawNumber( xpos + KILLS_OFFSET + 16 - ( 8 * width ), iKILLS_Y, width, 4, bufferofsonly); } else { pic = ( pic_t * )W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 ); StatusDrawColoredPic( ( xpos + KILLS_OFFSET ), iKILLS_Y, pic, bufferofsonly, playeruniformcolor ); StatusDrawColoredPic( ( xpos + KILLS_OFFSET + 8 ), iKILLS_Y, pic, bufferofsonly, playeruniformcolor ); } // Get codename if ( gamestate.teamplay ) { GetShortCodeName( codename, colorname[ playeruniformcolor ], KILLS_WIDTH - 2 ); } else { GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename, KILLS_WIDTH - 2 ); } // Draw name DrawGameString (xpos + 1, KILLS_NAME_Y, codename, bufferofsonly); // Advance to next position xpos += KILLS_WIDTH; if ( xpos >= iGLOBAL_SCREENWIDTH ) { break; } } for( rank = BATTLE_NumberOfTeams; rank <= MAXKILLBOXES; rank++ ) { if ( xpos >= iGLOBAL_SCREENWIDTH ) { break; } pic = blankfragpic; DrawPPic( xpos, iKILLS_Y, pic->width, pic->height, (byte *)&pic->data, 1, true, bufferofsonly ); // Advance to next position xpos += KILLS_WIDTH; } } //****************************************************************************** // // DrawPlayers () // //****************************************************************************** void DrawPlayers ( void ) { int num; int xpos; char codename[ MAXCODENAMELENGTH ]; int length; int width; int height; int team; int player; int character; pic_t *pic; pic_t *enemy; pic_t *friend; num = W_GetNumForName( "botpic1" ); scorenums[ 0 ]= ( pic_t * )W_CacheLumpName( "kilnum0", PU_CACHE, Cvt_pic_t, 1 ); friend = ( pic_t * )W_CacheLumpName( "t_friend", PU_CACHE, Cvt_pic_t, 1 ); enemy = ( pic_t * )W_CacheLumpName( "t_enemy", PU_CACHE, Cvt_pic_t, 1 ); // Draw all the losers CurrentFont = tinyfont; xpos = (iGLOBAL_SCREENWIDTH - min( numplayers, MAXKILLBOXES ) * KILLS_WIDTH ) / 2; //SetTextMode ( );//PLAYERSTATE for( team = 0; team < BATTLE_NumberOfTeams; team++ ) { for( player = 0; player < numplayers; player++ ) { if ( BATTLE_Team[ player ] == team ) { character = PLAYERSTATE[ player ].player; fragpic[ character ] = ( pic_t * )W_CacheLumpNum( num + character, PU_CACHE, Cvt_pic_t, 1 ); if ( ( numplayers <= MAXKILLBOXES ) || ( player != consoleplayer ) ) { // Set uniformcolor playeruniformcolor = PLAYERSTATE[ player ].uniformcolor; // Draw player's point box pic = fragpic[ PLAYERSTATE[ player ].player ]; VWB_DrawPic ( xpos, PLAYERS_Y, pic ); if ( gamestate.teamplay ) { if ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] ) { VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, friend ); } else { VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, enemy ); } } strcpy( KillStr.str, "00" ); KillStr.length = strlen ( KillStr.str ); DrawNumber( xpos + KILLS_OFFSET, PLAYERS_Y, 2, 4, true ); // Get codename strcpy( codename, PLAYERSTATE[ player ].codename ); // Shorten name to fit into point count length = strlen( codename ); US_MeasureStr( &width, &height, "%s", codename ); while( width > KILLS_WIDTH ) { codename[ length ] = 0; length--; US_MeasureStr( &width, &height, "%s", codename ); } // Draw name PrintX = xpos; PrintY = PLAYERS_NAME_Y; US_Print( codename ); // Advance to next position xpos += KILLS_WIDTH; } } if ( xpos >= iGLOBAL_SCREENWIDTH ) { break; } } if ( xpos >= iGLOBAL_SCREENWIDTH ) { break; } } } //****************************************************************************** // // StatusDrawPic () // //****************************************************************************** void StatusDrawPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly) { DrawMPPic (x, y, nums->width, nums->height, 0, (byte *)&nums->data, bufferofsonly); } //****************************************************************************** // // StatusDrawColoredPic () // //****************************************************************************** void StatusDrawColoredPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly, int color) { DrawColoredMPPic (x, y, nums->width, nums->height, 0, (byte *)&nums->data, bufferofsonly, color); } //****************************************************************************** // // DrawGameString () // // draw string to game screen at x,y // //****************************************************************************** void DrawGameString (int x, int y, const char * str, boolean bufferofsonly) { byte *tempbuf; px=x; py=y; if (bufferofsonly==true) VW_DrawPropString (str); else { tempbuf=bufferofs; bufferofs=page1start; VW_DrawPropString (str); #ifdef DOS px=x; py=y; bufferofs=page2start; VW_DrawPropString (str); px=x; py=y; bufferofs=page3start; VW_DrawPropString (str); #endif bufferofs=tempbuf; } } //****************************************************************************** // // DrawNumber () // // right justifies and pads with zeros // //****************************************************************************** void DrawNumber (int x, int y, int width, int which, boolean bufferofsonly) { unsigned length,c; char *str; byte z; switch (which) { case 1: str = ScoreStr.str; length = ScoreStr.length; break; case 2: str = LivesStr.str; length = LivesStr.length; break; case 3: str = TriadStr.str; length = TriadStr.length; break; case 4: case 5: case 6: str = KillStr.str; length = KillStr.length; break; } z = width - length; // Num zeros while (z) { switch (which) { case 1: StatusDrawPic (x, y, scorenums[0], bufferofsonly); x+=8; break; case 2: StatusDrawPic (x, y, lifenums[0], bufferofsonly); x+=8; break; case 3: StatusDrawPic (x, y, lifeptnums[0], bufferofsonly); x+=6; break; case 4: StatusDrawColoredPic (x, y, scorenums[0], bufferofsonly, playeruniformcolor); x+=8; break; case 5: StatusDrawPic (x, y, lifeptnums[0], bufferofsonly); x+=6; break; case 6: StatusDrawPic (x, y, lifenums[0], bufferofsonly); x+=8; break; } z--; } c = length <= (unsigned)width ? 0 : length-width; while (c < length) { switch (which) { case 1: StatusDrawPic (x, y, scorenums[str[c]-'0'], bufferofsonly); x+=8; break; case 2: StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly); x+=8; break; case 3: StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly); x+=6; break; case 4: StatusDrawColoredPic (x, y, scorenums[str[c]-'0'], bufferofsonly, playeruniformcolor); x+=8; break; case 5: StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly); x+=6; break; case 6: StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly); x+=8; break; } c++; } } //****************************************************************************** // // HealPlayer () // //****************************************************************************** void HealPlayer ( int points, objtype *ob ) { playertype *pstate; int maxhitpoints; M_LINKSTATE( ob, pstate ); pstate->health += points; maxhitpoints = MaxHitpointsForCharacter( pstate ); if ( pstate->health > maxhitpoints ) { pstate->health = maxhitpoints; } if ( ( SHOW_BOTTOM_STATUS_BAR() ) && ( ob == player ) ) { DrawBarHealth( false ); } } //****************************************************************************** // // DrawLives () // //****************************************************************************** void DrawLives ( boolean bufferofsonly ) { if ( !SHOW_TOP_STATUS_BAR() ) { return; } if ( !EndLevelStuff ) { DrawNumber( LIVES_X, LIVES_Y, 2, 2, bufferofsonly ); } } //****************************************************************************** // // GiveExtraMan () // //****************************************************************************** void GiveExtraMan (void) { if (locplayerstate->lives < 99) locplayerstate->lives++; UpdateLives (locplayerstate->lives); DrawLives (false); // SD_PlaySound (BONUS1UPSND); } //****************************************************************************** // // DrawScore () // //****************************************************************************** void DrawScore ( boolean bufferofsonly ) { if ( !SHOW_TOP_STATUS_BAR() ) { return; } if ( !BATTLEMODE ) { DrawNumber( SCORE_X, SCORE_Y, 10, 1, bufferofsonly ); } } //****************************************************************************** // // GivePoints () // //****************************************************************************** void GivePoints (long points) { gamestate.score += points; UpdateScore (gamestate.score); if (!EndLevelStuff) DrawScore (false); } //****************************************************************************** // // GiveKey () // //****************************************************************************** void GiveKey (int key) { locplayerstate->keys |= (1<lives + newlives) <= 99) locplayerstate->lives += newlives; else locplayerstate->lives = 99; UpdateLives (locplayerstate->lives); DrawLives (false); } #define EnableOldWeapon(pstate) \ { \ LASTSTAT->flags |= FL_ABP; \ LASTSTAT->flags &= ~FL_RESPAWN; \ MakeStatActive(LASTSTAT); \ pstate->weaponx = ob->tilex; \ pstate->weapony = ob->tiley; \ } //****************************************************************************** // // GiveWeapon () // //****************************************************************************** void GiveWeapon ( objtype *ob, int weapon ) { playertype *pstate; M_LINKSTATE( ob, pstate ); if ( pstate->weapon == weapon ) { return; } pstate->HASBULLETWEAPON[ weapon ] = 1; if ( ( pstate->weapon == pstate->bulletweapon ) && ( pstate->weapon < weapon ) ) { pstate->new_weapon = weapon; pstate->weapondowntics = WEAPONS[ pstate->weapon ].screenheight / GMOVE; if ( ( ob == player ) && ( SHOW_BOTTOM_STATUS_BAR() ) ) { DrawBarAmmo( false ); } } if ( gamestate.BattleOptions.WeaponPersistence ) { SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(weapon),9); EnableOldWeapon(pstate); } if ( weapon > pstate->bulletweapon ) { pstate->bulletweapon = weapon; } } //****************************************************************************** // // GiveMissileWeapon () // //****************************************************************************** void GiveMissileWeapon(objtype * ob, int which) { playertype * pstate; //pstate = (ob==player)?(&playerstate):(&remoteplayerstate); M_LINKSTATE(ob,pstate); if (!gamestate.BattleOptions.WeaponPersistence) { if (pstate->ammo && (pstate->missileweapon != -1) && (!(WEAPON_IS_MAGICAL(which))) && (!(WEAPON_IS_MAGICAL(pstate->missileweapon))) ) { int nx,ny; nx = ob->tilex; ny = ob->tiley; //FindEmptyTile(&nx,&ny); if (IsPlatform(nx,ny)) SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),9); else { int newz = sprites[ob->tilex][ob->tiley]->z; SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),-1); LASTSTAT->z = newz; } LASTSTAT->ammo = pstate->ammo; EnableOldWeapon(pstate); } } else if (!WEAPON_IS_MAGICAL(which)) { int newz = sprites[ob->tilex][ob->tiley]->z; SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(which),9); LASTSTAT->z = newz; EnableOldWeapon(pstate); } pstate->new_weapon = pstate->missileweapon = which; pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE; } //****************************************************************************** // // DrawKeys () // //****************************************************************************** void DrawKeys ( boolean bufferofsonly ) { if ( !SHOW_TOP_STATUS_BAR() ) { return; } if ( locplayerstate->keys & 1 ) { GameMemToScreen( keys[ 0 ], KeyX[ 0 ], KEY_Y, bufferofsonly ); } if ( locplayerstate->keys & 2 ) { GameMemToScreen( keys[ 1 ], KeyX[ 1 ], KEY_Y, bufferofsonly ); } if ( locplayerstate->keys & 4 ) { GameMemToScreen( keys[ 2 ], KeyX[ 2 ], KEY_Y, bufferofsonly ); } if ( locplayerstate->keys & 8 ) { GameMemToScreen( keys[ 3 ], KeyX[ 3 ], KEY_Y, bufferofsonly ); } } //****************************************************************************** // // StatusDrawTime () // //****************************************************************************** void StatusDrawTime ( unsigned x, unsigned y, unsigned num, boolean bufferofsonly ) { DrawMPPic( x, y, timenums[ num ]->width, timenums[ num ]->height, 0, ( byte * )&timenums[ num ]->data, bufferofsonly ); } //****************************************************************************** // // DrawTimeNumber () // // right justifies and pads with blanks // //****************************************************************************** void DrawTimeNumber (int x, int y, int number, boolean seconds, boolean bufferofsonly) { char str[20]; ltoa (number,str,10); if (seconds) { if (number < 10) { StatusDrawTime (x, y, 0, bufferofsonly); StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly); } else { StatusDrawTime (x, y, str[0]-'0', bufferofsonly); StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly); } } else { if (number < 10) StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly); else { StatusDrawTime (x, y, str[0]-'0', bufferofsonly); StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly); } } } //****************************************************************************** // // DrawTimeXY () // //****************************************************************************** void DrawTimeXY ( int x, int y, int sec, boolean bufferofsonly ) { int min; int hour; while (sec > ( ( 9 * 3600 ) + 3599 ) ) { sec -= ( ( 9 * 3600 ) + 3599 ); } hour = sec / 3600; min = ( sec / 60 ) - ( hour * 60 ); sec %= 60; DrawTimeNumber ( x + HOUR_X, y, hour, false, bufferofsonly ); DrawTimeNumber ( x + MIN_X, y, min, true, bufferofsonly ); DrawTimeNumber ( x + SEC_X, y, sec, true, bufferofsonly ); } //****************************************************************************** // // DrawTime () // //****************************************************************************** void DrawTime ( boolean bufferofsonly ) { int sec; if ( !SHOW_TOP_STATUS_BAR() ) { return; } if (timelimitenabled == true) { sec = (timelimit-gamestate.TimeCount) / VBLCOUNTER; } else { sec = gamestate.TimeCount / VBLCOUNTER; } if ( oldsec != sec ) { oldsec = sec; DrawTimeXY( GAMETIME_X, GAMETIME_Y, sec, bufferofsonly) ; } } //****************************************************************************** // // DrawMPPic () // // Purpose // Draws a masked, planer pic at xpos, ypos. // // Parms // xpos - x position. // ypos - y position. // width - width of pic : should be << 2. // height - height of pic. // src - data to draw. // // Returns // Nothing. // //****************************************************************************** void DrawMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly) { int olddest; int dest; int x; int y; int planes; byte mask; byte pixel; mask = 1 << (xpos&3); #ifdef DOS olddest = ylookup[ypos] + (xpos>>2); #else olddest = ylookup[ypos] + xpos; #endif for (planes = 0; planes < 4; planes++) { VGAMAPMASK (mask); dest = olddest; #ifndef DOS dest += planes; #endif for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *src++; if (pixel != 255) { if (bufferofsonly) *(dest+bufferofs) = pixel; else { *(dest+page1start) = pixel; *(dest+page2start) = pixel; *(dest+page3start) = pixel; } } #ifdef DOS dest++; #else dest += 4; #endif } #ifdef DOS dest += (linewidth-width); #else dest += (linewidth-width*4); #endif } if (heightmod) src += (heightmod*width); #ifdef DOS mask <<= 1; if (mask == 16) { mask = 1; olddest++; } #endif } } //****************************************************************************** // // DrawColoredMPPic () // // Purpose // Draws a masked, planer pic at xpos, ypos. // // Parms // xpos - x position. // ypos - y position. // width - width of pic : should be << 2. // height - height of pic. // src - data to draw. // // Returns // Nothing. // //****************************************************************************** void DrawColoredMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly, int color) { int olddest; int dest; int x; int y; int planes; byte mask; byte pixel; byte * cmap; cmap=playermaps[color]+(1<<12); mask = 1 << (xpos&3); #ifdef DOS olddest = ylookup[ypos] + (xpos>>2); #else olddest = ylookup[ypos] + xpos; #endif for (planes = 0; planes < 4; planes++) { VGAMAPMASK (mask); dest = olddest; #ifndef DOS dest += planes; #endif for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *src++; pixel = *(cmap+pixel); if (pixel != 255) { if (bufferofsonly) *(dest+bufferofs) = pixel; else { *(dest+page1start) = pixel; *(dest+page2start) = pixel; *(dest+page3start) = pixel; } } #ifdef DOS dest++; #else dest += 4; #endif } #ifdef DOS dest += (linewidth-width); #else dest += (linewidth-width*4); #endif } if (heightmod) src += (heightmod*width); #ifdef DOS mask <<= 1; if (mask == 16) { mask = 1; olddest++; } #endif } } //****************************************************************************** // // UpdateScore () // //****************************************************************************** void UpdateScore (unsigned int num) { if (num > 999999999) { num = 999999999; gamestate.score = 999999999; } ltoa (num, ScoreStr.str, 10); ScoreStr.length = strlen (ScoreStr.str); } //****************************************************************************** // // UpdateLives () // //****************************************************************************** void UpdateLives (int num) { ltoa (num, LivesStr.str, 10); LivesStr.length = strlen (LivesStr.str); } //**************************************************************************** // // ClearTriads () // //**************************************************************************** void ClearTriads (playertype * pstate) { pstate->triads = 0; ltoa (pstate->triads, TriadStr.str, 10); TriadStr.length = strlen (TriadStr.str); } //**************************************************************************** // // UpdateTriads () // //**************************************************************************** void UpdateTriads (objtype * ob, int num) { playertype * pstate; M_LINKSTATE(ob,pstate); pstate->triads += num; if (pstate->triads >= 100) { GiveLives(1); if (ob==player) { AddMessage("100 Life Item Points! Extra Life!",MSG_BONUS); SD_PlaySoundRTP (SD_GET1UPSND, player->x, player->y); } pstate->triads -= 100; } if (ob==player) { ltoa (pstate->triads, TriadStr.str, 10); TriadStr.length = strlen (TriadStr.str); } } //**************************************************************************** // // DrawTriads () // //**************************************************************************** void DrawTriads ( boolean bufferofsonly ) { if ( !SHOW_TOP_STATUS_BAR() ) { return; } if ( !EndLevelStuff ) { DrawNumber( TRIAD_X, TRIAD_Y, 2, 3, bufferofsonly ); } } //****************************************************************************** // // DrawPPic () // //****************************************************************************** void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly) { int olddest; int dest; int x; int y; int planes; byte mask; byte pixel; int k; int amt; #ifdef DOS if (up) amt = 2; else amt = -2; #else if (up) amt = 8; else amt = -8; #endif mask = 1; #ifdef DOS olddest = ylookup[ypos] + (xpos>>2); #else olddest = ylookup[ypos] + xpos; #endif for (planes = 0; planes < 4; planes++) { VGAMAPMASK (mask); dest = olddest; #ifndef DOS dest += planes; #endif for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *src++; if (pixel != 255) { for (k = 0; k < num; k++) { if (bufferofsonly) *(dest+bufferofs+(amt*k)) = pixel; else { *(dest+page1start+(amt*k)) = pixel; *(dest+page2start+(amt*k)) = pixel; *(dest+page3start+(amt*k)) = pixel; } } } #ifdef DOS dest++; #else dest += 4; #endif } #ifdef DOS dest += (linewidth-width); #else dest += (linewidth-width*4); #endif } mask <<= 1; } } //**************************************************************************** // // DrawBarHealth () // //**************************************************************************** void DrawBarHealth ( boolean bufferofsonly ) { int percenthealth; int health_y; if ( !SHOW_BOTTOM_STATUS_BAR() ) { return; } health_y = iGLOBAL_HEALTH_Y; if ( SHOW_KILLS() ) { health_y -= KILLS_HEIGHT; } percenthealth = ( locplayerstate->health * 10 ) / MaxHitpointsForCharacter( locplayerstate ); oldpercenthealth = percenthealth + 1; if ( playstate == ex_died ) { DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16, ( byte * )&erase->data, 10, true, bufferofsonly ); return; } if ( locplayerstate->health <= 0 ) { oldpercenthealth = 0; } if ( oldpercenthealth >= 11 ) { oldpercenthealth = 10; } if ( oldpercenthealth < 4 ) { DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16, ( byte * )&health[ 0 ]->data, oldpercenthealth, true, bufferofsonly ); } else if ( oldpercenthealth < 5 ) { DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16, (byte *)&health[ 1 ]->data, oldpercenthealth, true, bufferofsonly ); } else { DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16, ( byte * )&health[ 2 ]->data, oldpercenthealth, true, bufferofsonly ); } if ( oldpercenthealth < 10 ) { DrawPPic( iGLOBAL_HEALTH_X + ( 8 * oldpercenthealth ), health_y, 8 >> 2, 16, ( byte * )&erase->data, 10 - oldpercenthealth, true, bufferofsonly ); } } //**************************************************************************** // // DrawBarAmmo () // //**************************************************************************** void DrawBarAmmo ( boolean bufferofsonly ) { int ammo_y; if ( ( !SHOW_BOTTOM_STATUS_BAR() ) || ( playstate == ex_died ) ) { return; } ammo_y = iGLOBAL_AMMO_Y; if ( SHOW_KILLS() ) { ammo_y -= KILLS_HEIGHT; } DrawPPic ( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16, ( byte * )&erase->data, 10, false, bufferofsonly ); if ( !ARMED( player->dirchoosetime ) ) { return; } if ((locplayerstate->new_weapon < wp_bazooka) || (locplayerstate->new_weapon == wp_godhand) || ( gamestate.BattleOptions.Ammo == bo_infinite_shots ) ) { DrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16, ( byte * )&ammo[ 0 ]->data, 1, true, bufferofsonly); DrawPPic( iGLOBAL_AMMO_X - 32, ammo_y + 1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); } #if (SHAREWARE == 0) else if ( locplayerstate->new_weapon == wp_dog ) { DrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16, ( byte * )&ammo[12]->data, 1, true, bufferofsonly ); DrawPPic( iGLOBAL_AMMO_X - 32, ammo_y + 1, 8 >> 2, 16, ( byte * )&erase->data, 2, true, bufferofsonly ); } #endif else { DrawPPic( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16, ( byte * )&ammo[ locplayerstate->new_weapon]->data, locplayerstate->ammo, false, bufferofsonly ); } } //****************************************************************************** // // SingleDrawPPic () // //****************************************************************************** void SingleDrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up) { byte *olddest; byte *dest; int x; int y; int planes; byte mask; byte pixel; int k; int amt; #ifdef DOS if (up) amt = 2; else amt = -2; #else if (up) amt = 8; else amt = -8; #endif mask = 1; #ifdef DOS olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + (xpos>>2)); #else olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + xpos); #endif for (planes = 0; planes < 4; planes++) { VGAMAPMASK (mask); dest = olddest; #ifndef DOS dest += planes; #endif for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *src++; if (pixel != 255) { for (k = 0; k < num; k++) { *(dest+(amt*k)) = pixel; } } #ifdef DOS dest++; #else dest += 4; #endif } #ifdef DOS dest += (linewidth-width); #else dest += (linewidth-width*4); #endif } mask <<= 1; } } //**************************************************************************** // // DrawStats () // //**************************************************************************** void DrawStats ( void ) { int percenthealth; int health_y; int ammo_y; if ( ( !SHOW_PLAYER_STATS() ) || ( playstate == ex_died ) || ( locplayerstate->health <= 0 ) ) { return; } // Uncomment this if we want transparent health only on sizes < 16 // if ( viewsize < 16 ) // { // pic_t *shape; // // shape = W_CacheLumpName( "backtile", PU_CACHE ); // DrawTiledRegion( 0, 160, 320, 24, shape ); // } health_y = iGLOBAL_HEALTH_Y; ammo_y = iGLOBAL_AMMO_Y; if ( SHOW_KILLS() ) { health_y -= KILLS_HEIGHT; ammo_y -= KILLS_HEIGHT; } if ( oldplayerhealth != locplayerstate->health ) { oldplayerhealth = locplayerstate->health; percenthealth = ( locplayerstate->health * 10 ) / MaxHitpointsForCharacter( locplayerstate ); oldpercenthealth = percenthealth + 1; } if ( oldpercenthealth > 10 ) { oldpercenthealth = 10; } if ( oldpercenthealth < 4 ) { SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16, ( byte * )&health[ 3 ]->data, oldpercenthealth, true); } else if ( oldpercenthealth < 5 ) { SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16, ( byte * )&health[ 4 ]->data, oldpercenthealth, true ); } else { SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16, ( byte * )&health[ 5 ]->data, oldpercenthealth, true ); } if ( ARMED( consoleplayer ) ) { if ((locplayerstate->new_weapon < wp_bazooka) || (locplayerstate->new_weapon == wp_godhand) || (gamestate.BattleOptions.Ammo == bo_infinite_shots ) ) { SingleDrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16, ( byte * )&ammo[13]->data, 1, true ); } #if (SHAREWARE == 0) else if ( locplayerstate->new_weapon == wp_dog ) { SingleDrawPPic( iGLOBAL_AMMO_X - 16, ammo_y + 1, 24 >> 2, 16, ( byte * )&ammo[25]->data, 1, true ); } #endif else { SingleDrawPPic( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16, ( byte * )&ammo[13 + locplayerstate->new_weapon]->data, locplayerstate->ammo, false ); } } } //**************************************************************************** // // DrawPauseXY () // //**************************************************************************** void DrawPauseXY (int x, int y) { pic_t *p; byte *buftmp; buftmp = bufferofs; if (GamePaused == true) { p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1); VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y); //VWB_DrawPic (x, y, p); bufferofs = buftmp; DrawEpisodeLevel (x,y); //VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y); } else { p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("wait"), PU_CACHE, Cvt_pic_t, 1); VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y); //VWB_DrawPic (x, y, p); } bufferofs = buftmp; } //**************************************************************************** // // DrawPause () // //**************************************************************************** void DrawPause (void) { pic_t *p; byte *bufftemp = bufferofs; bufferofs -= screenofs; if (GamePaused == true) { bufferofs = bufftemp; p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1); DrawPauseXY( (iGLOBAL_SCREENWIDTH-(p->width<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-p->height)>>1);//bna++ //DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1); /* //buf = (byte *) SafeMalloc (64000); w = p->width; h = p->height; x = (iGLOBAL_SCREENWIDTH-((p->width)<<2) ) >>1; y = (iGLOBAL_SCREENHEIGHT-(p->height))>>1; x1 = (iGLOBAL_SCREENWIDTH-((p->width*2)<<2) ) >>1; y1 = (iGLOBAL_SCREENHEIGHT-(p->height*2))>>1; source = bufferofs + (iGLOBAL_SCREENWIDTH*y)+x; target = bufferofs + (iGLOBAL_SCREENWIDTH*y1)+x1; // memcpy(tmpPICbuf,bufftemp,iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT); bufferofs = bufftemp;//(byte *)tmpPICbuf;//buf;//write picture in tmpbuf VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y); bufferofs = bufftemp; DrawEpisodeLevel (x,y); //VL_MemStrechedToScreen ((byte *)&p->data, p->width, p->height,(iGLOBAL_SCREENWIDTH-((p->width*2)<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-(p->height*2))>>1); //DrawEpisodeLevel (x,y); //VL_MemToScreen ((byte *)&p->data, p->width, p->height,0, 0); //bufferofs = bufftemp;//move ptr back //write it back to bufferofs while streching //buf = bufftemp; //b = tmpPICbuf ; source = bufferofs + (iGLOBAL_SCREENWIDTH*y)+x+(w*4); target = bufferofs + (iGLOBAL_SCREENWIDTH*y1)+x+(2*w*4); //first strech lines in x direction for (y=0;ywidth<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-p->height)>>1);//bna++ //DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1); } // VH_UpdateScreen () ; bufferofs = bufftemp; } //**************************************************************************** // // GM_DrawBonus () // //**************************************************************************** void GM_DrawBonus ( int which ) { int x; if ( which < stat_gasmask ) { x = POWERUP1X; poweruptime = GetBonusTimeForItem(which); poweradjust = (poweruptime >> 4); powerupheight = 0; GM_UpdateBonus(poweruptime-poweradjust - 1,true); } else { x = POWERUP2X; protectiontime = GetBonusTimeForItem(which); poweradjust = (protectiontime >> 4); protectionheight = 0; GM_UpdateBonus(protectiontime-poweradjust-1,false); } } //****************************************************************************** // // GM_UpdateBonus () // //****************************************************************************** void GM_UpdateBonus ( int time, int powerup ) { pic_t *shape; int shapenum; if ( powerup ) { if ( time < ( poweruptime - poweradjust ) ) { powerupheight++; if ( !SHOW_TOP_STATUS_BAR() ) { poweruptime = time; } } } else { if ( time < ( protectiontime - poweradjust ) ) { protectionheight++; if ( !SHOW_TOP_STATUS_BAR() ) { protectiontime = time; } } } if ( !SHOW_TOP_STATUS_BAR() ) { return; } if ( !time ) { if ( powerup == 1 ) { shapenum = POWERUP1X; } else { shapenum = POWERUP2X; } GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width, eraseb->height, shapenum, POWERUPY ); return; } if ( powerup ) { if ( time < ( poweruptime - poweradjust ) ) { if ( player->flags & FL_GODMODE ) { shapenum = powerpics; } else if ( player->flags & FL_DOGMODE ) { shapenum = powerpics + 1; } else if ( player->flags & FL_FLEET ) { shapenum = powerpics + 2; } else if ( player->flags & FL_ELASTO ) { shapenum = powerpics + 3; } else if ( player->flags & FL_SHROOMS ) { shapenum = powerpics + 4; } else { GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width, eraseb->height, POWERUP1X, POWERUPY ); return; } poweruptime = time; shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 ); GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width, eraseb->height, POWERUP1X, POWERUPY ); DrawMPPic( POWERUP1X, POWERUPY + powerupheight, shape->width, shape->height - powerupheight, powerupheight, ( byte * )&shape->data, false ); } } else { if ( time < ( protectiontime - poweradjust ) ) { if ( player->flags & FL_BPV ) { shapenum = powerpics + 6; } else if ( player->flags & FL_GASMASK ) { shapenum = powerpics + 5; } else if ( player->flags & FL_AV ) { shapenum = powerpics + 7; } protectiontime = time; shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 ); GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width, eraseb->height, POWERUP2X, POWERUPY ); DrawMPPic( POWERUP2X, POWERUPY + protectionheight, shape->width, shape->height - protectionheight, protectionheight, ( byte * )&shape->data, false ); } } } //****************************************************************************** // // Drawpic () // // Purpose // Draws a masked, planer pic at xpos, ypos. // // Parms // xpos - x position. // ypos - y position. // width - width of pic : should be << 2. // height - height of pic. // src - data to draw. // // Returns // Nothing. // //****************************************************************************** void Drawpic (int xpos, int ypos, int width, int height, byte *src) { byte *olddest; byte *dest; int x; int y; int planes; byte mask; byte pixel; mask = 1 << (xpos&3); #ifdef DOS olddest = (byte *)(bufferofs + ylookup[ypos] + (xpos>>2)); #else olddest = (byte *)(bufferofs + ylookup[ypos] + xpos); #endif for (planes = 0; planes < 4; planes++) { VGAMAPMASK (mask); dest = olddest; #ifdef DOS dest += planes; #endif for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *src++; if (pixel != 255) *(dest) = pixel; #ifdef DOS dest++; #else dest += 4; #endif } #ifdef DOS dest += (linewidth-width); #else dest += (linewidth-width*4); #endif } #ifdef DOS mask <<= 1; if (mask == 16) { mask = 1; olddest++; } #endif } } //****************************************************************************** // // DrawEpisodeLevel () // // right justifies and pads with blanks // //****************************************************************************** void DrawEpisodeLevel (int x, int y) { int level; char str[20]; pic_t *p; if (!BATTLEMODE) { ltoa (gamestate.episode, str, 10); //bna-- Drawpic (x+29, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+29, y+16); if ((gamestate.mapon == 6) || (gamestate.mapon == 14) || (gamestate.mapon == 22) || (gamestate.mapon == 32) || (gamestate.mapon == 33)) { p = (pic_t *) W_CacheLumpName ("tnumb", PU_CACHE, Cvt_pic_t, 1); //Drawpic (x+40, y+16, 8>>2, 16, (byte *)&p->data); VL_MemToScreenClipped ((byte *)&p->data, 8>>2, 16, x+40, y+16); if (gamestate.mapon == 6) level = 1; else if (gamestate.mapon == 14) level = 2; else if (gamestate.mapon == 22) level = 3; else if (gamestate.mapon == 32) level = 4; else level = 5; } else level = GetLevel (gamestate.episode, gamestate.mapon); level = abs(level); ltoa (level, str, 10); if (level < 10){ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16); }else{ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16); //Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[1]-'0']->data, 8>>2, 16, x+57, y+16); } } else { p = (pic_t *) W_CacheLumpName ("battp", PU_CACHE, Cvt_pic_t, 1); //Drawpic (x+16, y+15, 32>>2, 16, (byte *)&p->data); VL_MemToScreenClipped ((byte *)&p->data, 32>>2, 16, x+16, y+15); level = abs(gamestate.mapon + 1); ltoa (level, str, 10); if (level < 10){ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16); }else { //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16); //Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data); VL_MemToScreenClipped ((byte *)&timenums[str[1]-'0']->data, 8>>2, 16, x+57, y+16); } } } //****************************************************************************** // // GM_MemToScreen () // //****************************************************************************** void GM_MemToScreen (byte *source, int width, int height, int x, int y) { int dest; byte *dest1, *dest2, *dest3, mask; byte *screen1, *screen2, *screen3; int plane; int w; #ifdef DOS dest = ylookup[y]+(x>>2); #else dest = ylookup[y]+x; #endif mask = 1 << (x&3); dest1 = (byte *)(dest+page1start); dest2 = (byte *)(dest+page2start); dest3 = (byte *)(dest+page3start); for (plane = 0; plane<4; plane++) { VGAMAPMASK (mask); screen1 = dest1; screen2 = dest2; screen3 = dest3; for (y = 0; y < height; y++, screen1 += linewidth, screen2 += linewidth, screen3 += linewidth, source+=width) { #ifdef DOS memcpy (screen1, source, width); memcpy (screen2, source, width); memcpy (screen3, source, width); #else for (x = 0; x < width; x++) { screen1[x*4+plane] = source[x]; screen2[x*4+plane] = source[x]; screen3[x*4+plane] = source[x]; } #endif } #ifdef DOS mask <<= 1; if (mask == 16) { mask = 1; dest1++; dest2++; dest3++; } #endif } } //========================================================================== /* ================== = = ScreenShake = ================== */ void ScreenShake (void) { static int which = 0; // SetTextMode ( ); if (SHAKETICS != 0xFFFF) { SHAKETICS -= tics; if (SHAKETICS >= 0xFF00){SHAKETICS = 0xFFFF;}//bna safety val check which = (RandomNumber ("ScreenShake",0) & 3); switch (which) { case 0: displayofs += 1; MoveScreenUpLeft();//SetTextMode ( ); DrawPlayScreen(true);//repaint ammo and life stat break; case 1: displayofs -= 1; MoveScreenUpRight(); DrawPlayScreen(true);//repaint ammo and life stat break; case 2: displayofs += 3*iGLOBAL_SCREENBWIDE; MoveScreenDownLeft(); DrawPlayScreen(true);//repaint ammo and life stat break; case 3: displayofs -= 3*iGLOBAL_SCREENBWIDE; MoveScreenDownRight(); DrawPlayScreen(true);//repaint ammo and life stat break; } } } //****************************************************************************** // // DoBorderShifts () // //****************************************************************************** void DoBorderShifts (void) { if (damagecount) { if (damagecount > 100) damagecount = 100; damagecount -= 6; if (damagecount < 0) damagecount = 0; SetBorderColor (*(colormap+(((100-damagecount)>>2)<<8)+48)); borderset = true; } else if (borderset) { SetBorderColor (0); borderset = false; } } //****************************************************************************** // // DrawHighScores () // //****************************************************************************** void DrawHighScores (void) { char buffer[16]; #if (SHAREWARE == 0) char buffer1[5]; #endif int i, w, h; HighScore *s; for (i = 0, s = Scores; i < MaxScores; i++, s++) { PrintY = 25 + (16 * i); // // name // PrintX = 3*8; DrawMenuBufPropString (PrintX, PrintY, s->name); // // level // ultoa (s->completed, buffer, 10); PrintX = (17 * 8)-10; #if (SHAREWARE == 0) itoa (s->episode, buffer1, 10); DrawMenuBufPropString (PrintX, PrintY, buffer1); #else DrawMenuBufPropString (PrintX, PrintY, "S"); #endif DrawMenuBufPropString (PrintX, PrintY, "-"); #if (SHAREWARE == 0) if (s->completed == 7) DrawMenuBufPropString (PrintX, PrintY, "B"); else if (s->completed == 8) DrawMenuBufPropString (PrintX, PrintY, "S"); else if (s->completed == 9) DrawMenuBufPropString (PrintX, PrintY, "C"); else if (s->completed == 10) DrawMenuBufPropString (PrintX, PrintY, "D"); else DrawMenuBufPropString (PrintX, PrintY, buffer); #else DrawMenuBufPropString (PrintX, PrintY, buffer); #endif // // score // ultoa(s->score,buffer,10); VW_MeasurePropString (buffer, &w, &h); PrintX = (33 * 8) - w; DrawMenuBufPropString (PrintX, PrintY, buffer); } } //****************************************************************************** // // CheckHighScore () // //****************************************************************************** void CheckHighScore (long score, word other, boolean INMENU) { word i,j; int n; HighScore myscore; int level; MenuFadeIn(); if (!INMENU) SetupMenuBuf (); strcpy (myscore.name,""); myscore.score = score; level = GetLevel (gamestate.episode, other-1); myscore.episode = gamestate.episode; myscore.completed = level; CurrentFont = smallfont; for (i = 0, n = -1; i < MaxScores; i++) { if ((myscore.score > Scores[i].score) || ((myscore.score == Scores[i].score) && (myscore.completed > Scores[i].completed))) { for (j = MaxScores; --j > i;) Scores[j] = Scores[j - 1]; Scores[i] = myscore; n = i; break; } } if (INMENU) { SetAlternateMenuBuf(); SetMenuTitle ("High Scores"); ClearMenuBuf(); DrawHighScores (); if (n != -1) DisplayInfo (6); else DisplayInfo (5); FlipMenuBuf (); } else { ClearMenuBuf (); SetMenuTitle ("High Scores"); DrawHighScores (); if (n != -1) DisplayInfo (6); else DisplayInfo (5); RefreshMenuBuf (0); } if (n != -1) { PrintY = 25 + (16 * n); PrintX = 3*8; US_LineInput (PrintX, PrintY, Scores[n].name, NULL, true, 10, 98, 0); } else { IN_ClearKeysDown (); if ( INMENU ) { while( !IN_CheckAck () ) { RefreshMenuBuf (0); } } else { for( i = 0; i <= 150; i += tics ) { RefreshMenuBuf (0); if (IN_CheckAck ()) { break; } } } } if (INMENU) { SD_Play (SD_ESCPRESSEDSND); } else { ShutdownMenuBuf (); } } //=========================================================================== //#define HEADERX 140 //#define BONERNAMEX 170 #define HEADERX 152 #define BONERNAMEX 166 /* ================== = = DrawEOLHeader () = ================== */ void DrawEOLHeader ( int playstate ) { int health; char tempstr[ 15 ]; char *string; int level; int w; int h; VWB_TBar( 30, 5, 250, 75 ); switch( playstate ) { case ex_skiplevel : if ( ( gamestate.violence >= vl_high ) && ( gamestate.difficulty >= gd_hard ) ) { string = "LEVEL WUSSED OUT ON!"; } else { string = "LEVEL SKIPPED."; } break; case ex_secretdone : string = "SECRET LEVEL COMPLETED!"; break; case ex_secretlevel : string = "SECRET EXIT TAKEN!"; break; case ex_gameover : string = "GAME COMPLETED!"; break; case ex_bossdied : string = "BOSS DEFEATED!"; break; default : string = "LEVEL COMPLETED!"; break; } VW_MeasurePropString( string, &w, &h ); px = ( 320 - w ) / 2; py = 10; VWB_DrawPropString( string ); // draw episode number string = "EPISODE"; VW_MeasurePropString( string, &w, &h ); px = HEADERX - w; py = 25; VWB_DrawPropString( string ); itoa( gamestate.episode, tempstr, 10 ); px = BONERNAMEX; VWB_DrawPropString( tempstr ); // draw area number level = GetLevel( gamestate.episode, gamestate.mapon ); itoa( level, tempstr, 10 ); py = 35; if ( playstate == ex_secretdone ) { string = "SECRET AREA"; } else if ( playstate == ex_bossdied ) { string = "BOSS AREA"; } else if ( gamestate.mapon == 32 ) { string = "CHASE AREA"; } else { string = "AREA"; } VW_MeasurePropString( string, &w, &h); px = HEADERX - w; VWB_DrawPropString( string ); if ( gamestate.mapon != 33 ) { px = BONERNAMEX; VWB_DrawPropString( tempstr ); } string = "SCORE"; VW_MeasurePropString( string, &w, &h); px = HEADERX - w; py = 45; VWB_DrawPropString( string ); px = BONERNAMEX; itoa( gamestate.score, tempstr, 10 ); VWB_DrawPropString( tempstr ); string = "HEALTH"; VW_MeasurePropString( string, &w, &h ); px = HEADERX - w; py = 55; VWB_DrawPropString( string ); px = BONERNAMEX; health = ( ( locplayerstate->health * 100 ) / MaxHitpointsForCharacter( locplayerstate ) ); itoa( health, tempstr, 10 ); VWB_DrawPropString( tempstr ); VWB_DrawPropString( "%" ); // // Secret count // { char str1[10]; char str2[10]; itoa(gamestate.secretcount,&(str1[0]),10); strcat(str1," / "); itoa(gamestate.secrettotal,&(str2[0]),10); strcat(str1,str2); string = "SECRET WALLS"; VW_MeasurePropString( string, &w, &h ); px = HEADERX - w; py = 65; VWB_DrawPropString( string ); px = BONERNAMEX; VWB_DrawPropString( str1 ); } VW_UpdateScreen (); } boolean EndBonusFirst; boolean EndBonusSkip; int EndBonusNumBonuses; int EndBonusVoice; int EndBonusStartY; void DrawEndBonus ( char *string, char *bonusstring, int type ) { int w; int h; int health; char tempstr[ 15 ]; if ( EndBonusFirst ) { VWB_TBar( 5, EndBonusStartY - 2, 310, 4 ); EndBonusFirst = false; } VWB_TBar( 5, EndBonusStartY + 2, 310, 10 ); VW_MeasurePropString( string, &w, &h ); py = EndBonusStartY; if ( bonusstring == NULL ) { px = ( 320 - w ) / 2; VWB_DrawPropString( string ); } else { px = BONERNAMEX - w; VWB_DrawPropString( string ); EndBonusNumBonuses++; VW_MeasurePropString( bonusstring, &w, &h ); px = 310 - w; py = EndBonusStartY; VWB_DrawPropString( bonusstring ); } // Update Score py = 45; px = BONERNAMEX; V_ReDrawBkgnd( px, py, 107, 11, false ); VWB_TBar( px, py, 107, 11 ); itoa( gamestate.score, tempstr, 10 ); VWB_DrawPropString( tempstr ); // Update Health py = 55; px = BONERNAMEX; V_ReDrawBkgnd( px, py, 107, 11, false ); VWB_TBar( px, py, 107, 11 ); health = ( ( locplayerstate->health * 100 ) / MaxHitpointsForCharacter( locplayerstate ) ); itoa( health, tempstr, 10 ); VWB_DrawPropString( tempstr ); VWB_DrawPropString( "%" ); switch( type ) { case 0 : EndBonusVoice = SD_Play( SD_ENDBONUS1SND ); break; case 1 : EndBonusVoice = SD_Play( SD_NOBONUSSND ); break; case 2 : VL_FillPalette(255,255,255); //bna--VW_UpdateScreen(); VL_FadeIn(0,255,origpal,10); EndBonusVoice = SD_Play( SD_LIGHTNINGSND ); break; } EndBonusStartY += 10; //bna--VW_UpdateScreen(); while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip ) { if ( IN_CheckAck() ) { EndBonusSkip = true; } } } /* ================== = = LevelCompleted = = Exit with the screen faded out = ================== */ extern int OLDLMWEAPON; extern int OLDLWEAPON; void LevelCompleted ( exit_t playstate ) { objtype *obj; boolean dobonus; int i; int kr; int sr; int tr; int missileratio; int superratio; int healthratio; int democraticratio; int plantratio; int cnt; pic_t *tmpPic; // byte *picbuf; EndBonusNumBonuses = 0; EndBonusFirst = true; EndBonusSkip = false; EndBonusStartY = 90; EnableScreenStretch(); tmpPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 ); VWB_DrawPic( 0, 0, tmpPic ); VW_UpdateScreen(); // DisableScreenStretch(); IN_StartAck(); EndBonusVoice = 0; if ( playstate != ex_bossdied ) { EndBonusVoice = SD_Play( SD_LEVELDONESND ); VL_FillPalette( 255, 255, 255 ); VL_FadeIn( 0, 255, origpal, 10 ); if ( player->flags & FL_DOGMODE ) { MU_StartSong( song_dogend ); } else { MU_StartSong( song_endlevel ); } } BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 ); VWB_DrawPic( 0, 0, BkPic ); CheckHolidays(); CurrentFont = smallfont; // Kill powerups if ( player->flags & FL_ELASTO ) { player->flags &= ~FL_NOFRICTION; } player->flags &= ~( FL_FLEET | FL_SHROOMS | FL_ELASTO | FL_GODMODE | FL_DOGMODE | FL_BPV | FL_AV | FL_GASMASK ); // Turn off quickload for next level pickquick = false; // // FIGURE RATIOS OUT BEFOREHAND // kr = 0; tr = 0; tr = 0; superratio = 0; missileratio = 0; healthratio = 0; democraticratio = 0; plantratio = 0; if ( gamestate.killtotal ) { kr = ( int )( ( ( int )gamestate.killcount ) * 100 ) / ( ( int )gamestate.killtotal ); } if ( gamestate.secrettotal ) { sr = ( int )( ( ( int )gamestate.secretcount ) * 100 ) / ( ( int )gamestate.secrettotal ); } if ( gamestate.treasuretotal ) { tr = ( int )( ( ( int )gamestate.treasurecount ) * 100 ) / ( ( int )gamestate.treasuretotal ); } if ( gamestate.supertotal ) { superratio = ( int )( ( ( int )gamestate.supercount ) * 100 ) / ( ( int )gamestate.supertotal ); } if ( gamestate.missiletotal ) { missileratio = ( int )( ( ( int )gamestate.missilecount ) * 100 ) / ( ( int )gamestate.missiletotal ); } if ( gamestate.healthtotal ) { healthratio = ( int )( ( ( int )gamestate.healthcount ) * 100 ) / ( ( int )gamestate.healthtotal ); } if ( gamestate.democratictotal ) { democraticratio = ( int )( ( ( int )gamestate.democraticcount ) * 100 ) / ( ( int )gamestate.democratictotal ); } if ( gamestate.planttotal ) { plantratio = ( int )( ( ( int )gamestate.plantcount ) * 100 ) / ( ( int )gamestate.planttotal ); } DrawEOLHeader( playstate ); /* //bna section store picture because its written on again // store screen first picbuf = (byte *)SafeMalloc (64000); memcpy(picbuf ,bufferofs ,64000); EnableScreenStretch(); VW_UpdateScreen();//tmpPICbuf is destroyed here DisableScreenStretch(); //copy it back memcpy(bufferofs ,picbuf , 64000); //bna section end */ EndBonusSkip = true; while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip ) { //bna--VW_UpdateScreen(); if ( IN_CheckAck() ) { EndBonusSkip = true; } } // tmpPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 ); // VWB_DrawPic( 0, 0, tmpPic ); if ( GetNextMap(player->tilex,player->tiley) == -1) { if ( gamestate.dipballs == 3 ) { gamestate.score += 100000; DrawEndBonus( "DIP BONUS", "100000 POINTS", 0 ); EndBonusStartY += 10; } if ( locplayerstate->lives > 0 ) { char str[20]; char str2[60]; DrawEndBonus( "EXTRA LIVES BONUS", "\0", 0 ); itoa(locplayerstate->lives,str,10); strcpy(str2,str); strcat(str2," EXTRA LIVES ="); DrawEndBonus( "\0", str2, 0 ); itoa(locplayerstate->lives,str,10); strcpy(str2,str); strcat(str2," X 10000 = "); itoa(locplayerstate->lives*10000,str,10); strcat(str2,str); strcat(str2," POINTS"); gamestate.score += 10000*locplayerstate->lives; DrawEndBonus( "\0", str2, 0 ); } } else { // // Check for SKIN OF YO TEETH // if ( locplayerstate->health <= 10 ) { locplayerstate->health = MaxHitpointsForCharacter( locplayerstate ); DrawEndBonus( "SKIN OF YOUR TEETH", "100% HEALTH", 0 ); } // BULL IN CHINA SHOP BONUS if ( tr == 100 ) { gamestate.score += 10000; DrawEndBonus( "BULL IN CHINA SHOP", "10000 POINTS", 0 ); } // SUPERCHARE BONUS if ( superratio == 100 ) { gamestate.score += 10000; DrawEndBonus( "SUPERCHARGE BONUS", "10000 POINTS", 0 ); } // BLEEDER BONUS if ( healthratio == 100 ) { gamestate.score += 10000; DrawEndBonus( "BLEEDER BONUS", "10000 POINTS", 0 ); } // ADRENALINE BONUS if ( kr == 100 ) { gamestate.score += 10000; DrawEndBonus( "ADRENALINE BONUS", "10000 POINTS", 0 ); } // CURIOSITY BONUS dobonus = true; // // Check switches cnt = lastswitch - &switches[ 0 ]; if ( cnt != 0 ) { for ( i = 0; i < cnt; i++ ) { if ( ( switches[ i ].flags & FL_S_FLIPPED ) == 0 ) { dobonus = false; break; } } } // // Check pillars for ( obj = FIRSTACTOR; obj != NULL; obj = obj->next ) { if ( ( obj->obclass == pillarobj ) && ( ( obj->flags & FL_FLIPPED ) == 0 ) ) { dobonus = false; } } if ( ( gamestate.secrettotal ) && ( sr != 100 ) ) { dobonus = false; } if ( dobonus ) { gamestate.score += 10000; DrawEndBonus( "CURIOSITY BONUS", "10000 POINTS", 0 ); } // GROUND ZERO BONUS if ( gamestate.DOGROUNDZEROBONUS ) { gamestate.score += 10000; DrawEndBonus( "GROUND ZERO BONUS", "10000 POINTS", 0 ); } // REPUBLICAN BONUS 1 if ( missileratio == 100 ) { gamestate.score += 5000; DrawEndBonus( "REPUBLICAN BONUS 1", " 5000 POINTS", 0 ); } // REPUBLICAN BONUS 2 if (plantratio == 100) { gamestate.score += 5000; DrawEndBonus( "REPUBLICAN BONUS 2", " 5000 POINTS", 0 ); } // DEMOCRATIC BONUS 1 if ( gamestate.DODEMOCRATICBONUS1 ) { gamestate.score += 5000; DrawEndBonus( "DEMOCRATIC BONUS 1", " 5000 POINTS", 0 ); } // DEMOCRATIC BONUS 2 if (democraticratio == 100) { gamestate.score += 5000; DrawEndBonus( "DEMOCRATIC BONUS 2", " 5000 POINTS", 0 ); } } if ( EndBonusNumBonuses == 0 ) { DrawEndBonus( "NO BONUS!", NULL, 1 ); } if ( ( EndBonusNumBonuses != 0 ) || ( playstate == ex_gameover ) ) { SD_Play( PlayerSnds[ locplayerstate->player ] ); // DO BONUS BONUS if ( EndBonusNumBonuses == NUMBONUSES ) { IN_StartAck(); while( !IN_CheckAck() ) { ; } BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 ); VWB_DrawPic( 0, 0, BkPic ); gamestate.score += BONUSBONUS; DrawEOLHeader( playstate ); EndBonusFirst = true; EndBonusStartY = 110; EndBonusSkip = true; DrawEndBonus( "BONUS BONUS! 1,000,000 POINTS!", NULL, 2 ); } else if ( ( kr == 100 ) && ( dobonus ) ) { IN_StartAck(); while( !IN_CheckAck() ) { ; } BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 ); VWB_DrawPic( 0, 0, BkPic ); DrawEOLHeader( playstate ); EndBonusFirst = true; EndBonusStartY = 110; DrawEndBonus( "You have done well.", NULL, 3 ); #if (SHAREWARE==1) EndBonusVoice = SD_Play( SD_RICOCHET3SND ); #else EndBonusVoice = SD_Play( SD_PERCENT100SND ); #endif EndBonusSkip = false; DrawEndBonus( "This level is toast.", NULL, 3 ); } } //bna section // EnableScreenStretch();//bna++ VW_UpdateScreen();//bna++ // DisableScreenStretch();//bna++ //bna section end IN_StartAck(); while( !IN_CheckAck() ) { ; } EndLevelStuff = false; CurrentFont = smallfont; } void DrawTallyHeader ( int which ) { pic_t *Name; pic_t *KillCount; pic_t *TimesYouKilledPerson; pic_t *TimesPersonKilledYou; pic_t *Suicides; pic_t *Score; pic_t *Blank; pic_t *TopBar; Name = ( pic_t * )W_CacheLumpName( "t_name", PU_CACHE, Cvt_pic_t, 1 ); Blank = ( pic_t * )W_CacheLumpName( "t_blnk", PU_CACHE, Cvt_pic_t, 1 ); KillCount = ( pic_t * )W_CacheLumpName( "t_kcount", PU_CACHE, Cvt_pic_t, 1 ); TimesYouKilledPerson = ( pic_t * )W_CacheLumpName( "t_kilper", PU_CACHE, Cvt_pic_t, 1 ); TimesPersonKilledYou = ( pic_t * )W_CacheLumpName( "t_perkil" , PU_CACHE, Cvt_pic_t, 1 ); Suicides = ( pic_t * )W_CacheLumpName( "t_suicid", PU_CACHE, Cvt_pic_t, 1 ); Score = ( pic_t * )W_CacheLumpName( "t_score", PU_CACHE, Cvt_pic_t, 1 ); TopBar = ( pic_t * )W_CacheLumpName( "t_bar", PU_CACHE, Cvt_pic_t, 1 ); IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1 ); switch( which ) { case 0 : VWB_DrawPic ( 8, 8, TopBar ); DrawIntensityString( 12, 11, "FINAL SCORE", 20 ); VWB_DrawPic ( 8, 24, Name ); VWB_DrawPic ( 136, 24, KillCount ); VWB_DrawPic ( 184, 24, Suicides ); VWB_DrawPic ( 272, 24, Score ); break; case 1 : VWB_DrawPic ( 8, 8, TopBar ); DrawIntensityString( 12, 11, "FINAL SCORE", 20 ); VWB_DrawPic ( 8, 24, Name ); VWB_DrawPic ( 136, 24, Blank ); VWB_DrawPic ( 272, 24, Score ); break; case 2 : VWB_DrawPic ( 8, 8, TopBar ); DrawIntensityString( 12, 11, "YOUR KILLS", 20 ); VWB_DrawPic ( 8, 24, Name ); VWB_DrawPic ( 136, 24, KillCount ); VWB_DrawPic ( 184, 24, TimesYouKilledPerson ); break; case 3 : VWB_DrawPic ( 8, 8, TopBar ); DrawIntensityString( 12, 11, "YOUR DEATHS", 20 ); VWB_DrawPic ( 8, 24, Name ); VWB_DrawPic ( 136, 24, TimesPersonKilledYou ); break; //bna added case 4 : VWB_DrawPic ( 198+48, 8, Blank ); VWB_DrawPic ( 8, 8, TopBar ); DrawIntensityString( 12, 11, "FINAL SCORE", 20 ); VWB_DrawPic ( 8, 24, TopBar );//used to blank VWB_DrawPic ( 8, 24, Name ); VWB_DrawPic ( 136, 24, KillCount); VWB_DrawPic ( 198, 24, TimesPersonKilledYou); VWB_DrawPic ( 198+48, 24, Blank ); VWB_DrawPic ( 272, 24, Score ); break; //bna added end } DrawTimeXY( TALLYTIME_X, TALLYTIME_Y, gamestate.TimeCount / VBLCOUNTER, true ); } #define BT_RANK_X 23 #define BT_PLAYER_X 30 #define BT_KILLS_X ( 139 + ( ( 40 + 20 ) / 2 ) ) #define BT_DEATHS_X ( 193 + ( ( 56 + 20 ) / 2 ) ) //#define BT_SCORE_X ( 263 + ( ( 46 + 20 ) / 2 ) ) #define BT_SCORE_X ( 273 + ( ( 46 + 20 ) / 2 ) ) void ShowKills( int localplayer ) { int w; int h; int i; int j; int temp; int rank; int player; int killer; int victim; int color; char tempstr[15]; int KillCount[ MAXPLAYERS ]; int Order[ MAXPLAYERS ]; int NumPlayers; // show at the most 11 players NumPlayers = min( numplayers, 11 ); // Count kills for( killer = 0; killer < NumPlayers; killer++ ) { Order[ killer ] = killer; KillCount[ killer ] = 0; for( victim = 0; victim < NumPlayers; victim++ ) { if ( BATTLE_Team[ victim ] != BATTLE_Team[ killer ] ) { KillCount[ killer ] += WhoKilledWho[ killer ][ victim ]; } } } for( i = 0; i < NumPlayers - 1; i++ ) { for( j = i + 1; j < NumPlayers; j++ ) { if ( KillCount[ Order[ i ] ] < KillCount[ Order[ j ] ] ) { temp = Order[ i ]; Order[ i ] = Order[ j ]; Order[ j ] = temp; } } } DrawTallyHeader( 2 ); IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1); CurrentFont = smallfont; py = 43; for( rank = 0; rank < NumPlayers; rank++ ) { player = Order[ rank ]; color = 21; // Highlight the your score if ( player == localplayer ) { // Change to Intensity color = 241; } // Draw rank if not tied with previous rank if ( ( rank == 0 ) || ( KillCount[ player ] != KillCount[ Order[ rank - 1 ] ] ) ) { itoa( rank + 1, tempstr, 10 ); } else { strcpy( tempstr, "Tie" ); } VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_RANK_X - w, py, tempstr, color ); // Draw name DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color ); // Draw kills itoa( KillCount[ player ], tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_KILLS_X - w, py, tempstr, color ); // Draw times you killed that person if ( player != localplayer ) { itoa( WhoKilledWho[ localplayer ][ player ], tempstr, 10 ); } else { strcpy( tempstr, "-" ); } VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color ); if ( gamestate.teamplay ) { DrawIntensityString( BT_DEATHS_X + 16, py, colorname[ PLAYERSTATE[ player ].uniformcolor ], color ); } py += h; } } void ShowDeaths( int localplayer ) { int w; int h; int i; int j; int temp; int rank; int player; int killer; int victim; int color; char tempstr[15]; int DeathCount[ MAXPLAYERS ]; int Order[ MAXPLAYERS ]; int NumPlayers; // show at the most 11 players NumPlayers = min( numplayers, 11 ); // Count Deaths for( victim = 0; victim < NumPlayers; victim++ ) { Order[ victim ] = victim; DeathCount[ victim ] = 0; for( killer = 0; killer < NumPlayers; killer++ ) { DeathCount[ victim ] += WhoKilledWho[ killer ][ victim ]; } } for( i = 0; i < NumPlayers - 1; i++ ) { for( j = i + 1; j < NumPlayers; j++ ) { if ( DeathCount[ Order[ i ] ] < DeathCount[ Order[ j ] ] ) { temp = Order[ i ]; Order[ i ] = Order[ j ]; Order[ j ] = temp; } } } DrawTallyHeader( 3 ); IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1); CurrentFont = smallfont; py = 43; for( rank = 0; rank < NumPlayers; rank++ ) { player = Order[ rank ]; color = 21; // Highlight the your score if ( player == localplayer ) { // Change to Intensity color = 241; } // Draw rank if not tied with previous rank if ( ( rank == 0 ) || ( DeathCount[ player ] != DeathCount[ Order[ rank - 1 ] ] ) ) { itoa( rank + 1, tempstr, 10 ); } else { strcpy( tempstr, "Tie" ); } VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_RANK_X - w, py, tempstr, color ); // Draw name DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color ); // Draw deaths itoa( DeathCount[ player ], tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_KILLS_X - w, py, tempstr, color ); // Draw times you were killed by that person itoa( WhoKilledWho[ player ][ localplayer ], tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color ); if ( gamestate.teamplay ) { DrawIntensityString( BT_DEATHS_X + 16, py, colorname[ PLAYERSTATE[ player ].uniformcolor ], color ); } py += h; } } void ShowEndScore( int localplayer ) { int w; int h; int rank; int leader; int team; int color; int killer; int victim; int killcount; int suicidecount; char tempstr[15]; boolean dofullstats; int NumPlayers; // show at the most 11 players NumPlayers = min( numplayers, 11 ); dofullstats = false; switch( gamestate.battlemode ) { case battle_Normal : case battle_ScoreMore : case battle_Hunter : dofullstats = true; DrawTallyHeader( 0 ); break; case battle_Collector : case battle_Scavenger : case battle_Tag : case battle_Eluder : case battle_Deluder : case battle_CaptureTheTriad : dofullstats = false; DrawTallyHeader( 1 ); break; } IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1); CurrentFont = smallfont; py = 43; for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ ) { team = BATTLE_PlayerOrder[ rank ]; color = 21; if ( team == BATTLE_Team[ localplayer ] ) { // Change to Intensity color = 241; } // Draw rank if not tied with previous rank if ( ( rank == 0 ) || ( BATTLE_Points[ team ] != BATTLE_Points[ BATTLE_PlayerOrder[ rank - 1 ] ] ) ) { itoa( rank + 1, tempstr, 10 ); } else { strcpy( tempstr, "Tie" ); } VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_RANK_X - w, py, tempstr, color ); // Draw name of team leader leader = BATTLE_TeamLeader[ team ]; if ( gamestate.teamplay ) { DrawIntensityString( BT_PLAYER_X, py, colorname[ PLAYERSTATE[ leader ].uniformcolor ], color ); } else { DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ leader ].codename, color ); } if ( dofullstats ) { // Count how many kills each person on the team got killcount = 0; suicidecount = 0; for( killer = 0; killer < NumPlayers; killer++ ) { if ( BATTLE_Team[ killer ] == team ) { for( victim = 0; victim < NumPlayers; victim++ ) { if ( BATTLE_Team[ victim ] != team ) { killcount += WhoKilledWho[ killer ][ victim ]; } else { suicidecount += WhoKilledWho[ killer ][ victim ]; } } } } // Draw kills itoa( killcount, tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_KILLS_X - w, py, tempstr, color ); // Draw suicides itoa( suicidecount, tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color ); } // Draw Score itoa( BATTLE_Points[ team ], tempstr, 10 ); VW_MeasureIntensityPropString ( tempstr, &w, &h); DrawIntensityString( BT_SCORE_X - w, py, tempstr, color ); py += h; } } void BattleLevelCompleted ( int localplayer ) { ControlInfo ci; int w; int h; int key; int Screen; int LastScreen; int Player; char text[80]; EnableScreenStretch(); IN_ClearKeysDown (); Player = localplayer; Screen = 1; LastScreen = 0; key = -1; while( 1 ) { if ( Screen != LastScreen ) { VL_DrawPostPic (W_GetNumForName("trilogo")); switch( Screen ) { case 1 : ShowEndScore( Player ); break; case 2 : ShowKills( Player ); break; case 3 : ShowDeaths( Player ); break; } CurrentFont = tinyfont; sprintf ( text, "Page %d of 3. Use arrows to switch stats. " "Press Esc to quit.", Screen ); VW_MeasurePropString ( text, &w, &h); py = 192; px = ( 320 - w ) / 2; VWB_DrawPropString ( text ); VW_UpdateScreen (); do { ReadAnyControl (&ci); } while( ci.dir == (dirtype)key ); } LastScreen = Screen; ReadAnyControl ( &ci ); key = ci.dir; if ( ( Screen > 1 ) && ( key == dir_West ) ) { Screen--; MN_PlayMenuSnd (SD_MOVECURSORSND); } else if ( ( Screen < 3 ) && ( key == dir_East ) ) { Screen++; MN_PlayMenuSnd (SD_MOVECURSORSND); } // Allow us to select which player to view if ( Keyboard[ sc_RShift ] && ( key == dir_South ) ) { Player++; if ( Player >= numplayers ) { Player = 0; } LastScreen = 0; MN_PlayMenuSnd (SD_SELECTSND); } if ( Keyboard[ sc_RShift ] && ( key == dir_North ) ) { Player--; if ( Player < 0 ) { Player = numplayers - 1; } LastScreen = 0; MN_PlayMenuSnd (SD_SELECTSND); } if ( Keyboard[sc_Escape] ) { break; } } while ( Keyboard[sc_Escape] ) { IN_UpdateKeyboard (); } MN_PlayMenuSnd (SD_ESCPRESSEDSND); CurrentFont = smallfont; } //========================================================================== /* ================== = = FindAngleToWindow = ================== */ int FindAngleToWindow ( int tx, int ty ) { if (!IsWindow(tx+1,ty)) return ANG180; else if (!IsWindow(tx-1,ty)) return 0; else if (!IsWindow(tx,ty+1)) return ANG90; else return ANG270; } #define STARTRADIUS (0xa000) #define STOPRADIUS (0x14000) #define DEATHRADIUS (STOPRADIUS-STARTRADIUS) #define ROTRATE (5) #define TOTALDEATHROT (FINEANGLES<<1) #define RADIUSINC ((DEATHRADIUS)/(TOTALDEATHROT)) /* ================== = = ZoomDeathOkay = ================== */ boolean ZoomDeathOkay ( void ) { int x,y; int radius; if ( !( (player->state==&s_ashwait) || ((player->flags & FL_HBM) && (gamestate.violence >= vl_high)) ) ) return false; radius=STOPRADIUS; x=player->x; y=player->y; while (radius>0) { if (tilemap[x>>16][(y+radius)>>16]) return false; if (tilemap[x>>16][(y-radius)>>16]) return false; if (tilemap[(x-radius)>>16][y>>16]) return false; if (tilemap[(x+radius)>>16][y>>16]) return false; if (tilemap[(x+radius)>>16][(y+radius)>>16]) return false; if (tilemap[(x+radius)>>16][(y-radius)>>16]) return false; if (tilemap[(x-radius)>>16][(y+radius)>>16]) return false; if (tilemap[(x-radius)>>16][(y-radius)>>16]) return false; radius-=0x10000; } return true; } /* ================== = = Died = ================== */ #define DEATHROTATE 6 extern boolean dopefish; void Died (void) { long dx,dy; int iangle,curangle,clockwise,change; int da; int rate; lbm_t *LBM; int slowrate; playertype *pstate; objtype * killerobj=(objtype *)player->target; player->yzangle=0; if (killerobj == NULL) killerobj = player; if (CheckParm("slowdeath")) slowrate=3; else slowrate=0; M_LINKSTATE (player, pstate); if ( (ZoomDeathOkay()==true) && (pstate->falling==false)) { int x,y,z,radius,heightoffset; int endangle,startangle,killangle; boolean deadflagset; objtype * dummy; x=player->x; y=player->y; z=player->z; dummy=player; SpawnPlayerobj (x>>16, y>>16, 0, 0); player=dummy; dummy=new; dummy->x=x; dummy->drawx=x; dummy->y=y; dummy->z=z; dummy->drawy=y; dummy->flags=player->flags; player->momentumx=0; player->momentumy=0; player->speed=0; radius=STARTRADIUS; heightoffset=pstate->heightoffset; deadflagset=false; startangle=(player->angle+ANG180)&(FINEANGLES-1); endangle=startangle+TOTALDEATHROT; killangle=startangle+(TOTALDEATHROT>>1); if (dopefish==true) { AddMessage("Dopefish Death Cam",MSG_SYSTEM); } for (iangle=startangle;;) { if ( iangle > killangle ) { if ( deadflagset==false ) { dummy->hitpoints=0; pstate->health=0; dummy->flags &= ~FL_DYING; dummy->flags |= FL_SHOOTABLE; if (player->state==&s_ashwait) dummy->flags |= FL_SKELETON; Collision(dummy,(objtype*)NULL,0,0); deadflagset=true; if ( ( killerobj==player ) && ( gamestate.violence >= vl_high ) && ( gamestate.difficulty >= gd_hard ) ) { SD_Play( SD_YOUSUCKSND ); } else { SD_Play (SD_PLAYERTCDEATHSND+(pstate->player)); } } } else { dummy->flags &= ~FL_DYING; } if (dopefish==true) { dummy->momentumx+=(RandomNumber("Died",0)<<6)-(256<<5); dummy->momentumy+=(RandomNumber("Died",0)<<6)-(256<<5); } player->x=x+FixedMul(radius,costable[iangle&(FINEANGLES-1)]); player->y=y-FixedMul(radius,sintable[iangle&(FINEANGLES-1)]); player->z=dummy->z; player->angle=(iangle+ANG180)&(FINEANGLES-1); if (dopefish==true) { int dx,dy; dx = dummy->x - player->x; dy = player->y - dummy->y; if (dx && dy) player->angle = atan2_appx (dx,dy); } pstate->heightoffset=heightoffset; player->yzangle=0; UpdateGameObjects(); player->momentumx=0; player->momentumy=0; player->speed=0; ThreeDRefresh (); AnimateWalls(); DoSprites(); DoAnimatedMaskedWalls(); UpdatePlayers(); UpdateLightLevel(player->areanumber); if (ianglestate==dummy->state->next) && (iangle>=endangle) ) break; } } else if (pstate->falling==false) { // // swing around to face attacker // rate=DEATHROTATE-slowrate; { if (killerobj==player) { iangle=player->angle; if ( ( gamestate.violence >= vl_high ) && ( gamestate.difficulty >= gd_hard ) ) { SD_Play( SD_YOUSUCKSND ); } } else { SD_Play (SD_PLAYERTCDEATHSND+(pstate->player)); if (killerobj->which==PWALL) { dx = ((pwallobj_t *)killerobj)->x - player->x; dy = player->y - ((pwallobj_t *)killerobj)->y; } else { dx = killerobj->x - player->x; dy = player->y - killerobj->y; } iangle = atan2_appx (dx,dy); // returns -pi to pi } } da = iangle-player->angle; if (da>0) clockwise=1; else clockwise=0; da=abs(da); if (da>ANG180) { clockwise^=1; da=ANGLES-da; } curangle = player->angle; do { DoBorderShifts (); change = tics<= ANGLES) curangle -= ANGLES; if (curangle < 0) curangle += ANGLES; player->angle = (curangle & (FINEANGLES-1)); ThreeDRefresh (); CalcTics (); } while (da>0); } else { DrawFullSky(); FlipPage(); } while (damagecount) DoBorderShifts (); DoBorderShifts (); locplayerstate->weapon = -1; // take away weapon if ( (tedlevel == false) && // SO'S YA DON'T GET KILLED WHILE LAUNCHING! (timelimitenabled == false) ) locplayerstate->lives--; if (pstate->falling==false) { ThreeDRefresh (); } FlipPage(); FlipPage(); if (locplayerstate->lives > -1) { int rng; rng = RandomNumber ("Died",0); if (pstate->falling==true) { RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate))); SD_Play (SD_PLAYERTCDEATHSND+(pstate->player)); pstate->falling=false; } else if (rng < 64) RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(2+slowrate))); else if (rng < 128) { RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate))); } else if (rng < 192) RotateBuffer(0, (FINEANGLES*4), (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(3+slowrate))); else VL_FadeToColor (VBLCOUNTER*2, 100, 0, 0); screenfaded=false; VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1); gamestate.episode = 1; player->flags &= ~FL_DONE; InitializeWeapons (locplayerstate); ResetPlayerstate(locplayerstate); UpdateLives (locplayerstate->lives); UpdateScore (gamestate.score); DrawTriads(true); DrawLives (true); DrawKeys (true); DrawScore (true); } else { int rng; SD_Play (SD_GAMEOVERSND); rng=RandomNumber("Died",0); if (rng<64) RotateBuffer(0,(FINEANGLES>>1),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate))); else if (rng<128) VL_FadeToColor (VBLCOUNTER*3, 255, 255, 255); else if (rng<192) RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate))); else RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate))); screenfaded=false; VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1); MU_StartSong(song_gameover); #if (SHAREWARE==0) if (gamestate.violence==vl_excessive) LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1); else LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootnorm"), PU_CACHE, Cvt_lbm_t, 1); #else LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1); #endif VL_DecompressLBM (LBM,true); StopWind(); IN_UserInput (VBLCOUNTER*60); MainMenu[savegame].active = 0; MainMenu[viewscores].routine = (void *)CP_ViewScores; MainMenu[viewscores].texture[6] = '7'; MainMenu[viewscores].texture[7] = '\0'; MainMenu[viewscores].letter = 'V'; } ClearGraphicsScreen(); VL_FadeIn (0, 255, origpal, 15); } //****************************************************************************** // // DoLoadGameAction () // //****************************************************************************** static byte whichstr = 0; void DoLoadGameAction (void) { if ((SaveTime+1) < GetTicCount()) { byte *temp = bufferofs; bufferofs = displayofs; SaveTime = GetTicCount(); CurrentFont=tinyfont; px = 92; py = 152; if (whichstr) { // VW_DrawPropString ("ƒ"); VW_DrawPropString ("."); whichstr = 0; } else { // VW_DrawPropString ("„"); VW_DrawPropString ("."); whichstr = 1; } bufferofs = temp; } } //****************************************************************************** // // DoCheckSum () // //****************************************************************************** long DoCheckSum (byte *source, int size, long csum) { int i; long checksum; checksum = csum; for (i = 0; i < size; i++) checksum=updatecrc(checksum,*(source+i)); return checksum; } //****************************************************************************** // // CaculateSaveGameCheckSum () // //****************************************************************************** #define SAVECHECKSUMSIZE (10000) long CalculateSaveGameCheckSum (char * filename) { int handle; int lengthleft; int length; byte * altbuffer; long checksum; altbuffer=SafeMalloc(SAVECHECKSUMSIZE); checksum = 0; // Open the savegame file handle = SafeOpenRead (filename); lengthleft = filelength (handle); while (lengthleft>0) { length=SAVECHECKSUMSIZE; if (length>lengthleft) length=lengthleft; SafeRead(handle,altbuffer,length); checksum = DoCheckSum (altbuffer, length, checksum); lengthleft-=length; } SafeFree(altbuffer); close (handle); return checksum; } //****************************************************************************** // // StoreBuffer // //****************************************************************************** void StoreBuffer (int handle, byte * src, int size) { SafeWrite(handle,&size,sizeof(size)); SafeWrite(handle,src,size); } //****************************************************************************** // // SaveTag // //****************************************************************************** void SaveTag (int handle, char * tag, int size) { SafeWrite(handle,tag,size); } //****************************************************************************** // // SaveTheGame () // // Expects game to be premalloced // //****************************************************************************** boolean SaveTheGame (int num, gamestorage_t * game) { char loadname[MAX_PATH]="rottgam0.rot"; char filename[MAX_PATH]; byte * altbuffer; int size; int avail; int savehandle; int crc; int i; char letter; int myticcount; if (num > 15 || num < 0) Error("Illegal Saved game value=%d\n",num); // // Save Alternate Game Level information for reloading game // memset (&game->info, 0, sizeof (game->info)); if (GameLevels.avail == true) { memcpy (&game->info.path[0], &GameLevels.path[0], sizeof (GameLevels.path)); memcpy (&game->info.file[0], &GameLevels.file[0], sizeof (GameLevels.file)); game->info.avail = true; } game->mapcrc=GetMapCRC (gamestate.mapon); // Create the proper file name itoa(num,&loadname[7],16); loadname[8]='.'; GetPathFromEnvironment( filename, ApogeePath, loadname ); #if PLATFORM_DOS { struct diskfree_t dfree; // Determine available disk space letter = toupper(filename[0]); if ( (letter >= 'A') && (letter <= 'Q') ) { if (_dos_getdiskfree ((letter-'A'+1), &dfree)) Error ("Error in _dos_getdiskfree call\n"); } else { if (_dos_getdiskfree (0, &dfree)) Error ("Error in _dos_getdiskfree call\n"); } avail = (int) dfree.avail_clusters * dfree.bytes_per_sector * dfree.sectors_per_cluster; avail -= 8192; // Check to see if we have enough if (avail < MAXSAVEDGAMESIZE) { CP_DisplayMsg ("There is not enough\nspace on your disk\nto Save Game!\nPress any key to continue", 13); return (false); } } #endif // Open the savegame file savehandle = SafeOpenWrite (filename); // Save out file tag size=4; SaveTag(savehandle,"ROTT",size); // Save out header size=sizeof(*game); SafeWrite(savehandle,game,size); ///////////////////////////////////////////////////////////////////////////// // Save out rest of save game file beyond this point ///////////////////////////////////////////////////////////////////////////// // Door Tag size=4; SaveTag(savehandle,"DOOR",size); // Doors SaveDoors(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // Elevator Tag size = 9; SaveTag(savehandle,"ELEVATORS",size); // Elevators SaveElevators(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // Pushwall Tag size=5; SaveTag(savehandle,"PWALL",size); // PushWalls SavePushWalls(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // MaskedWalls Tag size=5; SaveTag(savehandle,"MWALL",size); // Masked Walls SaveMaskedWalls(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // Switches Tag size=6; SaveTag(savehandle,"SWITCH",size); // Switches SaveSwitches(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // Statics Tag size=6; SaveTag(savehandle,"STATIC",size); // Statics SaveStatics(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // Actors Tag size=5; SaveTag(savehandle,"ACTOR",size); // Actors SaveActors(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // TouchPlates Tag size=5; SaveTag(savehandle,"TOUCH",size); // TouchPlates SaveTouchPlates(&altbuffer,&size); StoreBuffer(savehandle,altbuffer,size); SafeFree(altbuffer); // GameState Tag size=9; SaveTag(savehandle,"GAMESTATE",size); // GameState size=sizeof(gamestate); SafeWrite(savehandle,&gamestate,size); // PlayerState Tag size=12; SaveTag(savehandle,"PLAYERSTATES",size); // PlayerStates size=sizeof(playertype); for(i=0;i15 || num<0) Error("Illegal Load game value=%d\n",num); // Create the proper file name itoa(num,&loadname[7],16); loadname[8]='.'; GetPathFromEnvironment( filename, ApogeePath, loadname ); // Load the file totalsize=LoadFile(filename,(void **)&loadbuffer); bufptr=loadbuffer; // Calculate checksum checksum = DoCheckSum (loadbuffer, totalsize-sizeof(checksum), 0); // Retrieve saved checksum memcpy (&savedchecksum,loadbuffer+(totalsize-sizeof(savedchecksum)),sizeof(savedchecksum)); // Compare the two checksums; if (checksum!=savedchecksum) { if (CP_DisplayMsg ("Your Saved Game file is\n" "shall we say, \"corrupted\".\n" "Would you like to\n" "continue anyway (Y/N)?\n", 12)==false) { return false; } } // Load in file tag size=4; LoadTag(&bufptr,"ROTT",size); // Load in header size=sizeof(*game); memcpy(game,bufptr,size); bufptr+=size; if (game->version!=ROTTVERSION) return false; memcpy (&GameLevels, &game->info, sizeof (GameLevels)); gamestate.episode=game->episode; gamestate.mapon=game->area; mapcrc=GetMapCRC (gamestate.mapon); if (mapcrc!=game->mapcrc) return false; ///////////////////////////////////////////////////////////////////////////// // Load in rest of saved game file beyond this point ///////////////////////////////////////////////////////////////////////////// // Free up the current level Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level gamestate.battlemode = battle_StandAloneGame; BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] ); BATTLE_Init( gamestate.battlemode, 1 ); DoLoadGameAction (); SetupGameLevel(); // This prevents a nasty glitch when loading some saved games PreCacheGroup(W_GetNumForName("BULLETHO"),W_GetNumForName("ALTBHO"),cache_transpatch_t); // Door Tag size=4; LoadTag(&bufptr,"DOOR",size); // Doors DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadDoors(altbuffer,size); SafeFree(altbuffer); // Elevator Tag size = 9; LoadTag(&bufptr,"ELEVATORS",size); // Elevators DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadElevators(altbuffer,size); SafeFree(altbuffer); // Pushwall Tag size=5; LoadTag(&bufptr,"PWALL",size); // PushWalls DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadPushWalls(altbuffer,size); SafeFree(altbuffer); #if 0 // Animated Walls Tag size=5; LoadTag(&bufptr,"AWALL",size); // Animated Walls size=LoadBuffer(&altbuffer,&bufptr); LoadAnimWalls(altbuffer,size); SafeFree(altbuffer); #endif // MaskedWalls Tag size=5; LoadTag(&bufptr,"MWALL",size); // Masked Walls DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadMaskedWalls(altbuffer,size); SafeFree(altbuffer); // Switches Tag size=6; LoadTag(&bufptr,"SWITCH",size); // Switches DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadSwitches(altbuffer,size); SafeFree(altbuffer); // Statics Tag size=6; LoadTag(&bufptr,"STATIC",size); // Statics DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadStatics(altbuffer,size); SafeFree(altbuffer); // Actors Tag size=5; LoadTag(&bufptr,"ACTOR",size); // Actors DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadActors(altbuffer,size); SafeFree(altbuffer); // TouchPlates Tag size=5; LoadTag(&bufptr,"TOUCH",size); // TouchPlates DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); LoadTouchPlates(altbuffer,size); SafeFree(altbuffer); // SetupWindows SetupWindows(); // GameState Tag size=9; LoadTag(&bufptr,"GAMESTATE",size); // GameState DoLoadGameAction (); size=sizeof(gamestate); memcpy(&gamestate,bufptr,size); bufptr+=size; // PlayerState Tag size=12; LoadTag(&bufptr,"PLAYERSTATES",size); // PlayerState DoLoadGameAction (); size=sizeof(playertype); for(i=0;iguntarget=0; locplayerstate->targettime=0; // Mapseen Tag size=7; LoadTag(&bufptr,"MAPSEEN",size); // MapSeen DoLoadGameAction (); size=sizeof(mapseen); memcpy(&mapseen,bufptr,size); bufptr+=size; // Song Tag size=4; LoadTag(&bufptr,"SONG",size); // Song info DoLoadGameAction (); size=LoadBuffer(&altbuffer,&bufptr); MU_LoadMusic(altbuffer,size); SafeFree(altbuffer); // Misc Tag size=4; LoadTag(&bufptr,"MISC",size); // Misc // ticcount DoLoadGameAction (); size=sizeof(myticcount); memcpy((void *)&myticcount,bufptr,size); bufptr+=size; SaveTime = myticcount; ISR_SetTime(myticcount); // shaketics DoLoadGameAction (); size=sizeof(SHAKETICS); memcpy(&SHAKETICS,bufptr,size); bufptr+=size; // damagecount DoLoadGameAction (); size=sizeof(damagecount); memcpy(&damagecount,bufptr,size); bufptr+=size; // viewsize DoLoadGameAction (); size=sizeof(viewsize); memcpy(&viewsize,bufptr,size); bufptr+=size; // powerup times DoLoadGameAction (); size = sizeof (poweruptime); memcpy (&poweruptime, bufptr, size); bufptr += size; size = sizeof (protectiontime); memcpy (&protectiontime, bufptr, size); bufptr += size; size = sizeof (powerupheight); memcpy (&powerupheight, bufptr, size); bufptr += size; size = sizeof (protectionheight); memcpy (&protectionheight, bufptr, size); bufptr += size; size = sizeof (poweradjust); memcpy (&poweradjust, bufptr, size); bufptr += size; // Set the viewsize SetViewSize(viewsize); DoLoadGameAction (); // Connect areas ConnectAreas (); DoLoadGameAction (); // Free up the loadbuffer SafeFree (loadbuffer); DoLoadGameAction (); Illuminate(); IN_UpdateKeyboard (); LoadPlayer (); DoLoadGameAction (); SetupPlayScreen(); UpdateScore (gamestate.score); UpdateLives (locplayerstate->lives); UpdateTriads (player, 0); PreCache (); InitializeMessages(); for (i=0;i<100;i++) UpdateLightLevel(player->areanumber); CalcTics(); CalcTics(); pickquick = true; return (true); } //****************************************************************************** // // GetSavedMessage () // // Expects message to be premalloced // //****************************************************************************** void GetSavedMessage (int num, char * message) { gamestorage_t game; char loadname[45]="rottgam0.rot"; char filename[128]; byte * loadbuffer; byte * bufptr; int size; if (num>15 || num<0) Error("Illegal Load game value=%d\n",num); // Create the proper file name itoa(num,&loadname[7],16); loadname[8]='.'; GetPathFromEnvironment( filename, ApogeePath, loadname ); // Load the file size=LoadFile(filename,(void **)&loadbuffer); bufptr=loadbuffer; size=4; LoadTag(&bufptr,"ROTT",size); // Load in header size=sizeof(game); memcpy(&game,bufptr,size); strcpy(message,game.message); SafeFree(loadbuffer); } //****************************************************************************** // // GetSavedHeader () // // Expects game to be premalloced // //****************************************************************************** void GetSavedHeader (int num, gamestorage_t * game) { char loadname[45]="rottgam0.rot"; char filename[128]; byte * loadbuffer; byte * bufptr; int size; if (num>15 || num<0) Error("Illegal Load game value=%d\n",num); // Create the proper file name itoa(num,&loadname[7],16); loadname[8]='.'; GetPathFromEnvironment( filename, ApogeePath, loadname ); // Load the file size=LoadFile(filename, (void **)&loadbuffer); bufptr=loadbuffer; size=4; LoadTag(&bufptr,"ROTT",size); // Load in header size=sizeof(*game); memcpy(game,bufptr,size); SafeFree(loadbuffer); } //****************************************************************************** // // GetLevel () // //****************************************************************************** int GetLevel (int episode, int mapon) { int level; level = (mapon+1) - ((episode-1) << 3); return (level); }