mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
parent
25feac8f80
commit
376b2633f4
13 changed files with 145 additions and 26 deletions
|
@ -5,6 +5,7 @@
|
|||
- fixed Lara never stepping backwards off a step using her right foot (#1602)
|
||||
- fixed blood spawning on Lara from gunshots using incorrect positioning data (#2253)
|
||||
- fixed Lara activating triggers one frame too early (#2205, regression from 0.7)
|
||||
- fixed savegame incompatibility with OG (#2271, regression from 0.8)
|
||||
- fixed stopwatch showing wrong UI in some circumstances (#2221, regression from 0.8)
|
||||
- fixed excessive braid movement when dead in windy rooms (#2265, regression from 0.8)
|
||||
- fixed item counter shown even for a single medipack (#2222, regression from 0.3)
|
||||
|
|
|
@ -586,7 +586,6 @@ typedef struct __unaligned {
|
|||
uint32_t hits;
|
||||
uint32_t distance;
|
||||
uint16_t kills;
|
||||
uint16_ secrets_count;
|
||||
uint8_t secrets_flags;
|
||||
uint8_t medipacks;
|
||||
} STATISTICS_INFO;
|
||||
|
|
|
@ -388,7 +388,7 @@ void InitialiseLevelFlags(void)
|
|||
g_SaveGame.current_stats.ammo_hits = 0;
|
||||
g_SaveGame.current_stats.ammo_used = 0;
|
||||
g_SaveGame.current_stats.medipacks = 0;
|
||||
g_SaveGame.current_stats.secrets_bitmap = 0;
|
||||
g_SaveGame.current_stats.secret_flags = 0;
|
||||
}
|
||||
|
||||
void GetCarriedItems(void)
|
||||
|
|
|
@ -45,6 +45,8 @@ static void M_Read(void *ptr, size_t size);
|
|||
#define SPECIAL_READ_WRITE(name, type) static type M_Read##name(void);
|
||||
SPECIAL_READ_WRITES
|
||||
static void M_Skip(size_t size);
|
||||
static void M_ReadStartInfo(MYFILE *fp, START_INFO *start);
|
||||
static void M_ReadStats(MYFILE *fp, LEVEL_STATS *const stats);
|
||||
static void M_ReadItems(void);
|
||||
static void M_ReadLara(LARA_INFO *lara);
|
||||
static void M_ReadLaraArm(LARA_ARM *arm);
|
||||
|
@ -55,6 +57,8 @@ static void M_Write(const void *ptr, size_t size);
|
|||
#undef SPECIAL_READ_WRITE
|
||||
#define SPECIAL_READ_WRITE(name, type) static void M_Write##name(type value);
|
||||
SPECIAL_READ_WRITES
|
||||
static void M_WriteStartInfo(MYFILE *fp, const START_INFO *start);
|
||||
static void M_WriteStats(MYFILE *fp, const LEVEL_STATS *stats);
|
||||
static void M_WriteItems(void);
|
||||
static void M_WriteLara(const LARA_INFO *lara);
|
||||
static void M_WriteLaraArm(const LARA_ARM *arm);
|
||||
|
@ -90,6 +94,49 @@ static void M_Skip(const size_t size)
|
|||
m_BufPtr += size;
|
||||
}
|
||||
|
||||
static void M_ReadStartInfo(MYFILE *const fp, START_INFO *const start)
|
||||
{
|
||||
start->pistol_ammo = File_ReadU16(fp);
|
||||
start->magnum_ammo = File_ReadU16(fp);
|
||||
start->uzi_ammo = File_ReadU16(fp);
|
||||
start->shotgun_ammo = File_ReadU16(fp);
|
||||
start->m16_ammo = File_ReadU16(fp);
|
||||
start->grenade_ammo = File_ReadU16(fp);
|
||||
start->harpoon_ammo = File_ReadU16(fp);
|
||||
start->small_medipacks = File_ReadU8(fp);
|
||||
start->large_medipacks = File_ReadU8(fp);
|
||||
start->reserved1 = File_ReadU8(fp);
|
||||
start->flares = File_ReadU8(fp);
|
||||
start->gun_status = File_ReadU8(fp);
|
||||
start->gun_type = File_ReadU8(fp);
|
||||
|
||||
const uint16_t flags = File_ReadU16(fp);
|
||||
// clang-format off
|
||||
start->available = (flags & 0x01) ? 1 : 0;
|
||||
start->has_pistols = (flags & 0x02) ? 1 : 0;
|
||||
start->has_magnums = (flags & 0x04) ? 1 : 0;
|
||||
start->has_uzis = (flags & 0x08) ? 1 : 0;
|
||||
start->has_shotgun = (flags & 0x10) ? 1 : 0;
|
||||
start->has_m16 = (flags & 0x20) ? 1 : 0;
|
||||
start->has_grenade = (flags & 0x40) ? 1 : 0;
|
||||
start->has_harpoon = (flags & 0x80) ? 1 : 0;
|
||||
// clang-format on
|
||||
|
||||
File_ReadU16(fp);
|
||||
M_ReadStats(fp, &start->stats);
|
||||
}
|
||||
|
||||
static void M_ReadStats(MYFILE *const fp, LEVEL_STATS *const stats)
|
||||
{
|
||||
stats->timer = File_ReadU32(fp);
|
||||
stats->ammo_used = File_ReadU32(fp);
|
||||
stats->ammo_hits = File_ReadU32(fp);
|
||||
stats->distance = File_ReadU32(fp);
|
||||
stats->kills = File_ReadU16(fp);
|
||||
stats->secret_flags = File_ReadU8(fp);
|
||||
stats->medipacks = File_ReadU8(fp);
|
||||
}
|
||||
|
||||
static void M_ReadItems(void)
|
||||
{
|
||||
for (int32_t item_num = 0; item_num < g_LevelItemCount; item_num++) {
|
||||
|
@ -358,6 +405,50 @@ static void M_Write(const void *ptr, const size_t size)
|
|||
WriteSG(ptr, size);
|
||||
}
|
||||
|
||||
static void M_WriteStartInfo(MYFILE *const fp, const START_INFO *const start)
|
||||
{
|
||||
File_WriteU16(fp, start->pistol_ammo);
|
||||
File_WriteU16(fp, start->magnum_ammo);
|
||||
File_WriteU16(fp, start->uzi_ammo);
|
||||
File_WriteU16(fp, start->shotgun_ammo);
|
||||
File_WriteU16(fp, start->m16_ammo);
|
||||
File_WriteU16(fp, start->grenade_ammo);
|
||||
File_WriteU16(fp, start->harpoon_ammo);
|
||||
File_WriteU8(fp, start->small_medipacks);
|
||||
File_WriteU8(fp, start->large_medipacks);
|
||||
File_WriteU8(fp, start->reserved1);
|
||||
File_WriteU8(fp, start->flares);
|
||||
File_WriteU8(fp, start->gun_status);
|
||||
File_WriteU8(fp, start->gun_type);
|
||||
|
||||
uint16_t flags = 0;
|
||||
// clang-format off
|
||||
if (start->available) { flags |= 0x01; }
|
||||
if (start->has_pistols) { flags |= 0x02; }
|
||||
if (start->has_magnums) { flags |= 0x04; }
|
||||
if (start->has_uzis) { flags |= 0x08; }
|
||||
if (start->has_shotgun) { flags |= 0x10; }
|
||||
if (start->has_m16) { flags |= 0x20; }
|
||||
if (start->has_grenade) { flags |= 0x40; }
|
||||
if (start->has_harpoon) { flags |= 0x80; }
|
||||
// clang-format on
|
||||
File_WriteU16(fp, flags);
|
||||
|
||||
File_WriteU16(fp, 0);
|
||||
M_WriteStats(fp, &start->stats);
|
||||
}
|
||||
|
||||
static void M_WriteStats(MYFILE *const fp, const LEVEL_STATS *const stats)
|
||||
{
|
||||
File_WriteU32(fp, stats->timer);
|
||||
File_WriteU32(fp, stats->ammo_used);
|
||||
File_WriteU32(fp, stats->ammo_hits);
|
||||
File_WriteU32(fp, stats->distance);
|
||||
File_WriteU16(fp, stats->kills);
|
||||
File_WriteU8(fp, stats->secret_flags);
|
||||
File_WriteU8(fp, stats->medipacks);
|
||||
}
|
||||
|
||||
static void M_WriteItems(void)
|
||||
{
|
||||
for (int32_t i = 0; i < g_LevelItemCount; i++) {
|
||||
|
@ -559,7 +650,7 @@ void InitialiseStartInfo(void)
|
|||
g_SaveGame.start[i].stats.distance = 0;
|
||||
g_SaveGame.start[i].stats.kills = 0;
|
||||
g_SaveGame.start[i].stats.medipacks = 0;
|
||||
g_SaveGame.start[i].stats.secrets_bitmap = 0;
|
||||
g_SaveGame.start[i].stats.secret_flags = 0;
|
||||
}
|
||||
|
||||
g_SaveGame.start[LV_GYM].available = 1;
|
||||
|
@ -910,8 +1001,7 @@ bool S_FrontEndCheck(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
int32_t S_SaveGame(
|
||||
const void *const save_data, const size_t save_size, const int32_t slot_num)
|
||||
int32_t S_SaveGame(const int32_t slot_num)
|
||||
{
|
||||
char file_name[80];
|
||||
sprintf(file_name, "savegame.%d", slot_num);
|
||||
|
@ -924,7 +1014,23 @@ int32_t S_SaveGame(
|
|||
sprintf(file_name, "%s", g_GF_LevelNames[g_SaveGame.current_level]);
|
||||
File_WriteData(fp, file_name, 75);
|
||||
File_WriteS32(fp, g_SaveCounter);
|
||||
File_WriteData(fp, save_data, save_size);
|
||||
for (int32_t i = 0; i < 24; i++) {
|
||||
M_WriteStartInfo(fp, &g_SaveGame.start[i]);
|
||||
}
|
||||
M_WriteStats(fp, &g_SaveGame.current_stats);
|
||||
File_WriteS16(fp, g_SaveGame.current_level);
|
||||
File_WriteU8(fp, g_SaveGame.bonus_flag);
|
||||
for (int32_t i = 0; i < 2; i++) {
|
||||
File_WriteU8(fp, g_SaveGame.num_pickup[i]);
|
||||
}
|
||||
for (int32_t i = 0; i < 4; i++) {
|
||||
File_WriteU8(fp, g_SaveGame.num_puzzle[i]);
|
||||
}
|
||||
for (int32_t i = 0; i < 4; i++) {
|
||||
File_WriteU8(fp, g_SaveGame.num_key[i]);
|
||||
}
|
||||
File_WriteS16(fp, 0);
|
||||
File_WriteData(fp, g_SaveGame.buffer, MAX_SG_BUFFER_SIZE);
|
||||
File_Close(fp);
|
||||
|
||||
char save_num_text[16];
|
||||
|
@ -942,8 +1048,7 @@ int32_t S_SaveGame(
|
|||
return true;
|
||||
}
|
||||
|
||||
int32_t S_LoadGame(
|
||||
void *const save_data, const size_t save_size, const int32_t slot_num)
|
||||
int32_t S_LoadGame(const int32_t slot_num)
|
||||
{
|
||||
char file_name[80];
|
||||
sprintf(file_name, "savegame.%d", slot_num);
|
||||
|
@ -954,7 +1059,23 @@ int32_t S_LoadGame(
|
|||
}
|
||||
File_Skip(fp, 75);
|
||||
File_Skip(fp, 4);
|
||||
File_ReadData(fp, save_data, save_size);
|
||||
for (int32_t i = 0; i < 24; i++) {
|
||||
M_ReadStartInfo(fp, &g_SaveGame.start[i]);
|
||||
}
|
||||
M_ReadStats(fp, &g_SaveGame.current_stats);
|
||||
g_SaveGame.current_level = File_ReadS16(fp);
|
||||
g_SaveGame.bonus_flag = File_ReadU8(fp);
|
||||
for (int32_t i = 0; i < 2; i++) {
|
||||
g_SaveGame.num_pickup[i] = File_ReadU8(fp);
|
||||
}
|
||||
for (int32_t i = 0; i < 4; i++) {
|
||||
g_SaveGame.num_puzzle[i] = File_ReadU8(fp);
|
||||
}
|
||||
for (int32_t i = 0; i < 4; i++) {
|
||||
g_SaveGame.num_key[i] = File_ReadU8(fp);
|
||||
}
|
||||
File_ReadS16(fp);
|
||||
File_ReadData(fp, g_SaveGame.buffer, MAX_SG_BUFFER_SIZE);
|
||||
File_Close(fp);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@ void ReadSG(void *pointer, size_t size);
|
|||
|
||||
void GetSavedGamesList(REQUEST_INFO *req);
|
||||
bool S_FrontEndCheck(void);
|
||||
int32_t S_SaveGame(const void *save_data, size_t save_size, int32_t slot_num);
|
||||
int32_t S_LoadGame(void *save_data, size_t save_size, int32_t slot_num);
|
||||
int32_t S_SaveGame(int32_t slot_num);
|
||||
int32_t S_LoadGame(int32_t slot_num);
|
||||
|
|
|
@ -206,15 +206,15 @@ bool Inv_AddItem(const GAME_OBJECT_ID object_id)
|
|||
return true;
|
||||
|
||||
case O_SECRET_1:
|
||||
g_SaveGame.current_stats.secrets_bitmap |= 1;
|
||||
g_SaveGame.current_stats.secret_flags |= 1;
|
||||
return true;
|
||||
|
||||
case O_SECRET_2:
|
||||
g_SaveGame.current_stats.secrets_bitmap |= 2;
|
||||
g_SaveGame.current_stats.secret_flags |= 2;
|
||||
return true;
|
||||
|
||||
case O_SECRET_3:
|
||||
g_SaveGame.current_stats.secrets_bitmap |= 4;
|
||||
g_SaveGame.current_stats.secret_flags |= 4;
|
||||
return true;
|
||||
|
||||
case O_KEY_ITEM_1:
|
||||
|
|
|
@ -754,8 +754,7 @@ GAME_FLOW_COMMAND InvRing_Close(INV_RING *const ring)
|
|||
if (g_Inv_ExtraData[0] == 0) {
|
||||
// first passport page: load game.
|
||||
Inv_RemoveAllItems();
|
||||
S_LoadGame(
|
||||
&g_SaveGame, sizeof(SAVEGAME_INFO), g_Inv_ExtraData[1]);
|
||||
S_LoadGame(g_Inv_ExtraData[1]);
|
||||
gf_cmd = (GAME_FLOW_COMMAND) {
|
||||
.action = GF_START_SAVED_GAME,
|
||||
.param = g_Inv_ExtraData[1],
|
||||
|
@ -792,8 +791,7 @@ GAME_FLOW_COMMAND InvRing_Close(INV_RING *const ring)
|
|||
} else {
|
||||
CreateSaveGameInfo();
|
||||
const int16_t slot_num = g_Inv_ExtraData[1];
|
||||
S_SaveGame(
|
||||
&g_SaveGame, sizeof(SAVEGAME_INFO), slot_num);
|
||||
S_SaveGame(slot_num);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -55,9 +55,9 @@ static void M_DoPickup(const int16_t item_num)
|
|||
|
||||
if ((item->object_id == O_SECRET_1 || item->object_id == O_SECRET_2
|
||||
|| item->object_id == O_SECRET_3)
|
||||
&& (g_SaveGame.current_stats.secrets_bitmap & 1)
|
||||
+ ((g_SaveGame.current_stats.secrets_bitmap >> 1) & 1)
|
||||
+ ((g_SaveGame.current_stats.secrets_bitmap >> 2) & 1)
|
||||
&& (g_SaveGame.current_stats.secret_flags & 1)
|
||||
+ ((g_SaveGame.current_stats.secret_flags >> 1) & 1)
|
||||
+ ((g_SaveGame.current_stats.secret_flags >> 2) & 1)
|
||||
>= 3) {
|
||||
GF_ModifyInventory(g_CurrentLevel, 1);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ bool Savegame_IsSlotFree(const int32_t slot_idx)
|
|||
bool Savegame_Save(const int32_t slot_idx)
|
||||
{
|
||||
CreateSaveGameInfo();
|
||||
S_SaveGame(&g_SaveGame, sizeof(SAVEGAME_INFO), slot_idx);
|
||||
S_SaveGame(slot_idx);
|
||||
GetSavedGamesList(&g_LoadGameRequester);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -410,7 +410,7 @@ void Shell_Main(void)
|
|||
break;
|
||||
|
||||
case GF_START_SAVED_GAME:
|
||||
S_LoadGame(&g_SaveGame, sizeof(SAVEGAME_INFO), gf_cmd.param);
|
||||
S_LoadGame(gf_cmd.param);
|
||||
if (g_SaveGame.current_level > g_GameFlow.num_levels) {
|
||||
Shell_ExitSystemFmt(
|
||||
"GameMain: STARTSAVEDGAME with invalid level number (%d)",
|
||||
|
|
|
@ -47,7 +47,7 @@ FINAL_STATS Stats_ComputeFinalStats(void)
|
|||
// TODO: #170, consult GFE_NUM_SECRETS rather than hardcoding this
|
||||
if (i < total_levels - 2) {
|
||||
for (int32_t j = 0; j < 3; j++) {
|
||||
if (g_SaveGame.start[i].stats.secrets_bitmap & (1 << j)) {
|
||||
if (g_SaveGame.start[i].stats.secret_flags & (1 << j)) {
|
||||
result.found_secrets++;
|
||||
}
|
||||
result.total_secrets++;
|
||||
|
|
|
@ -82,7 +82,7 @@ static void M_AddRowFromRole(
|
|||
char *ptr = buf;
|
||||
int32_t num_secrets = 0;
|
||||
for (int32_t i = 0; i < 3; i++) {
|
||||
if (((LEVEL_STATS *)stats)->secrets_bitmap & (1 << i)) {
|
||||
if (((LEVEL_STATS *)stats)->secret_flags & (1 << i)) {
|
||||
sprintf(ptr, "\\{secret %d}", i + 1);
|
||||
num_secrets++;
|
||||
} else {
|
||||
|
|
|
@ -165,7 +165,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
struct STATS_COMMON;
|
||||
uint8_t secrets_bitmap;
|
||||
uint8_t secret_flags;
|
||||
} LEVEL_STATS;
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue