stats/types: move statistic types to TRX

This moves the various statistic structs to TRX and updates naming and
types such that both games match as far as possible.
This commit is contained in:
lahm86 2025-04-08 18:12:32 +01:00
parent 989ba0ac6d
commit 4350fa2d10
18 changed files with 54 additions and 66 deletions

View file

@ -471,6 +471,7 @@
"CONTROL_CUSTOM_2": "User Keys 2", "CONTROL_CUSTOM_2": "User Keys 2",
"CONTROL_CUSTOM_3": "User Keys 3", "CONTROL_CUSTOM_3": "User Keys 3",
"CONTROL_DEFAULT_KEYS": "Default Keys", "CONTROL_DEFAULT_KEYS": "Default Keys",
"DETAIL_FLOAT_FMT": "%.1f",
"HEADING_GAME_OVER": "GAME OVER", "HEADING_GAME_OVER": "GAME OVER",
"HEADING_INVENTORY": "INVENTORY", "HEADING_INVENTORY": "INVENTORY",
"HEADING_ITEMS": "ITEMS", "HEADING_ITEMS": "ITEMS",

View file

@ -127,3 +127,4 @@ GS_DEFINE(PASSPORT_EXIT_TO_TITLE, "Exit to Title")
GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes") GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes")
GS_DEFINE(OSD_TRAPEZOID_FILTER_ON, "Trapezoid filter enabled") GS_DEFINE(OSD_TRAPEZOID_FILTER_ON, "Trapezoid filter enabled")
GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled") GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled")
GS_DEFINE(DETAIL_FLOAT_FMT, "%.1f")

View file

@ -1,3 +1,4 @@
#pragma once #pragma once
#include "stats/common.h" #include "stats/common.h"
#include "stats/types.h"

View file

@ -5,16 +5,18 @@
typedef struct STATS_COMMON { typedef struct STATS_COMMON {
uint32_t timer; uint32_t timer;
uint32_t kill_count; uint32_t kill_count;
uint32_t ammo_used;
uint32_t ammo_hits;
uint32_t distance_travelled;
uint16_t max_secret_count;
double medipacks_used;
#if TR_VERSION == 1
uint16_t secret_count; uint16_t secret_count;
uint16_t pickup_count; uint16_t pickup_count;
uint32_t max_kill_count; uint32_t max_kill_count;
uint16_t max_secret_count;
uint16_t max_pickup_count; uint16_t max_pickup_count;
uint32_t ammo_hits;
uint32_t ammo_used;
double medipacks_used;
uint32_t distance_travelled;
int32_t death_count; int32_t death_count;
#endif
} STATS_COMMON; } STATS_COMMON;
typedef struct { typedef struct {
@ -24,4 +26,8 @@ typedef struct {
typedef struct { typedef struct {
struct STATS_COMMON; struct STATS_COMMON;
#if TR_VERSION == 2
int32_t found_secrets;
int32_t total_secrets;
#endif
} FINAL_STATS; } FINAL_STATS;

View file

@ -26,7 +26,6 @@ GS_DEFINE(DETAIL_RENDER_MODE_FBO, "Framebuffer")
GS_DEFINE(DETAIL_RESOLUTION, "Resolution") GS_DEFINE(DETAIL_RESOLUTION, "Resolution")
GS_DEFINE(DETAIL_INTEGER_FMT, "%d") GS_DEFINE(DETAIL_INTEGER_FMT, "%d")
GS_DEFINE(DETAIL_STRING_FMT, "%s") GS_DEFINE(DETAIL_STRING_FMT, "%s")
GS_DEFINE(DETAIL_FLOAT_FMT, "%.1f")
GS_DEFINE(DETAIL_RESOLUTION_FMT, "%dx%d") GS_DEFINE(DETAIL_RESOLUTION_FMT, "%dx%d")
GS_DEFINE(CONTROL_RESET_DEFAULTS, "Reset All: Hold %s") GS_DEFINE(CONTROL_RESET_DEFAULTS, "Reset All: Hold %s")
GS_DEFINE(CONTROL_UNBIND, "Unbind: Hold %s") GS_DEFINE(CONTROL_UNBIND, "Unbind: Hold %s")

View file

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "game/stats/common.h" #include "game/stats/common.h"
#include "game/stats/types.h"
#include <libtrx/game/stats.h>

View file

@ -1,8 +1,9 @@
#pragma once #pragma once
#include "game/stats/types.h"
#include "global/types.h" #include "global/types.h"
#include <libtrx/game/stats.h>
void Stats_ObserveRoomsLoad(void); void Stats_ObserveRoomsLoad(void);
void Stats_CalculateStats(void); void Stats_CalculateStats(void);
int32_t Stats_GetPickups(void); int32_t Stats_GetPickups(void);

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "game/stats/types.h"
#include "global/const.h" #include "global/const.h"
#include <libtrx/game/anims.h> #include <libtrx/game/anims.h>
@ -21,6 +20,7 @@
#include <libtrx/game/rooms.h> #include <libtrx/game/rooms.h>
#include <libtrx/game/sound/enum.h> #include <libtrx/game/sound/enum.h>
#include <libtrx/game/sound/ids.h> #include <libtrx/game/sound/ids.h>
#include <libtrx/game/stats/types.h>
#include <libtrx/game/text.h> #include <libtrx/game/text.h>
#include <libtrx/game/types.h> #include <libtrx/game/types.h>

View file

@ -737,7 +737,7 @@ void Lara_UseItem(const GAME_OBJECT_ID obj_id)
CLAMPG(item->hit_points, LARA_MAX_HITPOINTS); CLAMPG(item->hit_points, LARA_MAX_HITPOINTS);
Inv_RemoveItem(O_SMALL_MEDIPACK_ITEM); Inv_RemoveItem(O_SMALL_MEDIPACK_ITEM);
Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS); Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS);
Stats_AddMedipacksUsed(1); Stats_AddMedipacksUsed(0.5);
} }
break; break;
@ -747,7 +747,7 @@ void Lara_UseItem(const GAME_OBJECT_ID obj_id)
item->hit_points = LARA_MAX_HITPOINTS; item->hit_points = LARA_MAX_HITPOINTS;
Inv_RemoveItem(O_LARGE_MEDIPACK_ITEM); Inv_RemoveItem(O_LARGE_MEDIPACK_ITEM);
Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS); Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS);
Stats_AddMedipacksUsed(2); Stats_AddMedipacksUsed(1);
} }
break; break;

View file

@ -94,12 +94,13 @@ static void M_Control(const int16_t item_num)
{ {
const RESUME_INFO *const current_info = const RESUME_INFO *const current_info =
Savegame_GetCurrentInfo(Game_GetCurrentLevel()); Savegame_GetCurrentInfo(Game_GetCurrentLevel());
if (current_info->stats.kills == g_FinalLevelCount && !g_FinalBossActive) { if (current_info->stats.kill_count == g_FinalLevelCount
&& !g_FinalBossActive) {
M_ActivateLastBoss(); M_ActivateLastBoss();
return; return;
} }
if (current_info->stats.kills > g_FinalLevelCount) { if (current_info->stats.kill_count > g_FinalLevelCount) {
g_FinalBossActive++; g_FinalBossActive++;
if (g_FinalBossActive == CUTSCENE_DELAY) { if (g_FinalBossActive == CUTSCENE_DELAY) {
M_PrepareCutscene(item_num); M_PrepareCutscene(item_num);

View file

@ -369,11 +369,11 @@ static JSON_ARRAY *M_DumpResumeInfo(void)
JSON_ObjectAppendInt(resume_obj, "ammo_hits", resume->stats.ammo_hits); JSON_ObjectAppendInt(resume_obj, "ammo_hits", resume->stats.ammo_hits);
JSON_ObjectAppendInt(resume_obj, "ammo_used", resume->stats.ammo_used); JSON_ObjectAppendInt(resume_obj, "ammo_used", resume->stats.ammo_used);
JSON_ObjectAppendInt( JSON_ObjectAppendInt(
resume_obj, "distance_travelled", resume->stats.distance); resume_obj, "distance_travelled", resume->stats.distance_travelled);
JSON_ObjectAppendInt(resume_obj, "kills", resume->stats.kills); JSON_ObjectAppendInt(resume_obj, "kills", resume->stats.kill_count);
JSON_ObjectAppendInt(resume_obj, "secrets", resume->stats.secret_flags); JSON_ObjectAppendInt(resume_obj, "secrets", resume->stats.secret_flags);
JSON_ObjectAppendDouble( JSON_ObjectAppendDouble(
resume_obj, "medipacks_used", resume->stats.medipacks); resume_obj, "medipacks_used", resume->stats.medipacks_used);
JSON_ObjectAppendInt( JSON_ObjectAppendInt(
resume_obj, "max_secrets", resume->stats.max_secret_count); resume_obj, "max_secrets", resume->stats.max_secret_count);
JSON_ArrayAppendObject(resume_arr, resume_obj); JSON_ArrayAppendObject(resume_arr, resume_obj);
@ -432,13 +432,13 @@ static bool M_LoadResumeInfo(JSON_ARRAY *const resume_arr)
resume->stats.timer = JSON_ObjectGetInt(resume_obj, "timer", 0); resume->stats.timer = JSON_ObjectGetInt(resume_obj, "timer", 0);
resume->stats.ammo_hits = JSON_ObjectGetInt(resume_obj, "ammo_hits", 0); resume->stats.ammo_hits = JSON_ObjectGetInt(resume_obj, "ammo_hits", 0);
resume->stats.ammo_used = JSON_ObjectGetInt(resume_obj, "ammo_used", 0); resume->stats.ammo_used = JSON_ObjectGetInt(resume_obj, "ammo_used", 0);
resume->stats.distance = resume->stats.distance_travelled =
JSON_ObjectGetInt(resume_obj, "distance_travelled", 0); JSON_ObjectGetInt(resume_obj, "distance_travelled", 0);
resume->stats.kills = JSON_ObjectGetInt(resume_obj, "kills", 0); resume->stats.kill_count = JSON_ObjectGetInt(resume_obj, "kills", 0);
resume->stats.secret_flags = resume->stats.secret_flags =
JSON_ObjectGetInt(resume_obj, "secrets", 0); JSON_ObjectGetInt(resume_obj, "secrets", 0);
resume->stats.medipacks = resume->stats.medipacks_used =
JSON_ObjectGetInt(resume_obj, "medipacks_used", 0); JSON_ObjectGetDouble(resume_obj, "medipacks_used", 0);
resume->stats.max_secret_count = resume->stats.max_secret_count =
JSON_ObjectGetInt(resume_obj, "max_secrets", 0); JSON_ObjectGetInt(resume_obj, "max_secrets", 0);
} }

View file

@ -180,10 +180,10 @@ static void M_ReadStats(LEVEL_STATS *const stats)
stats->timer = M_ReadU32(); stats->timer = M_ReadU32();
stats->ammo_used = M_ReadU32(); stats->ammo_used = M_ReadU32();
stats->ammo_hits = M_ReadU32(); stats->ammo_hits = M_ReadU32();
stats->distance = M_ReadU32(); stats->distance_travelled = M_ReadU32();
stats->kills = M_ReadU16(); stats->kill_count = M_ReadU16();
stats->secret_flags = M_ReadU8(); stats->secret_flags = M_ReadU8();
stats->medipacks = M_ReadU8(); stats->medipacks_used = M_ReadU8() / 2.0f;
} }
static void M_ReadItems(void) static void M_ReadItems(void)
@ -468,10 +468,10 @@ static void M_WriteStats(const LEVEL_STATS *const stats)
M_WriteU32(stats->timer); M_WriteU32(stats->timer);
M_WriteU32(stats->ammo_used); M_WriteU32(stats->ammo_used);
M_WriteU32(stats->ammo_hits); M_WriteU32(stats->ammo_hits);
M_WriteU32(stats->distance); M_WriteU32(stats->distance_travelled);
M_WriteU16(stats->kills); M_WriteU16(stats->kill_count);
M_WriteU8(stats->secret_flags); M_WriteU8(stats->secret_flags & 0xFF);
M_WriteU8(stats->medipacks); M_WriteU8(stats->medipacks_used * 2);
} }
static void M_WriteItems(void) static void M_WriteItems(void)

View file

@ -15,7 +15,7 @@
static int32_t m_CachedItemCount = 0; static int32_t m_CachedItemCount = 0;
static int32_t m_LevelSecrets = 0; static int32_t m_LevelSecrets = 0;
static bool M_SetSecretFlag(uint8_t *flags, GAME_OBJECT_ID obj_id); static bool M_SetSecretFlag(uint16_t *flags, GAME_OBJECT_ID obj_id);
#if USE_REAL_CLOCK #if USE_REAL_CLOCK
static CLOCK_TIMER m_StartCounter = { .type = CLOCK_TYPE_REAL }; static CLOCK_TIMER m_StartCounter = { .type = CLOCK_TYPE_REAL };
@ -50,7 +50,7 @@ void Stats_UpdateTimer(void)
} }
#endif #endif
static bool M_SetSecretFlag(uint8_t *const flags, const GAME_OBJECT_ID obj_id) static bool M_SetSecretFlag(uint16_t *const flags, const GAME_OBJECT_ID obj_id)
{ {
for (int32_t i = 0; i < 2; i++) { for (int32_t i = 0; i < 2; i++) {
const int32_t flag = 1 << ((obj_id - O_SECRET_1) + i * 3); const int32_t flag = 1 << ((obj_id - O_SECRET_1) + i * 3);
@ -79,9 +79,9 @@ FINAL_STATS Stats_ComputeFinalStats(const GF_LEVEL_TYPE level_type)
result.timer += stats->timer; result.timer += stats->timer;
result.ammo_used += stats->ammo_used; result.ammo_used += stats->ammo_used;
result.ammo_hits += stats->ammo_hits; result.ammo_hits += stats->ammo_hits;
result.kills += stats->kills; result.kill_count += stats->kill_count;
result.distance += stats->distance; result.distance_travelled += stats->distance_travelled;
result.medipacks += stats->medipacks; result.medipacks_used += stats->medipacks_used;
for (int32_t j = 0; j < stats->max_secret_count; j++) { for (int32_t j = 0; j < stats->max_secret_count; j++) {
if (stats->secret_flags & (1 << j)) { if (stats->secret_flags & (1 << j)) {
@ -102,7 +102,7 @@ void Stats_ObserveItemsLoad(void)
void Stats_CalculateStats(void) void Stats_CalculateStats(void)
{ {
m_LevelSecrets = 0; m_LevelSecrets = 0;
uint8_t secret_flags = 0; uint16_t secret_flags = 0;
for (int32_t i = 0; i < m_CachedItemCount; i++) { for (int32_t i = 0; i < m_CachedItemCount; i++) {
const ITEM *const item = Item_Get(i); const ITEM *const item = Item_Get(i);
@ -153,7 +153,7 @@ void Stats_AddKill(void)
{ {
RESUME_INFO *const current_info = RESUME_INFO *const current_info =
Savegame_GetCurrentInfo(Game_GetCurrentLevel()); Savegame_GetCurrentInfo(Game_GetCurrentLevel());
current_info->stats.kills++; current_info->stats.kill_count++;
} }
void Stats_AddAmmoHits(void) void Stats_AddAmmoHits(void)
@ -174,14 +174,14 @@ void Stats_AddMedipacksUsed(const double medipack_value)
{ {
RESUME_INFO *const current_info = RESUME_INFO *const current_info =
Savegame_GetCurrentInfo(Game_GetCurrentLevel()); Savegame_GetCurrentInfo(Game_GetCurrentLevel());
current_info->stats.medipacks += medipack_value; current_info->stats.medipacks_used += medipack_value;
} }
void Stats_AddDistanceTravelled(const XYZ_32 pos, const XYZ_32 last_pos) void Stats_AddDistanceTravelled(const XYZ_32 pos, const XYZ_32 last_pos)
{ {
RESUME_INFO *const current_info = RESUME_INFO *const current_info =
Savegame_GetCurrentInfo(Game_GetCurrentLevel()); Savegame_GetCurrentInfo(Game_GetCurrentLevel());
current_info->stats.distance += Math_Sqrt( current_info->stats.distance_travelled += Math_Sqrt(
SQUARE(pos.z - last_pos.z) + SQUARE(pos.y - last_pos.y) SQUARE(pos.z - last_pos.z) + SQUARE(pos.y - last_pos.y)
+ SQUARE(pos.x - last_pos.x)); + SQUARE(pos.x - last_pos.x));
} }

View file

@ -3,6 +3,7 @@
#include "global/types.h" #include "global/types.h"
#include <libtrx/game/game_flow.h> #include <libtrx/game/game_flow.h>
#include <libtrx/game/stats/types.h>
void Stats_StartTimer(void); void Stats_StartTimer(void);
void Stats_UpdateTimer(void); void Stats_UpdateTimer(void);

View file

@ -117,7 +117,7 @@ static void M_AddRowFromRole(
break; break;
case M_ROW_KILLS: case M_ROW_KILLS:
sprintf(buf, GS(STATS_BASIC_FMT), stats->kills); sprintf(buf, GS(STATS_BASIC_FMT), stats->kill_count);
M_AddRow(self, role, GS(STATS_KILLS), buf); M_AddRow(self, role, GS(STATS_KILLS), buf);
break; break;
@ -132,16 +132,12 @@ static void M_AddRowFromRole(
break; break;
case M_ROW_MEDIPACKS: case M_ROW_MEDIPACKS:
if ((stats->medipacks & 1) != 0) { sprintf(buf, GS(DETAIL_FLOAT_FMT), stats->medipacks_used);
sprintf(buf, "%d.5", stats->medipacks >> 1);
} else {
sprintf(buf, "%d.0", stats->medipacks >> 1);
}
M_AddRow(self, role, GS(STATS_MEDIPACKS_USED), buf); M_AddRow(self, role, GS(STATS_MEDIPACKS_USED), buf);
break; break;
case M_ROW_DISTANCE_TRAVELED: case M_ROW_DISTANCE_TRAVELED:
const int32_t distance = stats->distance / 445; const int32_t distance = stats->distance_travelled / 445;
if (distance < 1000) { if (distance < 1000) {
sprintf(buf, "%dm", distance); sprintf(buf, "%dm", distance);
} else { } else {

View file

@ -9,6 +9,7 @@
#include <libtrx/game/items.h> #include <libtrx/game/items.h>
#include <libtrx/game/math.h> #include <libtrx/game/math.h>
#include <libtrx/game/rooms/types.h> #include <libtrx/game/rooms/types.h>
#include <libtrx/game/stats/types.h>
#include <libtrx/game/text.h> #include <libtrx/game/text.h>
#include <libtrx/game/types.h> #include <libtrx/game/types.h>
@ -80,27 +81,6 @@ typedef enum {
DRAW_COLOR_KEY = 1, DRAW_COLOR_KEY = 1,
} DRAW_TYPE; } DRAW_TYPE;
typedef struct STATS_COMMON {
uint32_t timer;
uint32_t ammo_used;
uint32_t ammo_hits;
uint32_t distance;
uint16_t kills;
uint8_t medipacks;
uint16_t max_secret_count;
} STATS_COMMON;
typedef struct {
struct STATS_COMMON;
int32_t found_secrets;
int32_t total_secrets;
} FINAL_STATS;
typedef struct {
struct STATS_COMMON;
uint8_t secret_flags;
} LEVEL_STATS;
typedef struct { typedef struct {
uint16_t pistol_ammo; uint16_t pistol_ammo;
uint16_t magnum_ammo; uint16_t magnum_ammo;

View file

@ -171,7 +171,7 @@ WEAPON_INFO g_Weapons[] = {
}; };
int16_t g_FinalBossActive; int16_t g_FinalBossActive;
int16_t g_FinalLevelCount; uint16_t g_FinalLevelCount;
int16_t g_FinalBossCount; int16_t g_FinalBossCount;
int16_t g_FinalBossItem[5]; int16_t g_FinalBossItem[5];

View file

@ -62,7 +62,7 @@ extern bool g_CameraUnderwater;
extern char g_LevelFileName[256]; extern char g_LevelFileName[256];
extern WEAPON_INFO g_Weapons[]; extern WEAPON_INFO g_Weapons[];
extern int16_t g_FinalBossActive; extern int16_t g_FinalBossActive;
extern int16_t g_FinalLevelCount; extern uint16_t g_FinalLevelCount;
extern int16_t g_FinalBossCount; extern int16_t g_FinalBossCount;
extern int16_t g_FinalBossItem[5]; extern int16_t g_FinalBossItem[5];
extern REQUEST_INFO g_LoadGameRequester; extern REQUEST_INFO g_LoadGameRequester;