diff --git a/data/tr2/ship/cfg/TR2X_strings.json5 b/data/tr2/ship/cfg/TR2X_strings.json5 index 65078e21f..e190d1f1e 100644 --- a/data/tr2/ship/cfg/TR2X_strings.json5 +++ b/data/tr2/ship/cfg/TR2X_strings.json5 @@ -471,6 +471,7 @@ "CONTROL_CUSTOM_2": "User Keys 2", "CONTROL_CUSTOM_3": "User Keys 3", "CONTROL_DEFAULT_KEYS": "Default Keys", + "DETAIL_FLOAT_FMT": "%.1f", "HEADING_GAME_OVER": "GAME OVER", "HEADING_INVENTORY": "INVENTORY", "HEADING_ITEMS": "ITEMS", diff --git a/src/libtrx/include/libtrx/game/game_string.def b/src/libtrx/include/libtrx/game/game_string.def index c6fc6f3ff..64b75f544 100644 --- a/src/libtrx/include/libtrx/game/game_string.def +++ b/src/libtrx/include/libtrx/game/game_string.def @@ -127,3 +127,4 @@ GS_DEFINE(PASSPORT_EXIT_TO_TITLE, "Exit to Title") GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes") GS_DEFINE(OSD_TRAPEZOID_FILTER_ON, "Trapezoid filter enabled") GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled") +GS_DEFINE(DETAIL_FLOAT_FMT, "%.1f") diff --git a/src/libtrx/include/libtrx/game/stats.h b/src/libtrx/include/libtrx/game/stats.h index 547864ffb..e0ceb05c4 100644 --- a/src/libtrx/include/libtrx/game/stats.h +++ b/src/libtrx/include/libtrx/game/stats.h @@ -1,3 +1,4 @@ #pragma once #include "stats/common.h" +#include "stats/types.h" diff --git a/src/tr1/game/stats/types.h b/src/libtrx/include/libtrx/game/stats/types.h similarity index 83% rename from src/tr1/game/stats/types.h rename to src/libtrx/include/libtrx/game/stats/types.h index 2f69b7ede..64a82be99 100644 --- a/src/tr1/game/stats/types.h +++ b/src/libtrx/include/libtrx/game/stats/types.h @@ -5,16 +5,18 @@ typedef struct STATS_COMMON { uint32_t timer; 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 pickup_count; uint32_t max_kill_count; - uint16_t max_secret_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; +#endif } STATS_COMMON; typedef struct { @@ -24,4 +26,8 @@ typedef struct { typedef struct { struct STATS_COMMON; +#if TR_VERSION == 2 + int32_t found_secrets; + int32_t total_secrets; +#endif } FINAL_STATS; diff --git a/src/tr1/game/game_string.def b/src/tr1/game/game_string.def index 00b48d279..662b23be8 100644 --- a/src/tr1/game/game_string.def +++ b/src/tr1/game/game_string.def @@ -26,7 +26,6 @@ GS_DEFINE(DETAIL_RENDER_MODE_FBO, "Framebuffer") GS_DEFINE(DETAIL_RESOLUTION, "Resolution") GS_DEFINE(DETAIL_INTEGER_FMT, "%d") GS_DEFINE(DETAIL_STRING_FMT, "%s") -GS_DEFINE(DETAIL_FLOAT_FMT, "%.1f") GS_DEFINE(DETAIL_RESOLUTION_FMT, "%dx%d") GS_DEFINE(CONTROL_RESET_DEFAULTS, "Reset All: Hold %s") GS_DEFINE(CONTROL_UNBIND, "Unbind: Hold %s") diff --git a/src/tr1/game/stats.h b/src/tr1/game/stats.h index 12d2f11d9..d36f32fa5 100644 --- a/src/tr1/game/stats.h +++ b/src/tr1/game/stats.h @@ -1,4 +1,5 @@ #pragma once #include "game/stats/common.h" -#include "game/stats/types.h" + +#include diff --git a/src/tr1/game/stats/common.h b/src/tr1/game/stats/common.h index bc2c49037..d81c830bb 100644 --- a/src/tr1/game/stats/common.h +++ b/src/tr1/game/stats/common.h @@ -1,8 +1,9 @@ #pragma once -#include "game/stats/types.h" #include "global/types.h" +#include + void Stats_ObserveRoomsLoad(void); void Stats_CalculateStats(void); int32_t Stats_GetPickups(void); diff --git a/src/tr1/global/types.h b/src/tr1/global/types.h index a5193e877..e938b8d35 100644 --- a/src/tr1/global/types.h +++ b/src/tr1/global/types.h @@ -1,6 +1,5 @@ #pragma once -#include "game/stats/types.h" #include "global/const.h" #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/src/tr2/game/lara/control.c b/src/tr2/game/lara/control.c index 99bb80e79..8b5bf7c23 100644 --- a/src/tr2/game/lara/control.c +++ b/src/tr2/game/lara/control.c @@ -737,7 +737,7 @@ void Lara_UseItem(const GAME_OBJECT_ID obj_id) CLAMPG(item->hit_points, LARA_MAX_HITPOINTS); Inv_RemoveItem(O_SMALL_MEDIPACK_ITEM); Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS); - Stats_AddMedipacksUsed(1); + Stats_AddMedipacksUsed(0.5); } break; @@ -747,7 +747,7 @@ void Lara_UseItem(const GAME_OBJECT_ID obj_id) item->hit_points = LARA_MAX_HITPOINTS; Inv_RemoveItem(O_LARGE_MEDIPACK_ITEM); Sound_Effect(SFX_MENU_MEDI, nullptr, SPM_ALWAYS); - Stats_AddMedipacksUsed(2); + Stats_AddMedipacksUsed(1); } break; diff --git a/src/tr2/game/objects/general/final_level_counter.c b/src/tr2/game/objects/general/final_level_counter.c index ece7a9284..1b1968a73 100644 --- a/src/tr2/game/objects/general/final_level_counter.c +++ b/src/tr2/game/objects/general/final_level_counter.c @@ -94,12 +94,13 @@ static void M_Control(const int16_t item_num) { const RESUME_INFO *const current_info = 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(); return; } - if (current_info->stats.kills > g_FinalLevelCount) { + if (current_info->stats.kill_count > g_FinalLevelCount) { g_FinalBossActive++; if (g_FinalBossActive == CUTSCENE_DELAY) { M_PrepareCutscene(item_num); diff --git a/src/tr2/game/savegame/savegame_bson.c b/src/tr2/game/savegame/savegame_bson.c index bcc07e002..e50903ec8 100644 --- a/src/tr2/game/savegame/savegame_bson.c +++ b/src/tr2/game/savegame/savegame_bson.c @@ -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_used", resume->stats.ammo_used); JSON_ObjectAppendInt( - resume_obj, "distance_travelled", resume->stats.distance); - JSON_ObjectAppendInt(resume_obj, "kills", resume->stats.kills); + resume_obj, "distance_travelled", resume->stats.distance_travelled); + JSON_ObjectAppendInt(resume_obj, "kills", resume->stats.kill_count); JSON_ObjectAppendInt(resume_obj, "secrets", resume->stats.secret_flags); JSON_ObjectAppendDouble( - resume_obj, "medipacks_used", resume->stats.medipacks); + resume_obj, "medipacks_used", resume->stats.medipacks_used); JSON_ObjectAppendInt( resume_obj, "max_secrets", resume->stats.max_secret_count); 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.ammo_hits = JSON_ObjectGetInt(resume_obj, "ammo_hits", 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); - resume->stats.kills = JSON_ObjectGetInt(resume_obj, "kills", 0); + resume->stats.kill_count = JSON_ObjectGetInt(resume_obj, "kills", 0); resume->stats.secret_flags = JSON_ObjectGetInt(resume_obj, "secrets", 0); - resume->stats.medipacks = - JSON_ObjectGetInt(resume_obj, "medipacks_used", 0); + resume->stats.medipacks_used = + JSON_ObjectGetDouble(resume_obj, "medipacks_used", 0); resume->stats.max_secret_count = JSON_ObjectGetInt(resume_obj, "max_secrets", 0); } diff --git a/src/tr2/game/savegame/savegame_legacy.c b/src/tr2/game/savegame/savegame_legacy.c index 9d32b8c8a..72c16a4ab 100644 --- a/src/tr2/game/savegame/savegame_legacy.c +++ b/src/tr2/game/savegame/savegame_legacy.c @@ -180,10 +180,10 @@ static void M_ReadStats(LEVEL_STATS *const stats) stats->timer = M_ReadU32(); stats->ammo_used = M_ReadU32(); stats->ammo_hits = M_ReadU32(); - stats->distance = M_ReadU32(); - stats->kills = M_ReadU16(); + stats->distance_travelled = M_ReadU32(); + stats->kill_count = M_ReadU16(); stats->secret_flags = M_ReadU8(); - stats->medipacks = M_ReadU8(); + stats->medipacks_used = M_ReadU8() / 2.0f; } 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->ammo_used); M_WriteU32(stats->ammo_hits); - M_WriteU32(stats->distance); - M_WriteU16(stats->kills); - M_WriteU8(stats->secret_flags); - M_WriteU8(stats->medipacks); + M_WriteU32(stats->distance_travelled); + M_WriteU16(stats->kill_count); + M_WriteU8(stats->secret_flags & 0xFF); + M_WriteU8(stats->medipacks_used * 2); } static void M_WriteItems(void) diff --git a/src/tr2/game/stats.c b/src/tr2/game/stats.c index e9d88f01d..30a6ee15d 100644 --- a/src/tr2/game/stats.c +++ b/src/tr2/game/stats.c @@ -15,7 +15,7 @@ static int32_t m_CachedItemCount = 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 static CLOCK_TIMER m_StartCounter = { .type = CLOCK_TYPE_REAL }; @@ -50,7 +50,7 @@ void Stats_UpdateTimer(void) } #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++) { 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.ammo_used += stats->ammo_used; result.ammo_hits += stats->ammo_hits; - result.kills += stats->kills; - result.distance += stats->distance; - result.medipacks += stats->medipacks; + result.kill_count += stats->kill_count; + result.distance_travelled += stats->distance_travelled; + result.medipacks_used += stats->medipacks_used; for (int32_t j = 0; j < stats->max_secret_count; j++) { if (stats->secret_flags & (1 << j)) { @@ -102,7 +102,7 @@ void Stats_ObserveItemsLoad(void) void Stats_CalculateStats(void) { m_LevelSecrets = 0; - uint8_t secret_flags = 0; + uint16_t secret_flags = 0; for (int32_t i = 0; i < m_CachedItemCount; i++) { const ITEM *const item = Item_Get(i); @@ -153,7 +153,7 @@ void Stats_AddKill(void) { RESUME_INFO *const current_info = Savegame_GetCurrentInfo(Game_GetCurrentLevel()); - current_info->stats.kills++; + current_info->stats.kill_count++; } void Stats_AddAmmoHits(void) @@ -174,14 +174,14 @@ void Stats_AddMedipacksUsed(const double medipack_value) { RESUME_INFO *const current_info = 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) { RESUME_INFO *const current_info = 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.x - last_pos.x)); } diff --git a/src/tr2/game/stats.h b/src/tr2/game/stats.h index bb194c45a..570aa6d17 100644 --- a/src/tr2/game/stats.h +++ b/src/tr2/game/stats.h @@ -3,6 +3,7 @@ #include "global/types.h" #include +#include void Stats_StartTimer(void); void Stats_UpdateTimer(void); diff --git a/src/tr2/game/ui/widgets/stats_dialog.c b/src/tr2/game/ui/widgets/stats_dialog.c index 21d383a45..c78799c95 100644 --- a/src/tr2/game/ui/widgets/stats_dialog.c +++ b/src/tr2/game/ui/widgets/stats_dialog.c @@ -117,7 +117,7 @@ static void M_AddRowFromRole( break; 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); break; @@ -132,16 +132,12 @@ static void M_AddRowFromRole( break; case M_ROW_MEDIPACKS: - if ((stats->medipacks & 1) != 0) { - sprintf(buf, "%d.5", stats->medipacks >> 1); - } else { - sprintf(buf, "%d.0", stats->medipacks >> 1); - } + sprintf(buf, GS(DETAIL_FLOAT_FMT), stats->medipacks_used); M_AddRow(self, role, GS(STATS_MEDIPACKS_USED), buf); break; case M_ROW_DISTANCE_TRAVELED: - const int32_t distance = stats->distance / 445; + const int32_t distance = stats->distance_travelled / 445; if (distance < 1000) { sprintf(buf, "%dm", distance); } else { diff --git a/src/tr2/global/types_decomp.h b/src/tr2/global/types_decomp.h index f813da2dd..587c1ec6e 100644 --- a/src/tr2/global/types_decomp.h +++ b/src/tr2/global/types_decomp.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -80,27 +81,6 @@ typedef enum { DRAW_COLOR_KEY = 1, } 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 { uint16_t pistol_ammo; uint16_t magnum_ammo; diff --git a/src/tr2/global/vars.c b/src/tr2/global/vars.c index eee88ddda..37b78d315 100644 --- a/src/tr2/global/vars.c +++ b/src/tr2/global/vars.c @@ -171,7 +171,7 @@ WEAPON_INFO g_Weapons[] = { }; int16_t g_FinalBossActive; -int16_t g_FinalLevelCount; +uint16_t g_FinalLevelCount; int16_t g_FinalBossCount; int16_t g_FinalBossItem[5]; diff --git a/src/tr2/global/vars.h b/src/tr2/global/vars.h index 22c6e60e9..f64744d0a 100644 --- a/src/tr2/global/vars.h +++ b/src/tr2/global/vars.h @@ -62,7 +62,7 @@ extern bool g_CameraUnderwater; extern char g_LevelFileName[256]; extern WEAPON_INFO g_Weapons[]; extern int16_t g_FinalBossActive; -extern int16_t g_FinalLevelCount; +extern uint16_t g_FinalLevelCount; extern int16_t g_FinalBossCount; extern int16_t g_FinalBossItem[5]; extern REQUEST_INFO g_LoadGameRequester;