This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/GameResSend.cpp

416 lines
12 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Commando/GameResSend.cpp $
*
* DESCRIPTION
*
* PROGRAMMER
* $Author: Denzil_l $
*
* VERSION INFO
* $Revision: 25 $
* $Modtime: 1/14/02 10:40a $
*
******************************************************************************/
#include "GameResSend.h"
#include "GameData.h"
#include "Player.h"
#include "consolemode.h"
#include <Combat\PlayerType.h>
#include <WWOnline\GameResPacket.h>
#include <WWOnline\WOLSession.h>
#include <WWOnline\WOLProduct.h>
#include <WWOnline\WOLUser.h>
#include <WWLib\CPUDetect.h>
#include <WWLib\VerChk.h>
#include <WWLib\CPUDetect.h>
#include <WWLib\global.h>
#include <WWLib\md5.h>
#include <WW3D2\DX8Wrapper.h>
#include <windows.h>
using namespace WWOnline;
static void AddPlayerStats(GameResPacket& stats, cPlayer* player, WOL::Locale locale,
int winnerID, bool teamGame);
/******************************************************************************
*
* NAME
* SendGameResults
*
* DESCRIPTION
* Send game results for ladder ranking.
*
* INPUTS
* TheGame - The game played.
* Players - List of players.
*
* RESULT
* NONE
*
******************************************************************************/
void SendGameResults(unsigned long gameID, cGameData* theGame, SList<cPlayer>* playerList)
{
RefPtr<WWOnline::Session> session = WWOnline::Session::GetInstance(false);
if (!session.IsValid())
{
assert(session.IsValid() && "SendGameResults() WOLSession not instantiated.");
WWDEBUG_SAY(("ERROR: SendGameResults() WOLSession not instantiated.\n"));
return;
}
//---------------------------------------------------------------------------
// Gather game information
//---------------------------------------------------------------------------
GameResPacket stats;
// Unique identifier for this game session.
stats.Add_Field("IDNO", gameID);
// Product SKU
RefPtr<Product> product = Product::Current();
unsigned long gameSKU = product->GetSKU();
stats.Add_Field("GSKU", gameSKU);
// Version of executable.
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, sizeof(filename));
VS_FIXEDFILEINFO version;
GetVersionInfo(filename, &version);
stats.Add_Field("VERS", version.dwFileVersionMS);
// Executable build date
FILETIME createTime;
GetFileCreationTime(filename, &createTime);
SYSTEMTIME time;
FileTimeToSystemTime(&createTime, &time);
char buildDate[20];
sprintf(buildDate, "%02d/%02d/%04d %02d:%02d:%02d",
time.wMonth, time.wDay, time.wYear, time.wHour, time.wMinute, time.wSecond);
stats.Add_Field("DATE", buildDate);
// Proocessor information
stats.Add_Field("PROC", (char*)CPUDetectClass::Get_Processor_String());
stats.Add_Field("PSPD", (unsigned long)CPUDetectClass::Get_Processor_Speed());
// Amount of system memory on server
MEMORYSTATUS memStatus;
GlobalMemoryStatus(&memStatus);
stats.Add_Field("SMEM", (unsigned long)memStatus.dwTotalPhys);
// Video card information
DWORD cardInfo[4];
if (ConsoleBox.Is_Exclusive()) {
strcpy((char*)&cardInfo[0], "ConsoleMode");
} else {
const D3DADAPTER_IDENTIFIER8& adapter = DX8Wrapper::Get_Current_Adapter_Identifier();
cardInfo[0] = adapter.VendorId;
cardInfo[1] = adapter.DeviceId;
cardInfo[2] = adapter.SubSysId;
cardInfo[3] = adapter.Revision;
}
stats.Add_Field("SVID", (void*)cardInfo, sizeof(cardInfo));
// WOL Name of server
const WideStringClass& owner = theGame->Get_Owner();
StringClass serverName(true);
owner.Convert_To(serverName);
stats.Add_Field("SNAM", (char*)serverName.Peek_Buffer());
// Type of game played (Deathmatch, Capture the flag, CNC...)
// char* gameMode = (char*)theGame->Get_Game_Type_Name();
stats.Add_Field("MODE", "CNC");
// Name of the map used.
char *map_name = (char*)(theGame->Get_Map_Name().Peek_Buffer());
stats.Add_Field("GMAP", map_name);
// Was this a dedicated server?
bool dedicatedServer = theGame->IsDedicated.Get();
stats.Add_Field("DSVR", (char)dedicatedServer);
// Time game started
LPSYSTEMTIME gameTime = theGame->Get_Game_Start_Time();
char startTime[20];
sprintf(startTime, "%02d/%02d/%04d %02d:%02d:%02d",
gameTime->wMonth, gameTime->wDay, gameTime->wYear, gameTime->wHour, gameTime->wMinute, gameTime->wSecond);
stats.Add_Field("TIME", startTime);
// Duration of game
unsigned long duration = theGame->Get_Duration_Seconds();
stats.Add_Field("DURA", duration);
// Average FPS
unsigned long fps = theGame->Get_Frame_Count();
if (duration > 1)
{
fps = (fps / duration);
}
stats.Add_Field("AFPS", fps);
// Type of tournament
/*
char gameType = 'I';
if (theGame->Is_Team_Game())
{
gameType = 'T';
}
*/
char gameType = 'T';
if (theGame->IsClanGame.Is_True())
{
gameType = 'C';
}
char ranked = (theGame->IsLaddered.Is_True() == true) ? 'Y' : 'N';
char tournament[5];
sprintf(tournament, "%c%c ", gameType, ranked);
stats.Add_Field("TRNY", tournament);
// Include clan information
if (theGame->IsClanGame.Is_True())
{
unsigned long winningClan = 0;
unsigned long losingClan = 0;
int winner = theGame->Get_Winner_ID();
SLNode<cPlayer>* playerNode = playerList->Head();
for (int index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player->Is_Human())
{
RefPtr<UserData> user = session->FindUser(player->Get_Name());
if (user.IsValid() && (user->GetSquadID() != 0))
{
int playerType = player->Get_Player_Type();
if ((playerType == winner) && (winningClan == 0))
{
winningClan = user->GetSquadID();
}
else if (losingClan == 0)
{
losingClan = user->GetSquadID();
}
else
{
break;
}
}
}
}
stats.Add_Field("CLN1", winningClan);
stats.Add_Field("CLN2", losingClan);
}
//---------------------------------------------------------------------------
// Player information
//---------------------------------------------------------------------------
// Determine the number of players in the game
unsigned long numPlayers = 0;
SLNode<cPlayer>* playerNode = playerList->Head();
for (int index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player->Is_Human())
{
numPlayers++;
}
}
stats.Add_Field("PLRS", numPlayers);
// Gather per-player information
int winnerID = theGame->Get_Winner_ID();
playerNode = playerList->Head();
for (index = 0; index < playerList->Get_Count(); index++)
{
cPlayer* player = playerNode->Data();
if (player)
{
const WideStringClass& playerName = player->Get_Name();
// Player Location
WOL::Locale locale = WOL::LOC_UNKNOWN;
RefPtr<UserData> user = session->FindUser((const WCHAR*)playerName);
if (user.IsValid())
{
locale = user->GetLocale();
}
AddPlayerStats(stats, player, locale, winnerID, true);
}
playerNode = playerNode->Next();
}
unsigned long packetSize = 0;
unsigned long sig_offset = 0;
unsigned char* packet = stats.Create_Comms_Packet(packetSize, NULL, sig_offset);
WWDEBUG_SAY(("Sending game results packet. Size = %lu\n", packetSize));
#if(0)
#ifdef _DEBUG
HANDLE file = CreateFile("GameRes.dat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != file)
{
// Write generic contents
DWORD written;
WriteFile(file, packet, packetSize, &written, NULL);
CloseHandle(file);
}
else
{
WWDEBUG_SAY(("Failed to create GameRes.dat file."));
}
#endif
#endif
session->SendGameResults(packet, packetSize);
}
/******************************************************************************
*
* NAME
* AddPlayerStats
*
* DESCRIPTION
*
* INPUTS
* Stats - Game result packet to add player stats to.
* Player - Player to add stats for.
*
* RESULT
* NONE
*
******************************************************************************/
void AddPlayerStats(GameResPacket& stats, cPlayer* player, WOL::Locale locale,
int winnerID, bool isTeamed)
{
if (player->Is_Human())
{
// Players WOL name
const WideStringClass& playerName = player->Get_Name();
char name[10];
int len = wcstombs(name, (const WCHAR*)playerName, 10);
name[len] = 0;
stats.Add_Field("PNAM", name);
stats.Add_Field("PLOC", (unsigned long)locale);
int playerType = player->Get_Player_Type();
// Team (bit 31:win/lose, bits 7-0:team (0 = none, 1 = GDI, 2= NOD)
unsigned long team = 0;
if (isTeamed)
{
if (playerType == PLAYERTYPE_GDI)
{
team = 1;
}
else if (playerType == PLAYERTYPE_NOD)
{
team = 2;
}
}
if ((isTeamed && playerType == winnerID) || (!isTeamed && player->Get_Id() == winnerID))
{
team |= 0x80000000;
}
stats.Add_Field("TEAM", team);
// Score and other information
unsigned long score = (unsigned long)max<int>(player->Get_Score(), 0);
stats.Add_Field("PSCR", score);
stats.Add_Field("PPTS", (long)player->Get_Ladder_Points());
stats.Add_Field("PTIM", (unsigned long)player->Get_Game_Time());
stats.Add_Field("PHLT", (unsigned long)player->Get_Final_Health());
stats.Add_Field("PKIL", (unsigned long)player->Get_Deaths());
stats.Add_Field("EKIL", (unsigned long)player->Get_Enemies_Killed());
stats.Add_Field("AKIL", (unsigned long)player->Get_Allies_Killed());
stats.Add_Field("SHOT", (unsigned long)player->Get_Shots_Fired());
stats.Add_Field("HEDF", (unsigned long)player->Get_Head_Shots());
stats.Add_Field("TORF", (unsigned long)player->Get_Torso_Shots());
stats.Add_Field("ARMF", (unsigned long)player->Get_Arm_Shots());
stats.Add_Field("LEGF", (unsigned long)player->Get_Leg_Shots());
stats.Add_Field("CRTF", (unsigned long)player->Get_Crotch_Shots());
stats.Add_Field("PUPS", (unsigned long)player->Get_Powerups_Collected());
stats.Add_Field("VKIL", (unsigned long)player->Get_Vehiclies_Destroyed());
stats.Add_Field("VTIM", (unsigned long)player->Get_Vehicle_Time());
stats.Add_Field("NKFV", (unsigned long)player->Get_Kills_From_Vehicle());
stats.Add_Field("SQUI", (unsigned long)player->Get_Squishes());
stats.Add_Field("PCRD", (unsigned long)player->Get_Credit_Grant());
stats.Add_Field("BKIL", (unsigned long)player->Get_Building_Destroyed());
stats.Add_Field("HEDR", (unsigned long)player->Get_Head_Hit());
stats.Add_Field("TORR", (unsigned long)player->Get_Torso_Hit());
stats.Add_Field("ARMR", (unsigned long)player->Get_Arm_Hit());
stats.Add_Field("LEGR", (unsigned long)player->Get_Leg_Hit());
stats.Add_Field("CRTR", (unsigned long)player->Get_Crotch_Hit());
stats.Add_Field("FLGC", (unsigned long)0);//no more CTF! (unsigned long)player->Get_Flag_Caps());
// Weapon usage
int numWeapons = min<int>(255, player->Get_Weapon_Fired_Count());
for (int wepIndex = 0; wepIndex < numWeapons; wepIndex++)
{
unsigned long weaponInfo[2] = {0,0};
player->Get_Weapon_Fired(wepIndex, weaponInfo[0], weaponInfo[1]);
char token[5];
sprintf(token, "WP%02X", wepIndex);
stats.Add_Field(token, (void*)weaponInfo, sizeof(weaponInfo));
}
}
}