mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
1028 lines
22 KiB
C++
1028 lines
22 KiB
C++
// multiTrackDlg.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "multiTrack.h"
|
|
#include "multiTrackDlg.h"
|
|
#include "waitingDlg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMultiTrackDlg dialog
|
|
|
|
CMultiTrackDlg::CMultiTrackDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CMultiTrackDlg::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CMultiTrackDlg)
|
|
m_info = _T("Ready");
|
|
m_localInfo100 = _T("");
|
|
m_localInfo200 = _T("");
|
|
m_localInfo50 = _T("");
|
|
m_localInfoOverall = _T("");
|
|
m_remoteInfo100 = _T("");
|
|
m_remoteInfo200 = _T("");
|
|
m_remoteInfo50 = _T("");
|
|
m_remoteInfoOverall = _T("");
|
|
//}}AFX_DATA_INIT
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
void CMultiTrackDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CMultiTrackDlg)
|
|
DDX_Control(pDX, IDC_START_100, m_start100);
|
|
DDX_Control(pDX, IDC_START_200, m_start200);
|
|
DDX_Control(pDX, IDC_REMOTE_PROGRESS, m_remoteProgress);
|
|
DDX_Control(pDX, IDC_LOCAL_PROGRESS, m_localProgress);
|
|
DDX_Control(pDX, IDC_START_50, m_start50);
|
|
DDX_Text(pDX, IDC_INFO, m_info);
|
|
DDX_Text(pDX, IDC_LOCAL_INFO_100, m_localInfo100);
|
|
DDX_Text(pDX, IDC_LOCAL_INFO_200, m_localInfo200);
|
|
DDX_Text(pDX, IDC_LOCAL_INFO_50, m_localInfo50);
|
|
DDX_Text(pDX, IDC_LOCAL_INFO_OVERALL, m_localInfoOverall);
|
|
DDX_Text(pDX, IDC_REMOTE_INFO_100, m_remoteInfo100);
|
|
DDX_Text(pDX, IDC_REMOTE_INFO_200, m_remoteInfo200);
|
|
DDX_Text(pDX, IDC_REMOTE_INFO_50, m_remoteInfo50);
|
|
DDX_Text(pDX, IDC_REMOTE_INFO_OVERALL, m_remoteInfoOverall);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CMultiTrackDlg, CDialog)
|
|
//{{AFX_MSG_MAP(CMultiTrackDlg)
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
ON_BN_CLICKED(IDC_LOGOUT, OnLogout)
|
|
ON_WM_DESTROY()
|
|
ON_WM_TIMER()
|
|
ON_BN_CLICKED(IDC_START_50, OnStart50)
|
|
ON_BN_CLICKED(IDC_START_100, OnStart100)
|
|
ON_BN_CLICKED(IDC_START_200, OnStart200)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMultiTrackDlg message handlers
|
|
|
|
#define MSG_CONNECT "is" // client-pid, nick
|
|
#define MSG_CHALLENGE "is" // host-pid, challenge
|
|
#define MSG_CHALLENGE_TYPE 1
|
|
#define MSG_RESPONSE "s" // response
|
|
#define MSG_RESPONSE_TYPE 2
|
|
#define MSG_COUNTDOWN "ii" // event, count
|
|
#define MSG_COUNTDOWN_TYPE 3
|
|
#define MSG_START_RACE ""
|
|
#define MSG_START_RACE_TYPE 5
|
|
#define MSG_PROGRESS "i" // progress
|
|
#define MSG_PROGRESS_TYPE 6
|
|
#define MSG_END_RACE "i" // time
|
|
#define MSG_END_RACE_TYPE 7
|
|
#define MSG_CHAT "s" // message
|
|
#define MSG_CHAT_TYPE 8
|
|
|
|
#define HOST_PORT 38465
|
|
#define HOST_PORT_STRING ":38465"
|
|
#define CLIENT_PORT_STRING ":38446"
|
|
#define COUNTDOWN_START 5
|
|
|
|
#define TIMER_THINK 100
|
|
#define TIMER_COUNTDOWN 101
|
|
|
|
#define DEFRATING 1400
|
|
#define POINTSWIN 16
|
|
#define POINTSLOSS -16
|
|
|
|
CMultiTrackDlg * Dlg;
|
|
|
|
void ConnectedCallback
|
|
(
|
|
GT2Connection connection,
|
|
GT2Result result,
|
|
GT2Byte * message,
|
|
int len
|
|
)
|
|
{
|
|
if(result == GT2Success)
|
|
Dlg->m_state = JOIN_WAITING;
|
|
else
|
|
{
|
|
Dlg->m_state = JOIN_ERROR;
|
|
Dlg->m_connection = NULL;
|
|
}
|
|
}
|
|
|
|
void ReceivedCallback
|
|
(
|
|
GT2Connection connection,
|
|
GT2Byte * message,
|
|
int len,
|
|
GT2Bool reliable
|
|
)
|
|
{
|
|
if(!message || !len)
|
|
return;
|
|
|
|
GTMessageType type;
|
|
|
|
type = gtEncodedMessageType((char*)message);
|
|
|
|
if(type == MSG_CHALLENGE_TYPE)
|
|
{
|
|
ASSERT(!Dlg->m_hosting && (Dlg->m_state == JOIN_WAITING));
|
|
|
|
int pid;
|
|
char challenge[64];
|
|
char response[33];
|
|
if(gtDecode(MSG_CHALLENGE, (char*)message, len, &pid, challenge) == -1)
|
|
{
|
|
Dlg->m_state = JOIN_ERROR;
|
|
return;
|
|
}
|
|
|
|
GenerateAuth(challenge, (char *)(LPCSTR)Dlg->m_loginDlg.m_password, response);
|
|
|
|
// Send the response.
|
|
/////////////////////
|
|
char message[64];
|
|
int rcode;
|
|
rcode = gtEncode(MSG_RESPONSE_TYPE, MSG_RESPONSE, message, sizeof(message), response);
|
|
ASSERT(rcode != -1);
|
|
gt2Send(connection, (const GT2Byte*)message, rcode, GT2True);
|
|
|
|
Dlg->m_remoteProfile = pid;
|
|
Dlg->m_state = JOIN_CONNECTED;
|
|
}
|
|
else if(type == MSG_RESPONSE_TYPE)
|
|
{
|
|
ASSERT(Dlg->m_hosting && (Dlg->m_state == HOST_CHALLENGING));
|
|
|
|
char response[33];
|
|
if(gtDecode(MSG_RESPONSE, (char*)message, len, response) == -1)
|
|
{
|
|
Dlg->m_state = HOST_ERROR;
|
|
return;
|
|
}
|
|
Dlg->m_remoteResponse = response;
|
|
Dlg->m_state = HOST_CONNECTED;
|
|
}
|
|
else if(type == MSG_COUNTDOWN_TYPE)
|
|
{
|
|
ASSERT(!Dlg->m_hosting);
|
|
|
|
if(gtDecode(MSG_COUNTDOWN, (char*)message, len, &Dlg->m_event, &Dlg->m_countdown) == -1)
|
|
{
|
|
Dlg->m_state = JOIN_ERROR;
|
|
return;
|
|
}
|
|
|
|
Dlg->Countdown();
|
|
}
|
|
else if(type == MSG_START_RACE_TYPE)
|
|
{
|
|
ASSERT(!Dlg->m_hosting);
|
|
|
|
Dlg->StartRace();
|
|
}
|
|
else if(type == MSG_PROGRESS_TYPE)
|
|
{
|
|
if(Dlg->m_racing)
|
|
{
|
|
int progress;
|
|
if(gtDecode(MSG_PROGRESS, (char*)message, len, &progress) != -1)
|
|
Dlg->m_remoteProgress.SetPos(progress);
|
|
}
|
|
}
|
|
else if(type == MSG_END_RACE_TYPE)
|
|
{
|
|
if(Dlg->m_racing)
|
|
{
|
|
gtDecode(MSG_END_RACE, (char*)message, len, &Dlg->m_remoteTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClosedCallback
|
|
(
|
|
GT2Connection connection,
|
|
GT2CloseReason reason
|
|
)
|
|
{
|
|
if(reason != GT2LocalClose)
|
|
{
|
|
Dlg->MessageBox("Connection closed");
|
|
Dlg->Logout();
|
|
}
|
|
}
|
|
|
|
void ConnectAttemptCallback
|
|
(
|
|
GT2Socket listener,
|
|
GT2Connection connection,
|
|
unsigned int ip,
|
|
unsigned short port,
|
|
int latency,
|
|
GT2Byte * message,
|
|
int len
|
|
)
|
|
{
|
|
int pid = 0;
|
|
char nick[128];
|
|
|
|
// Only allow one connection.
|
|
/////////////////////////////
|
|
if(Dlg->m_connection)
|
|
{
|
|
gt2Reject(connection, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
// Decode the pid.
|
|
//////////////////
|
|
if(message && len)
|
|
{
|
|
if(gtDecodeNoType(MSG_CONNECT, (char*)message, len, &pid, nick) == -1)
|
|
pid = 0;
|
|
}
|
|
|
|
// If we didn't/couldn't get the pid, reject the attempt.
|
|
/////////////////////////////////////////////////////////
|
|
if(!pid)
|
|
{
|
|
gt2Reject(connection, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
// Accept the connection.
|
|
/////////////////////////
|
|
GT2ConnectionCallbacks callbacks;
|
|
memset(&callbacks, 0, sizeof(GT2ConnectionCallbacks));
|
|
callbacks.received = ReceivedCallback;
|
|
callbacks.closed = ClosedCallback;
|
|
if(!gt2Accept(connection, &callbacks))
|
|
return;
|
|
|
|
// Set some states.
|
|
///////////////////
|
|
Dlg->m_remoteProfile = pid;
|
|
Dlg->m_connection = connection;
|
|
Dlg->m_state = HOST_CHALLENGING;
|
|
Dlg->m_challenged = FALSE;
|
|
Dlg->m_remoteNick = nick;
|
|
}
|
|
|
|
/*void StoppedCallback
|
|
(
|
|
GTListener listener,
|
|
GTStopReason reason
|
|
)
|
|
{
|
|
if(reason != GTStopped)
|
|
{
|
|
Dlg->MessageBox("Listener stopped");
|
|
Dlg->Logout();
|
|
}
|
|
}*/
|
|
|
|
void SocketErrorCallback
|
|
(
|
|
GT2Socket socket
|
|
)
|
|
{
|
|
Dlg->MessageBox("Socket Error!");
|
|
Dlg->Logout();
|
|
}
|
|
|
|
BOOL CMultiTrackDlg::SetupHosting()
|
|
{
|
|
int rcode;
|
|
CString str;
|
|
|
|
if(!IsStatsConnected())
|
|
{
|
|
// Use the development system.
|
|
//////////////////////////////
|
|
strcpy(StatsServerHostname, "sdkdev.gamespy.com");
|
|
|
|
// Set the gamename and secret key.
|
|
///////////////////////////////////
|
|
strcpy(gcd_gamename, "st_rank");
|
|
gcd_secret_key[0] = '5';
|
|
gcd_secret_key[1] = '3';
|
|
gcd_secret_key[2] = 'J';
|
|
gcd_secret_key[3] = 'x';
|
|
gcd_secret_key[4] = '7';
|
|
gcd_secret_key[5] = 'W';
|
|
|
|
// Init the connection to the backend.
|
|
//////////////////////////////////////
|
|
rcode = InitStatsConnection(0);
|
|
if(rcode != GE_NOERROR)
|
|
{
|
|
str.Format("Failed to connect to the stats server (%d).", rcode);
|
|
MessageBox(str);
|
|
PostQuitMessage(1);
|
|
return TRUE;
|
|
}
|
|
|
|
// Get the challenge.
|
|
/////////////////////
|
|
m_challenge = GetChallenge(NULL);
|
|
}
|
|
|
|
/*
|
|
// Setup the listener's callbacks.
|
|
//////////////////////////////////
|
|
GTListenerCallbacks callbacks;
|
|
memset(&callbacks, 0, sizeof(GTListenerCallbacks));
|
|
callbacks.connectAttempt = ConnectAttemptCallback;
|
|
callbacks.stopped = StoppedCallback;
|
|
|
|
// Create the listener.
|
|
///////////////////////
|
|
m_listener = gtListen(gtAddressToString(0, HOST_PORT, NULL), &callbacks);
|
|
if(!m_listener)
|
|
return FALSE;
|
|
*/
|
|
|
|
GT2ConnectionCallbacks connectionCallbacks;
|
|
memset(&connectionCallbacks, 0, sizeof(GT2ConnectionCallbacks));
|
|
connectionCallbacks.received = ReceivedCallback;
|
|
connectionCallbacks.closed = ClosedCallback;
|
|
|
|
GT2Result aResult = gt2CreateSocket(&m_socket, HOST_PORT_STRING, 0, 0, SocketErrorCallback);
|
|
if (GT2Success != aResult)
|
|
return FALSE;
|
|
|
|
gt2Listen(m_socket, ConnectAttemptCallback);
|
|
|
|
m_state = HOST_LISTENING;
|
|
|
|
// Bring up the "waiting" dialog.
|
|
/////////////////////////////////
|
|
rcode = m_waitingDlg.DoModal();
|
|
|
|
// If it was cancelled, try again.
|
|
//////////////////////////////////
|
|
if(rcode != IDOK)
|
|
Logout();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CMultiTrackDlg::SetupJoining()
|
|
{
|
|
int rcode;
|
|
|
|
// Setup the address to connect to.
|
|
///////////////////////////////////
|
|
CString remoteAddress;
|
|
remoteAddress.Format("%s:%d", m_hostOrJoinDlg.m_joinAddress, HOST_PORT);
|
|
|
|
// Encode the profile id.
|
|
/////////////////////////
|
|
char buffer[64];
|
|
rcode = gtEncodeNoType(MSG_CONNECT, buffer, sizeof(buffer), m_loginDlg.m_profile, m_loginDlg.m_nick);
|
|
ASSERT(rcode != -1);
|
|
|
|
// Setup the callbacks.
|
|
///////////////////////
|
|
GT2ConnectionCallbacks callbacks;
|
|
memset(&callbacks, 0, sizeof(GT2ConnectionCallbacks));
|
|
callbacks.connected = ConnectedCallback;
|
|
callbacks.received = ReceivedCallback;
|
|
callbacks.closed = ClosedCallback;
|
|
|
|
// Create the socket
|
|
GT2Result aResult = gt2CreateSocket(&m_socket, CLIENT_PORT_STRING, 0, 0, SocketErrorCallback);
|
|
if (aResult != GT2Success)
|
|
{
|
|
MessageBox("Failed to create socket!");
|
|
return FALSE;
|
|
}
|
|
|
|
// Connect.
|
|
///////////
|
|
m_state = JOIN_CONNECTING;
|
|
aResult = gt2Connect(m_socket, &m_connection, remoteAddress, (const GT2Byte*)buffer, sizeof(buffer), -1, &callbacks, GT2False);
|
|
if(!m_connection)
|
|
return FALSE;
|
|
|
|
// Bring up the "waiting" dialog.
|
|
/////////////////////////////////
|
|
rcode = m_waitingDlg.DoModal();
|
|
|
|
// If it was cancelled, try again.
|
|
//////////////////////////////////
|
|
if(rcode != IDOK)
|
|
Logout();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CMultiTrackDlg::UpdateRatingsDisplay()
|
|
{
|
|
Dlg->UpdateData();
|
|
|
|
m_localInfoOverall.Format("%d", m_localRatings[0]);
|
|
m_localInfo50.Format("%d", m_localRatings[1]);
|
|
m_localInfo100.Format("%d", m_localRatings[2]);
|
|
m_localInfo200.Format("%d", m_localRatings[3]);
|
|
|
|
m_remoteInfoOverall.Format("%d", m_remoteRatings[0]);
|
|
m_remoteInfo50.Format("%d", m_remoteRatings[1]);
|
|
m_remoteInfo100.Format("%d", m_remoteRatings[2]);
|
|
m_remoteInfo200.Format("%d", m_remoteRatings[3]);
|
|
|
|
Dlg->UpdateData(FALSE);
|
|
}
|
|
|
|
GHTTPBool PlayerRatingsPageCompleted
|
|
(
|
|
GHTTPRequest request,
|
|
GHTTPResult result,
|
|
char * buffer,
|
|
__int64 bufferLen,
|
|
void * param
|
|
)
|
|
{
|
|
if(result == GHTTPSuccess)
|
|
{
|
|
BOOL localPlayer = (BOOL)param;
|
|
int ratings[4];
|
|
int rcode;
|
|
|
|
// Scan out ratings.
|
|
////////////////////
|
|
rcode = sscanf(buffer, "%d %d %d %d", &ratings[0], &ratings[1], &ratings[2], &ratings[3]);
|
|
if(rcode == 4)
|
|
{
|
|
if(localPlayer)
|
|
memcpy(Dlg->m_localRatings, ratings, sizeof(int) * 4);
|
|
else
|
|
memcpy(Dlg->m_remoteRatings, ratings, sizeof(int) * 4);
|
|
|
|
Dlg->UpdateRatingsDisplay();
|
|
}
|
|
}
|
|
|
|
return GHTTPTrue;
|
|
}
|
|
|
|
BOOL CMultiTrackDlg::SetupMatch()
|
|
{
|
|
int rcode;
|
|
BOOL result;
|
|
|
|
m_state = SETTING_UP;
|
|
|
|
ASSERT(!m_connection);
|
|
ASSERT(!m_socket);
|
|
|
|
m_state = 0;
|
|
m_remoteResponse.Empty();
|
|
m_remoteProfile = 0;
|
|
m_connection = NULL;
|
|
m_start50.EnableWindow(FALSE);
|
|
m_start100.EnableWindow(FALSE);
|
|
m_start200.EnableWindow(FALSE);
|
|
m_start = 0;
|
|
m_countdown = 0;
|
|
m_racing = FALSE;
|
|
m_event = EVENT_NONE;
|
|
m_numSteps = 0;
|
|
m_step = NONE;
|
|
|
|
do
|
|
{
|
|
// Login the user (actually just verifying the login).
|
|
//////////////////////////////////////////////////////
|
|
rcode = m_loginDlg.DoModal();
|
|
if(rcode != IDOK)
|
|
{
|
|
PostQuitMessage(1);
|
|
return FALSE;
|
|
}
|
|
|
|
// See if they want to host or join.
|
|
////////////////////////////////////
|
|
rcode = m_hostOrJoinDlg.DoModal();
|
|
}
|
|
while(rcode != IDOK);
|
|
|
|
m_connection = NULL;
|
|
m_hosting = (m_hostOrJoinDlg.m_hostOrJoin == HOSTORJOIN_HOST);
|
|
|
|
CString str;
|
|
str.Format("multiTrack%s", m_hosting?" (hosting)":"");
|
|
SetWindowText(str);
|
|
|
|
if(m_hosting)
|
|
result = SetupHosting();
|
|
else
|
|
result = SetupJoining();
|
|
|
|
if(result && m_hosting)
|
|
{
|
|
m_start50.EnableWindow();
|
|
m_start100.EnableWindow();
|
|
m_start200.EnableWindow();
|
|
}
|
|
|
|
CString url;
|
|
url.Format("http://sdkdev.gamespy.com/games/st_rank/web/playerratings.asp?pid=%d", m_loginDlg.m_profile);
|
|
ghttpGet(url, GHTTPFalse, PlayerRatingsPageCompleted, (void *)TRUE);
|
|
url.Format("http://sdkdev.gamespy.com/games/st_rank/web/playerratings.asp?pid=%d", m_remoteProfile);
|
|
ghttpGet(url, GHTTPFalse, PlayerRatingsPageCompleted, (void *)FALSE);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL CMultiTrackDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
SetIcon(m_hIcon, TRUE);
|
|
SetIcon(m_hIcon, FALSE);
|
|
|
|
// Basic initialization.
|
|
////////////////////////
|
|
Dlg = this;
|
|
m_connection = NULL;
|
|
m_socket = NULL;
|
|
m_state = LOGGED_OUT;
|
|
m_countdown = 0;
|
|
m_racing = FALSE;
|
|
|
|
// Init gt.
|
|
///////////
|
|
//gt2Startup();
|
|
|
|
// Set a think timer.
|
|
/////////////////////
|
|
SetTimer(TIMER_THINK, 50, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CMultiTrackDlg::OnPaint()
|
|
{
|
|
if (IsIconic())
|
|
{
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
|
|
|
|
// Center icon in client rectangle
|
|
int cxIcon = GetSystemMetrics(SM_CXICON);
|
|
int cyIcon = GetSystemMetrics(SM_CYICON);
|
|
CRect rect;
|
|
GetClientRect(&rect);
|
|
int x = (rect.Width() - cxIcon + 1) / 2;
|
|
int y = (rect.Height() - cyIcon + 1) / 2;
|
|
|
|
// Draw the icon
|
|
dc.DrawIcon(x, y, m_hIcon);
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnPaint();
|
|
}
|
|
}
|
|
|
|
HCURSOR CMultiTrackDlg::OnQueryDragIcon()
|
|
{
|
|
return (HCURSOR) m_hIcon;
|
|
}
|
|
|
|
void CMultiTrackDlg::OnLogout()
|
|
{
|
|
m_state = LOGGED_OUT;
|
|
|
|
// Clean stuff up.
|
|
//////////////////
|
|
if(m_connection)
|
|
{
|
|
gt2CloseConnection(m_connection);
|
|
m_connection = NULL;
|
|
}
|
|
if(m_socket)
|
|
{
|
|
gt2CloseSocket(m_socket);
|
|
m_socket = NULL;
|
|
}
|
|
if(m_waitingDlg.m_hWnd && m_waitingDlg.IsWindowEnabled())
|
|
{
|
|
m_waitingDlg.EndDialog(IDCANCEL);
|
|
}
|
|
}
|
|
|
|
void CMultiTrackDlg::OnDestroy()
|
|
{
|
|
CDialog::OnDestroy();
|
|
|
|
if(IsStatsConnected())
|
|
CloseStatsConnection();
|
|
|
|
ghttpCleanup();
|
|
|
|
//gt2Cleanup(GT2False);
|
|
if (m_connection)
|
|
{
|
|
gt2CloseConnection(m_connection);
|
|
m_connection = NULL;
|
|
}
|
|
if (m_socket)
|
|
{
|
|
gt2CloseSocket(m_socket);
|
|
m_socket = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
int CalculateHandicap(int rating1, int rating2)
|
|
{
|
|
static int htable[] = { 12, 34, 56, 78, 101, 126, 151, 177, 206, 239, 273, 315, 366, 446, 471, 715 };
|
|
int diff;
|
|
int i;
|
|
|
|
diff = abs(rating1 - rating2);
|
|
|
|
for(i = 0 ; i < 16 ; i++)
|
|
{
|
|
if(diff < htable[i])
|
|
return i;
|
|
}
|
|
|
|
return 16;
|
|
}
|
|
|
|
void CMultiTrackDlg::UpdateStats()
|
|
{
|
|
int handicap;
|
|
|
|
handicap = CalculateHandicap(m_localRatings[0], m_remoteRatings[0]);
|
|
if(handicap)
|
|
{
|
|
if(m_localRatings[0] > m_remoteRatings[0])
|
|
{
|
|
m_localRatings[0] -= handicap;
|
|
m_remoteRatings[0] += handicap;
|
|
}
|
|
else
|
|
{
|
|
m_localRatings[0] += handicap;
|
|
m_remoteRatings[0] -= handicap;
|
|
}
|
|
}
|
|
|
|
handicap = CalculateHandicap(m_localRatings[m_event], m_remoteRatings[m_event]);
|
|
if(handicap)
|
|
{
|
|
if(m_localRatings[m_event] > m_remoteRatings[m_event])
|
|
{
|
|
m_localRatings[m_event] -= handicap;
|
|
m_remoteRatings[m_event] += handicap;
|
|
}
|
|
else
|
|
{
|
|
m_localRatings[m_event] += handicap;
|
|
m_remoteRatings[m_event] -= handicap;
|
|
}
|
|
}
|
|
|
|
if(m_localTime < m_remoteTime)
|
|
{
|
|
m_localRatings[0] += POINTSWIN;
|
|
m_localRatings[m_event] += POINTSWIN;
|
|
m_remoteRatings[0] += POINTSLOSS;
|
|
m_remoteRatings[m_event] += POINTSLOSS;
|
|
}
|
|
else if(m_remoteTime < m_localTime)
|
|
{
|
|
m_remoteRatings[0] += POINTSWIN;
|
|
m_remoteRatings[m_event] += POINTSWIN;
|
|
m_localRatings[0] += POINTSLOSS;
|
|
m_localRatings[m_event] += POINTSLOSS;
|
|
}
|
|
|
|
UpdateRatingsDisplay();
|
|
}
|
|
|
|
void CMultiTrackDlg::OnTimer(UINT nIDEvent)
|
|
{
|
|
char buffer[64];
|
|
int rcode;
|
|
|
|
if(nIDEvent == TIMER_THINK)
|
|
{
|
|
static BOOL thinking;
|
|
|
|
if(!thinking)
|
|
{
|
|
thinking = TRUE;
|
|
|
|
if (m_socket)
|
|
gt2Think(m_socket);
|
|
ghttpThink();
|
|
|
|
if(m_state == HOST_CHALLENGING)
|
|
{
|
|
if(!m_challenged)
|
|
{
|
|
// Send the challenge string and our profile.
|
|
/////////////////////////////////////////////
|
|
rcode = gtEncode(MSG_CHALLENGE_TYPE, MSG_CHALLENGE, buffer, sizeof(buffer), m_loginDlg.m_profile, (LPCSTR)m_challenge);
|
|
ASSERT(rcode != -1);
|
|
gt2Send(m_connection, (const unsigned char*)buffer, rcode, GT2True);
|
|
m_challenged = TRUE;
|
|
}
|
|
}
|
|
else if(m_state == HOST_CONNECTED)
|
|
{
|
|
m_waitingDlg.EndDialog(IDOK);
|
|
m_state = RACING;
|
|
}
|
|
else if(m_state == HOST_ERROR)
|
|
{
|
|
MessageBox("Error setting up hosting");
|
|
m_waitingDlg.EndDialog(IDCANCEL);
|
|
}
|
|
else if(m_state == JOIN_CONNECTED)
|
|
{
|
|
if(m_waitingDlg.m_hWnd && m_waitingDlg.IsWindowEnabled())
|
|
m_waitingDlg.EndDialog(IDOK);
|
|
}
|
|
else if(m_state == JOIN_ERROR)
|
|
{
|
|
MessageBox("Error joining a game");
|
|
m_waitingDlg.EndDialog(IDCANCEL);
|
|
}
|
|
|
|
thinking = FALSE;
|
|
}
|
|
|
|
if(m_state == LOGGED_OUT)
|
|
{
|
|
if(!Dlg->SetupMatch())
|
|
{
|
|
MessageBox("Error setting up the match");
|
|
Logout();
|
|
}
|
|
}
|
|
|
|
// Are we racing?
|
|
/////////////////
|
|
if(m_racing)
|
|
{
|
|
// Did we finish?
|
|
/////////////////
|
|
if(m_localTime)
|
|
{
|
|
// Did we both finish?
|
|
//////////////////////
|
|
if(m_remoteTime)
|
|
{
|
|
// Done racing.
|
|
///////////////
|
|
m_racing = FALSE;
|
|
|
|
// Show the times.
|
|
//////////////////
|
|
CString message;
|
|
if(m_localTime < m_remoteTime)
|
|
message.Format("You won!\n%0.3fs to %0.3fs", m_localTime / 1000.0, m_remoteTime / 1000.0);
|
|
else if(m_remoteTime < m_localTime)
|
|
message.Format("You lost!\n%0.3fs to %0.3fs", m_localTime / 1000.0, m_remoteTime / 1000.0);
|
|
else
|
|
message.Format("You tied!\n%0.3fs", m_localTime / 1000.0);
|
|
MessageBox(message);
|
|
|
|
m_localProgress.SetPos(0);
|
|
m_remoteProgress.SetPos(0);
|
|
|
|
// Report the stats.
|
|
////////////////////
|
|
if(m_hosting)
|
|
ReportStats();
|
|
|
|
m_event = EVENT_NONE;
|
|
|
|
UpdateStats();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Let our opponent know how far we are.
|
|
////////////////////////////////////////
|
|
rcode = gtEncode(MSG_PROGRESS_TYPE, MSG_PROGRESS, buffer, sizeof(buffer), m_numSteps);
|
|
ASSERT(rcode != -1);
|
|
gt2Send(m_connection, (const GT2Byte*)buffer, rcode, GT2False);
|
|
}
|
|
}
|
|
}
|
|
else if(nIDEvent == TIMER_COUNTDOWN)
|
|
{
|
|
m_countdown--;
|
|
if(m_countdown <= 0)
|
|
KillTimer(TIMER_COUNTDOWN);
|
|
|
|
if(m_countdown < 0)
|
|
return;
|
|
|
|
Countdown();
|
|
if(!m_countdown)
|
|
StartRace();
|
|
}
|
|
|
|
CDialog::OnTimer(nIDEvent);
|
|
}
|
|
|
|
void CMultiTrackDlg::Logout()
|
|
{
|
|
OnLogout();
|
|
}
|
|
|
|
void CMultiTrackDlg::Countdown()
|
|
{
|
|
if(m_hosting)
|
|
{
|
|
int rcode;
|
|
char message[32];
|
|
rcode = gtEncode(MSG_COUNTDOWN_TYPE, MSG_COUNTDOWN, message, sizeof(message), m_event, m_countdown);
|
|
ASSERT(rcode != -1);
|
|
gt2Send(m_connection, (const GT2Byte*)message, rcode, GT2True);
|
|
}
|
|
|
|
if(m_countdown)
|
|
{
|
|
UpdateData();
|
|
|
|
CString strEvent;
|
|
if(m_event == EVENT_50)
|
|
strEvent = "50m";
|
|
else if(m_event == EVENT_100)
|
|
strEvent = "100m";
|
|
else if(m_event == EVENT_200)
|
|
strEvent = "200m";
|
|
m_info.Format("%s starts in %ds", strEvent, m_countdown);
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
void CMultiTrackDlg::OnStart50()
|
|
{
|
|
// Start the countdown.
|
|
///////////////////////
|
|
m_countdown = COUNTDOWN_START;
|
|
SetTimer(TIMER_COUNTDOWN, 1000, NULL);
|
|
m_event = EVENT_50;
|
|
Countdown();
|
|
}
|
|
|
|
void CMultiTrackDlg::OnStart100()
|
|
{
|
|
// Start the countdown.
|
|
///////////////////////
|
|
m_countdown = COUNTDOWN_START;
|
|
SetTimer(TIMER_COUNTDOWN, 1000, NULL);
|
|
m_event = EVENT_100;
|
|
Countdown();
|
|
}
|
|
|
|
void CMultiTrackDlg::OnStart200()
|
|
{
|
|
// Start the countdown.
|
|
///////////////////////
|
|
m_countdown = COUNTDOWN_START;
|
|
SetTimer(TIMER_COUNTDOWN, 1000, NULL);
|
|
m_event = EVENT_200;
|
|
Countdown();
|
|
}
|
|
|
|
BOOL CMultiTrackDlg::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if(pMsg->message == WM_KEYDOWN)
|
|
{
|
|
int nChar = pMsg->wParam;
|
|
if((nChar == 'Z') || (nChar == 'X'))
|
|
{
|
|
if((pMsg->lParam & 0xFFFF) == 1)
|
|
{
|
|
CString str;
|
|
BOOL stepped = FALSE;
|
|
|
|
if((nChar == 'Z') && (m_step != LEFT))
|
|
{
|
|
m_step = LEFT;
|
|
m_numSteps++;
|
|
stepped = TRUE;
|
|
}
|
|
else if ((nChar == 'X') && (m_step != RIGHT))
|
|
{
|
|
m_step = RIGHT;
|
|
m_numSteps++;
|
|
stepped = TRUE;
|
|
}
|
|
|
|
if(stepped && m_racing)
|
|
{
|
|
m_localProgress.SetPos(m_numSteps);
|
|
if(m_numSteps == m_totalSteps)
|
|
{
|
|
m_localTime = (GetTickCount() - m_start);
|
|
str.Format("%0.3fs\n", m_localTime / 1000.0);
|
|
OutputDebugString(str);
|
|
//MessageBox(str);
|
|
|
|
UpdateData();
|
|
|
|
m_info = "Race Complete";
|
|
|
|
// Let them know we finished.
|
|
/////////////////////////////
|
|
char buffer[32];
|
|
int rcode;
|
|
rcode = gtEncode(MSG_END_RACE_TYPE, MSG_END_RACE, buffer, sizeof(buffer), m_localTime);
|
|
ASSERT(rcode != -1);
|
|
gt2Send(m_connection, (const GT2Byte*)buffer, rcode, GT2True);
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return CDialog::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CMultiTrackDlg::StartRace()
|
|
{
|
|
if(m_hosting)
|
|
{
|
|
int rcode;
|
|
char buffer[32];
|
|
rcode = gtEncode(MSG_START_RACE_TYPE, MSG_START_RACE, buffer, sizeof(buffer));
|
|
ASSERT(rcode != -1);
|
|
gt2Send(m_connection, (const GT2Byte*)buffer, rcode, GT2True);
|
|
}
|
|
|
|
m_localTime = 0;
|
|
m_remoteTime = 0;
|
|
m_racing = TRUE;
|
|
m_numSteps = 0;
|
|
m_step = NONE;
|
|
m_racing = TRUE;
|
|
m_start = GetTickCount();
|
|
if(m_event == EVENT_50)
|
|
m_totalSteps = RACE_STEPS_50;
|
|
else if(m_event == EVENT_100)
|
|
m_totalSteps = RACE_STEPS_100;
|
|
else if(m_event == EVENT_200)
|
|
m_totalSteps = RACE_STEPS_200;
|
|
m_localProgress.SetRange(0, m_totalSteps);
|
|
m_localProgress.SetPos(0);
|
|
m_remoteProgress.SetRange(0, m_totalSteps);
|
|
m_remoteProgress.SetPos(0);
|
|
|
|
UpdateData();
|
|
m_info.Format("GO!");
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CMultiTrackDlg::ReportStats()
|
|
{
|
|
char response[33];
|
|
|
|
// Game.
|
|
////////
|
|
NewGame(1);
|
|
BucketStringOp(NULL, "hostname", bo_set, (char *)(LPCSTR)m_loginDlg.m_nick, bl_server, 0);
|
|
BucketIntOp(NULL, "event", bo_set, m_event, bl_server, 0);
|
|
|
|
// Local player (host).
|
|
///////////////////////
|
|
NewPlayer(NULL, 0, (char *)(LPCSTR)m_loginDlg.m_nick);
|
|
BucketIntOp(NULL, "time", bo_set, m_localTime, bl_player, 0);
|
|
BucketIntOp(NULL, "pid", bo_set, m_loginDlg.m_profile, bl_player, 0);
|
|
GenerateAuth((char *)(LPCSTR)m_challenge, (char *)(LPCSTR)m_loginDlg.m_password, response);
|
|
BucketStringOp(NULL, "auth", bo_set, response, bl_player, 0);
|
|
|
|
// Remote player (joined).
|
|
//////////////////////////
|
|
NewPlayer(NULL, 1, (char *)(LPCSTR)m_remoteNick);
|
|
BucketIntOp(NULL, "time", bo_set, m_remoteTime, bl_player, 1);
|
|
BucketIntOp(NULL, "pid", bo_set, m_remoteProfile, bl_player, 1);
|
|
BucketStringOp(NULL, "auth", bo_set, (char *)(LPCSTR)m_remoteResponse, bl_player, 1);
|
|
|
|
SendGameSnapShot(NULL, NULL, SNAP_FINAL);
|
|
FreeGame(NULL);
|
|
}
|