mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
room: refactor lava and trigger interpretation
This creates an is_death_sector property on sectors and updates the checks for when this is applicable in terms of collision and trigger checks. Triggers are also now directly in sectors, and their list of commands. Most duplicated FD iterations are now removed; injection logic to follow suit and use the new approach.
This commit is contained in:
parent
3405e8ca80
commit
da2353e05f
18 changed files with 282 additions and 396 deletions
|
@ -782,20 +782,14 @@ void Camera_UpdateCutscene(void)
|
||||||
Viewport_SetFOV(ref->fov);
|
Viewport_SetFOV(ref->fov);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera_RefreshFromTrigger(int16_t type, int16_t *data)
|
void Camera_RefreshFromTrigger(const TRIGGER *const trigger)
|
||||||
{
|
{
|
||||||
int16_t trigger;
|
|
||||||
int16_t target_ok = 2;
|
int16_t target_ok = 2;
|
||||||
do {
|
for (int32_t i = 0; i < trigger->command_count; i++) {
|
||||||
trigger = *data++;
|
const TRIGGER_CMD *const cmd = &trigger->commands[i];
|
||||||
int16_t value = trigger & VALUE_BITS;
|
if (cmd->type == TO_CAMERA) {
|
||||||
|
if (cmd->parameter == g_Camera.last) {
|
||||||
switch (TRIG_BITS(trigger)) {
|
g_Camera.number = cmd->parameter;
|
||||||
case TO_CAMERA:
|
|
||||||
trigger = *data++;
|
|
||||||
|
|
||||||
if (value == g_Camera.last) {
|
|
||||||
g_Camera.number = value;
|
|
||||||
|
|
||||||
if (g_Camera.timer < 0 || g_Camera.type == CAM_LOOK
|
if (g_Camera.timer < 0 || g_Camera.type == CAM_LOOK
|
||||||
|| g_Camera.type == CAM_COMBAT) {
|
|| g_Camera.type == CAM_COMBAT) {
|
||||||
|
@ -808,15 +802,12 @@ void Camera_RefreshFromTrigger(int16_t type, int16_t *data)
|
||||||
} else {
|
} else {
|
||||||
target_ok = 0;
|
target_ok = 0;
|
||||||
}
|
}
|
||||||
break;
|
} else if (cmd->type == TO_TARGET) {
|
||||||
|
|
||||||
case TO_TARGET:
|
|
||||||
if (g_Camera.type != CAM_LOOK && g_Camera.type != CAM_COMBAT) {
|
if (g_Camera.type != CAM_LOOK && g_Camera.type != CAM_COMBAT) {
|
||||||
g_Camera.item = &g_Items[value];
|
g_Camera.item = &g_Items[cmd->parameter];
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (!(trigger & END_BIT));
|
}
|
||||||
|
|
||||||
if (g_Camera.item != NULL) {
|
if (g_Camera.item != NULL) {
|
||||||
if (!target_ok
|
if (!target_ok
|
||||||
|
|
|
@ -14,6 +14,6 @@ void Camera_Fixed(void);
|
||||||
void Camera_Update(void);
|
void Camera_Update(void);
|
||||||
void Camera_UpdateCutscene(void);
|
void Camera_UpdateCutscene(void);
|
||||||
void Camera_OffsetReset(void);
|
void Camera_OffsetReset(void);
|
||||||
void Camera_RefreshFromTrigger(int16_t type, int16_t *data);
|
void Camera_RefreshFromTrigger(const TRIGGER *trigger);
|
||||||
void Camera_MoveManual(void);
|
void Camera_MoveManual(void);
|
||||||
void Camera_Apply(void);
|
void Camera_Apply(void);
|
||||||
|
|
|
@ -135,8 +135,8 @@ void Collide_GetCollisionInfo(
|
||||||
&& coll->front_floor > 0) {
|
&& coll->front_floor > 0) {
|
||||||
coll->front_floor = 512;
|
coll->front_floor = 512;
|
||||||
} else if (
|
} else if (
|
||||||
coll->lava_is_pit && coll->front_floor > 0 && g_TriggerIndex
|
coll->lava_is_pit && coll->front_floor > 0
|
||||||
&& (g_TriggerIndex[0] & DATA_TYPE) == FT_LAVA) {
|
&& Room_GetPitSector(sector, x, z)->is_death_sector) {
|
||||||
coll->front_floor = 512;
|
coll->front_floor = 512;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,8 +170,8 @@ void Collide_GetCollisionInfo(
|
||||||
&& coll->left_floor > 0) {
|
&& coll->left_floor > 0) {
|
||||||
coll->left_floor = 512;
|
coll->left_floor = 512;
|
||||||
} else if (
|
} else if (
|
||||||
coll->lava_is_pit && coll->left_floor > 0 && g_TriggerIndex
|
coll->lava_is_pit && coll->left_floor > 0
|
||||||
&& (g_TriggerIndex[0] & DATA_TYPE) == FT_LAVA) {
|
&& Room_GetPitSector(sector, x, z)->is_death_sector) {
|
||||||
coll->left_floor = 512;
|
coll->left_floor = 512;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ void Collide_GetCollisionInfo(
|
||||||
&& coll->right_floor > 0) {
|
&& coll->right_floor > 0) {
|
||||||
coll->right_floor = 512;
|
coll->right_floor = 512;
|
||||||
} else if (
|
} else if (
|
||||||
coll->lava_is_pit && coll->right_floor > 0 && g_TriggerIndex
|
coll->lava_is_pit && coll->right_floor > 0
|
||||||
&& (g_TriggerIndex[0] & DATA_TYPE) == FT_LAVA) {
|
&& Room_GetPitSector(sector, x, z)->is_death_sector) {
|
||||||
coll->right_floor = 512;
|
coll->right_floor = 512;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ void Lara_HandleAboveWater(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
||||||
Item_UpdateRoom(item, -LARA_HEIGHT / 2);
|
Item_UpdateRoom(item, -LARA_HEIGHT / 2);
|
||||||
Gun_Control();
|
Gun_Control();
|
||||||
Room_TestTriggers(coll->trigger, false);
|
Room_TestTriggers(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lara_HandleSurface(ITEM_INFO *item, COLL_INFO *coll)
|
void Lara_HandleSurface(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
|
@ -307,7 +307,7 @@ void Lara_HandleSurface(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
||||||
Item_UpdateRoom(item, 100);
|
Item_UpdateRoom(item, 100);
|
||||||
Gun_Control();
|
Gun_Control();
|
||||||
Room_TestTriggers(coll->trigger, false);
|
Room_TestTriggers(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lara_HandleUnderwater(ITEM_INFO *item, COLL_INFO *coll)
|
void Lara_HandleUnderwater(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
|
@ -397,5 +397,5 @@ void Lara_HandleUnderwater(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
g_LaraCollisionRoutines[item->current_anim_state](item, coll);
|
||||||
Item_UpdateRoom(item, 0);
|
Item_UpdateRoom(item, 0);
|
||||||
Gun_Control();
|
Gun_Control();
|
||||||
Room_TestTriggers(coll->trigger, false);
|
Room_TestTriggers(item);
|
||||||
}
|
}
|
||||||
|
|
|
@ -556,7 +556,7 @@ bool Lara_LandedBad(ITEM_INFO *item, COLL_INFO *coll)
|
||||||
|
|
||||||
item->floor = height;
|
item->floor = height;
|
||||||
item->pos.y = height;
|
item->pos.y = height;
|
||||||
Room_TestTriggers(g_TriggerIndex, false);
|
Room_TestTriggers(item);
|
||||||
item->pos.y = old_y;
|
item->pos.y = old_y;
|
||||||
|
|
||||||
int landspeed = item->fall_speed - DAMAGE_START;
|
int landspeed = item->fall_speed - DAMAGE_START;
|
||||||
|
|
|
@ -116,13 +116,11 @@ void BaconLara_Control(int16_t item_num)
|
||||||
const int32_t h = Room_GetHeight(sector, x, y, z);
|
const int32_t h = Room_GetHeight(sector, x, y, z);
|
||||||
item->floor = h;
|
item->floor = h;
|
||||||
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
Room_TestTriggers(item);
|
||||||
if (item->pos.y >= h) {
|
if (item->pos.y >= h) {
|
||||||
item->floor = h;
|
item->floor = h;
|
||||||
item->pos.y = h;
|
item->pos.y = h;
|
||||||
sector = Room_GetSector(x, h, z, &room_num);
|
Room_TestTriggers(item);
|
||||||
Room_GetHeight(sector, x, h, z);
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
|
||||||
item->gravity_status = 0;
|
item->gravity_status = 0;
|
||||||
item->fall_speed = 0;
|
item->fall_speed = 0;
|
||||||
item->goal_anim_state = LS_DEATH;
|
item->goal_anim_state = LS_DEATH;
|
||||||
|
|
|
@ -255,10 +255,7 @@ void Torso_Control(int16_t item_num)
|
||||||
if (item->status == IS_DEACTIVATED) {
|
if (item->status == IS_DEACTIVATED) {
|
||||||
Sound_Effect(SFX_ATLANTEAN_DEATH, &item->pos, SPM_NORMAL);
|
Sound_Effect(SFX_ATLANTEAN_DEATH, &item->pos, SPM_NORMAL);
|
||||||
Effect_ExplodingDeath(item_num, -1, TORSO_PART_DAMAGE);
|
Effect_ExplodingDeath(item_num, -1, TORSO_PART_DAMAGE);
|
||||||
const SECTOR_INFO *const sector = Room_GetSector(
|
Room_TestTriggers(item);
|
||||||
item->pos.x, item->pos.y, item->pos.z, &item->room_number);
|
|
||||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
|
||||||
|
|
||||||
Item_Kill(item_num);
|
Item_Kill(item_num);
|
||||||
item->status = IS_DEACTIVATED;
|
item->status = IS_DEACTIVATED;
|
||||||
|
|
|
@ -116,11 +116,7 @@ void Scion_Control3(int16_t item_num)
|
||||||
if (counter == 0) {
|
if (counter == 0) {
|
||||||
item->status = IS_INVISIBLE;
|
item->status = IS_INVISIBLE;
|
||||||
item->hit_points = DONT_TARGET;
|
item->hit_points = DONT_TARGET;
|
||||||
int16_t room_num = item->room_number;
|
Room_TestTriggers(item);
|
||||||
const SECTOR_INFO *const sector =
|
|
||||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
|
||||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
|
||||||
Item_RemoveDrawn(item_num);
|
Item_RemoveDrawn(item_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#define LAVA_EMBER_DAMAGE 10
|
#define LAVA_EMBER_DAMAGE 10
|
||||||
#define LAVA_WEDGE_SPEED 25
|
#define LAVA_WEDGE_SPEED 25
|
||||||
|
|
||||||
bool Lava_TestFloor(ITEM_INFO *item)
|
bool Lava_TestFloor(const ITEM_INFO *const item)
|
||||||
{
|
{
|
||||||
if (item->hit_points < 0 || g_Lara.water_status == LWS_CHEAT
|
if (item->hit_points < 0 || g_Lara.water_status == LWS_CHEAT
|
||||||
|| (g_Lara.water_status == LWS_ABOVE_WATER
|
|| (g_Lara.water_status == LWS_ABOVE_WATER
|
||||||
|
@ -25,40 +25,11 @@ bool Lava_TestFloor(ITEM_INFO *item)
|
||||||
// OG fix: check if floor index has lava
|
// OG fix: check if floor index has lava
|
||||||
int16_t room_num = item->room_number;
|
int16_t room_num = item->room_number;
|
||||||
const SECTOR_INFO *const sector =
|
const SECTOR_INFO *const sector =
|
||||||
Room_GetSector(item->pos.x, 32000, item->pos.z, &room_num);
|
Room_GetSector(item->pos.x, MAX_HEIGHT, item->pos.z, &room_num);
|
||||||
|
return sector->is_death_sector;
|
||||||
int16_t *data = &g_FloorData[sector->index];
|
|
||||||
int16_t type;
|
|
||||||
do {
|
|
||||||
type = *data++;
|
|
||||||
|
|
||||||
switch (type & DATA_TYPE) {
|
|
||||||
case FT_TILT: {
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FT_ROOF:
|
|
||||||
case FT_DOOR:
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_LAVA:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case FT_TRIGGER:
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (!(type & END_BIT));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lava_Burn(ITEM_INFO *item)
|
void Lava_Burn(ITEM_INFO *const item)
|
||||||
{
|
{
|
||||||
if (g_Lara.water_status == LWS_CHEAT) {
|
if (g_Lara.water_status == LWS_CHEAT) {
|
||||||
return;
|
return;
|
||||||
|
@ -70,8 +41,9 @@ void Lava_Burn(ITEM_INFO *item)
|
||||||
|
|
||||||
int16_t room_num = item->room_number;
|
int16_t room_num = item->room_number;
|
||||||
const SECTOR_INFO *const sector =
|
const SECTOR_INFO *const sector =
|
||||||
Room_GetSector(item->pos.x, 32000, item->pos.z, &room_num);
|
Room_GetSector(item->pos.x, MAX_HEIGHT, item->pos.z, &room_num);
|
||||||
int16_t height = Room_GetHeight(sector, item->pos.x, 32000, item->pos.z);
|
const int16_t height =
|
||||||
|
Room_GetHeight(sector, item->pos.x, MAX_HEIGHT, item->pos.z);
|
||||||
|
|
||||||
if (item->floor != height) {
|
if (item->floor != height) {
|
||||||
return;
|
return;
|
||||||
|
@ -84,7 +56,7 @@ void Lava_Burn(ITEM_INFO *item)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
int16_t fx_num = Effect_Create(item->room_number);
|
const int16_t fx_num = Effect_Create(item->room_number);
|
||||||
if (fx_num != NO_ITEM) {
|
if (fx_num != NO_ITEM) {
|
||||||
FX_INFO *fx = &g_Effects[fx_num];
|
FX_INFO *fx = &g_Effects[fx_num];
|
||||||
fx->object_number = O_FLAME;
|
fx->object_number = O_FLAME;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
bool Lava_TestFloor(ITEM_INFO *item);
|
bool Lava_TestFloor(const ITEM_INFO *item);
|
||||||
void Lava_Burn(ITEM_INFO *item);
|
void Lava_Burn(ITEM_INFO *item);
|
||||||
|
|
||||||
void Lava_Setup(OBJECT_INFO *obj);
|
void Lava_Setup(OBJECT_INFO *obj);
|
||||||
|
|
|
@ -276,12 +276,7 @@ void MovableBlock_Control(int16_t item_num)
|
||||||
item->status = IS_NOT_ACTIVE;
|
item->status = IS_NOT_ACTIVE;
|
||||||
Item_RemoveActive(item_num);
|
Item_RemoveActive(item_num);
|
||||||
Room_AlterFloorHeight(item, -WALL_L);
|
Room_AlterFloorHeight(item, -WALL_L);
|
||||||
|
Room_TestTriggers(item);
|
||||||
room_num = item->room_number;
|
|
||||||
sector =
|
|
||||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
|
||||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ void RollingBall_Control(int16_t item_num)
|
||||||
item->floor =
|
item->floor =
|
||||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
||||||
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
Room_TestTriggers(item);
|
||||||
|
|
||||||
if (item->pos.y >= item->floor - STEP_L) {
|
if (item->pos.y >= item->floor - STEP_L) {
|
||||||
item->gravity_status = 0;
|
item->gravity_status = 0;
|
||||||
|
|
|
@ -113,11 +113,7 @@ void ThorsHandle_Control(int16_t item_num)
|
||||||
int32_t old_x = x;
|
int32_t old_x = x;
|
||||||
int32_t old_z = z;
|
int32_t old_z = z;
|
||||||
|
|
||||||
int16_t room_num = item->room_number;
|
Room_TestTriggers(item);
|
||||||
const SECTOR_INFO *const sector =
|
|
||||||
Room_GetSector(x, item->pos.y, z, &room_num);
|
|
||||||
Room_GetHeight(sector, x, item->pos.y, z);
|
|
||||||
Room_TestTriggers(g_TriggerIndex, true);
|
|
||||||
|
|
||||||
switch (item->rot.y) {
|
switch (item->rot.y) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
426
src/game/room.c
426
src/game/room.c
|
@ -1,6 +1,7 @@
|
||||||
#include "game/room.h"
|
#include "game/room.h"
|
||||||
|
|
||||||
#include "game/camera.h"
|
#include "game/camera.h"
|
||||||
|
#include "game/gamebuf.h"
|
||||||
#include "game/items.h"
|
#include "game/items.h"
|
||||||
#include "game/lot.h"
|
#include "game/lot.h"
|
||||||
#include "game/music.h"
|
#include "game/music.h"
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
|
|
||||||
#include <libtrx/utils.h>
|
#include <libtrx/utils.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define NEG_TILT(T, H) ((T * (H & (WALL_L - 1))) >> 2)
|
#define NEG_TILT(T, H) ((T * (H & (WALL_L - 1))) >> 2)
|
||||||
|
@ -28,7 +30,7 @@ int32_t g_FlipEffect = -1;
|
||||||
int32_t g_FlipStatus = 0;
|
int32_t g_FlipStatus = 0;
|
||||||
int32_t g_FlipMapTable[MAX_FLIP_MAPS] = { 0 };
|
int32_t g_FlipMapTable[MAX_FLIP_MAPS] = { 0 };
|
||||||
|
|
||||||
static void Room_TriggerMusicTrack(int16_t track, int16_t flags, int16_t type);
|
static void Room_TriggerMusicTrack(int16_t track, const TRIGGER *const trigger);
|
||||||
static void Room_AddFlipItems(ROOM_INFO *r);
|
static void Room_AddFlipItems(ROOM_INFO *r);
|
||||||
static void Room_RemoveFlipItems(ROOM_INFO *r);
|
static void Room_RemoveFlipItems(ROOM_INFO *r);
|
||||||
|
|
||||||
|
@ -36,17 +38,15 @@ static int16_t Room_GetFloorTiltHeight(
|
||||||
const SECTOR_INFO *sector, const int32_t x, const int32_t z);
|
const SECTOR_INFO *sector, const int32_t x, const int32_t z);
|
||||||
static int16_t Room_GetCeilingTiltHeight(
|
static int16_t Room_GetCeilingTiltHeight(
|
||||||
const SECTOR_INFO *sector, const int32_t x, const int32_t z);
|
const SECTOR_INFO *sector, const int32_t x, const int32_t z);
|
||||||
static SECTOR_INFO *Room_GetPitSector(
|
|
||||||
const SECTOR_INFO *sector, int32_t x, int32_t z);
|
|
||||||
static SECTOR_INFO *Room_GetSkySector(
|
static SECTOR_INFO *Room_GetSkySector(
|
||||||
const SECTOR_INFO *sector, int32_t x, int32_t z);
|
const SECTOR_INFO *sector, int32_t x, int32_t z);
|
||||||
|
|
||||||
static void Room_PopulateSectorData(
|
static void Room_PopulateSectorData(
|
||||||
SECTOR_INFO *sector, const int16_t *floor_data);
|
SECTOR_INFO *sector, const int16_t *floor_data);
|
||||||
|
|
||||||
static void Room_TriggerMusicTrack(int16_t track, int16_t flags, int16_t type)
|
static void Room_TriggerMusicTrack(int16_t track, const TRIGGER *const trigger)
|
||||||
{
|
{
|
||||||
if (track == MX_UNUSED_0 && type == TT_ANTIPAD) {
|
if (track == MX_UNUSED_0 && trigger->type == TT_ANTIPAD) {
|
||||||
Music_Stop();
|
Music_Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -108,16 +108,16 @@ static void Room_TriggerMusicTrack(int16_t track, int16_t flags, int16_t type)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TT_SWITCH) {
|
if (trigger->type == TT_SWITCH) {
|
||||||
g_MusicTrackFlags[track] ^= flags & IF_CODE_BITS;
|
g_MusicTrackFlags[track] ^= trigger->mask;
|
||||||
} else if (type == TT_ANTIPAD) {
|
} else if (trigger->type == TT_ANTIPAD) {
|
||||||
g_MusicTrackFlags[track] &= -1 - (flags & IF_CODE_BITS);
|
g_MusicTrackFlags[track] &= -1 - trigger->mask;
|
||||||
} else if (flags & IF_CODE_BITS) {
|
} else if (trigger->mask) {
|
||||||
g_MusicTrackFlags[track] |= flags & IF_CODE_BITS;
|
g_MusicTrackFlags[track] |= trigger->mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_MusicTrackFlags[track] & IF_CODE_BITS) == IF_CODE_BITS) {
|
if ((g_MusicTrackFlags[track] & IF_CODE_BITS) == IF_CODE_BITS) {
|
||||||
if (flags & IF_ONESHOT) {
|
if (trigger->one_shot) {
|
||||||
g_MusicTrackFlags[track] |= IF_ONESHOT;
|
g_MusicTrackFlags[track] |= IF_ONESHOT;
|
||||||
}
|
}
|
||||||
Music_Play(track);
|
Music_Play(track);
|
||||||
|
@ -235,7 +235,7 @@ void Room_GetNewRoom(int32_t x, int32_t y, int32_t z, int16_t room_num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SECTOR_INFO *Room_GetPitSector(
|
SECTOR_INFO *Room_GetPitSector(
|
||||||
const SECTOR_INFO *sector, const int32_t x, const int32_t z)
|
const SECTOR_INFO *sector, const int32_t x, const int32_t z)
|
||||||
{
|
{
|
||||||
while (sector->portal_room.pit != NO_ROOM) {
|
while (sector->portal_room.pit != NO_ROOM) {
|
||||||
|
@ -344,48 +344,22 @@ int16_t Room_GetCeiling(
|
||||||
int16_t height = Room_GetCeilingTiltHeight(sky_sector, x, z);
|
int16_t height = Room_GetCeilingTiltHeight(sky_sector, x, z);
|
||||||
|
|
||||||
sector = Room_GetPitSector(sector, x, z);
|
sector = Room_GetPitSector(sector, x, z);
|
||||||
if (!sector->index) {
|
if (sector->trigger == NULL) {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = &g_FloorData[sector->index];
|
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
|
||||||
do {
|
const TRIGGER_CMD *const cmd = §or->trigger->commands[i];
|
||||||
type = *data++;
|
if (cmd->type != TO_OBJECT) {
|
||||||
|
continue;
|
||||||
switch (type & DATA_TYPE) {
|
|
||||||
case FT_DOOR:
|
|
||||||
case FT_TILT:
|
|
||||||
case FT_ROOF:
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_LAVA:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_TRIGGER:
|
|
||||||
data++;
|
|
||||||
do {
|
|
||||||
trigger = *data++;
|
|
||||||
if (TRIG_BITS(trigger) != TO_OBJECT) {
|
|
||||||
if (TRIG_BITS(trigger) == TO_CAMERA) {
|
|
||||||
trigger = *data++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ITEM_INFO *item = &g_Items[trigger & VALUE_BITS];
|
|
||||||
OBJECT_INFO *object = &g_Objects[item->object_number];
|
|
||||||
if (object->ceiling_height_func) {
|
|
||||||
height =
|
|
||||||
object->ceiling_height_func(item, x, y, z, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!(trigger & END_BIT));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Shell_ExitSystem("GetCeiling(): Unknown type");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (!(type & END_BIT));
|
|
||||||
|
const ITEM_INFO *const item = &g_Items[cmd->parameter];
|
||||||
|
const OBJECT_INFO *const object = &g_Objects[item->object_number];
|
||||||
|
if (object->ceiling_height_func) {
|
||||||
|
height = object->ceiling_height_func(item, x, y, z, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
@ -398,57 +372,22 @@ int16_t Room_GetHeight(
|
||||||
|
|
||||||
int16_t height = Room_GetFloorTiltHeight(sector, x, z);
|
int16_t height = Room_GetFloorTiltHeight(sector, x, z);
|
||||||
|
|
||||||
g_TriggerIndex = NULL;
|
if (sector->trigger == NULL) {
|
||||||
|
|
||||||
if (!sector->index) {
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t *data = &g_FloorData[sector->index];
|
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
|
||||||
int16_t type;
|
const TRIGGER_CMD *const cmd = §or->trigger->commands[i];
|
||||||
int16_t trigger;
|
if (cmd->type != TO_OBJECT) {
|
||||||
do {
|
continue;
|
||||||
type = *data++;
|
|
||||||
|
|
||||||
switch (type & DATA_TYPE) {
|
|
||||||
case FT_TILT:
|
|
||||||
case FT_ROOF:
|
|
||||||
case FT_DOOR:
|
|
||||||
data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_LAVA:
|
|
||||||
g_TriggerIndex = data - 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_TRIGGER:
|
|
||||||
if (!g_TriggerIndex) {
|
|
||||||
g_TriggerIndex = data - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
data++;
|
|
||||||
do {
|
|
||||||
trigger = *data++;
|
|
||||||
if (TRIG_BITS(trigger) != TO_OBJECT) {
|
|
||||||
if (TRIG_BITS(trigger) == TO_CAMERA) {
|
|
||||||
trigger = *data++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ITEM_INFO *item = &g_Items[trigger & VALUE_BITS];
|
|
||||||
OBJECT_INFO *object = &g_Objects[item->object_number];
|
|
||||||
if (object->floor_height_func) {
|
|
||||||
height =
|
|
||||||
object->floor_height_func(item, x, y, z, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!(trigger & END_BIT));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Shell_ExitSystem("GetHeight(): Unknown type");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (!(type & END_BIT));
|
|
||||||
|
const ITEM_INFO *const item = &g_Items[cmd->parameter];
|
||||||
|
const OBJECT_INFO *const object = &g_Objects[item->object_number];
|
||||||
|
if (object->floor_height_func) {
|
||||||
|
height = object->floor_height_func(item, x, y, z, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
@ -698,6 +637,8 @@ static void Room_PopulateSectorData(
|
||||||
sector->floor.tilt = 0;
|
sector->floor.tilt = 0;
|
||||||
sector->ceiling.tilt = 0;
|
sector->ceiling.tilt = 0;
|
||||||
sector->portal_room.wall = NO_ROOM;
|
sector->portal_room.wall = NO_ROOM;
|
||||||
|
sector->is_death_sector = false;
|
||||||
|
sector->trigger = NULL;
|
||||||
|
|
||||||
if (sector->index == 0) {
|
if (sector->index == 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -722,18 +663,39 @@ static void Room_PopulateSectorData(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FT_LAVA:
|
case FT_LAVA:
|
||||||
break; // TODO: (bool)is_death_sector
|
sector->is_death_sector = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case FT_TRIGGER: {
|
case FT_TRIGGER: {
|
||||||
// TODO: (TRIGGER *)trigger
|
assert(sector->trigger == NULL);
|
||||||
|
|
||||||
|
TRIGGER *const trigger =
|
||||||
|
GameBuf_Alloc(sizeof(TRIGGER), GBUF_FLOOR_DATA);
|
||||||
|
sector->trigger = trigger;
|
||||||
|
|
||||||
const int16_t trig_setup = *data++;
|
const int16_t trig_setup = *data++;
|
||||||
const TRIGGER_TYPE trig_type = TRIG_TYPE(fd_entry);
|
trigger->type = TRIG_TYPE(fd_entry);
|
||||||
if (trig_type == TT_SWITCH || trig_type == TT_KEY
|
trigger->timer = trig_setup & 0xFF;
|
||||||
|| trig_type == TT_PICKUP) {
|
trigger->one_shot = trig_setup & IF_ONESHOT;
|
||||||
data++; // TODO: (int16_t)item_index
|
trigger->mask = trig_setup & IF_CODE_BITS;
|
||||||
|
trigger->item_index = NO_ITEM;
|
||||||
|
trigger->command_count = 0;
|
||||||
|
|
||||||
|
if (trigger->type == TT_SWITCH || trigger->type == TT_KEY
|
||||||
|
|| trigger->type == TT_PICKUP) {
|
||||||
|
const int16_t item_data = *data++;
|
||||||
|
trigger->item_index = item_data & VALUE_BITS;
|
||||||
|
if (item_data & END_BIT) {
|
||||||
|
// See City of Khamoon room 49 - two dangling key triggers
|
||||||
|
// with no commands. Exit early to avoid populating garbage
|
||||||
|
// command data.
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int16_t *command_data = data;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
trigger->command_count++;
|
||||||
int16_t command = *data++;
|
int16_t command = *data++;
|
||||||
if (TRIG_BITS(command) == TO_CAMERA) {
|
if (TRIG_BITS(command) == TO_CAMERA) {
|
||||||
command = *data++;
|
command = *data++;
|
||||||
|
@ -743,6 +705,22 @@ static void Room_PopulateSectorData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trigger->commands = GameBuf_Alloc(
|
||||||
|
sizeof(TRIGGER_CMD) * trigger->command_count, GBUF_FLOOR_DATA);
|
||||||
|
for (int32_t i = 0; i < trigger->command_count; i++) {
|
||||||
|
int16_t command = *command_data++;
|
||||||
|
TRIGGER_CMD *const cmd = &trigger->commands[i];
|
||||||
|
cmd->type = TRIG_BITS(command);
|
||||||
|
cmd->parameter = command & VALUE_BITS;
|
||||||
|
|
||||||
|
if (cmd->type == TO_CAMERA) {
|
||||||
|
command = *command_data++;
|
||||||
|
cmd->camera.timer = command & 0xFF;
|
||||||
|
cmd->camera.glide = (command & IF_CODE_BITS) >> 6;
|
||||||
|
cmd->camera.one_shot = command & IF_ONESHOT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,68 +730,65 @@ static void Room_PopulateSectorData(
|
||||||
} while (!(fd_entry & END_BIT));
|
} while (!(fd_entry & END_BIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Room_TestTriggers(int16_t *data, bool heavy)
|
void Room_TestTriggers(const ITEM_INFO *const item)
|
||||||
{
|
{
|
||||||
if (!data) {
|
const bool is_heavy = item->object_number != O_LARA;
|
||||||
|
int16_t room_num = item->room_number;
|
||||||
|
const SECTOR_INFO *const sector =
|
||||||
|
Room_GetSector(item->pos.x, MAX_HEIGHT, item->pos.z, &room_num);
|
||||||
|
|
||||||
|
if (!is_heavy && sector->is_death_sector && Lava_TestFloor(item)) {
|
||||||
|
Lava_Burn(g_LaraItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TRIGGER *const trigger = sector->trigger;
|
||||||
|
if (trigger == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*data & DATA_TYPE) == FT_LAVA) {
|
|
||||||
if (!heavy && Lava_TestFloor(g_LaraItem)) {
|
|
||||||
Lava_Burn(g_LaraItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*data & END_BIT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t type = (*data++ >> 8) & 0x3F;
|
|
||||||
int32_t switch_off = 0;
|
|
||||||
int32_t flip = 0;
|
|
||||||
int32_t new_effect = -1;
|
|
||||||
int16_t flags = *data++;
|
|
||||||
int16_t timer = flags & 0xFF;
|
|
||||||
|
|
||||||
if (g_Camera.type != CAM_HEAVY) {
|
if (g_Camera.type != CAM_HEAVY) {
|
||||||
Camera_RefreshFromTrigger(type, data);
|
Camera_RefreshFromTrigger(trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heavy) {
|
bool switch_off = false;
|
||||||
if (type != TT_HEAVY) {
|
bool flip_map = false;
|
||||||
|
int32_t new_effect = -1;
|
||||||
|
ITEM_INFO *camera_item = NULL;
|
||||||
|
|
||||||
|
if (is_heavy) {
|
||||||
|
if (trigger->type != TT_HEAVY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (type) {
|
switch (trigger->type) {
|
||||||
|
case TT_TRIGGER:
|
||||||
|
break;
|
||||||
|
|
||||||
case TT_SWITCH: {
|
case TT_SWITCH: {
|
||||||
int16_t value = *data++ & VALUE_BITS;
|
if (!Switch_Trigger(trigger->item_index, trigger->timer)) {
|
||||||
if (!Switch_Trigger(value, timer)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch_off = g_Items[value].current_anim_state == LS_RUN;
|
switch_off =
|
||||||
|
g_Items[trigger->item_index].current_anim_state == LS_RUN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TT_PAD:
|
case TT_PAD:
|
||||||
case TT_ANTIPAD:
|
case TT_ANTIPAD:
|
||||||
if (g_LaraItem->pos.y != g_LaraItem->floor) {
|
if (item->pos.y != item->floor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TT_KEY: {
|
case TT_KEY: {
|
||||||
int16_t value = *data++ & VALUE_BITS;
|
if (!KeyHole_Trigger(trigger->item_index)) {
|
||||||
if (!KeyHole_Trigger(value)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TT_PICKUP: {
|
case TT_PICKUP: {
|
||||||
int16_t value = *data++ & VALUE_BITS;
|
if (!Pickup_Trigger(trigger->item_index)) {
|
||||||
if (!Pickup_Trigger(value)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -831,38 +806,35 @@ void Room_TestTriggers(int16_t *data, bool heavy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ITEM_INFO *camera_item = NULL;
|
for (int32_t i = 0; i < trigger->command_count; i++) {
|
||||||
int16_t trigger;
|
const TRIGGER_CMD *const cmd = &trigger->commands[i];
|
||||||
do {
|
|
||||||
trigger = *data++;
|
|
||||||
int16_t value = trigger & VALUE_BITS;
|
|
||||||
|
|
||||||
switch (TRIG_BITS(trigger)) {
|
switch (cmd->type) {
|
||||||
case TO_OBJECT: {
|
case TO_OBJECT: {
|
||||||
ITEM_INFO *item = &g_Items[value];
|
const int16_t item_num = cmd->parameter;
|
||||||
|
ITEM_INFO *const item = &g_Items[item_num];
|
||||||
if (item->flags & IF_ONESHOT) {
|
if (item->flags & IF_ONESHOT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->timer = timer;
|
item->timer = trigger->timer;
|
||||||
if (timer != 1) {
|
if (item->timer != 1) {
|
||||||
item->timer *= LOGIC_FPS;
|
item->timer *= LOGIC_FPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TT_SWITCH) {
|
if (trigger->type == TT_SWITCH) {
|
||||||
item->flags ^= flags & IF_CODE_BITS;
|
item->flags ^= trigger->mask;
|
||||||
} else if (type == TT_ANTIPAD) {
|
} else if (trigger->type == TT_ANTIPAD) {
|
||||||
item->flags &= -1 - (flags & IF_CODE_BITS);
|
item->flags &= -1 - trigger->mask;
|
||||||
} else if (flags & IF_CODE_BITS) {
|
} else if (trigger->mask) {
|
||||||
item->flags |= flags & IF_CODE_BITS;
|
item->flags |= trigger->mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((item->flags & IF_CODE_BITS) != IF_CODE_BITS) {
|
if ((item->flags & IF_CODE_BITS) != IF_CODE_BITS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & IF_ONESHOT) {
|
if (trigger->one_shot) {
|
||||||
item->flags |= IF_ONESHOT;
|
item->flags |= IF_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,73 +843,71 @@ void Room_TestTriggers(int16_t *data, bool heavy)
|
||||||
if (item->status == IS_NOT_ACTIVE) {
|
if (item->status == IS_NOT_ACTIVE) {
|
||||||
item->touch_bits = 0;
|
item->touch_bits = 0;
|
||||||
item->status = IS_ACTIVE;
|
item->status = IS_ACTIVE;
|
||||||
Item_AddActive(value);
|
Item_AddActive(item_num);
|
||||||
LOT_EnableBaddieAI(value, 1);
|
LOT_EnableBaddieAI(item_num, 1);
|
||||||
} else if (item->status == IS_INVISIBLE) {
|
} else if (item->status == IS_INVISIBLE) {
|
||||||
item->touch_bits = 0;
|
item->touch_bits = 0;
|
||||||
if (LOT_EnableBaddieAI(value, 0)) {
|
if (LOT_EnableBaddieAI(item_num, 0)) {
|
||||||
item->status = IS_ACTIVE;
|
item->status = IS_ACTIVE;
|
||||||
} else {
|
} else {
|
||||||
item->status = IS_INVISIBLE;
|
item->status = IS_INVISIBLE;
|
||||||
}
|
}
|
||||||
Item_AddActive(value);
|
Item_AddActive(item_num);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
item->touch_bits = 0;
|
item->touch_bits = 0;
|
||||||
item->status = IS_ACTIVE;
|
item->status = IS_ACTIVE;
|
||||||
Item_AddActive(value);
|
Item_AddActive(item_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TO_CAMERA: {
|
case TO_CAMERA: {
|
||||||
trigger = *data++;
|
const int16_t camera_num = cmd->parameter;
|
||||||
int16_t camera_flags = trigger;
|
if (g_Camera.fixed[camera_num].flags & IF_ONESHOT) {
|
||||||
int16_t camera_timer = trigger & 0xFF;
|
|
||||||
|
|
||||||
if (g_Camera.fixed[value].flags & IF_ONESHOT) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Camera.number = value;
|
g_Camera.number = camera_num;
|
||||||
|
|
||||||
if (g_Camera.type == CAM_LOOK || g_Camera.type == CAM_COMBAT) {
|
if (g_Camera.type == CAM_LOOK || g_Camera.type == CAM_COMBAT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TT_COMBAT) {
|
if (trigger->type == TT_COMBAT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TT_SWITCH && timer && switch_off) {
|
if (trigger->type == TT_SWITCH && trigger->timer && switch_off) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_Camera.number == g_Camera.last && type != TT_SWITCH) {
|
if (g_Camera.number == g_Camera.last
|
||||||
|
&& trigger->type != TT_SWITCH) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Camera.timer = camera_timer;
|
g_Camera.timer = cmd->camera.timer;
|
||||||
if (g_Camera.timer != 1) {
|
if (g_Camera.timer != 1) {
|
||||||
g_Camera.timer *= LOGIC_FPS;
|
g_Camera.timer *= LOGIC_FPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (camera_flags & IF_ONESHOT) {
|
if (cmd->camera.one_shot) {
|
||||||
g_Camera.fixed[g_Camera.number].flags |= IF_ONESHOT;
|
g_Camera.fixed[g_Camera.number].flags |= IF_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Camera.speed = ((camera_flags & IF_CODE_BITS) >> 6) + 1;
|
g_Camera.speed = cmd->camera.glide + 1;
|
||||||
g_Camera.type = heavy ? CAM_HEAVY : CAM_FIXED;
|
g_Camera.type = is_heavy ? CAM_HEAVY : CAM_FIXED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TO_TARGET:
|
case TO_TARGET:
|
||||||
camera_item = &g_Items[value];
|
camera_item = &g_Items[cmd->parameter];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_SINK: {
|
case TO_SINK: {
|
||||||
OBJECT_VECTOR *obvector = &g_Camera.fixed[value];
|
OBJECT_VECTOR *obvector = &g_Camera.fixed[cmd->parameter];
|
||||||
|
|
||||||
if (g_Lara.LOT.required_box != obvector->flags) {
|
if (g_Lara.LOT.required_box != obvector->flags) {
|
||||||
g_Lara.LOT.target.x = obvector->x;
|
g_Lara.LOT.target.x = obvector->x;
|
||||||
|
@ -950,46 +920,48 @@ void Room_TestTriggers(int16_t *data, bool heavy)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TO_FLIPMAP:
|
case TO_FLIPMAP: {
|
||||||
if (g_FlipMapTable[value] & IF_ONESHOT) {
|
const int16_t flip_slot = cmd->parameter;
|
||||||
|
if (g_FlipMapTable[flip_slot] & IF_ONESHOT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TT_SWITCH) {
|
if (trigger->type == TT_SWITCH) {
|
||||||
g_FlipMapTable[value] ^= flags & IF_CODE_BITS;
|
g_FlipMapTable[flip_slot] ^= trigger->mask;
|
||||||
} else if (flags & IF_CODE_BITS) {
|
} else if (trigger->mask) {
|
||||||
g_FlipMapTable[value] |= flags & IF_CODE_BITS;
|
g_FlipMapTable[flip_slot] |= trigger->mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_FlipMapTable[value] & IF_CODE_BITS) == IF_CODE_BITS) {
|
if ((g_FlipMapTable[flip_slot] & IF_CODE_BITS) == IF_CODE_BITS) {
|
||||||
if (flags & IF_ONESHOT) {
|
if (trigger->one_shot) {
|
||||||
g_FlipMapTable[value] |= IF_ONESHOT;
|
g_FlipMapTable[flip_slot] |= IF_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_FlipStatus) {
|
if (!g_FlipStatus) {
|
||||||
flip = 1;
|
flip_map = true;
|
||||||
}
|
}
|
||||||
} else if (g_FlipStatus) {
|
} else if (g_FlipStatus) {
|
||||||
flip = 1;
|
flip_map = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TO_FLIPON:
|
case TO_FLIPON:
|
||||||
if ((g_FlipMapTable[value] & IF_CODE_BITS) == IF_CODE_BITS
|
if ((g_FlipMapTable[cmd->parameter] & IF_CODE_BITS) == IF_CODE_BITS
|
||||||
&& !g_FlipStatus) {
|
&& !g_FlipStatus) {
|
||||||
flip = 1;
|
flip_map = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_FLIPOFF:
|
case TO_FLIPOFF:
|
||||||
if ((g_FlipMapTable[value] & IF_CODE_BITS) == IF_CODE_BITS
|
if ((g_FlipMapTable[cmd->parameter] & IF_CODE_BITS) == IF_CODE_BITS
|
||||||
&& g_FlipStatus) {
|
&& g_FlipStatus) {
|
||||||
flip = 1;
|
flip_map = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_FLIPEFFECT:
|
case TO_FLIPEFFECT:
|
||||||
new_effect = value;
|
new_effect = cmd->parameter;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_FINISH:
|
case TO_FINISH:
|
||||||
|
@ -997,26 +969,28 @@ void Room_TestTriggers(int16_t *data, bool heavy)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_CD:
|
case TO_CD:
|
||||||
Room_TriggerMusicTrack(value, flags, type);
|
Room_TriggerMusicTrack(cmd->parameter, trigger);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_SECRET:
|
case TO_SECRET: {
|
||||||
if ((g_GameInfo.current[g_CurrentLevel].stats.secret_flags
|
const int16_t secret_num = 1 << cmd->parameter;
|
||||||
& (1 << value))) {
|
if (g_GameInfo.current[g_CurrentLevel].stats.secret_flags
|
||||||
|
& secret_num) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
g_GameInfo.current[g_CurrentLevel].stats.secret_flags |= 1 << value;
|
g_GameInfo.current[g_CurrentLevel].stats.secret_flags |= secret_num;
|
||||||
Music_Play(MX_SECRET);
|
Music_Play(MX_SECRET);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (!(trigger & END_BIT));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (camera_item
|
if (camera_item
|
||||||
&& (g_Camera.type == CAM_FIXED || g_Camera.type == CAM_HEAVY)) {
|
&& (g_Camera.type == CAM_FIXED || g_Camera.type == CAM_HEAVY)) {
|
||||||
g_Camera.item = camera_item;
|
g_Camera.item = camera_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flip) {
|
if (flip_map) {
|
||||||
Room_FlipMap();
|
Room_FlipMap();
|
||||||
if (new_effect != -1) {
|
if (new_effect != -1) {
|
||||||
g_FlipEffect = new_effect;
|
g_FlipEffect = new_effect;
|
||||||
|
@ -1032,50 +1006,24 @@ bool Room_IsOnWalkable(
|
||||||
sector = Room_GetPitSector(sector, x, z);
|
sector = Room_GetPitSector(sector, x, z);
|
||||||
|
|
||||||
int16_t height = sector->floor.height;
|
int16_t height = sector->floor.height;
|
||||||
|
if (sector->trigger == NULL) {
|
||||||
|
return room_height == height;
|
||||||
|
}
|
||||||
|
|
||||||
bool object_found = false;
|
bool object_found = false;
|
||||||
|
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
|
||||||
int16_t *floor_data = &g_FloorData[sector->index];
|
const TRIGGER_CMD *const cmd = §or->trigger->commands[i];
|
||||||
int16_t type;
|
if (cmd->type != TO_OBJECT) {
|
||||||
int16_t trigger;
|
continue;
|
||||||
int16_t trig_flags;
|
|
||||||
int16_t trig_type;
|
|
||||||
|
|
||||||
do {
|
|
||||||
type = *floor_data++;
|
|
||||||
|
|
||||||
switch (type & DATA_TYPE) {
|
|
||||||
case FT_TILT:
|
|
||||||
case FT_ROOF:
|
|
||||||
case FT_DOOR:
|
|
||||||
floor_data++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_LAVA:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_TRIGGER:
|
|
||||||
trig_flags = *floor_data;
|
|
||||||
floor_data++;
|
|
||||||
trig_type = (type >> 8) & 0x3F;
|
|
||||||
do {
|
|
||||||
trigger = *floor_data++;
|
|
||||||
|
|
||||||
if (TRIG_BITS(trigger) == TO_OBJECT) {
|
|
||||||
const int16_t item_num = trigger & VALUE_BITS;
|
|
||||||
ITEM_INFO *item = &g_Items[item_num];
|
|
||||||
OBJECT_INFO *object = &g_Objects[item->object_number];
|
|
||||||
if (object->floor_height_func) {
|
|
||||||
height =
|
|
||||||
object->floor_height_func(item, x, y, z, height);
|
|
||||||
object_found = true;
|
|
||||||
}
|
|
||||||
} else if (TRIG_BITS(trigger) == TO_CAMERA) {
|
|
||||||
trigger = *floor_data++;
|
|
||||||
}
|
|
||||||
} while (!(trigger & END_BIT));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (!(type & END_BIT));
|
|
||||||
|
const ITEM_INFO *const item = &g_Items[cmd->parameter];
|
||||||
|
const OBJECT_INFO *const object = &g_Objects[item->object_number];
|
||||||
|
if (object->floor_height_func) {
|
||||||
|
height = object->floor_height_func(item, x, y, z, height);
|
||||||
|
object_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return object_found && room_height == height;
|
return object_found && room_height == height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ void Room_GetNewRoom(int32_t x, int32_t y, int32_t z, int16_t room_num);
|
||||||
void Room_GetNearByRooms(
|
void Room_GetNearByRooms(
|
||||||
int32_t x, int32_t y, int32_t z, int32_t r, int32_t h, int16_t room_num);
|
int32_t x, int32_t y, int32_t z, int32_t r, int32_t h, int16_t room_num);
|
||||||
SECTOR_INFO *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
|
SECTOR_INFO *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
|
||||||
|
SECTOR_INFO *Room_GetPitSector(const SECTOR_INFO *sector, int32_t x, int32_t z);
|
||||||
int16_t Room_GetCeiling(
|
int16_t Room_GetCeiling(
|
||||||
const SECTOR_INFO *sector, int32_t x, int32_t y, int32_t z);
|
const SECTOR_INFO *sector, int32_t x, int32_t y, int32_t z);
|
||||||
int16_t Room_GetHeight(
|
int16_t Room_GetHeight(
|
||||||
|
@ -29,7 +30,7 @@ int16_t Room_GetIndexFromPos(int32_t x, int32_t y, int32_t z);
|
||||||
void Room_AlterFloorHeight(ITEM_INFO *item, int32_t height);
|
void Room_AlterFloorHeight(ITEM_INFO *item, int32_t height);
|
||||||
|
|
||||||
void Room_ParseFloorData(const int16_t *floor_data);
|
void Room_ParseFloorData(const int16_t *floor_data);
|
||||||
void Room_TestTriggers(int16_t *data, bool heavy);
|
void Room_TestTriggers(const ITEM_INFO *item);
|
||||||
void Room_FlipMap(void);
|
void Room_FlipMap(void);
|
||||||
bool Room_IsOnWalkable(
|
bool Room_IsOnWalkable(
|
||||||
const SECTOR_INFO *sector, int32_t x, int32_t y, int32_t z,
|
const SECTOR_INFO *sector, int32_t x, int32_t y, int32_t z,
|
||||||
|
|
|
@ -83,80 +83,49 @@ static void Stats_CheckTriggers(
|
||||||
const SECTOR_INFO *const sector =
|
const SECTOR_INFO *const sector =
|
||||||
&m_CachedSectorArray[room_num][z_sector + x_sector * r->z_size];
|
&m_CachedSectorArray[room_num][z_sector + x_sector * r->z_size];
|
||||||
|
|
||||||
if (!sector->index) {
|
if (sector->trigger == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t *data = &g_FloorData[sector->index];
|
for (int32_t i = 0; i < sector->trigger->command_count; i++) {
|
||||||
int16_t type;
|
const TRIGGER_CMD *const cmd = §or->trigger->commands[i];
|
||||||
int16_t trigger;
|
|
||||||
int16_t trig_flags;
|
|
||||||
int16_t trig_type;
|
|
||||||
do {
|
|
||||||
type = *data++;
|
|
||||||
|
|
||||||
switch (type & DATA_TYPE) {
|
if (cmd->type == TO_SECRET) {
|
||||||
case FT_TILT:
|
const int16_t secret_num = 1 << cmd->parameter;
|
||||||
case FT_ROOF:
|
if (!(m_SecretRoom & secret_num)) {
|
||||||
case FT_DOOR:
|
m_SecretRoom |= secret_num;
|
||||||
data++;
|
m_LevelSecrets++;
|
||||||
break;
|
}
|
||||||
|
} else if (cmd->type == TO_OBJECT) {
|
||||||
|
const int16_t item_num = cmd->parameter;
|
||||||
|
if (m_KillableItems[item_num]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
case FT_LAVA:
|
const ITEM_INFO *const item = &g_Items[item_num];
|
||||||
break;
|
|
||||||
|
|
||||||
case FT_TRIGGER:
|
// Add Pierre pickup and kills if oneshot
|
||||||
trig_flags = *data;
|
if (item->object_number == O_PIERRE && sector->trigger->one_shot) {
|
||||||
data++;
|
Stats_IncludeKillableItem(item_num);
|
||||||
trig_type = (type >> 8) & 0x3F;
|
}
|
||||||
do {
|
|
||||||
trigger = *data++;
|
// Check for only valid pods
|
||||||
if (TRIG_BITS(trigger) == TO_SECRET) {
|
if ((item->object_number == O_PODS
|
||||||
int16_t number = trigger & VALUE_BITS;
|
|| item->object_number == O_BIG_POD)
|
||||||
if (!(m_SecretRoom & (1 << number))) {
|
&& item->data != NULL) {
|
||||||
m_SecretRoom |= (1 << number);
|
const int16_t bug_item_num = *(int16_t *)item->data;
|
||||||
m_LevelSecrets++;
|
const ITEM_INFO *const bug_item = &g_Items[bug_item_num];
|
||||||
}
|
if (g_Objects[bug_item->object_number].loaded) {
|
||||||
|
Stats_IncludeKillableItem(item_num);
|
||||||
}
|
}
|
||||||
if (TRIG_BITS(trigger) != TO_OBJECT) {
|
}
|
||||||
if (TRIG_BITS(trigger) == TO_CAMERA) {
|
|
||||||
trigger = *data++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int16_t idx = trigger & VALUE_BITS;
|
|
||||||
|
|
||||||
if (m_KillableItems[idx]) {
|
// Add killable if object triggered
|
||||||
continue;
|
if (Stats_IsObjectKillable(item->object_number)) {
|
||||||
}
|
Stats_IncludeKillableItem(item_num);
|
||||||
|
}
|
||||||
ITEM_INFO *item = &g_Items[idx];
|
|
||||||
|
|
||||||
// Add Pierre pickup and kills if oneshot
|
|
||||||
if (item->object_number == O_PIERRE
|
|
||||||
&& trig_flags & IF_ONESHOT) {
|
|
||||||
Stats_IncludeKillableItem(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for only valid pods
|
|
||||||
if ((item->object_number == O_PODS
|
|
||||||
|| item->object_number == O_BIG_POD)
|
|
||||||
&& item->data != NULL) {
|
|
||||||
int16_t bug_item_num = *(int16_t *)item->data;
|
|
||||||
const ITEM_INFO *bug_item = &g_Items[bug_item_num];
|
|
||||||
if (g_Objects[bug_item->object_number].loaded) {
|
|
||||||
Stats_IncludeKillableItem(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add killable if object triggered
|
|
||||||
if (Stats_IsObjectKillable(item->object_number)) {
|
|
||||||
Stats_IncludeKillableItem(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!(trigger & END_BIT));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} while (!(type & END_BIT));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Stats_IsObjectKillable(int32_t obj_num)
|
static bool Stats_IsObjectKillable(int32_t obj_num)
|
||||||
|
|
|
@ -123,6 +123,7 @@
|
||||||
#define DONT_TARGET (-16384)
|
#define DONT_TARGET (-16384)
|
||||||
#define UNIT_SHADOW 256
|
#define UNIT_SHADOW 256
|
||||||
#define NO_HEIGHT (-32512)
|
#define NO_HEIGHT (-32512)
|
||||||
|
#define MAX_HEIGHT 32000
|
||||||
#define NO_BAD_POS (-NO_HEIGHT)
|
#define NO_BAD_POS (-NO_HEIGHT)
|
||||||
#define NO_BAD_NEG NO_HEIGHT
|
#define NO_BAD_NEG NO_HEIGHT
|
||||||
#define BAD_JUMP_CEILING ((STEP_L * 3) / 4) // = 192
|
#define BAD_JUMP_CEILING ((STEP_L * 3) / 4) // = 192
|
||||||
|
|
|
@ -1160,9 +1160,31 @@ typedef struct DOOR_INFOS {
|
||||||
DOOR_INFO door[];
|
DOOR_INFO door[];
|
||||||
} DOOR_INFOS;
|
} DOOR_INFOS;
|
||||||
|
|
||||||
|
typedef struct TRIGGER_CMD {
|
||||||
|
TRIGGER_OBJECT type;
|
||||||
|
int16_t parameter;
|
||||||
|
struct {
|
||||||
|
int8_t timer;
|
||||||
|
int8_t glide;
|
||||||
|
bool one_shot;
|
||||||
|
} camera;
|
||||||
|
} TRIGGER_CMD;
|
||||||
|
|
||||||
|
typedef struct TRIGGER {
|
||||||
|
TRIGGER_TYPE type;
|
||||||
|
int8_t timer;
|
||||||
|
int16_t mask;
|
||||||
|
bool one_shot;
|
||||||
|
int16_t item_index;
|
||||||
|
int32_t command_count;
|
||||||
|
TRIGGER_CMD *commands;
|
||||||
|
} TRIGGER;
|
||||||
|
|
||||||
typedef struct SECTOR_INFO {
|
typedef struct SECTOR_INFO {
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
int16_t box;
|
int16_t box;
|
||||||
|
bool is_death_sector;
|
||||||
|
TRIGGER *trigger;
|
||||||
struct {
|
struct {
|
||||||
uint8_t pit;
|
uint8_t pit;
|
||||||
uint8_t sky;
|
uint8_t sky;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue