Skip to content

Commit

Permalink
Added lap counter
Browse files Browse the repository at this point in the history
  • Loading branch information
Electron-x committed Oct 20, 2019
1 parent b8f7c72 commit 9f9a869
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 71 deletions.
187 changes: 123 additions & 64 deletions DoTelemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@
#include "dotelemetry.h"
#include "tmtelemetry.h"

// Forward declarations
BOOL IsRaceBeforeStart(STelemetryData* pTelemetry);
BOOL IsRaceRunning(STelemetryData* pTelemetry);
BOOL IsRaceFinished(STelemetryData* pTelemetry);

// Processing of the telemetry data
void DoTelemetry(STelemetryData* pTelemetry)
{
TCHAR szText[MAX_CONTROLTEXT];
static int nRaceNumber = 0; // Number of attempts
static Nat32 uLapCount = 0; // Current lap
static BOOL bAddFinalColumns = FALSE; // Append some stats after the end of each race

// Static variables for storing values for the statistics:
Expand Down Expand Up @@ -95,9 +101,38 @@ void DoTelemetry(STelemetryData* pTelemetry)
// Race state
if (pTelemetry->Current.Race.State != pTelemetry->Previous.Race.State)
{
// Handle the start of a race (race state changes from "BeforeState" to "Running")
if (pTelemetry->Previous.Race.State == STelemetry::ERaceState_BeforeState &&
pTelemetry->Current.Race.State == STelemetry::ERaceState_Running)
switch (pTelemetry->Current.Race.State)
{
case STelemetry::ERaceState_BeforeState:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceBeforeStart);
break;

case STelemetry::ERaceState_Running:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceRunning);
break;

case STelemetry::ERaceState_Finished:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceFinished);
break;

//case STelemetry::ERaceState_Eliminated:
// StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceEliminated);
// break;

default:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, TEXT(""));
}

// Handle the countdown
if (IsRaceBeforeStart(pTelemetry))
{
// Reset the lap counter
uLapCount = 0;
StatusBar_SetLapCount(hwndStatusBar, SBP_LAPS, uLapCount, pTelemetry->Current.Race.NbLaps);
}

// Handle the start of a race
if (IsRaceRunning(pTelemetry))
{
uTopSpeed = 0;
nNbGearchanges = 0;
Expand All @@ -116,6 +151,10 @@ void DoTelemetry(STelemetryData* pTelemetry)
bIsSlipping = pTelemetry->Current.Vehicle.WheelsIsSliping[0] || pTelemetry->Current.Vehicle.WheelsIsSliping[1] ||
pTelemetry->Current.Vehicle.WheelsIsSliping[2] || pTelemetry->Current.Vehicle.WheelsIsSliping[3];

// Set the lap counter to 1
uLapCount = 1;
StatusBar_SetLapCount(hwndStatusBar, SBP_LAPS, uLapCount, pTelemetry->Current.Race.NbLaps);

// Add a new race to the list-view control and increment the number of attempts
if (ListView_AddRace(hwndListView, nRaceNumber + 1, COLUMN_AUTOFIT) != -1)
nRaceNumber++;
Expand Down Expand Up @@ -158,10 +197,8 @@ void DoTelemetry(STelemetryData* pTelemetry)
}
}

// Handle the end of a race (race state changes from "Running" to "Finished" or "BeforeStart")
if (pTelemetry->Previous.Race.State == STelemetry::ERaceState_Running &&
(pTelemetry->Current.Race.State == STelemetry::ERaceState_Finished ||
pTelemetry->Current.Race.State == STelemetry::ERaceState_BeforeState))
// Handle the end of a race
if (IsRaceFinished(pTelemetry))
{
// Test if the checkpoint count has increased to differ between finished and restart
if (pTelemetry->Current.Race.NbCheckpoints > pTelemetry->Previous.Race.NbCheckpoints)
Expand All @@ -178,29 +215,59 @@ void DoTelemetry(STelemetryData* pTelemetry)
nRaceNumber--;
}

switch (pTelemetry->Current.Race.State)
pTelemetry->Previous.Race.State = pTelemetry->Current.Race.State;
}

// Number of checkpoints
if (pTelemetry->Current.Race.NbCheckpoints != pTelemetry->Previous.Race.NbCheckpoints)
{
// Add the new checkpoint time to the list-view control
Nat32 uCurrentNbCheckpoints = pTelemetry->Current.Race.NbCheckpoints;
if (uCurrentNbCheckpoints > 0 && uCurrentNbCheckpoints <= _countof(pTelemetry->Current.Race.CheckpointTimes) &&
uCurrentNbCheckpoints > uMaxNbCheckpoints)
{
case STelemetry::ERaceState_BeforeState:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceBeforeStart);
break;
if (dwColumns & COL_SECTORTIMES)
ListView_AddSectorTime(hwndListView, nRaceNumber, COLUMN_AUTOFIT, uCurrentNbCheckpoints,
pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 1],
uCurrentNbCheckpoints >= 2 ? pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 2] : 0);

case STelemetry::ERaceState_Running:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceRunning);
break;
if (dwColumns & COL_CHECKPOINTS)
ListView_AddCheckpointTime(hwndListView, nRaceNumber, COLUMN_AUTOFIT, uCurrentNbCheckpoints,
pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 1]);
}

case STelemetry::ERaceState_Finished:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceFinished);
break;
// Update the lap counter after crossing the start/finish line
Nat32 uCurrentLap = uLapCount;
Nat32 uNumberOfLaps = pTelemetry->Current.Race.NbLaps; // Could be zero
Nat32 uCheckpointsPerLap = pTelemetry->Current.Race.NbCheckpointsPerLap; // Always 0 with Trackmania Turbo

if (uCheckpointsPerLap != 0)
{
uCurrentLap = uCurrentNbCheckpoints / uCheckpointsPerLap;
// Correct the lap counter by one, except on restart and when crossing the finish line
if (uCurrentNbCheckpoints != 0 && (uCurrentLap < uNumberOfLaps || uNumberOfLaps == 0))
uCurrentLap++;
// Keep the number of laps driven after the race is over
if (uCurrentLap < uLapCount)
uCurrentLap = uLapCount;
}

if (uCurrentLap != uLapCount)
{
uLapCount = uCurrentLap;
StatusBar_SetLapCount(hwndStatusBar, SBP_LAPS, uLapCount, uNumberOfLaps);
}

//case STelemetry::ERaceState_Eliminated:
// StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, szRaceEliminated);
// break;
// Update the checkpoint counter
_sntprintf(szText, _countof(szText), szNbCheckpoints, uCurrentNbCheckpoints);
StatusBar_SetText(hwndStatusBar, SBP_CHECKPOINTS, szText, TRUE);

default:
StatusBar_SetText(hwndStatusBar, SBP_RACESTATE, TEXT(""));
}
// Here we have to store the highest number of checkpoints per game client so that
// the list is not flooded with data when Maniaplanet and Turbo run simultaneously
if (uCurrentNbCheckpoints > pTelemetry->Previous.Race.NbCheckpoints)
uMaxNbCheckpoints = uCurrentNbCheckpoints;

pTelemetry->Previous.Race.State = pTelemetry->Current.Race.State;
pTelemetry->Previous.Race.NbCheckpoints = uCurrentNbCheckpoints;
}

// Map name
Expand Down Expand Up @@ -237,45 +304,6 @@ void DoTelemetry(STelemetryData* pTelemetry)
pTelemetry->Previous.Race.Time = pTelemetry->Current.Race.Time;
}

// Number of respawns
if (pTelemetry->Current.Race.NbRespawns != pTelemetry->Previous.Race.NbRespawns)
{
_sntprintf(szText, _countof(szText), szNbRespawns, pTelemetry->Current.Race.NbRespawns);
StatusBar_SetText(hwndStatusBar, SBP_RESPAWNS, szText, TRUE);

pTelemetry->Previous.Race.NbRespawns = pTelemetry->Current.Race.NbRespawns;
}

// Number of checkpoints
if (pTelemetry->Current.Race.NbCheckpoints != pTelemetry->Previous.Race.NbCheckpoints)
{
// Add the new checkpoint time to the list-view control
Nat32 uCurrentNbCheckpoints = pTelemetry->Current.Race.NbCheckpoints;
if (uCurrentNbCheckpoints > 0 && uCurrentNbCheckpoints <= _countof(pTelemetry->Current.Race.CheckpointTimes) &&
uCurrentNbCheckpoints > uMaxNbCheckpoints)
{
// BUGBUG: It looks like we can't be sure that the checkpoint time was also already updated!
if (dwColumns & COL_SECTORTIMES)
ListView_AddSectorTime(hwndListView, nRaceNumber, COLUMN_AUTOFIT, uCurrentNbCheckpoints,
pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 1],
uCurrentNbCheckpoints >= 2 ? pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 2] : 0);

if (dwColumns & COL_CHECKPOINTS)
ListView_AddCheckpointTime(hwndListView, nRaceNumber, COLUMN_AUTOFIT, uCurrentNbCheckpoints,
pTelemetry->Current.Race.CheckpointTimes[uCurrentNbCheckpoints - 1]);
}

// Here we have to store the highest number of checkpoints per game client so that
// the list is not flooded with data when Maniaplanet and Turbo run simultaneously
if (uCurrentNbCheckpoints > pTelemetry->Previous.Race.NbCheckpoints)
uMaxNbCheckpoints = uCurrentNbCheckpoints;

_sntprintf(szText, _countof(szText), szNbCheckpoints, uCurrentNbCheckpoints);
StatusBar_SetText(hwndStatusBar, SBP_CHECKPOINTS, szText, TRUE);

pTelemetry->Previous.Race.NbCheckpoints = uCurrentNbCheckpoints;
}

// Speed
if (pTelemetry->Current.Vehicle.SpeedMeter != pTelemetry->Previous.Vehicle.SpeedMeter)
{
Expand Down Expand Up @@ -445,11 +473,17 @@ void DoTelemetry(STelemetryData* pTelemetry)
// Map UID
if (strcmp(pTelemetry->Current.Game.MapId, pTelemetry->Previous.Game.MapId) != 0)
{
// Clear all races after map change
if (strcmp(pTelemetry->Current.Game.MapId, "Unassigned") != 0)
{
// Clear all races after map change
if (ListView_DeleteAllRaces(hwndListView))
nRaceNumber = 0;

// Reset the lap counter
uLapCount = 0;
StatusBar_SetLapCount(hwndStatusBar, SBP_LAPS, uLapCount, pTelemetry->Current.Race.NbLaps);
}

lstrcpynA(pTelemetry->Previous.Game.MapId, pTelemetry->Current.Game.MapId, _countof(pTelemetry->Previous.Game.MapId));
}

Expand Down Expand Up @@ -512,6 +546,8 @@ void InitTelemetryData(STelemetryData* pTelemetry)
pTelemetry->Previous.Race.Time = (Nat32)-2; // -1 is a regular value
pTelemetry->Previous.Race.NbRespawns = (Nat32)-2; // -1 is a regular value
pTelemetry->Previous.Race.NbCheckpoints = (Nat32)-1;
pTelemetry->Previous.Race.NbCheckpointsPerLap = (Nat32)-1;
pTelemetry->Previous.Race.NbLaps = (Nat32)-1;

pTelemetry->Previous.Vehicle.InputSteer = -2.0f; // -1.0 is a regular value
pTelemetry->Previous.Vehicle.InputGasPedal = -1.0f;
Expand All @@ -525,3 +561,26 @@ void InitTelemetryData(STelemetryData* pTelemetry)
pTelemetry->Previous.Vehicle.RumbleIntensity = -1.0f;
pTelemetry->Previous.Vehicle.SpeedMeter = (Nat32)-1;
}

// Checks if the countdown has just started (race state changes from "Finished" or "Running" to "BeforeStart")
__inline BOOL IsRaceBeforeStart(STelemetryData* pTelemetry)
{
return ((pTelemetry->Previous.Race.State == STelemetry::ERaceState_Finished ||
pTelemetry->Previous.Race.State == STelemetry::ERaceState_Running) &&
pTelemetry->Current.Race.State == STelemetry::ERaceState_BeforeState);
}

// Checks if the race has just started (race state changes from "BeforeStart" to "Running")
__inline BOOL IsRaceRunning(STelemetryData* pTelemetry)
{
return (pTelemetry->Previous.Race.State == STelemetry::ERaceState_BeforeState &&
pTelemetry->Current.Race.State == STelemetry::ERaceState_Running);
}

// Checks if the race has just finished (race state changes from "Running" to "Finished" or "BeforeStart")
__inline BOOL IsRaceFinished(STelemetryData* pTelemetry)
{
return (pTelemetry->Previous.Race.State == STelemetry::ERaceState_Running &&
(pTelemetry->Current.Race.State == STelemetry::ERaceState_Finished ||
pTelemetry->Current.Race.State == STelemetry::ERaceState_BeforeState));
}
15 changes: 15 additions & 0 deletions Helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,21 @@ BOOL StatusBar_SetText(HWND hwndCtl, UINT uIndexType, LPCTSTR lpszText, BOOL bCe
}
}

BOOL StatusBar_SetLapCount(HWND hwndCtl, UINT uIndexType, UINT uCurrentLap, UINT uNumberOfLaps, BOOL bCenter)
{
TCHAR szText[MAX_CONTROLTEXT];

if (hwndCtl == NULL)
return FALSE;

if (uNumberOfLaps == 0)
_sntprintf(szText, _countof(szText), szCurLap, uCurrentLap);
else
_sntprintf(szText, _countof(szText), szNbLaps, uCurrentLap, uNumberOfLaps);

return StatusBar_SetText(hwndCtl, uIndexType, szText, bCenter);
}


void ListView_SelectAll(HWND hwndCtl)
{
Expand Down
4 changes: 3 additions & 1 deletion Helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const TCHAR szRaceBeforeStart[] = TEXT("Race: BeforeStart");
const TCHAR szRaceRunning[] = TEXT("Race: Running");
const TCHAR szRaceFinished[] = TEXT("Race: Finished");
const TCHAR szRaceEliminated[] = TEXT("Race: Eliminated");
const TCHAR szNbRespawns[] = TEXT("RSP: %d");
const TCHAR szCurLap[] = TEXT("Lap: %d");
const TCHAR szNbLaps[] = TEXT("Lap: %d/%d");
const TCHAR szNbCheckpoints[] = TEXT("CP: %d");
const TCHAR szSpeedKmh[] = TEXT("%d km/h");
const TCHAR szSpeedMph[] = TEXT("%d mph");
Expand Down Expand Up @@ -59,6 +60,7 @@ BOOL GetFileName(HWND hDlg, LPTSTR lpszFileName, SIZE_T cchStringLen, LPDWORD lp

// Status bar functions
BOOL StatusBar_SetText(HWND hwndCtl, UINT uIndexType, LPCTSTR lpszText, BOOL bCenter = FALSE);
BOOL StatusBar_SetLapCount(HWND hwndCtl, UINT uIndexType, UINT uCurrentLap, UINT uNumberOfLaps, BOOL bCenter = TRUE);

// List-view functions
void ListView_SelectAll(HWND hwndCtl);
Expand Down
2 changes: 1 addition & 1 deletion TMTelemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ BOOL WndProc_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
SetWindowFont(hwndStatusBar, GetStockFont(DEFAULT_GUI_FONT), FALSE);

// Set the number of parts and the coordinate of the right edge of each part
int aStatusBarParts[15] = { 125, 235, 385, 480, 555, 605, 650, 715, 790, 850, 940, 1030, 1120, 1180, -1 };
int aStatusBarParts[15] = { 125, 235, 385, 480, 555, 620, 665, 730, 805, 865, 955, 1045, 1135, 1195, -1 };
SIZE_T uParts = _countof(aStatusBarParts);
for (SIZE_T i = 0; i < (uParts - 1); i++)
aStatusBarParts[i] = MulDiv(aStatusBarParts[i], nDpi, USER_DEFAULT_SCREEN_DPI);
Expand Down
2 changes: 1 addition & 1 deletion TMTelemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ typedef enum _STATUSBAR_PART
SBP_MAPNAME,
SBP_PLAYERMODEL,
SBP_RACETIME,
SBP_RESPAWNS,
SBP_LAPS,
SBP_CHECKPOINTS,
SBP_SPEEDMETER,
SBP_ENGINERPM,
Expand Down
10 changes: 6 additions & 4 deletions maniaplanet_telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct STelemetry {
};
struct SGameState {
EGameState State;
char GameplayVariant[64]; // environment name 'stadium' 'canyon', ....
char GameplayVariant[64]; // player model 'StadiumCar', 'CanyonCar', ....
char MapId[64];
char MapName[256];
char __future__[128];
Expand All @@ -49,14 +49,16 @@ struct STelemetry {
Nat32 NbRespawns;
Nat32 NbCheckpoints;
Nat32 CheckpointTimes[125];
char __future__[32];
Nat32 NbCheckpointsPerLap; // new since Maniaplanet update 2019-10-10; not supported by Trackmania Turbo.
Nat32 NbLaps; // new since Maniaplanet update 2019-10-10; not supported by Trackmania Turbo.
char __future__[24];
};
struct SObjectState {
Nat32 Timestamp;
Nat32 DiscontinuityCount; // the number changes everytime the object is moved not continuously (== teleported).
Quat Rotation;
Vec3 Translation; // +x is "left", +y is "up", +z is "front"
Vec3 Velocity; // (world velocity)
Vec3 Translation; // +x is "left", +y is "up", +z is "front"
Vec3 Velocity; // (world velocity)
Nat32 LatestStableGroundContactTime;
char __future__[32];
};
Expand Down

0 comments on commit 9f9a869

Please sign in to comment.