mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
tr2/stats: determine secret count automatically
This fixes the hardcoded check to skip secret counts in statistics for the final two levels and allows to do away with the game flow's secret count mechanic, by counting the number of secret pickups in the level and storing in the stats. Resolves #1582.
This commit is contained in:
parent
e7809774f4
commit
fc4064582d
12 changed files with 73 additions and 11 deletions
|
@ -1,4 +1,5 @@
|
|||
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-0.10...develop) - ××××-××-××
|
||||
- fixed the final two levels not allowing for secrets to be counted in the statistics (#1582)
|
||||
|
||||
## [0.10](https://github.com/LostArtefacts/TRX/compare/tr2-0.9.2...tr2-0.10) - 2025-03-18
|
||||
- added support for 60 FPS rendering
|
||||
|
|
|
@ -128,6 +128,7 @@ game with new enhancements and features.
|
|||
#### Statistics
|
||||
- fixed the dragon counting as more than one kill if allowed to revive
|
||||
- fixed enemies that are run over by the skidoo not being counted in the statistics
|
||||
- fixed the final two levels not allowing for secrets to be counted in the statistics
|
||||
|
||||
#### Visuals
|
||||
- added quadrilateral texture correction
|
||||
|
|
|
@ -126,6 +126,14 @@ static DECLARE_GF_EVENT_HANDLER(M_HandlePlayLevel)
|
|||
break;
|
||||
}
|
||||
|
||||
Stats_CalculateStats();
|
||||
START_INFO *const resume = Savegame_GetCurrentInfo(level);
|
||||
if (resume != nullptr) {
|
||||
const int32_t secret_count = Stats_GetSecrets();
|
||||
resume->stats.max_secret_count = secret_count;
|
||||
g_SaveGame.current_stats.max_secret_count = secret_count;
|
||||
}
|
||||
|
||||
ASSERT(GF_GetCurrentLevel() == level);
|
||||
if (level->type == GFL_DEMO) {
|
||||
gf_cmd = GF_RunDemo(level->num);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "game/room.h"
|
||||
#include "game/shell.h"
|
||||
#include "game/sound.h"
|
||||
#include "game/stats.h"
|
||||
#include "global/const.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
|
@ -168,6 +169,8 @@ static void M_LoadFromFile(const GF_LEVEL *const level)
|
|||
Level_ReadPathingData(file);
|
||||
Level_ReadAnimatedTextureRanges(file);
|
||||
Level_ReadItems(file);
|
||||
// TODO: perhaps call from Level_LoadObjectsAndItems
|
||||
Stats_ObserveItemsLoad();
|
||||
|
||||
Level_ReadLightMap(file);
|
||||
Level_ReadCinematicFrames(file);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "game/lara/control.h"
|
||||
#include "game/lara/misc.h"
|
||||
#include "game/objects/common.h"
|
||||
#include "game/objects/vars.h"
|
||||
#include "game/output.h"
|
||||
#include "game/overlay.h"
|
||||
#include "game/room.h"
|
||||
|
@ -80,8 +81,7 @@ static void M_DoPickup(const int16_t item_num)
|
|||
Overlay_AddDisplayPickup(item->object_id);
|
||||
Inv_AddItem(item->object_id);
|
||||
|
||||
if ((item->object_id == O_SECRET_1 || item->object_id == O_SECRET_2
|
||||
|| item->object_id == O_SECRET_3)
|
||||
if (Object_IsType(item->object_id, g_SecretObjects)
|
||||
&& (g_SaveGame.current_stats.secret_flags & 1)
|
||||
+ ((g_SaveGame.current_stats.secret_flags >> 1) & 1)
|
||||
+ ((g_SaveGame.current_stats.secret_flags >> 2) & 1)
|
||||
|
|
|
@ -107,6 +107,15 @@ const GAME_OBJECT_ID g_PickupObjects[] = {
|
|||
// clang-format on
|
||||
};
|
||||
|
||||
const GAME_OBJECT_ID g_SecretObjects[] = {
|
||||
// clang-format off
|
||||
O_SECRET_1,
|
||||
O_SECRET_2,
|
||||
O_SECRET_3,
|
||||
NO_OBJECT,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
const GAME_OBJECT_ID g_DoorObjects[] = {
|
||||
// clang-format off
|
||||
O_DOOR_TYPE_1,
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
|
||||
extern const GAME_OBJECT_ID g_DoorObjects[];
|
||||
extern const GAME_OBJECT_ID g_TrapdoorObjects[];
|
||||
extern const GAME_OBJECT_ID g_SecretObjects[];
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "game/inventory.h"
|
||||
#include "game/music.h"
|
||||
#include "game/objects/common.h"
|
||||
#include "game/objects/vars.h"
|
||||
#include "game/output.h"
|
||||
#include "game/scaler.h"
|
||||
#include "game/text.h"
|
||||
|
@ -523,7 +524,7 @@ static void M_DrawPickups(void)
|
|||
|
||||
void Overlay_AddDisplayPickup(const GAME_OBJECT_ID obj_id)
|
||||
{
|
||||
if (obj_id == O_SECRET_1 || obj_id == O_SECRET_2 || obj_id == O_SECRET_3) {
|
||||
if (Object_IsType(obj_id, g_SecretObjects)) {
|
||||
Music_Play(g_GameFlow.secret_track, MPM_ALWAYS);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
#include "game/clock.h"
|
||||
#include "game/game_flow.h"
|
||||
#include "game/objects/vars.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/log.h>
|
||||
|
||||
#define USE_REAL_CLOCK 0
|
||||
|
||||
static int32_t m_CachedItemCount = 0;
|
||||
static int32_t m_LevelSecrets = 0;
|
||||
|
||||
#if USE_REAL_CLOCK
|
||||
static CLOCK_TIMER m_StartCounter = { .type = CLOCK_TYPE_REAL };
|
||||
static int32_t m_StartTimer = 0;
|
||||
|
@ -51,14 +55,12 @@ FINAL_STATS Stats_ComputeFinalStats(void)
|
|||
result.distance += g_SaveGame.start[i].stats.distance;
|
||||
result.medipacks += g_SaveGame.start[i].stats.medipacks;
|
||||
|
||||
// TODO: #170, consult GFE_NUM_SECRETS rather than hardcoding this
|
||||
if (i < level_table->count - 2) {
|
||||
for (int32_t j = 0; j < 3; j++) {
|
||||
if (g_SaveGame.start[i].stats.secret_flags & (1 << j)) {
|
||||
result.found_secrets++;
|
||||
}
|
||||
result.total_secrets++;
|
||||
for (int32_t j = 0; j < g_SaveGame.start[i].stats.max_secret_count;
|
||||
j++) {
|
||||
if (g_SaveGame.start[i].stats.secret_flags & (1 << j)) {
|
||||
result.found_secrets++;
|
||||
}
|
||||
result.total_secrets++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,3 +77,35 @@ void Stats_Reset(void)
|
|||
g_SaveGame.current_stats.medipacks = 0;
|
||||
g_SaveGame.current_stats.secret_flags = 0;
|
||||
}
|
||||
|
||||
void Stats_ObserveItemsLoad(void)
|
||||
{
|
||||
m_CachedItemCount = Item_GetLevelCount();
|
||||
}
|
||||
|
||||
void Stats_CalculateStats(void)
|
||||
{
|
||||
m_LevelSecrets = 0;
|
||||
int32_t secret_flags = 0;
|
||||
|
||||
for (int32_t i = 0; i < m_CachedItemCount; i++) {
|
||||
const ITEM *const item = Item_Get(i);
|
||||
if (item->object_id < 0 || item->object_id >= O_NUMBER_OF) {
|
||||
LOG_ERROR("Bad Object number (%d) on Item %d", item->object_id, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Object_IsType(item->object_id, g_SecretObjects)) {
|
||||
const int32_t flag = 1 << (item->object_id - O_SECRET_1);
|
||||
if ((secret_flags & flag) == 0) {
|
||||
m_LevelSecrets++;
|
||||
secret_flags |= flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t Stats_GetSecrets(void)
|
||||
{
|
||||
return m_LevelSecrets;
|
||||
}
|
||||
|
|
|
@ -5,4 +5,7 @@
|
|||
void Stats_StartTimer(void);
|
||||
void Stats_UpdateTimer(void);
|
||||
void Stats_Reset(void);
|
||||
void Stats_ObserveItemsLoad(void);
|
||||
void Stats_CalculateStats(void);
|
||||
int32_t Stats_GetSecrets(void);
|
||||
FINAL_STATS Stats_ComputeFinalStats(void);
|
||||
|
|
|
@ -156,7 +156,7 @@ static void M_AddLevelStatsRows(UI_STATS_DIALOG *const self)
|
|||
? (STATS_COMMON *)&g_SaveGame.current_stats
|
||||
: (STATS_COMMON *)&g_SaveGame.start[self->args.level_num].stats;
|
||||
M_AddRowFromRole(self, M_ROW_TIMER, stats);
|
||||
if (g_GF_NumSecrets != 0) {
|
||||
if (stats->max_secret_count != 0) {
|
||||
M_AddRowFromRole(self, M_ROW_LEVEL_SECRETS, stats);
|
||||
}
|
||||
M_AddRowFromRole(self, M_ROW_KILLS, stats);
|
||||
|
|
|
@ -87,6 +87,7 @@ typedef struct STATS_COMMON {
|
|||
uint32_t distance;
|
||||
uint16_t kills;
|
||||
uint8_t medipacks;
|
||||
uint16_t max_secret_count;
|
||||
} STATS_COMMON;
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue