inject: refactor floor data injection

Floor data injection now uses the common parser in `room.c`. This means
making the sector populator public and passing additional arguments to
allow parsing from index 0.
This commit is contained in:
lahm86 2024-08-09 12:09:59 +01:00
parent 78862ed321
commit f96220acb5
4 changed files with 30 additions and 121 deletions

View file

@ -4,6 +4,7 @@
#include "game/gamebuf.h"
#include "game/output.h"
#include "game/packer.h"
#include "game/room.h"
#include "global/const.h"
#include "global/vars.h"
#include "items.h"
@ -19,6 +20,7 @@
#define INJECTION_MAGIC MKTAG('T', '1', 'M', 'J')
#define INJECTION_CURRENT_VERSION 7
#define NULL_FD_INDEX ((uint16_t)(-1))
typedef enum INJECTION_VERSION {
INJ_VERSION_1 = 1,
@ -1163,65 +1165,13 @@ static void Inject_TriggerParameterChange(
const int16_t old_param = File_ReadS16(fp);
const int16_t new_param = File_ReadS16(fp);
if (!sector) {
return;
}
// If we can find an action item for the given sector that matches
// the command type and old (current) parameter, change it to the
// new parameter.
uint16_t fd_index = sector->index;
if (!fd_index) {
return;
}
while (1) {
uint16_t data = g_FloorData[fd_index++];
switch (data & DATA_TYPE) {
case FT_DOOR:
case FT_ROOF:
case FT_TILT:
fd_index++;
break;
case FT_LAVA:
break;
case FT_TRIGGER: {
uint16_t trig_type = (data & 0x3F00) >> 8;
fd_index++; // skip trigger setup
if (trig_type == TT_SWITCH || trig_type == TT_KEY
|| trig_type == TT_PICKUP) {
fd_index++; // skip entity reference
}
while (1) {
int16_t *command = &g_FloorData[fd_index++];
if (TRIG_BITS(*command) == cmd_type) {
int16_t param = *command & VALUE_BITS;
if (param == old_param) {
*command =
(*command & ~VALUE_BITS) | (new_param & VALUE_BITS);
return;
}
}
if (TRIG_BITS(*command) == TO_CAMERA) {
fd_index++; // skip camera setup
}
if (*command & END_BIT) {
break;
}
}
break;
}
}
if (data & END_BIT) {
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
TRIGGER_CMD *const cmd = &sector->trigger->commands[i];
if (cmd->type == cmd_type && cmd->parameter == old_param) {
cmd->parameter = new_param;
break;
}
}
@ -1229,57 +1179,14 @@ static void Inject_TriggerParameterChange(
static void Inject_SetMusicOneShot(SECTOR_INFO *sector)
{
if (!sector) {
if (sector == NULL || sector->trigger == NULL) {
return;
}
uint16_t fd_index = sector->index;
if (!fd_index) {
return;
}
while (1) {
uint16_t data = g_FloorData[fd_index++];
switch (data & DATA_TYPE) {
case FT_DOOR:
case FT_ROOF:
case FT_TILT:
fd_index++;
break;
case FT_LAVA:
break;
case FT_TRIGGER: {
uint16_t trig_type = TRIG_TYPE(data);
int16_t *flags = &g_FloorData[fd_index++];
if (trig_type == TT_SWITCH || trig_type == TT_KEY
|| trig_type == TT_PICKUP) {
fd_index++; // skip entity reference
}
while (1) {
int16_t *command = &g_FloorData[fd_index++];
if (TRIG_BITS(*command) == TO_CD) {
*flags |= IF_ONESHOT;
return;
}
if (TRIG_BITS(*command) == TO_CAMERA) {
fd_index++; // skip camera setup
}
if (*command & END_BIT) {
break;
}
}
return;
}
}
if (data & END_BIT) {
break;
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
const TRIGGER_CMD *const cmd = &sector->trigger->commands[i];
if (cmd->type == TO_CD) {
sector->trigger->one_shot = true;
}
}
}
@ -1294,16 +1201,14 @@ static void Inject_InsertFloorData(
int16_t data[data_length];
File_ReadItems(fp, data, sizeof(int16_t), data_length);
if (!sector) {
if (sector == NULL) {
return;
}
sector->index = level_info->floor_data_size;
for (int32_t i = 0; i < data_length; i++) {
g_FloorData[level_info->floor_data_size + i] = data[i];
}
level_info->floor_data_size += data_length;
// This will reset all FD properties in the sector based on the raw data
// imported. We pass a dummy null index to allow it to read from the
// beginning of the array.
Room_PopulateSectorData(sector, data, 0, NULL_FD_INDEX);
}
static void Inject_RoomShift(INJECTION *injection, int16_t room_num)

View file

@ -851,13 +851,13 @@ static bool Level_LoadTexturePages(MYFILE *fp)
static void Level_CompleteSetup(int32_t level_num)
{
Inject_AllInjections(&m_LevelInfo);
// Expand raw floor data into sectors
Room_ParseFloorData(g_FloorData);
// TODO: store raw FD temporarily in m_LevelInfo, release here and eliminate
// g_FloorData
Inject_AllInjections(&m_LevelInfo);
// Must be called post-injection to allow for floor data changes.
Stats_ObserveRoomsLoad();

View file

@ -21,6 +21,7 @@
#include <assert.h>
#include <stddef.h>
#define NULL_FD_INDEX 0
#define NEG_TILT(T, H) ((T * (H & (WALL_L - 1))) >> 2)
#define POS_TILT(T, H) ((T * ((WALL_L - 1 - H) & (WALL_L - 1))) >> 2)
@ -41,9 +42,6 @@ static int16_t Room_GetCeilingTiltHeight(
static SECTOR_INFO *Room_GetSkySector(
const SECTOR_INFO *sector, int32_t x, int32_t z);
static void Room_PopulateSectorData(
SECTOR_INFO *sector, const int16_t *floor_data);
static void Room_TriggerMusicTrack(int16_t track, const TRIGGER *const trigger)
{
if (track == MX_UNUSED_0 && trigger->type == TT_ANTIPAD) {
@ -622,13 +620,16 @@ void Room_ParseFloorData(const int16_t *floor_data)
for (int32_t i = 0; i < g_RoomCount; i++) {
const ROOM_INFO *const room = &g_RoomInfo[i];
for (int32_t j = 0; j < room->x_size * room->z_size; j++) {
Room_PopulateSectorData(&room->sectors[j], floor_data);
SECTOR_INFO *const sector = &room->sectors[j];
Room_PopulateSectorData(
&room->sectors[j], floor_data, sector->index, NULL_FD_INDEX);
}
}
}
static void Room_PopulateSectorData(
SECTOR_INFO *const sector, const int16_t *floor_data)
void Room_PopulateSectorData(
SECTOR_INFO *const sector, const int16_t *floor_data,
const uint16_t start_index, const uint16_t null_index)
{
sector->floor.tilt = 0;
sector->ceiling.tilt = 0;
@ -636,11 +637,11 @@ static void Room_PopulateSectorData(
sector->is_death_sector = false;
sector->trigger = NULL;
if (sector->index == 0) {
if (start_index == null_index) {
return;
}
const int16_t *data = &floor_data[sector->index];
const int16_t *data = &floor_data[start_index];
int16_t fd_entry;
do {
fd_entry = *data++;

View file

@ -30,6 +30,9 @@ int16_t Room_GetIndexFromPos(int32_t x, int32_t y, int32_t z);
void Room_AlterFloorHeight(ITEM_INFO *item, int32_t height);
void Room_ParseFloorData(const int16_t *floor_data);
void Room_PopulateSectorData(
SECTOR_INFO *sector, const int16_t *floor_data, uint16_t start_index,
uint16_t null_index);
void Room_TestTriggers(const ITEM_INFO *item);
void Room_FlipMap(void);
bool Room_IsOnWalkable(