//***************************************************************************** // void DUEL_DoWinSequence( ULONG ulPlayer ) { ULONG ulIdx; // Put the duel state in the win sequence state. if ( NETWORK_GetState( ) != NETSTATE_CLIENT ) DUEL_SetState( DS_WINSEQUENCE ); // Tell clients to do the win sequence. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_DoGameModeWinSequence( ulPlayer ); if ( NETWORK_GetState( ) != NETSTATE_SERVER ) { char szString[64]; DHUDMessageFadeOut *pMsg; screen->SetFont( BigFont ); sprintf( szString, "%s \\c-WINS!", players[ulPlayer].userinfo.netname ); V_ColorizeString( szString ); // Display "%s WINS!" HUD message. pMsg = new DHUDMessageFadeOut( szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, 'CNTR' ); screen->SetFont( SmallFont ); } // Award a victory or perfect medal to the winner. if ( NETWORK_GetState( ) != NETSTATE_CLIENT ) { LONG lMedal; // If the duel loser doesn't have any frags, give the winner a "Perfect!". if ( players[g_ulDuelLoser].fragcount <= 0 ) lMedal = MEDAL_PERFECT; else lMedal = MEDAL_VICTORY; // Give the player the medal. MEDAL_GiveMedal( ulPlayer, lMedal ); if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_GivePlayerMedal( ulPlayer, lMedal ); } for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if (( playeringame[ulIdx] ) && ( players[ulIdx].pSkullBot )) players[ulIdx].pSkullBot->PostEvent( BOTEVENT_DUEL_WINSEQUENCE ); } }
// [BB] Version of V_ColorizeString that accepts a FString as argument. // Hacks like "V_ColorizeString( (char *)g_MOTD.GetChars( ));" // are not needed anymore using this. void V_ColorizeString( FString &String ) { const int length = (int) String.Len(); char *tempCharArray = new char[length+1]; strncpy( tempCharArray, String.GetChars(), length ); tempCharArray[length] = 0; V_ColorizeString( tempCharArray ); String = tempCharArray; delete[] tempCharArray; }
// [BB] Strips color codes from a string respecting sv_colorstripmethod. void V_StripColors( char *pszString ) { switch ( sv_colorstripmethod ) { // Strip messages here of color codes. case 0: V_ColorizeString( pszString ); V_RemoveColorCodes( pszString ); break; // Don't strip out the color codes. case 1: V_ColorizeString( pszString ); break; // Just leave the damn thing alone! case 2: default: break; } }
// [RC] Strips color codes from an FString. void V_RemoveColorCodes( FString &String ) { const ULONG length = (ULONG) String.Len(); char *szString = new char[length+1]; // Copy the FString to a temporary char array. strncpy( szString, String.GetChars(), length ); szString[length] = 0; // Remove the colors. V_ColorizeString( szString ); V_RemoveColorCodes( szString ); // Convert back and clean up. String = szString; delete[] szString; }
static void DrawTeamScores( int x, int y ) { if (( GAMEMODE_GetCurrentFlags() & GMF_PLAYERSONTEAMS ) == 0 ) return; int numteams = TEAM_GetNumAvailableTeams(); FString text; // [TP] Common case if ( numteams == 2 ) { int scores[2] = { GetScoreForTeam( 0 ), GetScoreForTeam( 1 ) }; int leadingTeam = !!( scores[1] > scores[0] ); int losingTeam = 1 - leadingTeam; text.Format ("\\c%c%d\\cC - \\c%c%d", V_GetColorChar( TEAM_GetTextColor( leadingTeam )), scores[leadingTeam], V_GetColorChar( TEAM_GetTextColor( losingTeam )), scores[losingTeam] ); } else { int teams[MAX_TEAMS] = { 0, 1, 2, 3 }; std::sort( teams, teams + countof( teams ), TeamScoreSorter ); for ( int i = 0; i < numteams; ++i ) { if ( i > 0 ) text += "\\cC - "; text += "\\c"; text += V_GetColorChar( TEAM_GetTextColor( teams[i] )); text.AppendFormat( "%d", GetScoreForTeam( teams[i] )); } } V_ColorizeString( text ); screen->DrawText( HudFont, CR_UNTRANSLATED, x, y + 17, text.GetChars(), DTA_KeepRatio, true, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE ); }
//***************************************************************************** // void LASTMANSTANDING_TimeExpired( void ) { LONG lHighestHealth = 0; bool bTie = false; bool bFoundPlayer = false; LONG lWinner = -1; DHUDMessageFadeOut *pMsg; char szString[64]; // Don't end the level if we're not in a game. if ( LASTMANSTANDING_GetState( ) != LMSS_INPROGRESS ) return; // Try to find the player with the highest health. if ( lastmanstanding ) { TArray<ULONG> possibleWinners; for ( unsigned int i = 0; i < MAXPLAYERS; ++i ) possibleWinners.Push ( i ); // [BB] Find the player with the most lives left. PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetLivesLeft, possibleWinners ); // [BB] If more than one player has the most lives left, select the player with the highest lives. if ( possibleWinners.Size() != 1 ) PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetHealth, possibleWinners ); // [BB] If more then one player have the most lives and also the same health, then the game it a tie. if ( possibleWinners.Size() == 1 ) lWinner = possibleWinners[0]; else { lWinner = MAXPLAYERS; bTie = true; } } else if ( teamlms ) { if ( LASTMANSTANDING_TeamsWithAlivePlayersOn( ) == 1 ) { for ( ULONG i = 0; i < teams.Size( ); i++ ) { if ( TEAM_CountLivingAndRespawnablePlayers( i ) ) lWinner = i; } } else { lWinner = teams.Size( ); bTie = true; } } // If for some reason we don't have any players, just end the map like normal. if ( lWinner == -1 ) { if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" )); else Printf( "%s\n", GStrings( "TXT_TIMELIMIT" )); GAME_SetEndLevelDelay( 5 * TICRATE ); return; } // If there was a tie, then go into sudden death! if ( bTie ) { // Only print the message the instant we reach sudden death. if ( level.time == (int)( timelimit * TICRATE * 60 )) { sprintf( szString, "\\cdSUDDEN DEATH!" ); V_ColorizeString( szString ); if ( NETWORK_GetState( ) != NETSTATE_SERVER ) { // Display the HUD message. pMsg = new DHUDMessageFadeOut( BigFont, szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, MAKE_ID('C','N','T','R') ); } else { SERVERCOMMANDS_PrintHUDMessageFadeOut( szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f, "BigFont", false, MAKE_ID('C','N','T','R') ); } } return; } // Also, do the win sequence for the player. LASTMANSTANDING_DoWinSequence( lWinner ); // Give the winner a win. if ( lastmanstanding ) PLAYER_SetWins( &players[lWinner], players[lWinner].ulWins + 1 ); // [BB] In a team game of course give the win to the winning team. if ( teamlms ) TEAM_SetWinCount( lWinner, TEAM_GetWinCount( lWinner ) + 1, false ); if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" )); else Printf( "%s\n", GStrings( "TXT_TIMELIMIT" )); GAME_SetEndLevelDelay( 5 * TICRATE ); }
//***************************************************************************** // void LASTMANSTANDING_DoWinSequence( ULONG ulWinner ) { ULONG ulIdx; // Put the game state in the win sequence state. if (( NETWORK_GetState( ) != NETSTATE_CLIENT ) && ( CLIENTDEMO_IsPlaying( ) == false )) { LASTMANSTANDING_SetState( LMSS_WINSEQUENCE ); } // Tell clients to do the win sequence. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_DoGameModeWinSequence( ulWinner ); if ( NETWORK_GetState( ) != NETSTATE_SERVER ) { char szString[64]; DHUDMessageFadeOut *pMsg; if ( teamlms ) { if ( ulWinner == teams.Size( ) ) sprintf( szString, "\\cdDraw Game!" ); else sprintf( szString, "\\c%c%s Wins!", V_GetColorChar( TEAM_GetTextColor( ulWinner ) ), TEAM_GetName( ulWinner )); } else if ( ulWinner == MAXPLAYERS ) sprintf( szString, "\\cdDRAW GAME!" ); else sprintf( szString, "%s \\c-WINS!", players[ulWinner].userinfo.netname ); V_ColorizeString( szString ); // Display "%s WINS!" HUD message. pMsg = new DHUDMessageFadeOut( BigFont, szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, MAKE_ID('C','N','T','R') ); szString[0] = 0; pMsg = new DHUDMessageFadeOut( SmallFont, szString, 0.0f, 0.0f, 0, 0, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, MAKE_ID('F','R','A','G') ); pMsg = new DHUDMessageFadeOut( SmallFont, szString, 0.0f, 0.0f, 0, 0, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, MAKE_ID('P','L','A','C') ); } // Award a victory or perfect medal to the winner. if (( lastmanstanding ) && ( NETWORK_GetState( ) != NETSTATE_CLIENT ) && ( CLIENTDEMO_IsPlaying( ) == false )) { LONG lMedal; // If the winner has full health, give him a "Perfect!". if ( players[ulWinner].health == deh.MegasphereHealth ) lMedal = MEDAL_PERFECT; else lMedal = MEDAL_VICTORY; // Give the player the medal. MEDAL_GiveMedal( ulWinner, lMedal ); if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVERCOMMANDS_GivePlayerMedal( ulWinner, lMedal ); } for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if (( playeringame[ulIdx] ) && ( players[ulIdx].pSkullBot )) players[ulIdx].pSkullBot->PostEvent( BOTEVENT_LMS_WINSEQUENCE ); } }
//***************************************************************************** // void CHAT_Render( void ) { UCVarValue ValWidth; UCVarValue ValHeight; bool bScale; float fXScale; float fYScale; ULONG ulYPos; LONG lIdx; LONG lX; char szString[64]; if ( g_ulChatMode == CHATMODE_NONE ) return; ValWidth = con_virtualwidth.GetGenericRep( CVAR_Int ); ValHeight = con_virtualheight.GetGenericRep( CVAR_Int ); // Initialization. if (( con_scaletext ) && ( con_virtualwidth > 0 ) && ( con_virtualheight > 0 )) { fXScale = (float)ValWidth.Int / SCREENWIDTH; fYScale = (float)ValHeight.Int / SCREENHEIGHT; bScale = true; ulYPos = (( gamestate == GS_INTERMISSION ) ? SCREENHEIGHT : ST_Y ) - ( Scale( SCREENHEIGHT, SmallFont->GetHeight( ) + 1, ValHeight.Int )) + 1; } else { fXScale = 1.0f; fYScale = 1.0f; bScale = false; ulYPos = (( gamestate == GS_INTERMISSION ) ? SCREENHEIGHT : ST_Y ) - SmallFont->GetHeight( ) + 1; } lX = static_cast<LONG>(SmallFont->GetCharWidth( '_' ) * fXScale * 2 + SmallFont->StringWidth( g_pszChatPrompt )); // figure out if the text is wider than the screen-> // if so, only draw the right-most portion of it. for ( lIdx = g_lStringLength - 1; (( lIdx >= 0 ) && ( lX < ( (float)SCREENWIDTH * fXScale ))); lIdx-- ) { lX += SmallFont->GetCharWidth( g_szChatBuffer[lIdx] & 0x7f ); } // If lIdx is >= 0, then this chat string goes beyond the edge of the screen. if ( lIdx >= 0 ) lIdx++; else lIdx = 0; // Temporarily h4x0r the chat buffer string to include the cursor. g_szChatBuffer[g_lStringLength] = gameinfo.gametype == GAME_Doom ? '_' : '['; g_szChatBuffer[g_lStringLength+1] = 0; if ( g_ulChatMode == CHATMODE_GLOBAL ) { HUD_DrawText( SmallFont, CR_GREEN, 0, (LONG)( ulYPos * fYScale ), g_pszChatPrompt ); HUD_DrawText( SmallFont, CR_GRAY, SmallFont->StringWidth( g_pszChatPrompt ), (LONG)( ulYPos * fYScale ), g_szChatBuffer + lIdx ); } else { HUD_DrawText( SmallFont, CR_GREY, 0, (LONG)( ulYPos * fYScale ), g_pszChatPrompt ); HUD_DrawText( SmallFont, (TEAM_GetTextColor (players[consoleplayer].ulTeam)), SmallFont->StringWidth( g_pszChatPrompt ), (LONG)( ulYPos * fYScale ), g_szChatBuffer + lIdx ); } // [RC] Tell chatters about the iron curtain of LMS chat. if ( GAMEMODE_AreSpectatorsFordiddenToChatToPlayers() ) { // Is this the spectator talking? if ( players[consoleplayer].bSpectating ) sprintf( szString, "\\cdNOTE: \\ccPlayers cannot hear you chat" ); else sprintf( szString, "\\cdNOTE: \\ccSpectators cannot talk to you" ); V_ColorizeString( szString ); HUD_DrawText( SmallFont, CR_UNTRANSLATED, (LONG)(( ( bScale ? ValWidth.Int : SCREENWIDTH )/ 2 ) - ( SmallFont->StringWidth( szString ) / 2 )), (LONG)(( ulYPos * fYScale ) - ( SmallFont->GetHeight( ) * 2 ) + 1 ), szString ); } g_szChatBuffer[g_lStringLength] = 0; BorderTopRefresh = screen->GetPageCount( ); }
// [RC] Conforms names to meet standards. void V_CleanPlayerName( char *pszString ) { char *pszStart; char *p; char c; ULONG ulStringLength; ULONG ulTotalLength; ULONG ulNonWhitespace; char szColorlessName[256]; ulStringLength = static_cast<ULONG>(strlen( pszString )); ulTotalLength = 0; ulNonWhitespace = 0; // Start at the beginning of the string. p = pszString; pszStart = pszString; // The name must be longer than three characters. if ( ulStringLength < 3 ) { strcpy( pszString, "Player" ); return; } // Go through and remove the illegal characters. while ( (c = *p++) ) { if ( !v_IsCharAcceptableInNames(c) ) { ULONG ulPos; ulStringLength = static_cast<ULONG>(strlen( pszString )); // Shift the rest of the string back one. for ( ulPos = 0; ulPos < ulStringLength; ulPos++ ) pszString[ulPos] = pszString[ulPos + 1]; // Don't skip a character. p--; } else { pszString++; ulTotalLength++; } } // Cut the string at its new end. *pszString = 0; // [BB] Remove any trailing incomplete escaped color codes. Since we just removed // quite a bit from the string, it's possible that those are there now. // Note: We need to work on pszStart now, by now pszString only contains a pointer // to the end of the string. // [BB] I don't want to implement the trailing crap removement for escaped and // unescaped color codes, so I have to uncolorize, clean and colorize the name here. // Not so efficient, but V_CleanPlayerName is called seldom enough so that this // doesn't matter. FString tempString = pszStart; V_UnColorizeString ( tempString ); V_RemoveTrailingCrapFromFString ( tempString ); // [BB] If the name uses color codes, make sure that it is terminated with "\\c-". // V_RemoveTrailingCrapFromFString removes all trailing color codes including "\\c-". // This is necessary to catch incomplete color codes before the trailing "\\c-". // Hence, we have to re-add "\\c-" here. if ( ( tempString.IndexOf ( "\\c" ) != -1 ) ) { // [BB] In the uncolorized string, color codes need one additional char, take this // into account when checking whether the name is too long. FString tempColorizedString = tempString.GetChars(); V_ColorizeString ( tempColorizedString ); const unsigned int numColorCodes = tempString.Len() - tempColorizedString.Len(); if ( tempString.Len() > MAXPLAYERNAME - 3 + numColorCodes ) { tempString = tempString.Left ( MAXPLAYERNAME - 3 + numColorCodes ); V_RemoveTrailingCrapFromFString ( tempString ); } tempString += "\\c-"; } V_ColorizeString ( tempString ); sprintf ( pszStart, "%s", tempString.GetChars() ); // Determine the name's actual length. strncpy( szColorlessName, pszStart, 256 ); V_RemoveColorCodes( szColorlessName ); p = szColorlessName; ulNonWhitespace = 0; while ( (c = *p++) ) { if ( !v_IsCharacterWhitespace(c) ) ulNonWhitespace++; } // Check the length again, as characters were removed. if ( ulNonWhitespace < 3 ) strcpy( pszStart, "Player" ); }
//***************************************************************************** // BOOL CALLBACK settings_ServerTab_MOTDCallback( HWND hDlg, UINT Message, WPARAM wParam, LPARAM lParam ) { switch ( Message ) { case WM_CLOSE: EndDialog( hDlg, -1 ); break; case WM_INITDIALOG: { SendDlgItemMessage( hDlg, IDC_MOTD, EM_SETLIMITTEXT, 512, 0 ); // Initialize the MOTD. We have to turn "\n" into carriage returns. { char szBuffer[512]; char szInputString[512]; char *psz; char *pszString; char c; strncpy( szInputString, g_fsMOTD.GetChars( ), 512 ); szInputString[512-1] = 0; // Nifty little trick to turn "\n" into '\n', while maintaining the "\c" color codes. V_ColorizeString( szInputString ); V_UnColorizeString( szInputString, 256 ); pszString = szInputString; psz = szBuffer; while ( 1 ) { c = *pszString++; if ( c == '\0' ) { *psz = c; break; } if ( c == '\n' ) *psz++ = '\r'; *psz++ = c; } SetDlgItemText( hDlg, IDC_MOTD, szBuffer ); SendDlgItemMessage( hDlg, IDC_MOTD, EM_SETSEL, -1, 0 ); // [RC] Why doesn't this work? } } break; case WM_COMMAND: { switch ( LOWORD( wParam )) { case IDOK: { // MOTD. Zip up those linebreaks into \ns. char szBuffer[1024]; GetDlgItemText( hDlg, IDC_MOTD, szBuffer, 1024 ); { char szString[1024+64]; char *psz; char *pszString; char c; psz = szBuffer; pszString = szString; while ( 1 ) { c = *psz++; if ( c == 0 ) { *pszString = c; break; } else if ( c == '\r' ) { *pszString++ = '\\'; *pszString++ = 'n'; psz++; } else *pszString++ = c; } g_fsMOTD = szString; } } EndDialog( hDlg, -1 ); break; case IDCANCEL: EndDialog( hDlg, -1 ); break; } } break; default: return ( FALSE ); } return ( TRUE ); }