mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-12 21:41:48 +00:00
372 lines
11 KiB
C++
372 lines
11 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "Game_local.h"
|
|
#include "Leaderboards.h"
|
|
#include "MultiplayerGame.h"
|
|
|
|
/*
|
|
================================================================================================
|
|
|
|
Leaderboard stats column definitions - per Game Type.
|
|
|
|
================================================================================================
|
|
*/
|
|
|
|
|
|
static columnDef_t public_Deathmatch[] =
|
|
{
|
|
{ "Frags", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
//{ "Deaths", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
//{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
//{ "Score", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
};
|
|
|
|
static columnDef_t public_Tourney[] =
|
|
{
|
|
{ "Wins", 64, AGGREGATE_SUM, STATS_COLUMN_DISPLAY_NUMBER },
|
|
};
|
|
|
|
static columnDef_t public_TeamDeathmatch[] =
|
|
{
|
|
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
};
|
|
|
|
static columnDef_t public_LastmanStanding[] =
|
|
{
|
|
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
};
|
|
|
|
static columnDef_t public_CaptureTheFlag[] =
|
|
{
|
|
{ "Wins", 64, AGGREGATE_MAX, STATS_COLUMN_DISPLAY_NUMBER },
|
|
};
|
|
|
|
// This should match up to the ordering of the gameType_t. ( in MultiplayerGame.h )
|
|
const columnGameMode_t gameMode_columnDefs[] =
|
|
{
|
|
{ public_Deathmatch, ARRAY_COUNT( public_Deathmatch ), RANK_GREATEST_FIRST, false, false, "DM" }, // DEATHMATCH
|
|
{ public_Tourney, ARRAY_COUNT( public_Tourney ), RANK_GREATEST_FIRST, false, false, "TOURNEY" }, // TOURNEY
|
|
{ public_TeamDeathmatch, ARRAY_COUNT( public_TeamDeathmatch ), RANK_GREATEST_FIRST, false, false, "TDM" }, // TEAM DEATHMATCH
|
|
{ public_LastmanStanding, ARRAY_COUNT( public_LastmanStanding ), RANK_GREATEST_FIRST, false, false, "LMS" }, // LASTMAN STANDING
|
|
{ public_CaptureTheFlag, ARRAY_COUNT( public_CaptureTheFlag ), RANK_GREATEST_FIRST, false, false, "CTF" }, // CAPTURE THE FLAG
|
|
};
|
|
|
|
/*
|
|
=====================================
|
|
RetreiveLeaderboardID
|
|
|
|
Each map will move in blocks of n*modes.
|
|
ex. map 0 will have 0 - 4 Leaderboard id's blocked out.
|
|
map 1 will have 5 - 10 leaderboard id's blocked out.
|
|
|
|
if gamemode is added it will move in blocks of ARRAY_COUNT( modes )
|
|
|
|
=====================================
|
|
*/
|
|
int LeaderboardLocal_GetID( int mapIndex, int gametype )
|
|
{
|
|
assert( gametype > GAME_RANDOM );
|
|
|
|
return mapIndex * ARRAY_COUNT( gameMode_columnDefs ) + gametype;
|
|
}
|
|
|
|
/*
|
|
=====================================
|
|
LeaderboardLocal_Init
|
|
=====================================
|
|
*/
|
|
void LeaderboardLocal_Init()
|
|
{
|
|
|
|
const idList< mpMap_t > maps = common->GetMapList();
|
|
|
|
const char** gameModes = NULL;
|
|
const char** gameModesDisplay = NULL;
|
|
int numModes = game->GetMPGameModes( &gameModes, &gameModesDisplay );
|
|
|
|
// Iterate through all the available maps, and generate leaderboard Defs, and IDs for each.
|
|
for( int mapIdx = 0; mapIdx < maps.Num(); mapIdx++ )
|
|
{
|
|
|
|
for( int modeIdx = 0; modeIdx < numModes; modeIdx++ )
|
|
{
|
|
|
|
// Check the supported modes on the map.
|
|
if( maps[ mapIdx ].supportedModes & BIT( modeIdx ) )
|
|
{
|
|
|
|
const columnGameMode_t gamemode = gameMode_columnDefs[ modeIdx ];
|
|
|
|
// Generate a Leaderboard ID for the map/mode
|
|
int boardID = LeaderboardLocal_GetID( mapIdx, modeIdx );
|
|
|
|
|
|
// Create and Register the leaderboard with the sys_stats registered Leaderboards
|
|
leaderboardDefinition_t* newLeaderboardDef = Sys_CreateLeaderboardDef( boardID,
|
|
gamemode.numColumns,
|
|
gamemode.columnDef,
|
|
gamemode.rankOrder,
|
|
gamemode.supportsAttachments,
|
|
gamemode.checkAgainstCurrent );
|
|
|
|
|
|
|
|
// Set the leaderboard name.
|
|
const char* mapname = idLocalization::GetString( maps[ mapIdx ].mapName );
|
|
newLeaderboardDef->boardName.Format( "%s %s", mapname, gamemode.abrevName );
|
|
|
|
// sanity check.
|
|
if( Sys_FindLeaderboardDef( boardID ) != newLeaderboardDef )
|
|
{
|
|
idLib::Error( "Leaderboards_Init leaderboard creation failed" );
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
=====================================
|
|
LeaderboardLocal_Shutdown
|
|
=====================================
|
|
*/
|
|
void LeaderboardLocal_Shutdown()
|
|
{
|
|
|
|
Sys_DestroyLeaderboardDefs();
|
|
}
|
|
|
|
/*
|
|
=====================================
|
|
LeaderboardLocal_Upload
|
|
=====================================
|
|
*/
|
|
|
|
const static int FRAG_MULTIPLIER = 100;
|
|
const static int DEATH_MULTIPLIER = -50;
|
|
const static int WINS_MULTIPLIER = 20;
|
|
|
|
void LeaderboardLocal_Upload( lobbyUserID_t lobbyUserID, int gameType, leaderboardStats_t& stats )
|
|
{
|
|
assert( gameType > GAME_RANDOM );
|
|
|
|
int mapIdx = 0;
|
|
|
|
// Need to figure out What stat columns we want to base rank on. ( for now we'll use wins )
|
|
const column_t* gameTypeColumn = NULL;
|
|
const column_t defaultStats[] = { stats.wins };
|
|
|
|
// calculate DM score.
|
|
int dmScore = stats.frags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * WINS_MULTIPLIER ;
|
|
// TODO: Once leaderboard menu has correct columns- enable this -> const column_t dmStats[] = { stats.frags, stats.deaths, stats.wins, dmScore };
|
|
const column_t dmStats[] = { dmScore };
|
|
|
|
// Calculate TDM score.
|
|
int tdmScore = stats.frags * FRAG_MULTIPLIER + stats.teamfrags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * WINS_MULTIPLIER ;
|
|
const column_t tdmStats[] = { tdmScore };
|
|
|
|
// Calculate Tourney score.
|
|
int tourneyScore = stats.wins;
|
|
const column_t tnyStats[] = { tourneyScore };
|
|
|
|
// Calculate LMS score.
|
|
int lmsFrags = stats.frags;
|
|
if( lmsFrags < 0 )
|
|
{
|
|
lmsFrags = 0; // LMS NO LIVES LEFT = -20 on fragCount.
|
|
}
|
|
|
|
int lmsScore = lmsFrags * FRAG_MULTIPLIER + stats.wins * ( WINS_MULTIPLIER * 10 ) ;
|
|
const column_t lmsStats[] = { lmsScore };
|
|
|
|
// Calculate CTF score.
|
|
int ctfScore = stats.frags * FRAG_MULTIPLIER + stats.deaths * DEATH_MULTIPLIER + stats.wins * ( WINS_MULTIPLIER * 10 );
|
|
const column_t ctfStats[] = { ctfScore };
|
|
|
|
switch( gameType )
|
|
{
|
|
case GAME_DM:
|
|
gameTypeColumn = dmStats;
|
|
break;
|
|
case GAME_TDM:
|
|
gameTypeColumn = tdmStats;
|
|
break;
|
|
case GAME_TOURNEY:
|
|
gameTypeColumn = tnyStats;
|
|
break;
|
|
case GAME_LASTMAN:
|
|
gameTypeColumn = lmsStats;
|
|
break;
|
|
case GAME_CTF:
|
|
{
|
|
gameTypeColumn = ctfStats;
|
|
break;
|
|
}
|
|
default:
|
|
gameTypeColumn = defaultStats;
|
|
}
|
|
|
|
const idMatchParameters& matchParameters = session->GetActingGameStateLobbyBase().GetMatchParms();
|
|
const idList< mpMap_t > maps = common->GetMapList();
|
|
|
|
// need to find the map Index number
|
|
for( mapIdx = 0; mapIdx < maps.Num(); mapIdx++ )
|
|
{
|
|
if( matchParameters.mapName.Cmp( maps[ mapIdx ].mapFile ) == 0 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
int boardID = LeaderboardLocal_GetID( mapIdx, gameType );
|
|
const leaderboardDefinition_t* board = Sys_FindLeaderboardDef( boardID );
|
|
|
|
if( board )
|
|
{
|
|
session->LeaderboardUpload( lobbyUserID, board, gameTypeColumn );
|
|
}
|
|
else
|
|
{
|
|
idLib::Warning( "LeaderboardLocal_Upload invalid leaderboard with id of %d", boardID );
|
|
}
|
|
}
|
|
|
|
class idLeaderboardCallbackTest : public idLeaderboardCallback
|
|
{
|
|
void Call()
|
|
{
|
|
idLib::Printf( "Leaderboard information retrieved in user callback.\n" );
|
|
idLib::Printf( "%d total entries in leaderboard %d.\n", numRowsInLeaderboard, def->id );
|
|
for( int i = 0; i < rows.Num(); i++ )
|
|
{
|
|
idLib::Printf( "%d: %s rank:%lld", i, rows[i].name.c_str(), rows[i].rank );
|
|
for( int j = 0; j < def->numColumns; j++ )
|
|
{
|
|
idLib::Printf( ", score[%d]: %lld", j, rows[i].columns[j] );
|
|
}
|
|
idLib::Printf( "\n" );
|
|
}
|
|
}
|
|
idLeaderboardCallback* Clone() const
|
|
{
|
|
return new( TAG_PSN ) idLeaderboardCallbackTest( *this );
|
|
}
|
|
};
|
|
|
|
CONSOLE_COMMAND( testLeaderboardDownload, "<id 0 - n > <start = 1> <end = 100>", 0 )
|
|
{
|
|
idLeaderboardCallbackTest leaderboardCallbackTest;
|
|
|
|
int leaderboardID = 0;
|
|
int start = 1;
|
|
int end = 100;
|
|
|
|
if( args.Argc() > 1 )
|
|
{
|
|
leaderboardID = atoi( args.Argv( 1 ) );
|
|
}
|
|
|
|
if( args.Argc() > 2 )
|
|
{
|
|
start = atoi( args.Argv( 2 ) );
|
|
}
|
|
|
|
if( args.Argc() > 3 )
|
|
{
|
|
end = atoi( args.Argv( 3 ) );
|
|
}
|
|
|
|
const leaderboardDefinition_t* leaderboardDef = Sys_FindLeaderboardDef( leaderboardID );
|
|
|
|
if( leaderboardDef )
|
|
{
|
|
session->LeaderboardDownload( 0, leaderboardDef, start, end, leaderboardCallbackTest );
|
|
}
|
|
else
|
|
{
|
|
idLib::Warning( "Sys_FindLeaderboardDef() Unable to find board %d\n", leaderboardID );
|
|
}
|
|
|
|
}
|
|
|
|
CONSOLE_COMMAND( testLeaderboardUpload, "<gameType 0 - 4 > <frags = 0> <wins = 1>", 0 )
|
|
{
|
|
|
|
idLobbyBase& lobby = session->GetActingGameStateLobbyBase();
|
|
lobbyUserID_t user = lobby.GetLobbyUserIdByOrdinal( 0 );
|
|
|
|
gameType_t gameType = GAME_DM;
|
|
int frags = 0;
|
|
int wins = 1;
|
|
|
|
if( args.Argc() > 1 )
|
|
{
|
|
gameType = static_cast<gameType_t>( atoi( args.Argv( 1 ) ) );
|
|
}
|
|
|
|
if( args.Argc() > 2 )
|
|
{
|
|
frags = atoi( args.Argv( 2 ) );
|
|
}
|
|
|
|
if( args.Argc() > 3 )
|
|
{
|
|
wins = atoi( args.Argv( 3 ) );
|
|
}
|
|
|
|
leaderboardStats_t stats = { frags, wins, 0, 0 };
|
|
|
|
LeaderboardLocal_Upload( user, gameType , stats );
|
|
|
|
session->LeaderboardFlush();
|
|
|
|
}
|
|
|
|
|
|
|
|
CONSOLE_COMMAND( testLeaderboardUpload_SendToClients, "<gameType 0 - 4 > <frags = 0> <wins = 1>", 0 )
|
|
{
|
|
|
|
for( int playerIdx = 0; playerIdx < gameLocal.numClients; playerIdx++ )
|
|
{
|
|
|
|
leaderboardStats_t stats = { 1, 1, 1, 1 };
|
|
|
|
LeaderboardLocal_Upload( gameLocal.lobbyUserIDs[ playerIdx ], gameLocal.gameType, stats );
|
|
}
|
|
|
|
// Dont do this more than once.
|
|
session->LeaderboardFlush();
|
|
}
|
|
|