diff --git a/docs/progress.svg b/docs/progress.svg
index 16484890..5ac88c59 100644
--- a/docs/progress.svg
+++ b/docs/progress.svg
@@ -244,7 +244,7 @@
int32_t __cdecl Misc_Move3DPosTo3DPos(PHD_3DPOS *src_pos, const PHD_3DPOS *dest_pos, int32_t velocity, PHD_ANGLE ang_add);
int32_t __cdecl Game_Control(int32_t nframes, int32_t demo_mode);
void __cdecl Item_Animate(ITEM_INFO *item);
-int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM_STRUCT *anim);
+int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM *anim);
void __cdecl Item_Translate(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
SECTOR_INFO *__cdecl Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
int32_t __cdecl Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
@@ -677,7 +677,7 @@
bool __cdecl LOT_EnableBaddieAI(int16_t item_num, bool always);
void __cdecl LOT_InitialiseSlot(int16_t item_num, int32_t slot);
void __cdecl LOT_CreateZone(ITEM_INFO *item);
-void __cdecl LOT_ClearLOT(LOT_INFO *LOT);
+void __cdecl LOT_ClearLOT(LOT_INFO *lot);
void __cdecl ControlMissile(int16_t fx_num);
void __cdecl ShootAtLara(FX_INFO *fx);
int32_t __cdecl Effect_ExplodingDeath(int16_t item_num, int32_t mesh_bits, int16_t damage);
@@ -1806,7 +1806,7 @@
void __cdecl Requester_AddItem(REQUEST_INFO *req, const char *text1, uint32_t flags1, const char *text2, uint32_t flags2);
void __cdecl SpiderLeap(int16_t item_num, int16_t angle);
bool __cdecl Matrix_TranslateRel(int32_t x, int32_t y, int32_t z);
-int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM_STRUCT *anim);
+int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM *anim);
int16_t __cdecl DragonFire(int32_t x, int32_t y, int32_t z, int16_t speed, PHD_ANGLE yrot, int16_t room_num);
void __cdecl Overlay_DrawHealthBar(bool flash_state);
void __cdecl Lara_SlideEdgeJump(ITEM_INFO *item, COLL_INFO *coll);
@@ -2125,7 +2125,7 @@
void __cdecl HWR_FreeTexturePages(void);
LONG __cdecl SetRegistryStringValue(LPCTSTR lpValueName, LPCTSTR value, int32_t length);
void __cdecl Creature_Head(ITEM_INFO *item, int16_t required);
-void __cdecl LOT_ClearLOT(LOT_INFO *LOT);
+void __cdecl LOT_ClearLOT(LOT_INFO *lot);
void __cdecl Lara_CatchFire(void);
BOOL __cdecl ReadFileSync(HANDLE handle, LPVOID lpBuffer, DWORD nBytesToRead, LPDWORD lpnBytesRead, LPOVERLAPPED lpOverlapped);
void __cdecl AddDynamicLight(int32_t x, int32_t y, int32_t z, int32_t intensity, int32_t falloff);
diff --git a/docs/progress.txt b/docs/progress.txt
index 2bb2da69..63e751d8 100644
--- a/docs/progress.txt
+++ b/docs/progress.txt
@@ -510,7 +510,7 @@ typedef struct __unaligned { // decompiled
uint16_t pad: 10;
} COLL_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t min_x;
int16_t max_x;
int16_t min_y;
@@ -639,12 +639,12 @@ typedef struct __unaligned {
int16_t sample_num;
} WEAPON_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
XYZ_32 pos;
XYZ_16 rot;
int16_t room_num;
int16_t object_id;
- int16_t next_fx;
+ int16_t next_free;
int16_t next_active;
int16_t speed;
int16_t fall_speed;
@@ -663,14 +663,14 @@ typedef struct __unaligned {
int16_t enemy_facing;
} AI_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t exit_box;
uint16_t search_num;
int16_t next_expansion;
int16_t box_num;
} BOX_NODE;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
BOX_NODE *node;
int16_t head;
int16_t tail;
@@ -836,7 +836,7 @@ typedef enum {
GFE_REMOVE_AMMO = 22,
} GF_EVENTS;
-typedef enum {
+typedef enum { // decompiled
MOOD_BORED = 0,
MOOD_ATTACK = 1,
MOOD_ESCAPE = 2,
@@ -854,7 +854,7 @@ typedef struct __unaligned {
int32_t mesh_num;
} BITE_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t *frame_ptr;
int16_t interpolation;
int16_t current_anim_state;
@@ -868,15 +868,15 @@ typedef struct __unaligned {
int16_t change_idx;
int16_t num_commands;
int16_t command_idx;
-} ANIM_STRUCT;
+} ANIM;
-typedef struct {
+typedef struct { // decompiled
int16_t goal_anim_state;
int16_t num_ranges;
int16_t range_idx;
} ANIM_CHANGE;
-typedef struct {
+typedef struct { // decompiled
int16_t start_frame;
int16_t end_frame;
int16_t link_anim_num;
@@ -960,7 +960,7 @@ typedef struct __unaligned {
uint16_t flags;
} ROOM_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t head_rotation;
int16_t neck_rotation;
int16_t maximum_turn;
@@ -1174,7 +1174,7 @@ typedef struct __unaligned {
XYZ_32 mic_pos;
} CAMERA_INFO;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t *frame_base;
int16_t frame_num;
int16_t anim_num;
@@ -1187,11 +1187,11 @@ typedef struct __unaligned {
int16_t flash_gun;
} LARA_ARM;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int32_t ammo;
} AMMO_INFO;
-typedef enum {
+typedef enum { // decompiled
LWS_ABOVE_WATER = 0,
LWS_UNDERWATER = 1,
LWS_SURFACE = 2,
@@ -1199,7 +1199,7 @@ typedef enum {
LWS_WADE = 4,
} LARA_WATER_STATE;
-typedef struct __unaligned {
+typedef struct __unaligned { // decompiled
int16_t item_num;
int16_t gun_status;
int16_t gun_type;
@@ -1637,7 +1637,7 @@ typedef struct __unaligned {
int16_t roll;
} CINE_FRAME;
-typedef enum {
+typedef enum { // decompiled
IF_ONE_SHOT = 0x0100,
IF_CODE_BITS = 0x3E00,
IF_REVERSE = 0x4000,
@@ -1683,7 +1683,7 @@ typedef enum { // decompiled
IN_LOAD = 0x00800000,
} INPUT_STATE;
-typedef enum {
+typedef enum { // decompiled
LA_RUN = 0,
LA_WALK_FORWARD = 1,
LA_WALK_STOP_RIGHT = 2,
@@ -1904,7 +1904,7 @@ typedef enum {
LA_ZIPLINE_FALL = 217,
} LARA_ANIMATION;
-typedef enum {
+typedef enum { // decompiled
LA_EXTRA_BREATH = 0,
LA_EXTRA_PLUNGER = 1,
LA_EXTRA_YETI_KILL = 2,
@@ -1918,7 +1918,7 @@ typedef enum {
LA_EXTRA_FINAL_ANIM = 10,
} LARA_EXTRA_ANIMATION;
-typedef enum {
+typedef enum { // decompiled
LS_WALK = 0,
LS_RUN = 1,
LS_STOP = 2,
@@ -1999,7 +1999,7 @@ typedef enum {
LS_LAST = 77,
} LARA_STATE;
-typedef enum {
+typedef enum { // decompiled
LGS_ARMLESS = 0,
LGS_HANDS_BUSY = 1,
LGS_DRAW = 2,
@@ -2008,7 +2008,7 @@ typedef enum {
LGS_SPECIAL = 5,
} LARA_GUN_STATE;
-typedef enum {
+typedef enum { // decompiled
LGT_UNARMED = 0,
LGT_PISTOLS = 1,
LGT_MAGNUMS = 2,
@@ -2022,7 +2022,7 @@ typedef enum {
NUM_WEAPONS = 10,
} LARA_GUN_TYPE;
-typedef enum {
+typedef enum { // decompiled
LM_HIPS = 0,
LM_THIGH_L = 1,
LM_CALF_L = 2,
@@ -2407,7 +2407,7 @@ typedef enum {
HT_BIG_SLOPE = 2,
} HEIGHT_TYPE;
-typedef enum {
+typedef enum { // decompiled
DIR_UNKNOWN = -1,
DIR_NORTH = 0,
DIR_EAST = 1,
@@ -3031,7 +3031,7 @@ typedef enum {
# game/control.c
0x00414390 0x0356 + int32_t __cdecl Game_Control(int32_t nframes, int32_t demo_mode);
0x004146F0 0x0338 + void __cdecl Item_Animate(ITEM_INFO *item);
-0x00414A60 0x00AB + int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM_STRUCT *anim);
+0x00414A60 0x00AB + int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM *anim);
0x00414B10 0x005F + void __cdecl Item_Translate(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
0x00414B70 0x0198 + SECTOR_INFO *__cdecl Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
0x00414D10 0x0168 + int32_t __cdecl Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
@@ -3514,7 +3514,7 @@ typedef enum {
0x00432B10 0x01B0 + bool __cdecl LOT_EnableBaddieAI(int16_t item_num, bool always);
0x00432CC0 0x0106 + void __cdecl LOT_InitialiseSlot(int16_t item_num, int32_t slot);
0x00432ED0 0x00B8 + void __cdecl LOT_CreateZone(ITEM_INFO *item);
-0x00432F90 0x0049 + void __cdecl LOT_ClearLOT(LOT_INFO *LOT);
+0x00432F90 0x0049 + void __cdecl LOT_ClearLOT(LOT_INFO *lot);
# game/missile.c
0x00432FE0 0x02D0 -R void __cdecl ControlMissile(int16_t fx_num);
@@ -4435,7 +4435,7 @@ typedef enum {
0x005252B0 - int16_t **g_Meshes;
0x005252C0 - MATRIX g_IMMatrixStack[256];
0x005258F0 - int32_t g_IMFrac;
-0x005258F4 - ANIM_STRUCT *g_Anims;
+0x005258F4 - ANIM *g_Anims;
0x00525BE8 - int32_t *g_AnimBones;
0x00526180 - int32_t g_RoomCount;
0x00526184 - int32_t g_IMRate;
diff --git a/meson.build b/meson.build
index 25e950e0..384ced7f 100644
--- a/meson.build
+++ b/meson.build
@@ -19,6 +19,7 @@ c_compiler = meson.get_compiler('c')
build_opts = [
'-Wno-unused',
+ '-Wno-address-of-packed-member',
'-DMESON_BUILD',
'-fno-omit-frame-pointer',
'-ffile-prefix-map=../../src/=',
@@ -90,12 +91,10 @@ dll_sources = [
'src/game/camera.c',
'src/game/clock.c',
'src/game/collide.c',
- 'src/game/console/cmd/die.c',
'src/game/console/cmd/end_level.c',
'src/game/console/cmd/exit_game.c',
'src/game/console/cmd/exit_to_title.c',
'src/game/console/cmd/flipmap.c',
- 'src/game/console/cmd/fly.c',
'src/game/console/cmd/load_game.c',
'src/game/console/cmd/play_demo.c',
'src/game/console/cmd/play_level.c',
@@ -122,15 +121,14 @@ dll_sources = [
'src/game/inventory/ring.c',
'src/game/inventory/vars.c',
'src/game/items.c',
+ 'src/game/lara/cheat.c',
+ 'src/game/lara/col.c',
'src/game/lara/common.c',
- 'src/game/lara/lara_cheat.c',
- 'src/game/lara/lara_col.c',
- 'src/game/lara/lara_control.c',
- 'src/game/lara/lara_draw.c',
- 'src/game/lara/lara_look.c',
- 'src/game/lara/lara_misc.c',
- 'src/game/lara/lara_state.c',
+ 'src/game/lara/control.c',
+ 'src/game/lara/draw.c',
+ 'src/game/lara/look.c',
'src/game/lara/misc.c',
+ 'src/game/lara/state.c',
'src/game/level.c',
'src/game/los.c',
'src/game/lot.c',
diff --git a/src/decomp/decomp.c b/src/decomp/decomp.c
index 1b2279fe..26320885 100644
--- a/src/decomp/decomp.c
+++ b/src/decomp/decomp.c
@@ -12,8 +12,8 @@
#include "game/inventory/backpack.h"
#include "game/inventory/common.h"
#include "game/items.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_draw.h"
+#include "game/lara/control.h"
+#include "game/lara/draw.h"
#include "game/lot.h"
#include "game/math.h"
#include "game/music.h"
diff --git a/src/game/console/cmd/die.c b/src/game/console/cmd/die.c
deleted file mode 100644
index 20c121b6..00000000
--- a/src/game/console/cmd/die.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "game/console/cmd/die.h"
-
-#include "decomp/effects.h"
-#include "game/sound.h"
-#include "global/vars.h"
-
-static COMMAND_RESULT M_Entrypoint(const char *args);
-
-static COMMAND_RESULT M_Entrypoint(const char *const args)
-{
- if (!g_Objects[O_LARA].loaded) {
- return CR_UNAVAILABLE;
- }
-
- if (g_LaraItem->hit_points <= 0) {
- return CR_UNAVAILABLE;
- }
-
- Sound_Effect(SFX_LARA_FALL, &g_LaraItem->pos, SPM_NORMAL);
- Effect_ExplodingDeath(g_Lara.item_num, -1, 1);
-
- g_LaraItem->hit_points = 0;
- g_LaraItem->flags |= IF_INVISIBLE;
- return CR_SUCCESS;
-}
-
-CONSOLE_COMMAND g_Console_Cmd_Die = {
- .prefix = "abortion|natlastinks",
- .proc = M_Entrypoint,
-};
diff --git a/src/game/console/cmd/die.h b/src/game/console/cmd/die.h
deleted file mode 100644
index bf50d44b..00000000
--- a/src/game/console/cmd/die.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#include
-
-extern CONSOLE_COMMAND g_Console_Cmd_Die;
diff --git a/src/game/console/cmd/end_level.c b/src/game/console/cmd/end_level.c
index 94db367a..79d6c185 100644
--- a/src/game/console/cmd/end_level.c
+++ b/src/game/console/cmd/end_level.c
@@ -1,6 +1,6 @@
#include "game/console/cmd/end_level.h"
-#include "game/lara/lara_cheat.h"
+#include "game/lara/cheat.h"
#include
diff --git a/src/game/console/cmd/fly.c b/src/game/console/cmd/fly.c
deleted file mode 100644
index 4fe91a84..00000000
--- a/src/game/console/cmd/fly.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "game/console/cmd/fly.h"
-
-#include "game/game.h"
-#include "game/lara/lara_cheat.h"
-#include "global/vars.h"
-
-static COMMAND_RESULT M_Entrypoint(const char *args);
-
-static COMMAND_RESULT M_Entrypoint(const char *const args)
-{
- if (!Game_IsPlayable()) {
- return CR_UNAVAILABLE;
- }
- Lara_Cheat_EnterFlyMode();
- return CR_SUCCESS;
-}
-
-CONSOLE_COMMAND g_Console_Cmd_Fly = {
- .prefix = "fly",
- .proc = M_Entrypoint,
-};
diff --git a/src/game/console/cmd/fly.h b/src/game/console/cmd/fly.h
deleted file mode 100644
index 24e195a5..00000000
--- a/src/game/console/cmd/fly.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#include
-
-extern CONSOLE_COMMAND g_Console_Cmd_Fly;
diff --git a/src/game/console/cmd/teleport.c b/src/game/console/cmd/teleport.c
index 907574f2..affb7575 100644
--- a/src/game/console/cmd/teleport.c
+++ b/src/game/console/cmd/teleport.c
@@ -3,7 +3,7 @@
#include "game/game_string.h"
#include "game/gameflow/gameflow_new.h"
#include "game/items.h"
-#include "game/lara/lara_cheat.h"
+#include "game/lara/cheat.h"
#include "game/objects/names.h"
#include "game/objects/vars.h"
#include "game/random.h"
diff --git a/src/game/console/setup.c b/src/game/console/setup.c
index 9c962381..f7da151f 100644
--- a/src/game/console/setup.c
+++ b/src/game/console/setup.c
@@ -1,11 +1,9 @@
#include "game/console/setup.h"
-#include "game/console/cmd/die.h"
#include "game/console/cmd/end_level.h"
#include "game/console/cmd/exit_game.h"
#include "game/console/cmd/exit_to_title.h"
#include "game/console/cmd/flipmap.h"
-#include "game/console/cmd/fly.h"
#include "game/console/cmd/load_game.h"
#include "game/console/cmd/play_demo.h"
#include "game/console/cmd/play_level.h"
@@ -13,6 +11,8 @@
#include "game/console/cmd/teleport.h"
#include
+#include
+#include
#include
#include
#include
diff --git a/src/game/creature.c b/src/game/creature.c
index 390b33aa..4bd0e76e 100644
--- a/src/game/creature.c
+++ b/src/game/creature.c
@@ -3,7 +3,7 @@
#include "decomp/effects.h"
#include "game/box.h"
#include "game/items.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/misc.h"
#include "game/los.h"
#include "game/lot.h"
#include "game/math.h"
diff --git a/src/game/demo.c b/src/game/demo.c
index fd56723c..c994d724 100644
--- a/src/game/demo.c
+++ b/src/game/demo.c
@@ -4,7 +4,7 @@
#include "game/game.h"
#include "game/gameflow.h"
#include "game/items.h"
-#include "game/lara/lara_cheat.h"
+#include "game/lara/cheat.h"
#include "game/random.h"
#include "game/room.h"
#include "game/shell.h"
diff --git a/src/game/effects.c b/src/game/effects.c
index e6fad7fc..685ce612 100644
--- a/src/game/effects.c
+++ b/src/game/effects.c
@@ -32,16 +32,16 @@ static void M_RemoveDrawn(const int16_t fx_num)
FX_INFO *const fx = &g_Effects[fx_num];
int16_t link_num = g_Rooms[fx->room_num].fx_num;
if (link_num == fx_num) {
- g_Rooms[fx->room_num].fx_num = fx->next_fx;
+ g_Rooms[fx->room_num].fx_num = fx->next_free;
return;
}
while (link_num != NO_ITEM) {
- if (g_Effects[link_num].next_fx == fx_num) {
- g_Effects[link_num].next_fx = fx->next_fx;
+ if (g_Effects[link_num].next_free == fx_num) {
+ g_Effects[link_num].next_free = fx->next_free;
return;
}
- link_num = g_Effects[link_num].next_fx;
+ link_num = g_Effects[link_num].next_free;
}
}
@@ -52,9 +52,9 @@ void __cdecl Effect_InitialiseArray(void)
for (int32_t i = 0; i < MAX_EFFECTS - 1; i++) {
FX_INFO *const fx = &g_Effects[i];
- fx->next_fx = i + 1;
+ fx->next_free = i + 1;
}
- g_Effects[MAX_EFFECTS - 1].next_fx = NO_ITEM;
+ g_Effects[MAX_EFFECTS - 1].next_free = NO_ITEM;
}
int16_t __cdecl Effect_Create(const int16_t room_num)
@@ -65,11 +65,11 @@ int16_t __cdecl Effect_Create(const int16_t room_num)
}
FX_INFO *const fx = &g_Effects[fx_num];
- g_NextEffectFree = fx->next_fx;
+ g_NextEffectFree = fx->next_free;
ROOM_INFO *const room = &g_Rooms[room_num];
fx->room_num = room_num;
- fx->next_fx = room->fx_num;
+ fx->next_free = room->fx_num;
room->fx_num = fx_num;
fx->next_active = g_NextEffectActive;
@@ -86,7 +86,7 @@ void __cdecl Effect_Kill(const int16_t fx_num)
M_RemoveActive(fx_num);
M_RemoveDrawn(fx_num);
- fx->next_fx = g_NextEffectFree;
+ fx->next_free = g_NextEffectFree;
g_NextEffectFree = fx_num;
}
@@ -97,20 +97,20 @@ void __cdecl Effect_NewRoom(const int16_t fx_num, const int16_t room_num)
int16_t link_num = room->fx_num;
if (link_num == fx_num) {
- room->fx_num = fx->next_fx;
+ room->fx_num = fx->next_free;
} else {
while (link_num != NO_ITEM) {
- if (g_Effects[link_num].next_fx == fx_num) {
- g_Effects[link_num].next_fx = fx->next_fx;
+ if (g_Effects[link_num].next_free == fx_num) {
+ g_Effects[link_num].next_free = fx->next_free;
break;
}
- link_num = g_Effects[link_num].next_fx;
+ link_num = g_Effects[link_num].next_free;
}
}
fx->room_num = room_num;
room = &g_Rooms[room_num];
- fx->next_fx = room->fx_num;
+ fx->next_free = room->fx_num;
room->fx_num = fx_num;
}
diff --git a/src/game/game.c b/src/game/game.c
index ed92b9bf..489b17e6 100644
--- a/src/game/game.c
+++ b/src/game/game.c
@@ -6,7 +6,7 @@
#include "game/gameflow/gameflow_new.h"
#include "game/input.h"
#include "game/inventory/common.h"
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "game/music.h"
#include "game/overlay.h"
#include "game/room_draw.h"
diff --git a/src/game/gun/gun.c b/src/game/gun/gun.c
index fff6de1a..2d23a8e4 100644
--- a/src/game/gun/gun.c
+++ b/src/game/gun/gun.c
@@ -5,7 +5,7 @@
#include "game/gun/gun_rifle.h"
#include "game/input.h"
#include "game/inventory/backpack.h"
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "game/sound.h"
#include "global/funcs.h"
#include "global/vars.h"
diff --git a/src/game/gun/gun_rifle.c b/src/game/gun/gun_rifle.c
index d4d6181e..4cde241b 100644
--- a/src/game/gun/gun_rifle.c
+++ b/src/game/gun/gun_rifle.c
@@ -5,7 +5,7 @@
#include "game/gun/gun_misc.h"
#include "game/input.h"
#include "game/items.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/misc.h"
#include "game/math.h"
#include "game/random.h"
#include "game/sound.h"
diff --git a/src/game/inventory/common.c b/src/game/inventory/common.c
index 4c3caa5a..4aa7bd40 100644
--- a/src/game/inventory/common.c
+++ b/src/game/inventory/common.c
@@ -5,7 +5,7 @@
#include "game/inventory/backpack.h"
#include "game/inventory/ring.h"
#include "game/inventory/vars.h"
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "game/math_misc.h"
#include "game/matrix.h"
#include "game/music.h"
diff --git a/src/game/items.c b/src/game/items.c
index c5119df6..a9cadec7 100644
--- a/src/game/items.c
+++ b/src/game/items.c
@@ -445,7 +445,7 @@ void __cdecl Item_Animate(ITEM_INFO *const item)
item->hit_status = 0;
item->touch_bits = 0;
- const ANIM_STRUCT *anim = &g_Anims[item->anim_num];
+ const ANIM *anim = &g_Anims[item->anim_num];
item->frame_num++;
@@ -586,7 +586,7 @@ void __cdecl Item_Animate(ITEM_INFO *const item)
}
int32_t __cdecl Item_GetAnimChange(
- ITEM_INFO *const item, const ANIM_STRUCT *const anim)
+ ITEM_INFO *const item, const ANIM *const anim)
{
if (item->current_anim_state == item->goal_anim_state) {
return false;
@@ -651,7 +651,7 @@ int32_t __cdecl Item_IsTriggerActive(ITEM_INFO *const item)
int32_t __cdecl Item_GetFrames(
const ITEM_INFO *item, FRAME_INFO *frmptr[], int32_t *rate)
{
- const ANIM_STRUCT *const anim = &g_Anims[item->anim_num];
+ const ANIM *const anim = &g_Anims[item->anim_num];
const int32_t cur_frame_num = item->frame_num - anim->frame_base;
const int32_t size = anim->interpolation >> 8;
const int32_t key_frame_span = anim->interpolation & 0xFF;
diff --git a/src/game/items.h b/src/game/items.h
index 564e97c1..8884a2ba 100644
--- a/src/game/items.h
+++ b/src/game/items.h
@@ -24,7 +24,7 @@ int32_t __cdecl Item_TestPosition(
void __cdecl Item_AlignPosition(
const XYZ_32 *vec, const ITEM_INFO *src_item, ITEM_INFO *dst_item);
void __cdecl Item_Animate(ITEM_INFO *item);
-int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM_STRUCT *anim);
+int32_t __cdecl Item_GetAnimChange(ITEM_INFO *item, const ANIM *anim);
void __cdecl Item_Translate(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
int32_t __cdecl Item_IsTriggerActive(ITEM_INFO *item);
int32_t __cdecl Item_GetFrames(
diff --git a/src/game/lara/lara_cheat.c b/src/game/lara/cheat.c
similarity index 98%
rename from src/game/lara/lara_cheat.c
rename to src/game/lara/cheat.c
index 9317d5af..90765c87 100644
--- a/src/game/lara/lara_cheat.c
+++ b/src/game/lara/cheat.c
@@ -1,4 +1,4 @@
-#include "game/lara/lara_cheat.h"
+#include "game/lara/cheat.h"
#include "decomp/effects.h"
#include "game/camera.h"
@@ -8,7 +8,7 @@
#include "game/gun/gun.h"
#include "game/inventory/backpack.h"
#include "game/items.h"
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "game/math.h"
#include "game/objects/common.h"
#include "game/objects/vars.h"
@@ -110,7 +110,7 @@ void __cdecl Lara_Cheat_EndLevel(void)
Console_Log(GS(OSD_COMPLETE_LEVEL));
}
-bool __cdecl Lara_Cheat_EnterFlyMode(void)
+bool Lara_Cheat_EnterFlyMode(void)
{
if (g_LaraItem == NULL) {
return false;
@@ -157,7 +157,7 @@ bool __cdecl Lara_Cheat_EnterFlyMode(void)
return true;
}
-bool __cdecl Lara_Cheat_ExitFlyMode(void)
+bool Lara_Cheat_ExitFlyMode(void)
{
if (g_LaraItem == NULL) {
return false;
diff --git a/src/game/lara/lara_cheat.h b/src/game/lara/cheat.h
similarity index 81%
rename from src/game/lara/lara_cheat.h
rename to src/game/lara/cheat.h
index 7e004531..4ec8fd76 100644
--- a/src/game/lara/lara_cheat.h
+++ b/src/game/lara/cheat.h
@@ -4,8 +4,8 @@
#include
void __cdecl Lara_Cheat_EndLevel(void);
-bool __cdecl Lara_Cheat_EnterFlyMode(void);
-bool __cdecl Lara_Cheat_ExitFlyMode(void);
+bool Lara_Cheat_EnterFlyMode(void);
+bool Lara_Cheat_ExitFlyMode(void);
void __cdecl Lara_Cheat_GetStuff(void);
bool Lara_Cheat_GiveAllKeys(void);
bool Lara_Cheat_GiveAllGuns(void);
diff --git a/src/game/lara/lara_col.c b/src/game/lara/col.c
similarity index 99%
rename from src/game/lara/lara_col.c
rename to src/game/lara/col.c
index ded1284d..6f694516 100644
--- a/src/game/lara/lara_col.c
+++ b/src/game/lara/col.c
@@ -1,10 +1,10 @@
-#include "game/lara/lara_col.h"
+#include "game/lara/col.h"
#include "game/collide.h"
#include "game/input.h"
#include "game/items.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/control.h"
+#include "game/lara/misc.h"
#include "game/math.h"
#include "game/room.h"
#include "game/sound.h"
diff --git a/src/game/lara/lara_col.h b/src/game/lara/col.h
similarity index 100%
rename from src/game/lara/lara_col.h
rename to src/game/lara/col.h
diff --git a/src/game/lara/common.c b/src/game/lara/common.c
index b28f4d6c..10eafdc6 100644
--- a/src/game/lara/common.c
+++ b/src/game/lara/common.c
@@ -2,6 +2,11 @@
#include
+LARA_INFO *Lara_GetLaraInfo(void)
+{
+ return &g_Lara;
+}
+
ITEM_INFO *Lara_GetItem(void)
{
return g_LaraItem;
diff --git a/src/game/lara/lara_control.c b/src/game/lara/control.c
similarity index 99%
rename from src/game/lara/lara_control.c
rename to src/game/lara/control.c
index 0a189c4e..2444c003 100644
--- a/src/game/lara/lara_control.c
+++ b/src/game/lara/control.c
@@ -1,13 +1,13 @@
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "game/creature.h"
#include "game/gun/gun.h"
#include "game/input.h"
#include "game/inventory/backpack.h"
#include "game/items.h"
-#include "game/lara/lara_cheat.h"
-#include "game/lara/lara_look.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/cheat.h"
+#include "game/lara/look.h"
+#include "game/lara/misc.h"
#include "game/math.h"
#include "game/music.h"
#include "game/room.h"
@@ -498,7 +498,7 @@ void __cdecl Lara_Animate(ITEM_INFO *const item)
{
item->frame_num++;
- const ANIM_STRUCT *anim = &g_Anims[item->anim_num];
+ const ANIM *anim = &g_Anims[item->anim_num];
if (anim->num_changes > 0 && Item_GetAnimChange(item, anim)) {
anim = &g_Anims[item->anim_num];
item->current_anim_state = anim->current_anim_state;
diff --git a/src/game/lara/lara_control.h b/src/game/lara/control.h
similarity index 100%
rename from src/game/lara/lara_control.h
rename to src/game/lara/control.h
diff --git a/src/game/lara/lara_draw.c b/src/game/lara/draw.c
similarity index 99%
rename from src/game/lara/lara_draw.c
rename to src/game/lara/draw.c
index adf8b66b..db40e696 100644
--- a/src/game/lara/lara_draw.c
+++ b/src/game/lara/draw.c
@@ -1,4 +1,4 @@
-#include "game/lara/lara_draw.h"
+#include "game/lara/draw.h"
#include "game/items.h"
#include "game/matrix.h"
diff --git a/src/game/lara/lara_draw.h b/src/game/lara/draw.h
similarity index 100%
rename from src/game/lara/lara_draw.h
rename to src/game/lara/draw.h
diff --git a/src/game/lara/lara_misc.c b/src/game/lara/lara_misc.c
deleted file mode 100644
index fc258044..00000000
--- a/src/game/lara/lara_misc.c
+++ /dev/null
@@ -1,1851 +0,0 @@
-#include "game/lara/lara_misc.h"
-
-#include "decomp/decomp.h"
-#include "game/box.h"
-#include "game/collide.h"
-#include "game/effects.h"
-#include "game/input.h"
-#include "game/items.h"
-#include "game/lara/lara_control.h"
-#include "game/math.h"
-#include "game/matrix.h"
-#include "game/random.h"
-#include "game/room.h"
-#include "game/sound.h"
-#include "global/const.h"
-#include "global/funcs.h"
-#include "global/vars.h"
-
-#include
-
-#define MAX_BADDIE_COLLISION 20
-#define MOVE_SPEED 16
-#define MOVE_ANGLE (2 * PHD_DEGREE) // = 364
-#define CLIMB_HANG 900
-#define CLIMB_SHIFT 70
-
-static void __cdecl M_TakeHit(
- ITEM_INFO *const lara_item, const int32_t dx, const int32_t dz);
-
-static void __cdecl M_TakeHit(
- ITEM_INFO *const lara_item, const int32_t dx, const int32_t dz)
-{
- const PHD_ANGLE hit_angle = lara_item->rot.y + PHD_180 - Math_Atan(dz, dx);
- g_Lara.hit_direction = Math_GetDirection(hit_angle);
- if (g_Lara.hit_frame == 0) {
- Sound_Effect(SFX_LARA_INJURY, &lara_item->pos, SPM_NORMAL);
- }
- g_Lara.hit_frame++;
- CLAMPG(g_Lara.hit_frame, 34);
-}
-
-void __cdecl Lara_GetCollisionInfo(ITEM_INFO *item, COLL_INFO *coll)
-{
- coll->facing = g_Lara.move_angle;
- Collide_GetCollisionInfo(
- coll, item->pos.x, item->pos.y, item->pos.z, item->room_num,
- LARA_HEIGHT);
-}
-
-void __cdecl Lara_SlideSlope(ITEM_INFO *item, COLL_INFO *coll)
-{
- coll->bad_pos = NO_BAD_POS;
- coll->bad_neg = -STEP_L * 2;
- coll->bad_ceiling = 0;
- Lara_GetCollisionInfo(item, coll);
-
- if (Lara_HitCeiling(item, coll)) {
- return;
- }
-
- Lara_DeflectEdge(item, coll);
-
- if (coll->side_mid.floor > 200) {
- if (item->current_anim_state == LS_SLIDE) {
- item->goal_anim_state = LS_FORWARD_JUMP;
- item->current_anim_state = LS_FORWARD_JUMP;
- item->anim_num = LS_SURF_SWIM;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- } else {
- item->goal_anim_state = LS_FALL_BACK;
- item->current_anim_state = LS_FALL_BACK;
- item->anim_num = LA_FALL_BACK;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- }
- item->gravity = 1;
- item->fall_speed = 0;
- return;
- }
-
- Lara_TestSlide(item, coll);
- item->pos.y += coll->side_mid.floor;
- if (ABS(coll->x_tilt) <= 2 && ABS(coll->z_tilt) <= 2) {
- item->goal_anim_state = LS_STOP;
- }
-}
-
-int32_t __cdecl Lara_HitCeiling(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (coll->coll_type != COLL_TOP && coll->coll_type != COLL_CLAMP) {
- return 0;
- }
-
- item->pos.x = coll->old.x;
- item->pos.y = coll->old.y;
- item->pos.z = coll->old.z;
- item->goal_anim_state = LS_STOP;
- item->current_anim_state = LS_STOP;
- item->anim_num = LS_REACH;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->speed = 0;
- item->gravity = 0;
- item->fall_speed = 0;
- return 1;
-}
-
-int32_t __cdecl Lara_DeflectEdge(ITEM_INFO *item, COLL_INFO *coll)
-{
- switch (coll->coll_type) {
- case COLL_FRONT:
- case COLL_TOP_FRONT:
- Item_ShiftCol(item, coll);
- item->goal_anim_state = LS_STOP;
- item->current_anim_state = LS_STOP;
- item->gravity = 0;
- item->speed = 0;
- return 1;
-
- case COLL_LEFT:
- Item_ShiftCol(item, coll);
- item->rot.y += LARA_DEFLECT_ANGLE;
- return 0;
-
- case COLL_RIGHT:
- Item_ShiftCol(item, coll);
- item->rot.y -= LARA_DEFLECT_ANGLE;
- return 0;
-
- default:
- return 0;
- }
-}
-
-void __cdecl Lara_DeflectEdgeJump(ITEM_INFO *item, COLL_INFO *coll)
-{
- Item_ShiftCol(item, coll);
- switch (coll->coll_type) {
- case COLL_FRONT:
- case COLL_TOP_FRONT:
- if (!g_Lara.climb_status || item->speed != 2) {
- if (coll->side_mid.floor > 512) {
- item->goal_anim_state = LS_FAST_FALL;
- item->current_anim_state = LS_FAST_FALL;
- item->anim_num = LA_SMASH_JUMP;
- item->frame_num = g_Anims[item->anim_num].frame_base + 1;
- } else if (coll->side_mid.floor <= 128) {
- item->goal_anim_state = LS_LAND;
- item->current_anim_state = LS_LAND;
- item->anim_num = LA_JUMP_UP_LAND;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- }
- item->speed /= 4;
- g_Lara.move_angle += PHD_180;
- CLAMPL(item->fall_speed, 1);
- }
- break;
-
- case COLL_LEFT:
- item->rot.y += LARA_DEFLECT_ANGLE;
- break;
-
- case COLL_RIGHT:
- item->rot.y -= LARA_DEFLECT_ANGLE;
- break;
-
- case COLL_TOP:
- CLAMPL(item->fall_speed, 1);
- break;
-
- case COLL_CLAMP:
- item->pos.z -= (Math_Cos(coll->facing) * 100) >> W2V_SHIFT;
- item->pos.x -= (Math_Sin(coll->facing) * 100) >> W2V_SHIFT;
- item->speed = 0;
- coll->side_mid.floor = 0;
- if (item->fall_speed <= 0) {
- item->fall_speed = 16;
- }
- break;
-
- default:
- break;
- }
-}
-
-void __cdecl Lara_SlideEdgeJump(ITEM_INFO *item, COLL_INFO *coll)
-{
- Item_ShiftCol(item, coll);
-
- switch (coll->coll_type) {
- case COLL_LEFT:
- item->rot.y += LARA_DEFLECT_ANGLE;
- break;
-
- case COLL_RIGHT:
- item->rot.y -= LARA_DEFLECT_ANGLE;
- break;
-
- case COLL_TOP:
- case COLL_TOP_FRONT:
- CLAMPL(item->fall_speed, 1);
- break;
-
- case COLL_CLAMP:
- item->pos.z -= (Math_Cos(coll->facing) * 100) >> W2V_SHIFT;
- item->pos.x -= (Math_Sin(coll->facing) * 100) >> W2V_SHIFT;
- item->speed = 0;
- coll->side_mid.floor = 0;
- if (item->fall_speed <= 0) {
- item->fall_speed = 16;
- }
- break;
-
- default:
- break;
- }
-}
-
-int32_t __cdecl Lara_TestWall(
- ITEM_INFO *item, int32_t front, int32_t right, int32_t down)
-{
- int32_t x = item->pos.x;
- int32_t y = item->pos.y + down;
- int32_t z = item->pos.z;
-
- DIRECTION dir = Math_GetDirection(item->rot.y);
- switch (dir) {
- case DIR_NORTH:
- x -= right;
- break;
- case DIR_EAST:
- z -= right;
- break;
- case DIR_SOUTH:
- x += right;
- break;
- case DIR_WEST:
- z += right;
- break;
- default:
- break;
- }
-
- int16_t room_num = item->room_num;
- Room_GetSector(x, y, z, &room_num);
-
- switch (dir) {
- case DIR_NORTH:
- z += front;
- break;
- case DIR_EAST:
- x += front;
- break;
- case DIR_SOUTH:
- z -= front;
- break;
- case DIR_WEST:
- x -= front;
- break;
- default:
- break;
- }
-
- const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
- const int32_t height = Room_GetHeight(sector, x, y, z);
- const int32_t ceiling = Room_GetCeiling(sector, x, y, z);
- if (height == NO_HEIGHT) {
- return 1;
- }
- if (height - y > 0 && ceiling - y < 0) {
- return 0;
- }
- return 2;
-}
-
-int32_t __cdecl Lara_TestHangOnClimbWall(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (!g_Lara.climb_status || item->fall_speed < 0) {
- return 0;
- }
-
- DIRECTION dir = Math_GetDirection(item->rot.y);
- switch (dir) {
- case DIR_NORTH:
- case DIR_SOUTH:
- item->pos.z += coll->shift.z;
- break;
-
- case DIR_EAST:
- case DIR_WEST:
- item->pos.x += coll->shift.x;
- break;
-
- default:
- break;
- }
-
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- int32_t y = bounds->min_y;
- int32_t h = bounds->max_y - y;
-
- int32_t shift;
- if (!Lara_TestClimbPos(item, coll->radius, coll->radius, y, h, &shift)) {
- return 0;
- }
-
- if (!Lara_TestClimbPos(item, coll->radius, -coll->radius, y, h, &shift)) {
- return 0;
- }
-
- int32_t result = Lara_TestClimbPos(item, coll->radius, 0, y, h, &shift);
- switch (result) {
- case 0:
- case 1:
- return result;
-
- default:
- item->pos.y += shift;
- return 1;
- }
-}
-
-int32_t __cdecl Lara_TestClimbStance(ITEM_INFO *item, COLL_INFO *coll)
-{
- int32_t shift_r;
- int32_t result_r = Lara_TestClimbPos(
- item, coll->radius, coll->radius + LARA_CLIMB_WIDTH_RIGHT, -700,
- STEP_L * 2, &shift_r);
- if (result_r != 1) {
- return 0;
- }
-
- int32_t shift_l;
- int32_t result_l = Lara_TestClimbPos(
- item, coll->radius, -(coll->radius + LARA_CLIMB_WIDTH_LEFT), -700,
- STEP_L * 2, &shift_l);
- if (result_l != 1) {
- return 0;
- }
-
- int32_t shift = 0;
- if (shift_r) {
- if (shift_l) {
- if ((shift_r < 0) != (shift_l < 0)) {
- return 0;
- }
- if (shift_r < 0 && shift_l < shift_r) {
- shift = shift_l;
- } else if (shift_r > 0 && shift_l > shift_r) {
- shift = shift_l;
- } else {
- shift = shift_r;
- }
- } else {
- shift = shift_r;
- }
- } else if (shift_l) {
- shift = shift_l;
- }
-
- item->pos.y += shift;
- return 1;
-}
-
-void __cdecl Lara_HangTest(ITEM_INFO *item, COLL_INFO *coll)
-{
- coll->bad_pos = NO_BAD_POS;
- coll->bad_neg = NO_BAD_NEG;
- coll->bad_ceiling = 0;
- Lara_GetCollisionInfo(item, coll);
- bool flag = coll->side_front.floor < 200;
-
- item->gravity = 0;
- item->fall_speed = 0;
- g_Lara.move_angle = item->rot.y;
-
- DIRECTION dir = Math_GetDirection(item->rot.y);
- switch (dir) {
- case DIR_NORTH:
- item->pos.z += 2;
- break;
- case DIR_EAST:
- item->pos.x += 2;
- break;
- case DIR_SOUTH:
- item->pos.z -= 2;
- break;
- case DIR_WEST:
- item->pos.x -= 2;
- break;
- default:
- break;
- }
-
- coll->bad_pos = NO_BAD_POS;
- coll->bad_neg = -STEPUP_HEIGHT;
- coll->bad_ceiling = 0;
- Lara_GetCollisionInfo(item, coll);
-
- if (g_Lara.climb_status) {
- if (!(g_Input & IN_ACTION) || item->hit_points <= 0) {
- XYZ_32 pos = {
- .x = 0,
- .y = 0,
- .z = 0,
- };
- Collide_GetJointAbsPosition(item, &pos, 0);
- if (dir == DIR_NORTH || dir == DIR_SOUTH) {
- item->pos.x = pos.x;
- } else {
- item->pos.z = pos.z;
- }
-
- item->goal_anim_state = LS_FORWARD_JUMP;
- item->current_anim_state = LS_FORWARD_JUMP;
- item->anim_num = LA_FALL_START;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->pos.y += STEP_L;
- item->gravity = 1;
- item->speed = 2;
- item->fall_speed = 1;
- g_Lara.gun_status = LGS_ARMLESS;
- return;
- }
-
- if (!Lara_TestHangOnClimbWall(item, coll)) {
- item->pos.x = coll->old.x;
- item->pos.y = coll->old.y;
- item->pos.z = coll->old.z;
- item->goal_anim_state = LS_HANG;
- item->current_anim_state = LS_HANG;
- item->anim_num = LA_REACH_TO_HANG;
- item->frame_num = g_Anims[item->anim_num].frame_base + 21;
- return;
- }
-
- if (item->anim_num == LA_REACH_TO_HANG
- && item->frame_num == g_Anims[item->anim_num].frame_base + 21
- && Lara_TestClimbStance(item, coll)) {
- item->goal_anim_state = LS_CLIMB_STANCE;
- }
- return;
- }
-
- if (!(g_Input & IN_ACTION) || item->hit_points <= 0
- || coll->side_front.floor > 0) {
- item->goal_anim_state = LS_UP_JUMP;
- item->current_anim_state = LS_UP_JUMP;
- item->anim_num = LA_JUMP_UP;
- item->frame_num = g_Anims[item->anim_num].frame_base + 9;
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- item->pos.y += bounds->max_y;
- item->pos.x += coll->shift.x;
- item->pos.z += coll->shift.z;
- item->gravity = 1;
- item->speed = 2;
- item->fall_speed = 1;
- g_Lara.gun_status = LGS_ARMLESS;
- return;
- }
-
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- int32_t hdif = coll->side_front.floor - bounds->min_y;
-
- if (ABS(coll->side_left.floor - coll->side_right.floor) >= SLOPE_DIF
- || coll->side_mid.ceiling >= 0 || coll->coll_type != COLL_FRONT || flag
- || coll->hit_static || hdif < -SLOPE_DIF || hdif > SLOPE_DIF) {
- item->pos.x = coll->old.x;
- item->pos.y = coll->old.y;
- item->pos.z = coll->old.z;
- if (item->current_anim_state == LS_HANG_LEFT
- || item->current_anim_state == LS_HANG_RIGHT) {
- item->goal_anim_state = LS_HANG;
- item->current_anim_state = LS_HANG;
- item->anim_num = LA_REACH_TO_HANG;
- item->frame_num = g_Anims[item->anim_num].frame_base + 21;
- }
- return;
- }
-
- switch (dir) {
- case DIR_NORTH:
- case DIR_SOUTH:
- item->pos.z += coll->shift.z;
- break;
-
- case DIR_EAST:
- case DIR_WEST:
- item->pos.x += coll->shift.x;
- break;
-
- default:
- break;
- }
-
- item->pos.y += hdif;
-}
-
-int32_t __cdecl Lara_TestEdgeCatch(
- ITEM_INFO *item, COLL_INFO *coll, int32_t *edge)
-{
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- int32_t hdif1 = coll->side_front.floor - bounds->min_y;
- int32_t hdif2 = hdif1 + item->fall_speed;
- if ((hdif1 < 0 && hdif2 < 0) || (hdif1 > 0 && hdif2 > 0)) {
- hdif1 = item->pos.y + bounds->min_y;
- hdif2 = hdif1 + item->fall_speed;
- if ((hdif1 >> (WALL_SHIFT - 2)) == (hdif2 >> (WALL_SHIFT - 2))) {
- return 0;
- }
- if (item->fall_speed > 0) {
- *edge = hdif2 & ~(STEP_L - 1);
- } else {
- *edge = hdif1 & ~(STEP_L - 1);
- }
- return -1;
- }
-
- return ABS(coll->side_left.floor - coll->side_right.floor) < SLOPE_DIF;
-}
-
-int32_t __cdecl Lara_TestHangJumpUp(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
- || g_Lara.gun_status != LGS_ARMLESS || coll->hit_static
- || coll->side_mid.ceiling > -STEPUP_HEIGHT) {
- return 0;
- }
-
- int32_t edge;
- int32_t edge_catch = Lara_TestEdgeCatch(item, coll, &edge);
- if (!edge_catch
- || (edge_catch < 0 && !Lara_TestHangOnClimbWall(item, coll))) {
- return 0;
- }
-
- DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
- if (dir == DIR_UNKNOWN) {
- return 0;
- }
- int16_t angle = Math_DirectionToAngle(dir);
-
- item->goal_anim_state = LS_HANG;
- item->current_anim_state = LS_HANG;
- item->anim_num = LA_REACH_TO_HANG;
- item->frame_num = g_Anims[item->anim_num].frame_base + 12;
-
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- if (edge_catch > 0) {
- item->pos.y += coll->side_front.floor - bounds->min_y;
- } else {
- item->pos.y = edge - bounds->min_y;
- }
- item->pos.x += coll->shift.x;
- item->pos.z += coll->shift.z;
- item->rot.y = angle;
- item->speed = 0;
- item->gravity = 0;
- item->fall_speed = 0;
- g_Lara.gun_status = LGS_HANDS_BUSY;
- return 1;
-}
-
-int32_t __cdecl Lara_TestHangJump(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
- || g_Lara.gun_status != LGS_ARMLESS || coll->hit_static
- || coll->side_mid.ceiling > -STEPUP_HEIGHT
- || coll->side_mid.floor < 200) {
- return 0;
- }
-
- int32_t edge;
- int32_t edge_catch = Lara_TestEdgeCatch(item, coll, &edge);
- if (!edge_catch
- || (edge_catch < 0 && !Lara_TestHangOnClimbWall(item, coll))) {
- return 0;
- }
-
- DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
- if (dir == DIR_UNKNOWN) {
- return 0;
- }
- int16_t angle = Math_DirectionToAngle(dir);
-
- if (Lara_TestHangSwingIn(item, angle)) {
- item->anim_num = LA_REACH_TO_THIN_LEDGE;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- } else {
- item->anim_num = LA_REACH_TO_HANG;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- }
- item->current_anim_state = LS_HANG;
- item->goal_anim_state = LS_HANG;
-
- const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
- if (edge_catch > 0) {
- item->pos.y += coll->side_front.floor - bounds->min_y;
- item->pos.x += coll->shift.x;
- item->pos.z += coll->shift.z;
- } else {
- item->pos.y = edge - bounds->min_y;
- }
-
- item->rot.y = angle;
- item->speed = 2;
- item->gravity = 1;
- item->fall_speed = 1;
- g_Lara.gun_status = LGS_HANDS_BUSY;
- return 1;
-}
-
-int32_t __cdecl Lara_TestHangSwingIn(ITEM_INFO *item, PHD_ANGLE angle)
-{
- int32_t x = item->pos.x;
- int32_t y = item->pos.y;
- int32_t z = item->pos.z;
- int16_t room_num = item->room_num;
- switch (angle) {
- case 0:
- z += STEP_L;
- break;
- case PHD_90:
- x += STEP_L;
- break;
- case -PHD_180:
- z -= STEP_L;
- break;
- case -PHD_90:
- x -= STEP_L;
- break;
- }
-
- const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
- int32_t height = Room_GetHeight(sector, x, y, z);
- int32_t ceiling = Room_GetCeiling(sector, x, y, z);
- return height != NO_HEIGHT && height - y > 0 && ceiling - y < -400;
-}
-
-int32_t __cdecl Lara_TestVault(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
- || g_Lara.gun_status != LGS_ARMLESS) {
- return 0;
- }
-
- DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_VAULT_ANGLE);
- if (dir == DIR_UNKNOWN) {
- return 0;
- }
- int16_t angle = Math_DirectionToAngle(dir);
-
- int32_t left_floor = coll->side_left.floor;
- int32_t left_ceiling = coll->side_left.ceiling;
- int32_t right_floor = coll->side_right.floor;
- int32_t right_ceiling = coll->side_right.ceiling;
- int32_t front_floor = coll->side_front.floor;
- int32_t front_ceiling = coll->side_front.ceiling;
- bool slope = ABS(left_floor - right_floor) >= SLOPE_DIF;
-
- int32_t mid = STEP_L / 2;
- if (front_floor >= -STEP_L * 2 - mid && front_floor <= -STEP_L * 2 + mid) {
- if (slope || front_floor - front_ceiling < 0
- || left_floor - left_ceiling < 0
- || right_floor - right_ceiling < 0) {
- return 0;
- }
- item->goal_anim_state = LS_STOP;
- item->current_anim_state = LS_NULL;
- item->anim_num = LA_CLIMB_2CLICK;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->pos.y += front_floor + STEP_L * 2;
- g_Lara.gun_status = LGS_HANDS_BUSY;
- } else if (
- front_floor >= -STEP_L * 3 - mid && front_floor <= -STEP_L * 3 + mid) {
- if (slope || front_floor - front_ceiling < 0
- || left_floor - left_ceiling < 0
- || right_floor - right_ceiling < 0) {
- return 0;
- }
- item->goal_anim_state = LS_STOP;
- item->current_anim_state = LS_NULL;
- item->anim_num = LA_CLIMB_3CLICK;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->pos.y += front_floor + STEP_L * 3;
- g_Lara.gun_status = LGS_HANDS_BUSY;
- } else if (
- !slope && front_floor >= -STEP_L * 7 - mid
- && front_floor <= -STEP_L * 4 + mid) {
- item->goal_anim_state = LS_UP_JUMP;
- item->current_anim_state = LS_STOP;
- item->anim_num = LA_STAND_STILL;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- g_Lara.calc_fallspeed =
- -(Math_Sqrt(-2 * GRAVITY * (front_floor + 800)) + 3);
- Lara_Animate(item);
- } else if (
- g_Lara.climb_status && front_floor <= -1920
- && g_Lara.water_status != LWS_WADE && left_floor <= -STEP_L * 8 + mid
- && right_floor <= -STEP_L * 8
- && coll->side_mid.ceiling <= -STEP_L * 8 + mid + LARA_HEIGHT) {
- item->goal_anim_state = LS_UP_JUMP;
- item->current_anim_state = LS_STOP;
- item->anim_num = LA_STAND_STILL;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- g_Lara.calc_fallspeed = -116;
- Lara_Animate(item);
- } else if (
- g_Lara.climb_status
- && (front_floor < -STEP_L * 4 || front_ceiling >= LARA_HEIGHT - STEP_L)
- && coll->side_mid.ceiling <= -STEP_L * 5 + LARA_HEIGHT) {
- Item_ShiftCol(item, coll);
- if (Lara_TestClimbStance(item, coll)) {
- item->goal_anim_state = LS_CLIMB_STANCE;
- item->current_anim_state = LS_STOP;
- item->anim_num = LA_STAND_STILL;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- Lara_Animate(item);
- item->rot.y = angle;
- g_Lara.gun_status = LGS_HANDS_BUSY;
- return 1;
- }
- return 0;
- } else {
- return 0;
- }
-
- item->rot.y = angle;
- Item_ShiftCol(item, coll);
- return 1;
-}
-
-int32_t __cdecl Lara_TestSlide(ITEM_INFO *item, COLL_INFO *coll)
-{
- if (ABS(coll->x_tilt) <= 2 && ABS(coll->z_tilt) <= 2) {
- return 0;
- }
-
- int16_t angle = 0;
- if (coll->x_tilt > 2) {
- angle = -PHD_90;
- } else if (coll->x_tilt < -2) {
- angle = PHD_90;
- }
-
- if (coll->z_tilt > 2 && coll->z_tilt > ABS(coll->x_tilt)) {
- angle = PHD_180;
- } else if (coll->z_tilt < -2 && -coll->z_tilt > ABS(coll->x_tilt)) {
- angle = 0;
- }
-
- const int16_t angle_dif = angle - item->rot.y;
- Item_ShiftCol(item, coll);
-
- if (angle_dif >= -PHD_90 && angle_dif <= PHD_90) {
- if (item->current_anim_state == LS_SLIDE
- && g_LaraOldSlideAngle == angle) {
- return 1;
- }
- item->goal_anim_state = LS_SLIDE;
- item->current_anim_state = LS_SLIDE;
- item->anim_num = LA_SLIDE_FORWARD;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->rot.y = angle;
- } else {
- if (item->current_anim_state == LS_SLIDE_BACK
- && g_LaraOldSlideAngle == angle) {
- return 1;
- }
- item->goal_anim_state = LS_SLIDE_BACK;
- item->current_anim_state = LS_SLIDE_BACK;
- item->anim_num = LA_SLIDE_BACKWARD_START;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->rot.y = angle + PHD_180;
- }
-
- g_Lara.move_angle = angle;
- g_LaraOldSlideAngle = angle;
- return 1;
-}
-
-int16_t __cdecl Lara_FloorFront(ITEM_INFO *item, int16_t ang, int32_t dist)
-{
- const int32_t x = item->pos.x + ((dist * Math_Sin(ang)) >> W2V_SHIFT);
- const int32_t y = item->pos.y - LARA_HEIGHT;
- const int32_t z = item->pos.z + ((dist * Math_Cos(ang)) >> W2V_SHIFT);
- int16_t room_num = item->room_num;
- const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
- int32_t height = Room_GetHeight(sector, x, y, z);
- if (height != NO_HEIGHT) {
- height -= item->pos.y;
- }
- return height;
-}
-
-int32_t __cdecl Lara_LandedBad(ITEM_INFO *item, COLL_INFO *coll)
-{
- const int32_t x = item->pos.x;
- const int32_t y = item->pos.y;
- const int32_t z = item->pos.z;
-
- int16_t room_num = item->room_num;
- const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
- const int32_t height = Room_GetHeight(sector, x, y - LARA_HEIGHT, z);
- item->pos.y = height;
- item->floor = height;
-
- Room_TestTriggers(g_TriggerIndex, 0);
- int32_t land_speed = item->fall_speed - DAMAGE_START;
- item->pos.y = y;
- if (land_speed <= 0) {
- return 0;
- }
- if (land_speed <= DAMAGE_LENGTH) {
- item->hit_points += -LARA_MAX_HITPOINTS * land_speed * land_speed
- / (DAMAGE_LENGTH * DAMAGE_LENGTH);
- } else {
- item->hit_points = -1;
- }
- return item->hit_points <= 0;
-}
-
-int32_t __cdecl Lara_CheckForLetGo(ITEM_INFO *item, COLL_INFO *coll)
-{
- item->gravity = 0;
- item->fall_speed = 0;
-
- int16_t room_num = item->room_num;
- int32_t x = item->pos.x;
- int32_t y = item->pos.y;
- int32_t z = item->pos.z;
- const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
- Room_GetHeight(sector, x, y, z);
- coll->trigger = g_TriggerIndex;
- if ((g_Input & IN_ACTION) && item->hit_points > 0) {
- return 0;
- }
-
- item->goal_anim_state = LS_FORWARD_JUMP;
- item->current_anim_state = LS_FORWARD_JUMP;
- item->anim_num = LA_FALL_START;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->gravity = 1;
- item->speed = 2;
- item->fall_speed = 1;
- g_Lara.gun_status = LGS_ARMLESS;
- return 1;
-}
-
-void __cdecl Lara_GetJointAbsPosition(XYZ_32 *vec, int32_t joint)
-{
- FRAME_INFO *frmptr[2] = { NULL, NULL };
- if (g_Lara.hit_direction < 0) {
- int32_t rate;
- int32_t frac = Item_GetFrames(g_LaraItem, frmptr, &rate);
- if (frac) {
- Lara_GetJointAbsPosition_I(
- g_LaraItem, vec, frmptr[0], frmptr[1], frac, rate);
- return;
- }
- }
-
- const FRAME_INFO *frame_ptr = NULL;
- const OBJECT_INFO *obj = &g_Objects[g_LaraItem->object_id];
- if (g_Lara.hit_direction >= 0) {
- LARA_ANIMATION anim_num;
- switch (g_Lara.hit_direction) {
- case DIR_EAST:
- anim_num = LA_HIT_RIGHT;
- break;
- case DIR_SOUTH:
- anim_num = LA_HIT_BACK;
- break;
- case DIR_WEST:
- anim_num = LA_HIT_LEFT;
- break;
- default:
- anim_num = LA_HIT_FRONT;
- break;
- }
- const ANIM_STRUCT *anim = &g_Anims[anim_num];
- int32_t interpolation = anim->interpolation;
- frame_ptr = (const FRAME_INFO *)(anim->frame_ptr
- + (int32_t)(g_Lara.hit_frame
- * (interpolation >> 8)));
- } else {
- frame_ptr = frmptr[0];
- }
-
- Matrix_PushUnit();
- g_MatrixPtr->_03 = 0;
- g_MatrixPtr->_13 = 0;
- g_MatrixPtr->_23 = 0;
- Matrix_RotYXZ(g_LaraItem->rot.y, g_LaraItem->rot.x, g_LaraItem->rot.z);
-
- const int16_t *rot = frame_ptr->mesh_rots;
- const int32_t *bone = &g_AnimBones[obj->bone_idx];
-
- Matrix_TranslateRel(
- frame_ptr->offset.x, frame_ptr->offset.y, frame_ptr->offset.z);
- Matrix_RotYXZsuperpack(&rot, 0);
-
- Matrix_TranslateRel(bone[25], bone[26], bone[27]);
- Matrix_RotYXZsuperpack(&rot, 6);
- Matrix_RotYXZ(g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
-
- LARA_GUN_TYPE gun_type = LGT_UNARMED;
- if (g_Lara.gun_status == LGS_READY || g_Lara.gun_status == LGS_SPECIAL
- || g_Lara.gun_status == LGS_DRAW || g_Lara.gun_status == LGS_UNDRAW) {
- gun_type = g_Lara.gun_type;
- }
-
- if (g_Lara.gun_type == LGT_FLARE) {
- Matrix_TranslateRel(bone[41], bone[42], bone[43]);
- if (g_Lara.flare_control_left) {
- const LARA_ARM *arm = &g_Lara.left_arm;
- const ANIM_STRUCT *anim = &g_Anims[arm->anim_num];
- rot = &arm->frame_base
- [(anim->interpolation >> 8)
- * (arm->frame_num - anim->frame_base)
- + FBBOX_ROT];
- } else {
- rot = frame_ptr->mesh_rots;
- }
- Matrix_RotYXZsuperpack(&rot, 11);
-
- Matrix_TranslateRel(bone[45], bone[46], bone[47]);
- Matrix_RotYXZsuperpack(&rot, 0);
-
- Matrix_TranslateRel(bone[49], bone[50], bone[51]);
- Matrix_RotYXZsuperpack(&rot, 0);
- } else if (gun_type != LGT_UNARMED) {
- Matrix_TranslateRel(bone[29], bone[30], bone[31]);
-
- const LARA_ARM *arm = &g_Lara.right_arm;
- const ANIM_STRUCT *anim = &g_Anims[arm->anim_num];
- rot = &arm->frame_base
- [arm->frame_num * (anim->interpolation >> 8) + FBBOX_ROT];
- Matrix_RotYXZsuperpack(&rot, 8);
-
- Matrix_TranslateRel(bone[33], bone[34], bone[35]);
- Matrix_RotYXZsuperpack(&rot, 0);
-
- Matrix_TranslateRel(bone[37], bone[38], bone[39]);
- Matrix_RotYXZsuperpack(&rot, 0);
- }
-
- Matrix_TranslateRel(vec->x, vec->y, vec->z);
- vec->x = g_LaraItem->pos.x + (g_MatrixPtr->_03 >> W2V_SHIFT);
- vec->y = g_LaraItem->pos.y + (g_MatrixPtr->_13 >> W2V_SHIFT);
- vec->z = g_LaraItem->pos.z + (g_MatrixPtr->_23 >> W2V_SHIFT);
- Matrix_Pop();
-}
-
-void __cdecl Lara_GetJointAbsPosition_I(
- ITEM_INFO *item, XYZ_32 *vec, FRAME_INFO *frame1, FRAME_INFO *frame2,
- int32_t frac, int32_t rate)
-{
- const OBJECT_INFO *obj = &g_Objects[item->object_id];
-
- Matrix_PushUnit();
- g_MatrixPtr->_03 = 0;
- g_MatrixPtr->_13 = 0;
- g_MatrixPtr->_23 = 0;
- Matrix_RotYXZ(item->rot.y, item->rot.x, item->rot.z);
-
- const int32_t *const bone = &g_AnimBones[obj->bone_idx];
- const int16_t *rot1 = frame1->mesh_rots;
- const int16_t *rot2 = frame2->mesh_rots;
- Matrix_InitInterpolate(frac, rate);
-
- Matrix_TranslateRel_ID(
- frame1->offset.x, frame1->offset.y, frame1->offset.z, frame2->offset.x,
- frame2->offset.y, frame2->offset.z);
- Matrix_RotYXZsuperpack_I(&rot1, &rot2, 0);
-
- Matrix_TranslateRel_I(bone[25], bone[26], bone[27]);
- Matrix_RotYXZsuperpack_I(&rot1, &rot2, 6);
- Matrix_RotYXZ_I(g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
-
- LARA_GUN_TYPE gun_type = LGT_UNARMED;
- if (g_Lara.gun_status == LGS_READY || g_Lara.gun_status == LGS_SPECIAL
- || g_Lara.gun_status == LGS_DRAW || g_Lara.gun_status == LGS_UNDRAW) {
- gun_type = g_Lara.gun_type;
- }
-
- if (g_Lara.gun_type == LGT_FLARE) {
- Matrix_Interpolate();
- Matrix_TranslateRel(bone[29], bone[30], bone[31]);
- if (g_Lara.flare_control_left) {
- const LARA_ARM *arm = &g_Lara.left_arm;
- const ANIM_STRUCT *anim = &g_Anims[arm->anim_num];
- rot1 = &arm->frame_base
- [(anim->interpolation >> 8)
- * (arm->frame_num - anim->frame_base)
- + FBBOX_ROT];
- } else {
- rot1 = frame1->mesh_rots;
- }
- Matrix_RotYXZsuperpack(&rot1, 11);
-
- Matrix_TranslateRel(bone[45], bone[46], bone[47]);
- Matrix_RotYXZsuperpack(&rot1, 0);
-
- Matrix_TranslateRel(bone[49], bone[50], bone[51]);
- Matrix_RotYXZsuperpack(&rot1, 0);
- } else if (gun_type != LGT_UNARMED) {
- Matrix_Interpolate();
- Matrix_TranslateRel(bone[29], bone[30], bone[31]);
-
- const LARA_ARM *arm = &g_Lara.right_arm;
- const ANIM_STRUCT *anim = &g_Anims[arm->anim_num];
- rot1 = &arm->frame_base
- [arm->frame_num * (anim->interpolation >> 8) + FBBOX_ROT];
- Matrix_RotYXZsuperpack(&rot1, 8);
-
- Matrix_TranslateRel(bone[33], bone[34], bone[35]);
- Matrix_RotYXZsuperpack(&rot1, 0);
-
- Matrix_TranslateRel(bone[37], bone[38], bone[39]);
- Matrix_RotYXZsuperpack(&rot1, 0);
- }
-
- Matrix_TranslateRel(vec->x, vec->y, vec->z);
- vec->x = item->pos.x + (g_MatrixPtr->_03 >> W2V_SHIFT);
- vec->y = item->pos.y + (g_MatrixPtr->_13 >> W2V_SHIFT);
- vec->z = item->pos.z + (g_MatrixPtr->_23 >> W2V_SHIFT);
-
- Matrix_Pop();
-}
-
-void __cdecl Lara_TakeHit(
- ITEM_INFO *const lara_item, const COLL_INFO *const coll)
-{
- const int32_t dx = g_Lara.spaz_effect->pos.x - lara_item->pos.x;
- const int32_t dz = g_Lara.spaz_effect->pos.z - lara_item->pos.z;
- M_TakeHit(lara_item, dx, dz);
- g_Lara.spaz_effect_count--;
-}
-
-void __cdecl Lara_BaddieCollision(ITEM_INFO *lara_item, COLL_INFO *coll)
-{
- lara_item->hit_status = 0;
- g_Lara.hit_direction = -1;
- if (lara_item->hit_points <= 0) {
- return;
- }
-
- int16_t roomies[MAX_BADDIE_COLLISION] = { 0 };
- int32_t roomies_count = 0;
-
- roomies[roomies_count++] = lara_item->room_num;
-
- DOOR_INFOS *doors = g_Rooms[roomies[0]].doors;
- if (doors != NULL) {
- for (int32_t i = 0; i < doors->count; i++) {
- if (roomies_count >= MAX_BADDIE_COLLISION) {
- break;
- }
- roomies[roomies_count++] = doors->door[i].room;
- }
- }
-
- for (int32_t i = 0; i < roomies_count; i++) {
- int16_t item_num = g_Rooms[roomies[i]].item_num;
- while (item_num != NO_ITEM) {
- const ITEM_INFO *const item = &g_Items[item_num];
-
- // the collision routine can destroy the item - need to store the
- // next item beforehand
- const int16_t next_item_num = item->next_item;
-
- if (item->collidable && item->status != IS_INVISIBLE) {
- const OBJECT_INFO *const object = &g_Objects[item->object_id];
- if (object->collision) {
- // clang-format off
- const XYZ_32 d = {
- .x = lara_item->pos.x - item->pos.x,
- .y = lara_item->pos.y - item->pos.y,
- .z = lara_item->pos.z - item->pos.z,
- };
- if (d.x > -TARGET_DIST && d.x < TARGET_DIST &&
- d.y > -TARGET_DIST && d.y < TARGET_DIST &&
- d.z > -TARGET_DIST && d.z < TARGET_DIST) {
- object->collision(item_num, lara_item, coll);
- }
- // clang-format on
- }
- }
-
- item_num = next_item_num;
- }
- }
-
- if (g_Lara.spaz_effect_count) {
- Lara_TakeHit(lara_item, coll);
- }
-
- if (g_Lara.hit_direction == -1) {
- g_Lara.hit_frame = 0;
- }
-
- g_Inv_Chosen = -1;
-}
-
-void __cdecl Lara_Push(
- const ITEM_INFO *const item, ITEM_INFO *const lara_item,
- COLL_INFO *const coll, const bool spaz_on, const bool big_push)
-{
- int32_t dx = lara_item->pos.x - item->pos.x;
- int32_t dz = lara_item->pos.z - item->pos.z;
- const int32_t c = Math_Cos(item->rot.y);
- const int32_t s = Math_Sin(item->rot.y);
- int32_t rx = (c * dx - s * dz) >> W2V_SHIFT;
- int32_t rz = (c * dz + s * dx) >> W2V_SHIFT;
-
- const BOUNDS_16 *const bounds = &Item_GetBestFrame(item)->bounds;
- int32_t min_x = bounds->min_x;
- int32_t max_x = bounds->max_x;
- int32_t min_z = bounds->min_z;
- int32_t max_z = bounds->max_z;
-
- if (big_push) {
- max_x += coll->radius;
- min_z -= coll->radius;
- max_z += coll->radius;
- min_x -= coll->radius;
- }
-
- if (rx < min_x || rx > max_x || rz < min_z || rz > max_z) {
- return;
- }
-
- int32_t l = rx - min_x;
- int32_t r = max_x - rx;
- int32_t t = max_z - rz;
- int32_t b = rz - min_z;
-
- if (l <= r && l <= t && l <= b) {
- rx -= l;
- } else if (r <= l && r <= t && r <= b) {
- rx += r;
- } else if (t <= l && t <= r && t <= b) {
- rz += t;
- } else {
- rz = min_z;
- }
-
- lara_item->pos.x = item->pos.x + ((rz * s + rx * c) >> W2V_SHIFT);
- lara_item->pos.z = item->pos.z + ((rz * c - rx * s) >> W2V_SHIFT);
-
- rz = (bounds->max_z + bounds->min_z) / 2;
- rx = (bounds->max_x + bounds->min_x) / 2;
- dx -= (c * rx + s * rz) >> W2V_SHIFT;
- dz -= (c * rz - s * rx) >> W2V_SHIFT;
-
- if (spaz_on && bounds->max_y - bounds->min_y > STEP_L) {
- M_TakeHit(lara_item, dx, dz);
- }
-
- int16_t old_facing = coll->facing;
- coll->bad_pos = NO_BAD_POS;
- coll->bad_neg = -STEPUP_HEIGHT;
- coll->bad_ceiling = 0;
- coll->facing = Math_Atan(
- lara_item->pos.z - coll->old.z, lara_item->pos.x - coll->old.x);
- Collide_GetCollisionInfo(
- coll, lara_item->pos.x, lara_item->pos.y, lara_item->pos.z,
- lara_item->room_num, LARA_HEIGHT);
- coll->facing = old_facing;
-
- if (coll->coll_type != COLL_NONE) {
- lara_item->pos.x = coll->old.x;
- lara_item->pos.z = coll->old.z;
- } else {
- coll->old.x = lara_item->pos.x;
- coll->old.y = lara_item->pos.y;
- coll->old.z = lara_item->pos.z;
- Item_UpdateRoom(lara_item, -WALL_SHIFT);
- }
-}
-
-int32_t __cdecl Lara_MovePosition(
- XYZ_32 *vec, ITEM_INFO *item, ITEM_INFO *lara_item)
-{
- const XYZ_16 rot = {
- .x = item->rot.x,
- .y = item->rot.y,
- .z = item->rot.z,
- };
-
- Matrix_PushUnit();
- Matrix_RotYXZ(rot.y, rot.x, rot.z);
- const MATRIX *const m = g_MatrixPtr;
- const XYZ_32 shift = {
- .x = (vec->y * m->_01 + vec->z * m->_02 + vec->x * m->_00) >> W2V_SHIFT,
- .y = (vec->x * m->_10 + vec->z * m->_12 + vec->y * m->_11) >> W2V_SHIFT,
- .z = (vec->y * m->_21 + vec->x * m->_20 + vec->z * m->_22) >> W2V_SHIFT,
- };
- Matrix_Pop();
-
- const XYZ_32 new_pos = {
- .x = item->pos.x + shift.x,
- .y = item->pos.y + shift.y,
- .z = item->pos.z + shift.z,
- };
-
- if (item->object_id == O_FLARE_ITEM) {
- int16_t room_num = lara_item->room_num;
- const SECTOR_INFO *const sector =
- Room_GetSector(new_pos.x, new_pos.y, new_pos.z, &room_num);
- const int32_t height =
- Room_GetHeight(sector, new_pos.x, new_pos.y, new_pos.z);
- if (ABS(height - lara_item->pos.y) > STEP_L * 2) {
- return false;
- }
- if (XYZ_32_GetDistance(&new_pos, &lara_item->pos) < STEP_L) {
- return true;
- }
- }
-
- // TODO: get rid of this conversion
- const PHD_3DPOS new_pos_full = {
- .pos = new_pos,
- .rot = rot,
- };
- PHD_3DPOS src_pos = {
- .pos = lara_item->pos,
- .rot = lara_item->rot,
- };
- const int32_t result =
- Misc_Move3DPosTo3DPos(&src_pos, &new_pos_full, MOVE_SPEED, MOVE_ANGLE);
- lara_item->pos = src_pos.pos;
- lara_item->rot = src_pos.rot;
- return result;
-}
-
-int32_t __cdecl Lara_IsNearItem(const XYZ_32 *const pos, const int32_t distance)
-{
- return Item_IsNearItem(g_LaraItem, pos, distance);
-}
-
-int32_t __cdecl Lara_TestClimb(
- const int32_t x, const int32_t y, const int32_t z, const int32_t x_front,
- const int32_t z_front, const int32_t item_height, const int16_t item_room,
- int32_t *const shift)
-{
- *shift = 0;
- bool hang = true;
- if (!g_Lara.climb_status) {
- return 0;
- }
-
- const SECTOR_INFO *sector;
- int32_t height;
- int32_t ceiling;
-
- int16_t room_num = item_room;
- sector = Room_GetSector(x, y - 128, z, &room_num);
- height = Room_GetHeight(sector, x, y, z);
- if (height == NO_HEIGHT) {
- return 0;
- }
-
- height -= y + item_height + STEP_L / 2;
- if (height < -CLIMB_SHIFT) {
- return 0;
- }
- if (height < 0) {
- *shift = height;
- }
-
- ceiling = Room_GetCeiling(sector, x, y, z) - y;
- if (ceiling > CLIMB_SHIFT) {
- return 0;
- }
- if (ceiling > 0) {
- if (*shift) {
- return 0;
- }
- *shift = ceiling;
- }
-
- if (item_height + height < CLIMB_HANG) {
- hang = false;
- }
-
- const int32_t x2 = x + x_front;
- const int32_t z2 = z + z_front;
- sector = Room_GetSector(x2, y, z2, &room_num);
- height = Room_GetHeight(sector, x2, y, z2);
- if (height != NO_HEIGHT) {
- height -= y;
- }
-
- if (height > CLIMB_SHIFT) {
- ceiling = Room_GetCeiling(sector, x2, y, z2) - y;
- if (ceiling >= LARA_CLIMB_HEIGHT) {
- return 1;
- }
-
- if (ceiling > LARA_CLIMB_HEIGHT - CLIMB_SHIFT) {
- if (*shift > 0) {
- return hang ? -1 : 0;
- }
- *shift = ceiling - LARA_CLIMB_HEIGHT;
- return 1;
- }
-
- if (ceiling > 0) {
- return hang ? -1 : 0;
- }
-
- if (ceiling > -CLIMB_SHIFT && hang && *shift <= 0) {
- if (*shift > ceiling) {
- *shift = ceiling;
- }
-
- return -1;
- }
-
- return 0;
- }
-
- if (height > 0) {
- if (*shift < 0) {
- return 0;
- }
- if (height > *shift) {
- *shift = height;
- }
- }
-
- room_num = item_room;
- sector = Room_GetSector(x, item_height + y, z, &room_num);
- sector = Room_GetSector(x2, item_height + y, z2, &room_num);
- ceiling = Room_GetCeiling(sector, x2, item_height + y, z2);
- if (ceiling == NO_HEIGHT) {
- return 1;
- }
-
- ceiling -= y;
- if (ceiling <= height) {
- return 1;
- }
-
- if (ceiling >= LARA_CLIMB_HEIGHT) {
- return 1;
- }
-
- if (ceiling > LARA_CLIMB_HEIGHT - CLIMB_SHIFT) {
- if (*shift > 0) {
- return hang ? -1 : 0;
- }
- *shift = ceiling - LARA_CLIMB_HEIGHT;
- return 1;
- }
-
- return hang ? -1 : 0;
-}
-
-int32_t __cdecl Lara_TestClimbPos(
- const ITEM_INFO *const item, const int32_t front, const int32_t right,
- const int32_t origin, const int32_t height, int32_t *const shift)
-{
- const int32_t y = item->pos.y + origin;
- int32_t x;
- int32_t z;
- int32_t x_front = 0;
- int32_t z_front = 0;
-
- switch (Math_GetDirection(item->rot.y)) {
- case DIR_NORTH:
- x = item->pos.x + right;
- z = item->pos.z + front;
- z_front = 2;
- break;
-
- case DIR_EAST:
- x = item->pos.x + front;
- z = item->pos.z - right;
- x_front = 2;
- break;
-
- case DIR_SOUTH:
- x = item->pos.x - right;
- z = item->pos.z - front;
- z_front = -2;
- break;
-
- case DIR_WEST:
- x = item->pos.x - front;
- z = item->pos.z + right;
- x_front = -2;
- break;
-
- default:
- x = front;
- z = front;
- break;
- }
-
- return Lara_TestClimb(
- x, y, z, x_front, z_front, height, item->room_num, shift);
-}
-
-void __cdecl Lara_DoClimbLeftRight(
- ITEM_INFO *const item, const COLL_INFO *const coll, const int32_t result,
- const int32_t shift)
-{
- if (result == 1) {
- if (g_Input & IN_LEFT) {
- item->goal_anim_state = LS_CLIMB_LEFT;
- } else if (g_Input & IN_RIGHT) {
- item->goal_anim_state = LS_CLIMB_RIGHT;
- } else {
- item->goal_anim_state = LS_CLIMB_STANCE;
- }
- item->pos.y += shift;
- return;
- }
-
- if (result) {
- item->goal_anim_state = LS_HANG;
- do {
- Item_Animate(item);
- } while (item->current_anim_state != LS_HANG);
- item->pos.x = coll->old.x;
- item->pos.z = coll->old.z;
- return;
- }
-
- item->pos.x = coll->old.x;
- item->pos.z = coll->old.z;
- item->goal_anim_state = LS_CLIMB_STANCE;
- item->current_anim_state = LS_CLIMB_STANCE;
- if (coll->old_anim_state == LS_CLIMB_STANCE) {
- item->frame_num = coll->old_frame_num;
- item->anim_num = coll->old_anim_num;
- Lara_Animate(item);
- } else {
- item->anim_num = LA_LADDER_IDLE;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- }
-}
-
-int32_t __cdecl Lara_TestClimbUpPos(
- const ITEM_INFO *const item, const int32_t front, const int32_t right,
- int32_t *const shift, int32_t *const ledge)
-{
- const int32_t y = item->pos.y - LARA_CLIMB_HEIGHT - STEP_L;
- int32_t x;
- int32_t z;
- int32_t x_front = 0;
- int32_t z_front = 0;
-
- switch (Math_GetDirection(item->rot.y)) {
- case DIR_NORTH:
- x = item->pos.x + right;
- z = item->pos.z + front;
- z_front = 2;
- break;
-
- case DIR_EAST:
- x = item->pos.x + front;
- z = item->pos.z - right;
- x_front = 2;
- break;
-
- case DIR_SOUTH:
- x = item->pos.x - right;
- z = item->pos.z - front;
- z_front = -2;
- break;
-
- case DIR_WEST:
- z = item->pos.z + right;
- x = item->pos.x - front;
- x_front = -2;
- break;
-
- default:
- x = front;
- z = front;
- break;
- }
-
- *shift = 0;
-
- const SECTOR_INFO *sector;
- int32_t height;
- int32_t ceiling;
-
- int16_t room_num = item->room_num;
- sector = Room_GetSector(x, y, z, &room_num);
- ceiling = Room_GetCeiling(sector, x, y, z) + STEP_L - y;
- if (ceiling > CLIMB_SHIFT) {
- return 0;
- }
-
- if (ceiling > 0) {
- *shift = ceiling;
- }
-
- const int32_t x2 = x + x_front;
- const int32_t z2 = z + z_front;
- sector = Room_GetSector(x2, y, z2, &room_num);
- height = Room_GetHeight(sector, x2, y, z2);
- if (height == NO_HEIGHT) {
- *ledge = NO_HEIGHT;
- return 1;
- }
-
- height -= y;
- *ledge = height;
- if (height > STEP_L / 2) {
- ceiling = Room_GetCeiling(sector, x2, y, z2) - y;
- if (ceiling >= LARA_CLIMB_HEIGHT) {
- return 1;
- }
-
- if (height - ceiling > LARA_HEIGHT) {
- *shift = height;
- return -1;
- }
-
- return 0;
- }
-
- if (height > 0 && height > *shift) {
- *shift = height;
- }
-
- room_num = item->room_num;
- sector = Room_GetSector(x, y + LARA_CLIMB_HEIGHT, z, &room_num);
- sector = Room_GetSector(x2, y + LARA_CLIMB_HEIGHT, z2, &room_num);
- ceiling = Room_GetCeiling(sector, x2, y + LARA_CLIMB_HEIGHT, z2) - y;
- if (ceiling <= height) {
- return 1;
- }
-
- if (ceiling >= LARA_CLIMB_HEIGHT) {
- return 1;
- }
- return 0;
-}
-
-int32_t __cdecl Lara_GetWaterDepth(
- const int32_t x, const int32_t y, const int32_t z, int16_t room_num)
-{
- const ROOM_INFO *r = &g_Rooms[room_num];
- const SECTOR_INFO *sector;
-
- while (true) {
- int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
- int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
-
- if (z_sector <= 0) {
- z_sector = 0;
- if (x_sector < 1) {
- x_sector = 1;
- } else if (x_sector > r->x_size - 2) {
- x_sector = r->x_size - 2;
- }
- } else if (z_sector >= r->z_size - 1) {
- z_sector = r->z_size - 1;
- if (x_sector < 1) {
- x_sector = 1;
- } else if (x_sector > r->x_size - 2) {
- x_sector = r->x_size - 2;
- }
- } else if (x_sector < 0) {
- x_sector = 0;
- } else if (x_sector >= r->x_size) {
- x_sector = r->x_size - 1;
- }
-
- sector = &r->sector[z_sector + x_sector * r->z_size];
- const int16_t data = Room_GetDoor(sector);
- if (data == NO_ROOM) {
- break;
- }
- room_num = data;
- r = &g_Rooms[room_num];
- }
-
- if (r->flags & RF_UNDERWATER) {
- while (sector->sky_room != NO_ROOM) {
- r = &g_Rooms[sector->sky_room];
- if (!(r->flags & RF_UNDERWATER)) {
- const int32_t water_height = sector->ceiling << 8;
- sector = Room_GetSector(x, y, z, &room_num);
- return Room_GetHeight(sector, x, y, z) - water_height;
- }
- const int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
- const int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
- sector = &r->sector[z_sector + x_sector * r->z_size];
- }
- return 0x7FFF;
- }
-
- while (sector->pit_room != NO_ROOM) {
- r = &g_Rooms[sector->pit_room];
- if (r->flags & RF_UNDERWATER) {
- const int32_t water_height = sector->floor << 8;
- sector = Room_GetSector(x, y, z, &room_num);
- return Room_GetHeight(sector, x, y, z) - water_height;
- }
- const int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
- const int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
- sector = &r->sector[z_sector + x_sector * r->z_size];
- }
- return NO_HEIGHT;
-}
-
-void __cdecl Lara_TestWaterDepth(
- ITEM_INFO *const item, const COLL_INFO *const coll)
-{
- int16_t room_num = item->room_num;
-
- const SECTOR_INFO *const sector =
- Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
- const int32_t water_depth =
- Lara_GetWaterDepth(item->pos.x, item->pos.y, item->pos.z, room_num);
-
- if (water_depth == NO_HEIGHT) {
- item->pos = coll->old;
- item->fall_speed = 0;
- } else if (water_depth <= STEP_L * 2) {
- item->anim_num = LA_UNDERWATER_TO_STAND;
- item->frame_num = g_Anims[item->anim_num].frame_base;
- item->current_anim_state = LS_WATER_OUT;
- item->goal_anim_state = LS_STOP;
- item->rot.x = 0;
- item->rot.z = 0;
- item->gravity = 0;
- item->speed = 0;
- item->fall_speed = 0;
- g_Lara.water_status = LWS_WADE;
- item->pos.y =
- Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
- }
-}
-
-void __cdecl Lara_SwimCollision(ITEM_INFO *const item, COLL_INFO *const coll)
-{
- if (item->rot.x < -PHD_90 || item->rot.x > PHD_90) {
- g_Lara.move_angle = item->rot.y + PHD_180;
- } else {
- g_Lara.move_angle = item->rot.y;
- }
-
- coll->facing = g_Lara.move_angle;
-
- int32_t height = (LARA_HEIGHT * Math_Sin(item->rot.x)) >> W2V_SHIFT;
- if (height < 0) {
- height = -height;
- }
- CLAMPL(height, 200);
-
- coll->bad_neg = -height;
- Collide_GetCollisionInfo(
- coll, item->pos.x, item->pos.y + height / 2, item->pos.z,
- item->room_num, height);
- Item_ShiftCol(item, coll);
-
- switch (coll->coll_type) {
- case COLL_FRONT:
- if (item->rot.x > 35 * PHD_DEGREE) {
- item->rot.x += LARA_UW_WALL_DEFLECT;
- } else if (item->rot.x < -35 * PHD_DEGREE) {
- item->rot.x -= LARA_UW_WALL_DEFLECT;
- } else {
- item->fall_speed = 0;
- }
- break;
-
- case COLL_TOP:
- if (item->rot.x >= -45 * PHD_DEGREE) {
- item->rot.x -= LARA_UW_WALL_DEFLECT;
- }
- break;
-
- case COLL_TOP_FRONT:
- item->fall_speed = 0;
- break;
-
- case COLL_LEFT:
- item->rot.y += 5 * PHD_DEGREE;
- break;
-
- case COLL_RIGHT:
- item->rot.y -= 5 * PHD_DEGREE;
- break;
-
- case COLL_CLAMP:
- item->pos = coll->old;
- item->fall_speed = 0;
- return;
- }
-
- if (coll->side_mid.floor < 0) {
- item->rot.x += LARA_UW_WALL_DEFLECT;
- item->pos.y = coll->side_mid.floor + item->pos.y;
- }
-
- if (g_Lara.water_status != LWS_CHEAT && !g_Lara.extra_anim) {
- Lara_TestWaterDepth(item, coll);
- }
-}
-
-void __cdecl Lara_WaterCurrent(COLL_INFO *const coll)
-{
- ITEM_INFO *const item = g_LaraItem;
-
- int16_t room_num = g_LaraItem->room_num;
- const ROOM_INFO *const r = &g_Rooms[g_LaraItem->room_num];
- const int32_t z_sector = (g_LaraItem->pos.z - r->pos.z) >> WALL_SHIFT;
- const int32_t x_sector = (g_LaraItem->pos.x - r->pos.x) >> WALL_SHIFT;
- g_LaraItem->box_num = r->sector[z_sector + x_sector * r->z_size].box;
-
- if (g_Lara.creature == NULL) {
- g_Lara.current_active = 0;
- return;
- }
-
- XYZ_32 target;
- if (Box_CalculateTarget(&target, item, &g_Lara.creature->lot)
- == TARGET_NONE) {
- return;
- }
-
- target.x -= item->pos.x;
- if (target.x > g_Lara.current_active) {
- item->pos.x += g_Lara.current_active;
- } else if (target.x < -g_Lara.current_active) {
- item->pos.x -= g_Lara.current_active;
- } else {
- item->pos.x += target.x;
- }
-
- target.z -= item->pos.z;
- if (target.z > g_Lara.current_active) {
- item->pos.z += g_Lara.current_active;
- } else if (target.z < -g_Lara.current_active) {
- item->pos.z -= g_Lara.current_active;
- } else {
- item->pos.z += target.z;
- }
-
- target.y = target.y - item->pos.y;
- if (target.y > g_Lara.current_active) {
- item->pos.y += g_Lara.current_active;
- } else if (target.y < -g_Lara.current_active) {
- item->pos.y -= g_Lara.current_active;
- } else {
- item->pos.y += target.y;
- }
-
- g_Lara.current_active = 0;
- coll->facing =
- Math_Atan(item->pos.z - coll->old.z, item->pos.x - coll->old.x);
- Collide_GetCollisionInfo(
- coll, item->pos.x, item->pos.y + LARA_HEIGHT_UW / 2, item->pos.z,
- room_num, LARA_HEIGHT_UW);
-
- switch (coll->coll_type) {
- case COLL_FRONT:
- if (item->rot.x > 35 * PHD_DEGREE) {
- item->rot.x = item->rot.x + LARA_UW_WALL_DEFLECT;
- } else if (item->rot.x < -35 * PHD_DEGREE) {
- item->rot.x = item->rot.x - LARA_UW_WALL_DEFLECT;
- } else {
- item->fall_speed = 0;
- }
- break;
-
- case COLL_TOP:
- item->rot.x -= LARA_UW_WALL_DEFLECT;
- break;
-
- case COLL_TOP_FRONT:
- item->fall_speed = 0;
- break;
-
- case COLL_LEFT:
- item->rot.y += 910;
- break;
-
- case COLL_RIGHT:
- item->rot.y -= 910;
- break;
-
- default:
- break;
- }
-
- if (coll->side_mid.floor < 0) {
- item->pos.y += coll->side_mid.floor;
- item->rot.x += LARA_UW_WALL_DEFLECT;
- }
- Item_ShiftCol(item, coll);
-
- coll->old = item->pos;
-}
-
-void __cdecl Lara_CatchFire(void)
-{
- if (g_Lara.burn || g_Lara.water_status == LWS_CHEAT) {
- return;
- }
-
- const int16_t fx_num = Effect_Create(g_LaraItem->room_num);
- if (fx_num == NO_ITEM) {
- return;
- }
-
- FX_INFO *const fx = &g_Effects[fx_num];
- fx->frame_num = 0;
- fx->object_id = O_FLAME;
- fx->counter = -1;
- g_Lara.burn = 1;
-}
-
-void __cdecl Lara_TouchLava(ITEM_INFO *const item)
-{
- if (item->hit_points < 0 || g_Lara.water_status == LWS_CHEAT) {
- return;
- }
-
- int16_t room_num = item->room_num;
- const SECTOR_INFO *const sector =
- Room_GetSector(item->pos.x, MAX_HEIGHT, item->pos.z, &room_num);
- const int32_t height =
- Room_GetHeight(sector, item->pos.x, MAX_HEIGHT, item->pos.z);
- if (item->floor != height) {
- return;
- }
-
- item->hit_points = -1;
- item->hit_status = 1;
-
- for (int32_t i = 0; i < 10; i++) {
- const int16_t fx_num = Effect_Create(item->room_num);
- if (fx_num != NO_ITEM) {
- FX_INFO *const fx = &g_Effects[fx_num];
- fx->object_id = O_FLAME;
- fx->frame_num =
- g_Objects[O_FLAME].mesh_count * Random_GetControl() / 0x7FFF;
- fx->counter = -1 - 24 * Random_GetControl() / 0x7FFF;
- }
- }
-}
diff --git a/src/game/lara/lara_look.c b/src/game/lara/look.c
similarity index 98%
rename from src/game/lara/lara_look.c
rename to src/game/lara/look.c
index 3189a045..8ad48d11 100644
--- a/src/game/lara/lara_look.c
+++ b/src/game/lara/look.c
@@ -1,4 +1,4 @@
-#include "game/lara/lara_look.h"
+#include "game/lara/look.h"
#include "game/input.h"
#include "global/const.h"
diff --git a/src/game/lara/lara_look.h b/src/game/lara/look.h
similarity index 100%
rename from src/game/lara/lara_look.h
rename to src/game/lara/look.h
diff --git a/src/game/lara/misc.c b/src/game/lara/misc.c
index 4ff1e0c7..677d99d3 100644
--- a/src/game/lara/misc.c
+++ b/src/game/lara/misc.c
@@ -1,7 +1,1856 @@
+#include "game/lara/misc.h"
+
+#include "decomp/decomp.h"
+#include "game/box.h"
+#include "game/collide.h"
#include "game/effects.h"
+#include "game/input.h"
+#include "game/items.h"
+#include "game/lara/control.h"
+#include "game/math.h"
+#include "game/matrix.h"
+#include "game/random.h"
+#include "game/room.h"
+#include "game/sound.h"
+#include "global/const.h"
+#include "global/funcs.h"
#include "global/vars.h"
#include
+#include
+#include
+
+#define MAX_BADDIE_COLLISION 20
+#define MOVE_SPEED 16
+#define MOVE_ANGLE (2 * PHD_DEGREE) // = 364
+#define CLIMB_HANG 900
+#define CLIMB_SHIFT 70
+
+static void __cdecl M_TakeHit(
+ ITEM_INFO *const lara_item, const int32_t dx, const int32_t dz);
+
+static void __cdecl M_TakeHit(
+ ITEM_INFO *const lara_item, const int32_t dx, const int32_t dz)
+{
+ const PHD_ANGLE hit_angle = lara_item->rot.y + PHD_180 - Math_Atan(dz, dx);
+ g_Lara.hit_direction = Math_GetDirection(hit_angle);
+ if (g_Lara.hit_frame == 0) {
+ Sound_Effect(SFX_LARA_INJURY, &lara_item->pos, SPM_NORMAL);
+ }
+ g_Lara.hit_frame++;
+ CLAMPG(g_Lara.hit_frame, 34);
+}
+
+void __cdecl Lara_GetCollisionInfo(ITEM_INFO *item, COLL_INFO *coll)
+{
+ coll->facing = g_Lara.move_angle;
+ Collide_GetCollisionInfo(
+ coll, item->pos.x, item->pos.y, item->pos.z, item->room_num,
+ LARA_HEIGHT);
+}
+
+void __cdecl Lara_SlideSlope(ITEM_INFO *item, COLL_INFO *coll)
+{
+ coll->bad_pos = NO_BAD_POS;
+ coll->bad_neg = -STEP_L * 2;
+ coll->bad_ceiling = 0;
+ Lara_GetCollisionInfo(item, coll);
+
+ if (Lara_HitCeiling(item, coll)) {
+ return;
+ }
+
+ Lara_DeflectEdge(item, coll);
+
+ if (coll->side_mid.floor > 200) {
+ if (item->current_anim_state == LS_SLIDE) {
+ item->goal_anim_state = LS_FORWARD_JUMP;
+ item->current_anim_state = LS_FORWARD_JUMP;
+ item->anim_num = LS_SURF_SWIM;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ } else {
+ item->goal_anim_state = LS_FALL_BACK;
+ item->current_anim_state = LS_FALL_BACK;
+ item->anim_num = LA_FALL_BACK;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ }
+ item->gravity = 1;
+ item->fall_speed = 0;
+ return;
+ }
+
+ Lara_TestSlide(item, coll);
+ item->pos.y += coll->side_mid.floor;
+ if (ABS(coll->x_tilt) <= 2 && ABS(coll->z_tilt) <= 2) {
+ item->goal_anim_state = LS_STOP;
+ }
+}
+
+int32_t __cdecl Lara_HitCeiling(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (coll->coll_type != COLL_TOP && coll->coll_type != COLL_CLAMP) {
+ return 0;
+ }
+
+ item->pos.x = coll->old.x;
+ item->pos.y = coll->old.y;
+ item->pos.z = coll->old.z;
+ item->goal_anim_state = LS_STOP;
+ item->current_anim_state = LS_STOP;
+ item->anim_num = LS_REACH;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->speed = 0;
+ item->gravity = 0;
+ item->fall_speed = 0;
+ return 1;
+}
+
+int32_t __cdecl Lara_DeflectEdge(ITEM_INFO *item, COLL_INFO *coll)
+{
+ switch (coll->coll_type) {
+ case COLL_FRONT:
+ case COLL_TOP_FRONT:
+ Item_ShiftCol(item, coll);
+ item->goal_anim_state = LS_STOP;
+ item->current_anim_state = LS_STOP;
+ item->gravity = 0;
+ item->speed = 0;
+ return 1;
+
+ case COLL_LEFT:
+ Item_ShiftCol(item, coll);
+ item->rot.y += LARA_DEFLECT_ANGLE;
+ return 0;
+
+ case COLL_RIGHT:
+ Item_ShiftCol(item, coll);
+ item->rot.y -= LARA_DEFLECT_ANGLE;
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+void __cdecl Lara_DeflectEdgeJump(ITEM_INFO *item, COLL_INFO *coll)
+{
+ Item_ShiftCol(item, coll);
+ switch (coll->coll_type) {
+ case COLL_FRONT:
+ case COLL_TOP_FRONT:
+ if (!g_Lara.climb_status || item->speed != 2) {
+ if (coll->side_mid.floor > 512) {
+ item->goal_anim_state = LS_FAST_FALL;
+ item->current_anim_state = LS_FAST_FALL;
+ item->anim_num = LA_SMASH_JUMP;
+ item->frame_num = g_Anims[item->anim_num].frame_base + 1;
+ } else if (coll->side_mid.floor <= 128) {
+ item->goal_anim_state = LS_LAND;
+ item->current_anim_state = LS_LAND;
+ item->anim_num = LA_JUMP_UP_LAND;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ }
+ item->speed /= 4;
+ g_Lara.move_angle += PHD_180;
+ CLAMPL(item->fall_speed, 1);
+ }
+ break;
+
+ case COLL_LEFT:
+ item->rot.y += LARA_DEFLECT_ANGLE;
+ break;
+
+ case COLL_RIGHT:
+ item->rot.y -= LARA_DEFLECT_ANGLE;
+ break;
+
+ case COLL_TOP:
+ CLAMPL(item->fall_speed, 1);
+ break;
+
+ case COLL_CLAMP:
+ item->pos.z -= (Math_Cos(coll->facing) * 100) >> W2V_SHIFT;
+ item->pos.x -= (Math_Sin(coll->facing) * 100) >> W2V_SHIFT;
+ item->speed = 0;
+ coll->side_mid.floor = 0;
+ if (item->fall_speed <= 0) {
+ item->fall_speed = 16;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void __cdecl Lara_SlideEdgeJump(ITEM_INFO *item, COLL_INFO *coll)
+{
+ Item_ShiftCol(item, coll);
+
+ switch (coll->coll_type) {
+ case COLL_LEFT:
+ item->rot.y += LARA_DEFLECT_ANGLE;
+ break;
+
+ case COLL_RIGHT:
+ item->rot.y -= LARA_DEFLECT_ANGLE;
+ break;
+
+ case COLL_TOP:
+ case COLL_TOP_FRONT:
+ CLAMPL(item->fall_speed, 1);
+ break;
+
+ case COLL_CLAMP:
+ item->pos.z -= (Math_Cos(coll->facing) * 100) >> W2V_SHIFT;
+ item->pos.x -= (Math_Sin(coll->facing) * 100) >> W2V_SHIFT;
+ item->speed = 0;
+ coll->side_mid.floor = 0;
+ if (item->fall_speed <= 0) {
+ item->fall_speed = 16;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+int32_t __cdecl Lara_TestWall(
+ ITEM_INFO *item, int32_t front, int32_t right, int32_t down)
+{
+ int32_t x = item->pos.x;
+ int32_t y = item->pos.y + down;
+ int32_t z = item->pos.z;
+
+ DIRECTION dir = Math_GetDirection(item->rot.y);
+ switch (dir) {
+ case DIR_NORTH:
+ x -= right;
+ break;
+ case DIR_EAST:
+ z -= right;
+ break;
+ case DIR_SOUTH:
+ x += right;
+ break;
+ case DIR_WEST:
+ z += right;
+ break;
+ default:
+ break;
+ }
+
+ int16_t room_num = item->room_num;
+ Room_GetSector(x, y, z, &room_num);
+
+ switch (dir) {
+ case DIR_NORTH:
+ z += front;
+ break;
+ case DIR_EAST:
+ x += front;
+ break;
+ case DIR_SOUTH:
+ z -= front;
+ break;
+ case DIR_WEST:
+ x -= front;
+ break;
+ default:
+ break;
+ }
+
+ const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
+ const int32_t height = Room_GetHeight(sector, x, y, z);
+ const int32_t ceiling = Room_GetCeiling(sector, x, y, z);
+ if (height == NO_HEIGHT) {
+ return 1;
+ }
+ if (height - y > 0 && ceiling - y < 0) {
+ return 0;
+ }
+ return 2;
+}
+
+int32_t __cdecl Lara_TestHangOnClimbWall(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (!g_Lara.climb_status || item->fall_speed < 0) {
+ return 0;
+ }
+
+ DIRECTION dir = Math_GetDirection(item->rot.y);
+ switch (dir) {
+ case DIR_NORTH:
+ case DIR_SOUTH:
+ item->pos.z += coll->shift.z;
+ break;
+
+ case DIR_EAST:
+ case DIR_WEST:
+ item->pos.x += coll->shift.x;
+ break;
+
+ default:
+ break;
+ }
+
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ int32_t y = bounds->min_y;
+ int32_t h = bounds->max_y - y;
+
+ int32_t shift;
+ if (!Lara_TestClimbPos(item, coll->radius, coll->radius, y, h, &shift)) {
+ return 0;
+ }
+
+ if (!Lara_TestClimbPos(item, coll->radius, -coll->radius, y, h, &shift)) {
+ return 0;
+ }
+
+ int32_t result = Lara_TestClimbPos(item, coll->radius, 0, y, h, &shift);
+ switch (result) {
+ case 0:
+ case 1:
+ return result;
+
+ default:
+ item->pos.y += shift;
+ return 1;
+ }
+}
+
+int32_t __cdecl Lara_TestClimbStance(ITEM_INFO *item, COLL_INFO *coll)
+{
+ int32_t shift_r;
+ int32_t result_r = Lara_TestClimbPos(
+ item, coll->radius, coll->radius + LARA_CLIMB_WIDTH_RIGHT, -700,
+ STEP_L * 2, &shift_r);
+ if (result_r != 1) {
+ return 0;
+ }
+
+ int32_t shift_l;
+ int32_t result_l = Lara_TestClimbPos(
+ item, coll->radius, -(coll->radius + LARA_CLIMB_WIDTH_LEFT), -700,
+ STEP_L * 2, &shift_l);
+ if (result_l != 1) {
+ return 0;
+ }
+
+ int32_t shift = 0;
+ if (shift_r) {
+ if (shift_l) {
+ if ((shift_r < 0) != (shift_l < 0)) {
+ return 0;
+ }
+ if (shift_r < 0 && shift_l < shift_r) {
+ shift = shift_l;
+ } else if (shift_r > 0 && shift_l > shift_r) {
+ shift = shift_l;
+ } else {
+ shift = shift_r;
+ }
+ } else {
+ shift = shift_r;
+ }
+ } else if (shift_l) {
+ shift = shift_l;
+ }
+
+ item->pos.y += shift;
+ return 1;
+}
+
+void __cdecl Lara_HangTest(ITEM_INFO *item, COLL_INFO *coll)
+{
+ coll->bad_pos = NO_BAD_POS;
+ coll->bad_neg = NO_BAD_NEG;
+ coll->bad_ceiling = 0;
+ Lara_GetCollisionInfo(item, coll);
+ bool flag = coll->side_front.floor < 200;
+
+ item->gravity = 0;
+ item->fall_speed = 0;
+ g_Lara.move_angle = item->rot.y;
+
+ DIRECTION dir = Math_GetDirection(item->rot.y);
+ switch (dir) {
+ case DIR_NORTH:
+ item->pos.z += 2;
+ break;
+ case DIR_EAST:
+ item->pos.x += 2;
+ break;
+ case DIR_SOUTH:
+ item->pos.z -= 2;
+ break;
+ case DIR_WEST:
+ item->pos.x -= 2;
+ break;
+ default:
+ break;
+ }
+
+ coll->bad_pos = NO_BAD_POS;
+ coll->bad_neg = -STEPUP_HEIGHT;
+ coll->bad_ceiling = 0;
+ Lara_GetCollisionInfo(item, coll);
+
+ if (g_Lara.climb_status) {
+ if (!(g_Input & IN_ACTION) || item->hit_points <= 0) {
+ XYZ_32 pos = {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ };
+ Collide_GetJointAbsPosition(item, &pos, 0);
+ if (dir == DIR_NORTH || dir == DIR_SOUTH) {
+ item->pos.x = pos.x;
+ } else {
+ item->pos.z = pos.z;
+ }
+
+ item->goal_anim_state = LS_FORWARD_JUMP;
+ item->current_anim_state = LS_FORWARD_JUMP;
+ item->anim_num = LA_FALL_START;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->pos.y += STEP_L;
+ item->gravity = 1;
+ item->speed = 2;
+ item->fall_speed = 1;
+ g_Lara.gun_status = LGS_ARMLESS;
+ return;
+ }
+
+ if (!Lara_TestHangOnClimbWall(item, coll)) {
+ item->pos.x = coll->old.x;
+ item->pos.y = coll->old.y;
+ item->pos.z = coll->old.z;
+ item->goal_anim_state = LS_HANG;
+ item->current_anim_state = LS_HANG;
+ item->anim_num = LA_REACH_TO_HANG;
+ item->frame_num = g_Anims[item->anim_num].frame_base + 21;
+ return;
+ }
+
+ if (item->anim_num == LA_REACH_TO_HANG
+ && item->frame_num == g_Anims[item->anim_num].frame_base + 21
+ && Lara_TestClimbStance(item, coll)) {
+ item->goal_anim_state = LS_CLIMB_STANCE;
+ }
+ return;
+ }
+
+ if (!(g_Input & IN_ACTION) || item->hit_points <= 0
+ || coll->side_front.floor > 0) {
+ item->goal_anim_state = LS_UP_JUMP;
+ item->current_anim_state = LS_UP_JUMP;
+ item->anim_num = LA_JUMP_UP;
+ item->frame_num = g_Anims[item->anim_num].frame_base + 9;
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ item->pos.y += bounds->max_y;
+ item->pos.x += coll->shift.x;
+ item->pos.z += coll->shift.z;
+ item->gravity = 1;
+ item->speed = 2;
+ item->fall_speed = 1;
+ g_Lara.gun_status = LGS_ARMLESS;
+ return;
+ }
+
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ int32_t hdif = coll->side_front.floor - bounds->min_y;
+
+ if (ABS(coll->side_left.floor - coll->side_right.floor) >= SLOPE_DIF
+ || coll->side_mid.ceiling >= 0 || coll->coll_type != COLL_FRONT || flag
+ || coll->hit_static || hdif < -SLOPE_DIF || hdif > SLOPE_DIF) {
+ item->pos.x = coll->old.x;
+ item->pos.y = coll->old.y;
+ item->pos.z = coll->old.z;
+ if (item->current_anim_state == LS_HANG_LEFT
+ || item->current_anim_state == LS_HANG_RIGHT) {
+ item->goal_anim_state = LS_HANG;
+ item->current_anim_state = LS_HANG;
+ item->anim_num = LA_REACH_TO_HANG;
+ item->frame_num = g_Anims[item->anim_num].frame_base + 21;
+ }
+ return;
+ }
+
+ switch (dir) {
+ case DIR_NORTH:
+ case DIR_SOUTH:
+ item->pos.z += coll->shift.z;
+ break;
+
+ case DIR_EAST:
+ case DIR_WEST:
+ item->pos.x += coll->shift.x;
+ break;
+
+ default:
+ break;
+ }
+
+ item->pos.y += hdif;
+}
+
+int32_t __cdecl Lara_TestEdgeCatch(
+ ITEM_INFO *item, COLL_INFO *coll, int32_t *edge)
+{
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ int32_t hdif1 = coll->side_front.floor - bounds->min_y;
+ int32_t hdif2 = hdif1 + item->fall_speed;
+ if ((hdif1 < 0 && hdif2 < 0) || (hdif1 > 0 && hdif2 > 0)) {
+ hdif1 = item->pos.y + bounds->min_y;
+ hdif2 = hdif1 + item->fall_speed;
+ if ((hdif1 >> (WALL_SHIFT - 2)) == (hdif2 >> (WALL_SHIFT - 2))) {
+ return 0;
+ }
+ if (item->fall_speed > 0) {
+ *edge = hdif2 & ~(STEP_L - 1);
+ } else {
+ *edge = hdif1 & ~(STEP_L - 1);
+ }
+ return -1;
+ }
+
+ return ABS(coll->side_left.floor - coll->side_right.floor) < SLOPE_DIF;
+}
+
+int32_t __cdecl Lara_TestHangJumpUp(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
+ || g_Lara.gun_status != LGS_ARMLESS || coll->hit_static
+ || coll->side_mid.ceiling > -STEPUP_HEIGHT) {
+ return 0;
+ }
+
+ int32_t edge;
+ int32_t edge_catch = Lara_TestEdgeCatch(item, coll, &edge);
+ if (!edge_catch
+ || (edge_catch < 0 && !Lara_TestHangOnClimbWall(item, coll))) {
+ return 0;
+ }
+
+ DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
+ if (dir == DIR_UNKNOWN) {
+ return 0;
+ }
+ int16_t angle = Math_DirectionToAngle(dir);
+
+ item->goal_anim_state = LS_HANG;
+ item->current_anim_state = LS_HANG;
+ item->anim_num = LA_REACH_TO_HANG;
+ item->frame_num = g_Anims[item->anim_num].frame_base + 12;
+
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ if (edge_catch > 0) {
+ item->pos.y += coll->side_front.floor - bounds->min_y;
+ } else {
+ item->pos.y = edge - bounds->min_y;
+ }
+ item->pos.x += coll->shift.x;
+ item->pos.z += coll->shift.z;
+ item->rot.y = angle;
+ item->speed = 0;
+ item->gravity = 0;
+ item->fall_speed = 0;
+ g_Lara.gun_status = LGS_HANDS_BUSY;
+ return 1;
+}
+
+int32_t __cdecl Lara_TestHangJump(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
+ || g_Lara.gun_status != LGS_ARMLESS || coll->hit_static
+ || coll->side_mid.ceiling > -STEPUP_HEIGHT
+ || coll->side_mid.floor < 200) {
+ return 0;
+ }
+
+ int32_t edge;
+ int32_t edge_catch = Lara_TestEdgeCatch(item, coll, &edge);
+ if (!edge_catch
+ || (edge_catch < 0 && !Lara_TestHangOnClimbWall(item, coll))) {
+ return 0;
+ }
+
+ DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_HANG_ANGLE);
+ if (dir == DIR_UNKNOWN) {
+ return 0;
+ }
+ int16_t angle = Math_DirectionToAngle(dir);
+
+ if (Lara_TestHangSwingIn(item, angle)) {
+ item->anim_num = LA_REACH_TO_THIN_LEDGE;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ } else {
+ item->anim_num = LA_REACH_TO_HANG;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ }
+ item->current_anim_state = LS_HANG;
+ item->goal_anim_state = LS_HANG;
+
+ const BOUNDS_16 *const bounds = Item_GetBoundsAccurate(item);
+ if (edge_catch > 0) {
+ item->pos.y += coll->side_front.floor - bounds->min_y;
+ item->pos.x += coll->shift.x;
+ item->pos.z += coll->shift.z;
+ } else {
+ item->pos.y = edge - bounds->min_y;
+ }
+
+ item->rot.y = angle;
+ item->speed = 2;
+ item->gravity = 1;
+ item->fall_speed = 1;
+ g_Lara.gun_status = LGS_HANDS_BUSY;
+ return 1;
+}
+
+int32_t __cdecl Lara_TestHangSwingIn(ITEM_INFO *item, PHD_ANGLE angle)
+{
+ int32_t x = item->pos.x;
+ int32_t y = item->pos.y;
+ int32_t z = item->pos.z;
+ int16_t room_num = item->room_num;
+ switch (angle) {
+ case 0:
+ z += STEP_L;
+ break;
+ case PHD_90:
+ x += STEP_L;
+ break;
+ case -PHD_180:
+ z -= STEP_L;
+ break;
+ case -PHD_90:
+ x -= STEP_L;
+ break;
+ }
+
+ const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
+ int32_t height = Room_GetHeight(sector, x, y, z);
+ int32_t ceiling = Room_GetCeiling(sector, x, y, z);
+ return height != NO_HEIGHT && height - y > 0 && ceiling - y < -400;
+}
+
+int32_t __cdecl Lara_TestVault(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (coll->coll_type != COLL_FRONT || !(g_Input & IN_ACTION)
+ || g_Lara.gun_status != LGS_ARMLESS) {
+ return 0;
+ }
+
+ DIRECTION dir = Math_GetDirectionCone(item->rot.y, LARA_VAULT_ANGLE);
+ if (dir == DIR_UNKNOWN) {
+ return 0;
+ }
+ int16_t angle = Math_DirectionToAngle(dir);
+
+ int32_t left_floor = coll->side_left.floor;
+ int32_t left_ceiling = coll->side_left.ceiling;
+ int32_t right_floor = coll->side_right.floor;
+ int32_t right_ceiling = coll->side_right.ceiling;
+ int32_t front_floor = coll->side_front.floor;
+ int32_t front_ceiling = coll->side_front.ceiling;
+ bool slope = ABS(left_floor - right_floor) >= SLOPE_DIF;
+
+ int32_t mid = STEP_L / 2;
+ if (front_floor >= -STEP_L * 2 - mid && front_floor <= -STEP_L * 2 + mid) {
+ if (slope || front_floor - front_ceiling < 0
+ || left_floor - left_ceiling < 0
+ || right_floor - right_ceiling < 0) {
+ return 0;
+ }
+ item->goal_anim_state = LS_STOP;
+ item->current_anim_state = LS_NULL;
+ item->anim_num = LA_CLIMB_2CLICK;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->pos.y += front_floor + STEP_L * 2;
+ g_Lara.gun_status = LGS_HANDS_BUSY;
+ } else if (
+ front_floor >= -STEP_L * 3 - mid && front_floor <= -STEP_L * 3 + mid) {
+ if (slope || front_floor - front_ceiling < 0
+ || left_floor - left_ceiling < 0
+ || right_floor - right_ceiling < 0) {
+ return 0;
+ }
+ item->goal_anim_state = LS_STOP;
+ item->current_anim_state = LS_NULL;
+ item->anim_num = LA_CLIMB_3CLICK;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->pos.y += front_floor + STEP_L * 3;
+ g_Lara.gun_status = LGS_HANDS_BUSY;
+ } else if (
+ !slope && front_floor >= -STEP_L * 7 - mid
+ && front_floor <= -STEP_L * 4 + mid) {
+ item->goal_anim_state = LS_UP_JUMP;
+ item->current_anim_state = LS_STOP;
+ item->anim_num = LA_STAND_STILL;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ g_Lara.calc_fallspeed =
+ -(Math_Sqrt(-2 * GRAVITY * (front_floor + 800)) + 3);
+ Lara_Animate(item);
+ } else if (
+ g_Lara.climb_status && front_floor <= -1920
+ && g_Lara.water_status != LWS_WADE && left_floor <= -STEP_L * 8 + mid
+ && right_floor <= -STEP_L * 8
+ && coll->side_mid.ceiling <= -STEP_L * 8 + mid + LARA_HEIGHT) {
+ item->goal_anim_state = LS_UP_JUMP;
+ item->current_anim_state = LS_STOP;
+ item->anim_num = LA_STAND_STILL;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ g_Lara.calc_fallspeed = -116;
+ Lara_Animate(item);
+ } else if (
+ g_Lara.climb_status
+ && (front_floor < -STEP_L * 4 || front_ceiling >= LARA_HEIGHT - STEP_L)
+ && coll->side_mid.ceiling <= -STEP_L * 5 + LARA_HEIGHT) {
+ Item_ShiftCol(item, coll);
+ if (Lara_TestClimbStance(item, coll)) {
+ item->goal_anim_state = LS_CLIMB_STANCE;
+ item->current_anim_state = LS_STOP;
+ item->anim_num = LA_STAND_STILL;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ Lara_Animate(item);
+ item->rot.y = angle;
+ g_Lara.gun_status = LGS_HANDS_BUSY;
+ return 1;
+ }
+ return 0;
+ } else {
+ return 0;
+ }
+
+ item->rot.y = angle;
+ Item_ShiftCol(item, coll);
+ return 1;
+}
+
+int32_t __cdecl Lara_TestSlide(ITEM_INFO *item, COLL_INFO *coll)
+{
+ if (ABS(coll->x_tilt) <= 2 && ABS(coll->z_tilt) <= 2) {
+ return 0;
+ }
+
+ int16_t angle = 0;
+ if (coll->x_tilt > 2) {
+ angle = -PHD_90;
+ } else if (coll->x_tilt < -2) {
+ angle = PHD_90;
+ }
+
+ if (coll->z_tilt > 2 && coll->z_tilt > ABS(coll->x_tilt)) {
+ angle = PHD_180;
+ } else if (coll->z_tilt < -2 && -coll->z_tilt > ABS(coll->x_tilt)) {
+ angle = 0;
+ }
+
+ const int16_t angle_dif = angle - item->rot.y;
+ Item_ShiftCol(item, coll);
+
+ if (angle_dif >= -PHD_90 && angle_dif <= PHD_90) {
+ if (item->current_anim_state == LS_SLIDE
+ && g_LaraOldSlideAngle == angle) {
+ return 1;
+ }
+ item->goal_anim_state = LS_SLIDE;
+ item->current_anim_state = LS_SLIDE;
+ item->anim_num = LA_SLIDE_FORWARD;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->rot.y = angle;
+ } else {
+ if (item->current_anim_state == LS_SLIDE_BACK
+ && g_LaraOldSlideAngle == angle) {
+ return 1;
+ }
+ item->goal_anim_state = LS_SLIDE_BACK;
+ item->current_anim_state = LS_SLIDE_BACK;
+ item->anim_num = LA_SLIDE_BACKWARD_START;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->rot.y = angle + PHD_180;
+ }
+
+ g_Lara.move_angle = angle;
+ g_LaraOldSlideAngle = angle;
+ return 1;
+}
+
+int16_t __cdecl Lara_FloorFront(ITEM_INFO *item, int16_t ang, int32_t dist)
+{
+ const int32_t x = item->pos.x + ((dist * Math_Sin(ang)) >> W2V_SHIFT);
+ const int32_t y = item->pos.y - LARA_HEIGHT;
+ const int32_t z = item->pos.z + ((dist * Math_Cos(ang)) >> W2V_SHIFT);
+ int16_t room_num = item->room_num;
+ const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
+ int32_t height = Room_GetHeight(sector, x, y, z);
+ if (height != NO_HEIGHT) {
+ height -= item->pos.y;
+ }
+ return height;
+}
+
+int32_t __cdecl Lara_LandedBad(ITEM_INFO *item, COLL_INFO *coll)
+{
+ const int32_t x = item->pos.x;
+ const int32_t y = item->pos.y;
+ const int32_t z = item->pos.z;
+
+ int16_t room_num = item->room_num;
+ const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
+ const int32_t height = Room_GetHeight(sector, x, y - LARA_HEIGHT, z);
+ item->pos.y = height;
+ item->floor = height;
+
+ Room_TestTriggers(g_TriggerIndex, 0);
+ int32_t land_speed = item->fall_speed - DAMAGE_START;
+ item->pos.y = y;
+ if (land_speed <= 0) {
+ return 0;
+ }
+ if (land_speed <= DAMAGE_LENGTH) {
+ item->hit_points += -LARA_MAX_HITPOINTS * land_speed * land_speed
+ / (DAMAGE_LENGTH * DAMAGE_LENGTH);
+ } else {
+ item->hit_points = -1;
+ }
+ return item->hit_points <= 0;
+}
+
+int32_t __cdecl Lara_CheckForLetGo(ITEM_INFO *item, COLL_INFO *coll)
+{
+ item->gravity = 0;
+ item->fall_speed = 0;
+
+ int16_t room_num = item->room_num;
+ int32_t x = item->pos.x;
+ int32_t y = item->pos.y;
+ int32_t z = item->pos.z;
+ const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
+ Room_GetHeight(sector, x, y, z);
+ coll->trigger = g_TriggerIndex;
+ if ((g_Input & IN_ACTION) && item->hit_points > 0) {
+ return 0;
+ }
+
+ item->goal_anim_state = LS_FORWARD_JUMP;
+ item->current_anim_state = LS_FORWARD_JUMP;
+ item->anim_num = LA_FALL_START;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->gravity = 1;
+ item->speed = 2;
+ item->fall_speed = 1;
+ g_Lara.gun_status = LGS_ARMLESS;
+ return 1;
+}
+
+void __cdecl Lara_GetJointAbsPosition(XYZ_32 *vec, int32_t joint)
+{
+ FRAME_INFO *frmptr[2] = { NULL, NULL };
+ if (g_Lara.hit_direction < 0) {
+ int32_t rate;
+ int32_t frac = Item_GetFrames(g_LaraItem, frmptr, &rate);
+ if (frac) {
+ Lara_GetJointAbsPosition_I(
+ g_LaraItem, vec, frmptr[0], frmptr[1], frac, rate);
+ return;
+ }
+ }
+
+ const FRAME_INFO *frame_ptr = NULL;
+ const OBJECT_INFO *obj = &g_Objects[g_LaraItem->object_id];
+ if (g_Lara.hit_direction >= 0) {
+ LARA_ANIMATION anim_num;
+ switch (g_Lara.hit_direction) {
+ case DIR_EAST:
+ anim_num = LA_HIT_RIGHT;
+ break;
+ case DIR_SOUTH:
+ anim_num = LA_HIT_BACK;
+ break;
+ case DIR_WEST:
+ anim_num = LA_HIT_LEFT;
+ break;
+ default:
+ anim_num = LA_HIT_FRONT;
+ break;
+ }
+ const ANIM *anim = &g_Anims[anim_num];
+ int32_t interpolation = anim->interpolation;
+ frame_ptr = (const FRAME_INFO *)(anim->frame_ptr
+ + (int32_t)(g_Lara.hit_frame
+ * (interpolation >> 8)));
+ } else {
+ frame_ptr = frmptr[0];
+ }
+
+ Matrix_PushUnit();
+ g_MatrixPtr->_03 = 0;
+ g_MatrixPtr->_13 = 0;
+ g_MatrixPtr->_23 = 0;
+ Matrix_RotYXZ(g_LaraItem->rot.y, g_LaraItem->rot.x, g_LaraItem->rot.z);
+
+ const int16_t *rot = frame_ptr->mesh_rots;
+ const int32_t *bone = &g_AnimBones[obj->bone_idx];
+
+ Matrix_TranslateRel(
+ frame_ptr->offset.x, frame_ptr->offset.y, frame_ptr->offset.z);
+ Matrix_RotYXZsuperpack(&rot, 0);
+
+ Matrix_TranslateRel(bone[25], bone[26], bone[27]);
+ Matrix_RotYXZsuperpack(&rot, 6);
+ Matrix_RotYXZ(g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
+
+ LARA_GUN_TYPE gun_type = LGT_UNARMED;
+ if (g_Lara.gun_status == LGS_READY || g_Lara.gun_status == LGS_SPECIAL
+ || g_Lara.gun_status == LGS_DRAW || g_Lara.gun_status == LGS_UNDRAW) {
+ gun_type = g_Lara.gun_type;
+ }
+
+ if (g_Lara.gun_type == LGT_FLARE) {
+ Matrix_TranslateRel(bone[41], bone[42], bone[43]);
+ if (g_Lara.flare_control_left) {
+ const LARA_ARM *arm = &g_Lara.left_arm;
+ const ANIM *anim = &g_Anims[arm->anim_num];
+ rot = &arm->frame_base
+ [(anim->interpolation >> 8)
+ * (arm->frame_num - anim->frame_base)
+ + FBBOX_ROT];
+ } else {
+ rot = frame_ptr->mesh_rots;
+ }
+ Matrix_RotYXZsuperpack(&rot, 11);
+
+ Matrix_TranslateRel(bone[45], bone[46], bone[47]);
+ Matrix_RotYXZsuperpack(&rot, 0);
+
+ Matrix_TranslateRel(bone[49], bone[50], bone[51]);
+ Matrix_RotYXZsuperpack(&rot, 0);
+ } else if (gun_type != LGT_UNARMED) {
+ Matrix_TranslateRel(bone[29], bone[30], bone[31]);
+
+ const LARA_ARM *arm = &g_Lara.right_arm;
+ const ANIM *anim = &g_Anims[arm->anim_num];
+ rot = &arm->frame_base
+ [arm->frame_num * (anim->interpolation >> 8) + FBBOX_ROT];
+ Matrix_RotYXZsuperpack(&rot, 8);
+
+ Matrix_TranslateRel(bone[33], bone[34], bone[35]);
+ Matrix_RotYXZsuperpack(&rot, 0);
+
+ Matrix_TranslateRel(bone[37], bone[38], bone[39]);
+ Matrix_RotYXZsuperpack(&rot, 0);
+ }
+
+ Matrix_TranslateRel(vec->x, vec->y, vec->z);
+ vec->x = g_LaraItem->pos.x + (g_MatrixPtr->_03 >> W2V_SHIFT);
+ vec->y = g_LaraItem->pos.y + (g_MatrixPtr->_13 >> W2V_SHIFT);
+ vec->z = g_LaraItem->pos.z + (g_MatrixPtr->_23 >> W2V_SHIFT);
+ Matrix_Pop();
+}
+
+void __cdecl Lara_GetJointAbsPosition_I(
+ ITEM_INFO *item, XYZ_32 *vec, FRAME_INFO *frame1, FRAME_INFO *frame2,
+ int32_t frac, int32_t rate)
+{
+ const OBJECT_INFO *obj = &g_Objects[item->object_id];
+
+ Matrix_PushUnit();
+ g_MatrixPtr->_03 = 0;
+ g_MatrixPtr->_13 = 0;
+ g_MatrixPtr->_23 = 0;
+ Matrix_RotYXZ(item->rot.y, item->rot.x, item->rot.z);
+
+ const int32_t *const bone = &g_AnimBones[obj->bone_idx];
+ const int16_t *rot1 = frame1->mesh_rots;
+ const int16_t *rot2 = frame2->mesh_rots;
+ Matrix_InitInterpolate(frac, rate);
+
+ Matrix_TranslateRel_ID(
+ frame1->offset.x, frame1->offset.y, frame1->offset.z, frame2->offset.x,
+ frame2->offset.y, frame2->offset.z);
+ Matrix_RotYXZsuperpack_I(&rot1, &rot2, 0);
+
+ Matrix_TranslateRel_I(bone[25], bone[26], bone[27]);
+ Matrix_RotYXZsuperpack_I(&rot1, &rot2, 6);
+ Matrix_RotYXZ_I(g_Lara.torso_y_rot, g_Lara.torso_x_rot, g_Lara.torso_z_rot);
+
+ LARA_GUN_TYPE gun_type = LGT_UNARMED;
+ if (g_Lara.gun_status == LGS_READY || g_Lara.gun_status == LGS_SPECIAL
+ || g_Lara.gun_status == LGS_DRAW || g_Lara.gun_status == LGS_UNDRAW) {
+ gun_type = g_Lara.gun_type;
+ }
+
+ if (g_Lara.gun_type == LGT_FLARE) {
+ Matrix_Interpolate();
+ Matrix_TranslateRel(bone[29], bone[30], bone[31]);
+ if (g_Lara.flare_control_left) {
+ const LARA_ARM *arm = &g_Lara.left_arm;
+ const ANIM *anim = &g_Anims[arm->anim_num];
+ rot1 = &arm->frame_base
+ [(anim->interpolation >> 8)
+ * (arm->frame_num - anim->frame_base)
+ + FBBOX_ROT];
+ } else {
+ rot1 = frame1->mesh_rots;
+ }
+ Matrix_RotYXZsuperpack(&rot1, 11);
+
+ Matrix_TranslateRel(bone[45], bone[46], bone[47]);
+ Matrix_RotYXZsuperpack(&rot1, 0);
+
+ Matrix_TranslateRel(bone[49], bone[50], bone[51]);
+ Matrix_RotYXZsuperpack(&rot1, 0);
+ } else if (gun_type != LGT_UNARMED) {
+ Matrix_Interpolate();
+ Matrix_TranslateRel(bone[29], bone[30], bone[31]);
+
+ const LARA_ARM *arm = &g_Lara.right_arm;
+ const ANIM *anim = &g_Anims[arm->anim_num];
+ rot1 = &arm->frame_base
+ [arm->frame_num * (anim->interpolation >> 8) + FBBOX_ROT];
+ Matrix_RotYXZsuperpack(&rot1, 8);
+
+ Matrix_TranslateRel(bone[33], bone[34], bone[35]);
+ Matrix_RotYXZsuperpack(&rot1, 0);
+
+ Matrix_TranslateRel(bone[37], bone[38], bone[39]);
+ Matrix_RotYXZsuperpack(&rot1, 0);
+ }
+
+ Matrix_TranslateRel(vec->x, vec->y, vec->z);
+ vec->x = item->pos.x + (g_MatrixPtr->_03 >> W2V_SHIFT);
+ vec->y = item->pos.y + (g_MatrixPtr->_13 >> W2V_SHIFT);
+ vec->z = item->pos.z + (g_MatrixPtr->_23 >> W2V_SHIFT);
+
+ Matrix_Pop();
+}
+
+void __cdecl Lara_TakeHit(
+ ITEM_INFO *const lara_item, const COLL_INFO *const coll)
+{
+ const int32_t dx = g_Lara.spaz_effect->pos.x - lara_item->pos.x;
+ const int32_t dz = g_Lara.spaz_effect->pos.z - lara_item->pos.z;
+ M_TakeHit(lara_item, dx, dz);
+ g_Lara.spaz_effect_count--;
+}
+
+void __cdecl Lara_BaddieCollision(ITEM_INFO *lara_item, COLL_INFO *coll)
+{
+ lara_item->hit_status = 0;
+ g_Lara.hit_direction = -1;
+ if (lara_item->hit_points <= 0) {
+ return;
+ }
+
+ int16_t roomies[MAX_BADDIE_COLLISION] = { 0 };
+ int32_t roomies_count = 0;
+
+ roomies[roomies_count++] = lara_item->room_num;
+
+ DOOR_INFOS *doors = g_Rooms[roomies[0]].doors;
+ if (doors != NULL) {
+ for (int32_t i = 0; i < doors->count; i++) {
+ if (roomies_count >= MAX_BADDIE_COLLISION) {
+ break;
+ }
+ roomies[roomies_count++] = doors->door[i].room;
+ }
+ }
+
+ for (int32_t i = 0; i < roomies_count; i++) {
+ int16_t item_num = g_Rooms[roomies[i]].item_num;
+ while (item_num != NO_ITEM) {
+ const ITEM_INFO *const item = &g_Items[item_num];
+
+ // the collision routine can destroy the item - need to store the
+ // next item beforehand
+ const int16_t next_item_num = item->next_item;
+
+ if (item->collidable && item->status != IS_INVISIBLE) {
+ const OBJECT_INFO *const object = &g_Objects[item->object_id];
+ if (object->collision) {
+ // clang-format off
+ const XYZ_32 d = {
+ .x = lara_item->pos.x - item->pos.x,
+ .y = lara_item->pos.y - item->pos.y,
+ .z = lara_item->pos.z - item->pos.z,
+ };
+ if (d.x > -TARGET_DIST && d.x < TARGET_DIST &&
+ d.y > -TARGET_DIST && d.y < TARGET_DIST &&
+ d.z > -TARGET_DIST && d.z < TARGET_DIST) {
+ object->collision(item_num, lara_item, coll);
+ }
+ // clang-format on
+ }
+ }
+
+ item_num = next_item_num;
+ }
+ }
+
+ if (g_Lara.spaz_effect_count) {
+ Lara_TakeHit(lara_item, coll);
+ }
+
+ if (g_Lara.hit_direction == -1) {
+ g_Lara.hit_frame = 0;
+ }
+
+ g_Inv_Chosen = -1;
+}
+
+void __cdecl Lara_Push(
+ const ITEM_INFO *const item, ITEM_INFO *const lara_item,
+ COLL_INFO *const coll, const bool spaz_on, const bool big_push)
+{
+ int32_t dx = lara_item->pos.x - item->pos.x;
+ int32_t dz = lara_item->pos.z - item->pos.z;
+ const int32_t c = Math_Cos(item->rot.y);
+ const int32_t s = Math_Sin(item->rot.y);
+ int32_t rx = (c * dx - s * dz) >> W2V_SHIFT;
+ int32_t rz = (c * dz + s * dx) >> W2V_SHIFT;
+
+ const BOUNDS_16 *const bounds = &Item_GetBestFrame(item)->bounds;
+ int32_t min_x = bounds->min_x;
+ int32_t max_x = bounds->max_x;
+ int32_t min_z = bounds->min_z;
+ int32_t max_z = bounds->max_z;
+
+ if (big_push) {
+ max_x += coll->radius;
+ min_z -= coll->radius;
+ max_z += coll->radius;
+ min_x -= coll->radius;
+ }
+
+ if (rx < min_x || rx > max_x || rz < min_z || rz > max_z) {
+ return;
+ }
+
+ int32_t l = rx - min_x;
+ int32_t r = max_x - rx;
+ int32_t t = max_z - rz;
+ int32_t b = rz - min_z;
+
+ if (l <= r && l <= t && l <= b) {
+ rx -= l;
+ } else if (r <= l && r <= t && r <= b) {
+ rx += r;
+ } else if (t <= l && t <= r && t <= b) {
+ rz += t;
+ } else {
+ rz = min_z;
+ }
+
+ lara_item->pos.x = item->pos.x + ((rz * s + rx * c) >> W2V_SHIFT);
+ lara_item->pos.z = item->pos.z + ((rz * c - rx * s) >> W2V_SHIFT);
+
+ rz = (bounds->max_z + bounds->min_z) / 2;
+ rx = (bounds->max_x + bounds->min_x) / 2;
+ dx -= (c * rx + s * rz) >> W2V_SHIFT;
+ dz -= (c * rz - s * rx) >> W2V_SHIFT;
+
+ if (spaz_on && bounds->max_y - bounds->min_y > STEP_L) {
+ M_TakeHit(lara_item, dx, dz);
+ }
+
+ int16_t old_facing = coll->facing;
+ coll->bad_pos = NO_BAD_POS;
+ coll->bad_neg = -STEPUP_HEIGHT;
+ coll->bad_ceiling = 0;
+ coll->facing = Math_Atan(
+ lara_item->pos.z - coll->old.z, lara_item->pos.x - coll->old.x);
+ Collide_GetCollisionInfo(
+ coll, lara_item->pos.x, lara_item->pos.y, lara_item->pos.z,
+ lara_item->room_num, LARA_HEIGHT);
+ coll->facing = old_facing;
+
+ if (coll->coll_type != COLL_NONE) {
+ lara_item->pos.x = coll->old.x;
+ lara_item->pos.z = coll->old.z;
+ } else {
+ coll->old.x = lara_item->pos.x;
+ coll->old.y = lara_item->pos.y;
+ coll->old.z = lara_item->pos.z;
+ Item_UpdateRoom(lara_item, -WALL_SHIFT);
+ }
+}
+
+int32_t __cdecl Lara_MovePosition(
+ XYZ_32 *vec, ITEM_INFO *item, ITEM_INFO *lara_item)
+{
+ const XYZ_16 rot = {
+ .x = item->rot.x,
+ .y = item->rot.y,
+ .z = item->rot.z,
+ };
+
+ Matrix_PushUnit();
+ Matrix_RotYXZ(rot.y, rot.x, rot.z);
+ const MATRIX *const m = g_MatrixPtr;
+ const XYZ_32 shift = {
+ .x = (vec->y * m->_01 + vec->z * m->_02 + vec->x * m->_00) >> W2V_SHIFT,
+ .y = (vec->x * m->_10 + vec->z * m->_12 + vec->y * m->_11) >> W2V_SHIFT,
+ .z = (vec->y * m->_21 + vec->x * m->_20 + vec->z * m->_22) >> W2V_SHIFT,
+ };
+ Matrix_Pop();
+
+ const XYZ_32 new_pos = {
+ .x = item->pos.x + shift.x,
+ .y = item->pos.y + shift.y,
+ .z = item->pos.z + shift.z,
+ };
+
+ if (item->object_id == O_FLARE_ITEM) {
+ int16_t room_num = lara_item->room_num;
+ const SECTOR_INFO *const sector =
+ Room_GetSector(new_pos.x, new_pos.y, new_pos.z, &room_num);
+ const int32_t height =
+ Room_GetHeight(sector, new_pos.x, new_pos.y, new_pos.z);
+ if (ABS(height - lara_item->pos.y) > STEP_L * 2) {
+ return false;
+ }
+ if (XYZ_32_GetDistance(&new_pos, &lara_item->pos) < STEP_L) {
+ return true;
+ }
+ }
+
+ // TODO: get rid of this conversion
+ const PHD_3DPOS new_pos_full = {
+ .pos = new_pos,
+ .rot = rot,
+ };
+ PHD_3DPOS src_pos = {
+ .pos = lara_item->pos,
+ .rot = lara_item->rot,
+ };
+ const int32_t result =
+ Misc_Move3DPosTo3DPos(&src_pos, &new_pos_full, MOVE_SPEED, MOVE_ANGLE);
+ lara_item->pos = src_pos.pos;
+ lara_item->rot = src_pos.rot;
+ return result;
+}
+
+int32_t __cdecl Lara_IsNearItem(const XYZ_32 *const pos, const int32_t distance)
+{
+ return Item_IsNearItem(g_LaraItem, pos, distance);
+}
+
+int32_t __cdecl Lara_TestClimb(
+ const int32_t x, const int32_t y, const int32_t z, const int32_t x_front,
+ const int32_t z_front, const int32_t item_height, const int16_t item_room,
+ int32_t *const shift)
+{
+ *shift = 0;
+ bool hang = true;
+ if (!g_Lara.climb_status) {
+ return 0;
+ }
+
+ const SECTOR_INFO *sector;
+ int32_t height;
+ int32_t ceiling;
+
+ int16_t room_num = item_room;
+ sector = Room_GetSector(x, y - 128, z, &room_num);
+ height = Room_GetHeight(sector, x, y, z);
+ if (height == NO_HEIGHT) {
+ return 0;
+ }
+
+ height -= y + item_height + STEP_L / 2;
+ if (height < -CLIMB_SHIFT) {
+ return 0;
+ }
+ if (height < 0) {
+ *shift = height;
+ }
+
+ ceiling = Room_GetCeiling(sector, x, y, z) - y;
+ if (ceiling > CLIMB_SHIFT) {
+ return 0;
+ }
+ if (ceiling > 0) {
+ if (*shift) {
+ return 0;
+ }
+ *shift = ceiling;
+ }
+
+ if (item_height + height < CLIMB_HANG) {
+ hang = false;
+ }
+
+ const int32_t x2 = x + x_front;
+ const int32_t z2 = z + z_front;
+ sector = Room_GetSector(x2, y, z2, &room_num);
+ height = Room_GetHeight(sector, x2, y, z2);
+ if (height != NO_HEIGHT) {
+ height -= y;
+ }
+
+ if (height > CLIMB_SHIFT) {
+ ceiling = Room_GetCeiling(sector, x2, y, z2) - y;
+ if (ceiling >= LARA_CLIMB_HEIGHT) {
+ return 1;
+ }
+
+ if (ceiling > LARA_CLIMB_HEIGHT - CLIMB_SHIFT) {
+ if (*shift > 0) {
+ return hang ? -1 : 0;
+ }
+ *shift = ceiling - LARA_CLIMB_HEIGHT;
+ return 1;
+ }
+
+ if (ceiling > 0) {
+ return hang ? -1 : 0;
+ }
+
+ if (ceiling > -CLIMB_SHIFT && hang && *shift <= 0) {
+ if (*shift > ceiling) {
+ *shift = ceiling;
+ }
+
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (height > 0) {
+ if (*shift < 0) {
+ return 0;
+ }
+ if (height > *shift) {
+ *shift = height;
+ }
+ }
+
+ room_num = item_room;
+ sector = Room_GetSector(x, item_height + y, z, &room_num);
+ sector = Room_GetSector(x2, item_height + y, z2, &room_num);
+ ceiling = Room_GetCeiling(sector, x2, item_height + y, z2);
+ if (ceiling == NO_HEIGHT) {
+ return 1;
+ }
+
+ ceiling -= y;
+ if (ceiling <= height) {
+ return 1;
+ }
+
+ if (ceiling >= LARA_CLIMB_HEIGHT) {
+ return 1;
+ }
+
+ if (ceiling > LARA_CLIMB_HEIGHT - CLIMB_SHIFT) {
+ if (*shift > 0) {
+ return hang ? -1 : 0;
+ }
+ *shift = ceiling - LARA_CLIMB_HEIGHT;
+ return 1;
+ }
+
+ return hang ? -1 : 0;
+}
+
+int32_t __cdecl Lara_TestClimbPos(
+ const ITEM_INFO *const item, const int32_t front, const int32_t right,
+ const int32_t origin, const int32_t height, int32_t *const shift)
+{
+ const int32_t y = item->pos.y + origin;
+ int32_t x;
+ int32_t z;
+ int32_t x_front = 0;
+ int32_t z_front = 0;
+
+ switch (Math_GetDirection(item->rot.y)) {
+ case DIR_NORTH:
+ x = item->pos.x + right;
+ z = item->pos.z + front;
+ z_front = 2;
+ break;
+
+ case DIR_EAST:
+ x = item->pos.x + front;
+ z = item->pos.z - right;
+ x_front = 2;
+ break;
+
+ case DIR_SOUTH:
+ x = item->pos.x - right;
+ z = item->pos.z - front;
+ z_front = -2;
+ break;
+
+ case DIR_WEST:
+ x = item->pos.x - front;
+ z = item->pos.z + right;
+ x_front = -2;
+ break;
+
+ default:
+ x = front;
+ z = front;
+ break;
+ }
+
+ return Lara_TestClimb(
+ x, y, z, x_front, z_front, height, item->room_num, shift);
+}
+
+void __cdecl Lara_DoClimbLeftRight(
+ ITEM_INFO *const item, const COLL_INFO *const coll, const int32_t result,
+ const int32_t shift)
+{
+ if (result == 1) {
+ if (g_Input & IN_LEFT) {
+ item->goal_anim_state = LS_CLIMB_LEFT;
+ } else if (g_Input & IN_RIGHT) {
+ item->goal_anim_state = LS_CLIMB_RIGHT;
+ } else {
+ item->goal_anim_state = LS_CLIMB_STANCE;
+ }
+ item->pos.y += shift;
+ return;
+ }
+
+ if (result) {
+ item->goal_anim_state = LS_HANG;
+ do {
+ Item_Animate(item);
+ } while (item->current_anim_state != LS_HANG);
+ item->pos.x = coll->old.x;
+ item->pos.z = coll->old.z;
+ return;
+ }
+
+ item->pos.x = coll->old.x;
+ item->pos.z = coll->old.z;
+ item->goal_anim_state = LS_CLIMB_STANCE;
+ item->current_anim_state = LS_CLIMB_STANCE;
+ if (coll->old_anim_state == LS_CLIMB_STANCE) {
+ item->frame_num = coll->old_frame_num;
+ item->anim_num = coll->old_anim_num;
+ Lara_Animate(item);
+ } else {
+ item->anim_num = LA_LADDER_IDLE;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ }
+}
+
+int32_t __cdecl Lara_TestClimbUpPos(
+ const ITEM_INFO *const item, const int32_t front, const int32_t right,
+ int32_t *const shift, int32_t *const ledge)
+{
+ const int32_t y = item->pos.y - LARA_CLIMB_HEIGHT - STEP_L;
+ int32_t x;
+ int32_t z;
+ int32_t x_front = 0;
+ int32_t z_front = 0;
+
+ switch (Math_GetDirection(item->rot.y)) {
+ case DIR_NORTH:
+ x = item->pos.x + right;
+ z = item->pos.z + front;
+ z_front = 2;
+ break;
+
+ case DIR_EAST:
+ x = item->pos.x + front;
+ z = item->pos.z - right;
+ x_front = 2;
+ break;
+
+ case DIR_SOUTH:
+ x = item->pos.x - right;
+ z = item->pos.z - front;
+ z_front = -2;
+ break;
+
+ case DIR_WEST:
+ z = item->pos.z + right;
+ x = item->pos.x - front;
+ x_front = -2;
+ break;
+
+ default:
+ x = front;
+ z = front;
+ break;
+ }
+
+ *shift = 0;
+
+ const SECTOR_INFO *sector;
+ int32_t height;
+ int32_t ceiling;
+
+ int16_t room_num = item->room_num;
+ sector = Room_GetSector(x, y, z, &room_num);
+ ceiling = Room_GetCeiling(sector, x, y, z) + STEP_L - y;
+ if (ceiling > CLIMB_SHIFT) {
+ return 0;
+ }
+
+ if (ceiling > 0) {
+ *shift = ceiling;
+ }
+
+ const int32_t x2 = x + x_front;
+ const int32_t z2 = z + z_front;
+ sector = Room_GetSector(x2, y, z2, &room_num);
+ height = Room_GetHeight(sector, x2, y, z2);
+ if (height == NO_HEIGHT) {
+ *ledge = NO_HEIGHT;
+ return 1;
+ }
+
+ height -= y;
+ *ledge = height;
+ if (height > STEP_L / 2) {
+ ceiling = Room_GetCeiling(sector, x2, y, z2) - y;
+ if (ceiling >= LARA_CLIMB_HEIGHT) {
+ return 1;
+ }
+
+ if (height - ceiling > LARA_HEIGHT) {
+ *shift = height;
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (height > 0 && height > *shift) {
+ *shift = height;
+ }
+
+ room_num = item->room_num;
+ sector = Room_GetSector(x, y + LARA_CLIMB_HEIGHT, z, &room_num);
+ sector = Room_GetSector(x2, y + LARA_CLIMB_HEIGHT, z2, &room_num);
+ ceiling = Room_GetCeiling(sector, x2, y + LARA_CLIMB_HEIGHT, z2) - y;
+ if (ceiling <= height) {
+ return 1;
+ }
+
+ if (ceiling >= LARA_CLIMB_HEIGHT) {
+ return 1;
+ }
+ return 0;
+}
+
+int32_t __cdecl Lara_GetWaterDepth(
+ const int32_t x, const int32_t y, const int32_t z, int16_t room_num)
+{
+ const ROOM_INFO *r = &g_Rooms[room_num];
+ const SECTOR_INFO *sector;
+
+ while (true) {
+ int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
+ int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
+
+ if (z_sector <= 0) {
+ z_sector = 0;
+ if (x_sector < 1) {
+ x_sector = 1;
+ } else if (x_sector > r->x_size - 2) {
+ x_sector = r->x_size - 2;
+ }
+ } else if (z_sector >= r->z_size - 1) {
+ z_sector = r->z_size - 1;
+ if (x_sector < 1) {
+ x_sector = 1;
+ } else if (x_sector > r->x_size - 2) {
+ x_sector = r->x_size - 2;
+ }
+ } else if (x_sector < 0) {
+ x_sector = 0;
+ } else if (x_sector >= r->x_size) {
+ x_sector = r->x_size - 1;
+ }
+
+ sector = &r->sector[z_sector + x_sector * r->z_size];
+ const int16_t data = Room_GetDoor(sector);
+ if (data == NO_ROOM) {
+ break;
+ }
+ room_num = data;
+ r = &g_Rooms[room_num];
+ }
+
+ if (r->flags & RF_UNDERWATER) {
+ while (sector->sky_room != NO_ROOM) {
+ r = &g_Rooms[sector->sky_room];
+ if (!(r->flags & RF_UNDERWATER)) {
+ const int32_t water_height = sector->ceiling << 8;
+ sector = Room_GetSector(x, y, z, &room_num);
+ return Room_GetHeight(sector, x, y, z) - water_height;
+ }
+ const int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
+ const int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
+ sector = &r->sector[z_sector + x_sector * r->z_size];
+ }
+ return 0x7FFF;
+ }
+
+ while (sector->pit_room != NO_ROOM) {
+ r = &g_Rooms[sector->pit_room];
+ if (r->flags & RF_UNDERWATER) {
+ const int32_t water_height = sector->floor << 8;
+ sector = Room_GetSector(x, y, z, &room_num);
+ return Room_GetHeight(sector, x, y, z) - water_height;
+ }
+ const int32_t z_sector = (z - r->pos.z) >> WALL_SHIFT;
+ const int32_t x_sector = (x - r->pos.x) >> WALL_SHIFT;
+ sector = &r->sector[z_sector + x_sector * r->z_size];
+ }
+ return NO_HEIGHT;
+}
+
+void __cdecl Lara_TestWaterDepth(
+ ITEM_INFO *const item, const COLL_INFO *const coll)
+{
+ int16_t room_num = item->room_num;
+
+ const SECTOR_INFO *const sector =
+ Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
+ const int32_t water_depth =
+ Lara_GetWaterDepth(item->pos.x, item->pos.y, item->pos.z, room_num);
+
+ if (water_depth == NO_HEIGHT) {
+ item->pos = coll->old;
+ item->fall_speed = 0;
+ } else if (water_depth <= STEP_L * 2) {
+ item->anim_num = LA_UNDERWATER_TO_STAND;
+ item->frame_num = g_Anims[item->anim_num].frame_base;
+ item->current_anim_state = LS_WATER_OUT;
+ item->goal_anim_state = LS_STOP;
+ item->rot.x = 0;
+ item->rot.z = 0;
+ item->gravity = 0;
+ item->speed = 0;
+ item->fall_speed = 0;
+ g_Lara.water_status = LWS_WADE;
+ item->pos.y =
+ Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
+ }
+}
+
+void __cdecl Lara_SwimCollision(ITEM_INFO *const item, COLL_INFO *const coll)
+{
+ if (item->rot.x < -PHD_90 || item->rot.x > PHD_90) {
+ g_Lara.move_angle = item->rot.y + PHD_180;
+ } else {
+ g_Lara.move_angle = item->rot.y;
+ }
+
+ coll->facing = g_Lara.move_angle;
+
+ int32_t height = (LARA_HEIGHT * Math_Sin(item->rot.x)) >> W2V_SHIFT;
+ if (height < 0) {
+ height = -height;
+ }
+ CLAMPL(height, 200);
+
+ coll->bad_neg = -height;
+ Collide_GetCollisionInfo(
+ coll, item->pos.x, item->pos.y + height / 2, item->pos.z,
+ item->room_num, height);
+ Item_ShiftCol(item, coll);
+
+ switch (coll->coll_type) {
+ case COLL_FRONT:
+ if (item->rot.x > 35 * PHD_DEGREE) {
+ item->rot.x += LARA_UW_WALL_DEFLECT;
+ } else if (item->rot.x < -35 * PHD_DEGREE) {
+ item->rot.x -= LARA_UW_WALL_DEFLECT;
+ } else {
+ item->fall_speed = 0;
+ }
+ break;
+
+ case COLL_TOP:
+ if (item->rot.x >= -45 * PHD_DEGREE) {
+ item->rot.x -= LARA_UW_WALL_DEFLECT;
+ }
+ break;
+
+ case COLL_TOP_FRONT:
+ item->fall_speed = 0;
+ break;
+
+ case COLL_LEFT:
+ item->rot.y += 5 * PHD_DEGREE;
+ break;
+
+ case COLL_RIGHT:
+ item->rot.y -= 5 * PHD_DEGREE;
+ break;
+
+ case COLL_CLAMP:
+ item->pos = coll->old;
+ item->fall_speed = 0;
+ return;
+ }
+
+ if (coll->side_mid.floor < 0) {
+ item->rot.x += LARA_UW_WALL_DEFLECT;
+ item->pos.y = coll->side_mid.floor + item->pos.y;
+ }
+
+ if (g_Lara.water_status != LWS_CHEAT && !g_Lara.extra_anim) {
+ Lara_TestWaterDepth(item, coll);
+ }
+}
+
+void __cdecl Lara_WaterCurrent(COLL_INFO *const coll)
+{
+ ITEM_INFO *const item = g_LaraItem;
+
+ int16_t room_num = g_LaraItem->room_num;
+ const ROOM_INFO *const r = &g_Rooms[g_LaraItem->room_num];
+ const int32_t z_sector = (g_LaraItem->pos.z - r->pos.z) >> WALL_SHIFT;
+ const int32_t x_sector = (g_LaraItem->pos.x - r->pos.x) >> WALL_SHIFT;
+ g_LaraItem->box_num = r->sector[z_sector + x_sector * r->z_size].box;
+
+ if (g_Lara.creature == NULL) {
+ g_Lara.current_active = 0;
+ return;
+ }
+
+ XYZ_32 target;
+ if (Box_CalculateTarget(&target, item, &g_Lara.creature->lot)
+ == TARGET_NONE) {
+ return;
+ }
+
+ target.x -= item->pos.x;
+ if (target.x > g_Lara.current_active) {
+ item->pos.x += g_Lara.current_active;
+ } else if (target.x < -g_Lara.current_active) {
+ item->pos.x -= g_Lara.current_active;
+ } else {
+ item->pos.x += target.x;
+ }
+
+ target.z -= item->pos.z;
+ if (target.z > g_Lara.current_active) {
+ item->pos.z += g_Lara.current_active;
+ } else if (target.z < -g_Lara.current_active) {
+ item->pos.z -= g_Lara.current_active;
+ } else {
+ item->pos.z += target.z;
+ }
+
+ target.y = target.y - item->pos.y;
+ if (target.y > g_Lara.current_active) {
+ item->pos.y += g_Lara.current_active;
+ } else if (target.y < -g_Lara.current_active) {
+ item->pos.y -= g_Lara.current_active;
+ } else {
+ item->pos.y += target.y;
+ }
+
+ g_Lara.current_active = 0;
+ coll->facing =
+ Math_Atan(item->pos.z - coll->old.z, item->pos.x - coll->old.x);
+ Collide_GetCollisionInfo(
+ coll, item->pos.x, item->pos.y + LARA_HEIGHT_UW / 2, item->pos.z,
+ room_num, LARA_HEIGHT_UW);
+
+ switch (coll->coll_type) {
+ case COLL_FRONT:
+ if (item->rot.x > 35 * PHD_DEGREE) {
+ item->rot.x = item->rot.x + LARA_UW_WALL_DEFLECT;
+ } else if (item->rot.x < -35 * PHD_DEGREE) {
+ item->rot.x = item->rot.x - LARA_UW_WALL_DEFLECT;
+ } else {
+ item->fall_speed = 0;
+ }
+ break;
+
+ case COLL_TOP:
+ item->rot.x -= LARA_UW_WALL_DEFLECT;
+ break;
+
+ case COLL_TOP_FRONT:
+ item->fall_speed = 0;
+ break;
+
+ case COLL_LEFT:
+ item->rot.y += 910;
+ break;
+
+ case COLL_RIGHT:
+ item->rot.y -= 910;
+ break;
+
+ default:
+ break;
+ }
+
+ if (coll->side_mid.floor < 0) {
+ item->pos.y += coll->side_mid.floor;
+ item->rot.x += LARA_UW_WALL_DEFLECT;
+ }
+ Item_ShiftCol(item, coll);
+
+ coll->old = item->pos;
+}
+
+void __cdecl Lara_CatchFire(void)
+{
+ if (g_Lara.burn || g_Lara.water_status == LWS_CHEAT) {
+ return;
+ }
+
+ const int16_t fx_num = Effect_Create(g_LaraItem->room_num);
+ if (fx_num == NO_ITEM) {
+ return;
+ }
+
+ FX_INFO *const fx = &g_Effects[fx_num];
+ fx->frame_num = 0;
+ fx->object_id = O_FLAME;
+ fx->counter = -1;
+ g_Lara.burn = 1;
+}
+
+void __cdecl Lara_TouchLava(ITEM_INFO *const item)
+{
+ if (item->hit_points < 0 || g_Lara.water_status == LWS_CHEAT) {
+ return;
+ }
+
+ int16_t room_num = item->room_num;
+ const SECTOR_INFO *const sector =
+ Room_GetSector(item->pos.x, MAX_HEIGHT, item->pos.z, &room_num);
+ const int32_t height =
+ Room_GetHeight(sector, item->pos.x, MAX_HEIGHT, item->pos.z);
+ if (item->floor != height) {
+ return;
+ }
+
+ item->hit_points = -1;
+ item->hit_status = 1;
+
+ for (int32_t i = 0; i < 10; i++) {
+ const int16_t fx_num = Effect_Create(item->room_num);
+ if (fx_num != NO_ITEM) {
+ FX_INFO *const fx = &g_Effects[fx_num];
+ fx->object_id = O_FLAME;
+ fx->frame_num =
+ g_Objects[O_FLAME].mesh_count * Random_GetControl() / 0x7FFF;
+ fx->counter = -1 - 24 * Random_GetControl() / 0x7FFF;
+ }
+ }
+}
void __cdecl Lara_Extinguish(void)
{
diff --git a/src/game/lara/lara_misc.h b/src/game/lara/misc.h
similarity index 100%
rename from src/game/lara/lara_misc.h
rename to src/game/lara/misc.h
diff --git a/src/game/lara/lara_state.c b/src/game/lara/state.c
similarity index 99%
rename from src/game/lara/lara_state.c
rename to src/game/lara/state.c
index 409af56e..02bb64aa 100644
--- a/src/game/lara/lara_state.c
+++ b/src/game/lara/state.c
@@ -1,10 +1,10 @@
-#include "game/lara/lara_state.h"
+#include "game/lara/state.h"
#include "game/input.h"
#include "game/inventory/backpack.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_look.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/control.h"
+#include "game/lara/look.h"
+#include "game/lara/misc.h"
#include "game/music.h"
#include "game/output.h"
#include "game/room.h"
diff --git a/src/game/lara/lara_state.h b/src/game/lara/state.h
similarity index 100%
rename from src/game/lara/lara_state.h
rename to src/game/lara/state.h
diff --git a/src/game/level.c b/src/game/level.c
index 4fd4b037..5a8353f9 100644
--- a/src/game/level.c
+++ b/src/game/level.c
@@ -243,13 +243,13 @@ static int32_t __cdecl M_LoadAnims(VFILE *const file, int32_t **frame_pointers)
BENCHMARK *const benchmark = Benchmark_Start();
const int32_t num_anims = VFile_ReadS32(file);
LOG_INFO("anims: %d", num_anims);
- g_Anims = game_malloc(sizeof(ANIM_STRUCT) * num_anims, GBUF_ANIMS);
+ g_Anims = game_malloc(sizeof(ANIM) * num_anims, GBUF_ANIMS);
if (frame_pointers != NULL) {
*frame_pointers = Memory_Alloc(sizeof(int32_t) * num_anims);
}
for (int32_t i = 0; i < num_anims; i++) {
- ANIM_STRUCT *const anim = &g_Anims[i];
+ ANIM *const anim = &g_Anims[i];
const int32_t frame_idx = VFile_ReadS32(file);
if (frame_pointers != NULL) {
(*frame_pointers)[i] = frame_idx;
@@ -886,7 +886,7 @@ bool __cdecl Level_Load(const char *const file_name, const int32_t level_num)
M_LoadAnimFrames(file);
for (int32_t i = 0; i < num_anims; i++) {
- ANIM_STRUCT *const anim = &g_Anims[i];
+ ANIM *const anim = &g_Anims[i];
// TODO: this is horrible
anim->frame_ptr = ((int16_t *)g_AnimFrames) + frame_pointers[i] / 2;
}
diff --git a/src/game/objects/common.c b/src/game/objects/common.c
index 7276dd5c..3f1586c8 100644
--- a/src/game/objects/common.c
+++ b/src/game/objects/common.c
@@ -1,7 +1,7 @@
#include "game/objects/common.h"
#include "game/items.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/misc.h"
#include "global/funcs.h"
#include "global/vars.h"
diff --git a/src/game/objects/effects/ember.c b/src/game/objects/effects/ember.c
index d1b82cc1..ceebb2c9 100644
--- a/src/game/objects/effects/ember.c
+++ b/src/game/objects/effects/ember.c
@@ -1,8 +1,8 @@
#include "game/objects/effects/ember.h"
#include "game/effects.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/control.h"
+#include "game/lara/misc.h"
#include "game/math.h"
#include "game/room.h"
#include "global/vars.h"
diff --git a/src/game/objects/effects/flame.c b/src/game/objects/effects/flame.c
index efb8602c..8ee20f0d 100644
--- a/src/game/objects/effects/flame.c
+++ b/src/game/objects/effects/flame.c
@@ -2,8 +2,8 @@
#include "game/collide.h"
#include "game/effects.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/control.h"
+#include "game/lara/misc.h"
#include "game/room.h"
#include "game/sound.h"
#include "global/funcs.h"
diff --git a/src/game/objects/general/body_part.c b/src/game/objects/general/body_part.c
index 274e0e3d..00bef5c8 100644
--- a/src/game/objects/general/body_part.c
+++ b/src/game/objects/general/body_part.c
@@ -1,8 +1,8 @@
#include "game/objects/general/body_part.h"
#include "game/effects.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/control.h"
+#include "game/lara/misc.h"
#include "game/math.h"
#include "game/room.h"
#include "game/sound.h"
diff --git a/src/game/objects/general/door.c b/src/game/objects/general/door.c
index cf904274..416a35c7 100644
--- a/src/game/objects/general/door.c
+++ b/src/game/objects/general/door.c
@@ -1,7 +1,7 @@
#include "game/objects/general/door.h"
#include "game/items.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/misc.h"
#include "global/funcs.h"
#include "global/vars.h"
diff --git a/src/game/objects/vehicles/boat.c b/src/game/objects/vehicles/boat.c
index cfb04c4a..15c3ece0 100644
--- a/src/game/objects/vehicles/boat.c
+++ b/src/game/objects/vehicles/boat.c
@@ -4,7 +4,7 @@
#include "game/effects.h"
#include "game/input.h"
#include "game/items.h"
-#include "game/lara/lara_look.h"
+#include "game/lara/look.h"
#include "game/math.h"
#include "game/objects/common.h"
#include "game/random.h"
diff --git a/src/game/room.c b/src/game/room.c
index 1bc5c093..78a163b0 100644
--- a/src/game/room.c
+++ b/src/game/room.c
@@ -3,7 +3,7 @@
#include "game/box.h"
#include "game/camera.h"
#include "game/items.h"
-#include "game/lara/lara_misc.h"
+#include "game/lara/misc.h"
#include "game/lot.h"
#include "game/math.h"
#include "game/music.h"
diff --git a/src/game/room_draw.c b/src/game/room_draw.c
index ed65f9d9..1a04bf18 100644
--- a/src/game/room_draw.c
+++ b/src/game/room_draw.c
@@ -1,7 +1,7 @@
#include "game/room_draw.h"
#include "game/effects.h"
-#include "game/lara/lara_draw.h"
+#include "game/lara/draw.h"
#include "game/matrix.h"
#include "game/output.h"
#include "global/funcs.h"
@@ -434,7 +434,7 @@ void __cdecl Room_DrawSingleRoomObjects(const int16_t room_num)
while (fx_num != NO_ITEM) {
const FX_INFO *const fx = &g_Effects[fx_num];
Effect_Draw(fx_num);
- fx_num = fx->next_fx;
+ fx_num = fx->next_free;
}
Matrix_Pop();
diff --git a/src/global/types.h b/src/global/types.h
index 7e2f4fc0..7879c65d 100644
--- a/src/global/types.h
+++ b/src/global/types.h
@@ -5,7 +5,10 @@
#include "const.h"
#include
+#include
#include
+#include
+#include
#include
#include
@@ -465,15 +468,6 @@ typedef enum {
DRAW_COLOR_KEY = 1,
} DRAW_TYPE;
-typedef struct __unaligned {
- int16_t min_x;
- int16_t max_x;
- int16_t min_y;
- int16_t max_y;
- int16_t min_z;
- int16_t max_z;
-} BOUNDS_16;
-
typedef struct __unaligned {
int16_t mesh_idx;
uint16_t flags;
@@ -553,20 +547,6 @@ typedef struct __unaligned {
int16_t sample_num;
} WEAPON_INFO;
-typedef struct __unaligned {
- XYZ_32 pos;
- XYZ_16 rot;
- int16_t room_num;
- int16_t object_id;
- int16_t next_fx;
- int16_t next_active;
- int16_t speed;
- int16_t fall_speed;
- int16_t frame_num;
- int16_t counter;
- int16_t shade;
-} FX_INFO;
-
typedef struct __unaligned {
int16_t zone_num;
int16_t enemy_zone_num;
@@ -577,28 +557,6 @@ typedef struct __unaligned {
int16_t enemy_facing;
} AI_INFO;
-typedef struct __unaligned {
- int16_t exit_box;
- uint16_t search_num;
- int16_t next_expansion;
- int16_t box_num;
-} BOX_NODE;
-
-typedef struct __unaligned {
- BOX_NODE *node;
- int16_t head;
- int16_t tail;
- uint16_t search_num;
- uint16_t block_mask;
- int16_t step;
- int16_t drop;
- int16_t fly;
- int16_t zone_count;
- int16_t target_box;
- int16_t required_box;
- XYZ_32 target;
-} LOT_INFO;
-
typedef enum {
GFL_NOLEVEL = -1,
GFL_TITLE = 0,
@@ -750,13 +708,6 @@ typedef enum {
GFE_REMOVE_AMMO = 22,
} GF_EVENTS;
-typedef enum {
- MOOD_BORED = 0,
- MOOD_ATTACK = 1,
- MOOD_ESCAPE = 2,
- MOOD_STALK = 3,
-} MOOD_TYPE;
-
typedef enum {
TARGET_NONE = 0,
TARGET_PRIMARY = 1,
@@ -768,35 +719,6 @@ typedef struct __unaligned {
int32_t mesh_num;
} BITE_INFO;
-typedef struct __unaligned {
- int16_t *frame_ptr;
- int16_t interpolation;
- int16_t current_anim_state;
- int32_t velocity;
- int32_t acceleration;
- int16_t frame_base;
- int16_t frame_end;
- int16_t jump_anim_num;
- int16_t jump_frame_num;
- int16_t num_changes;
- int16_t change_idx;
- int16_t num_commands;
- int16_t command_idx;
-} ANIM_STRUCT;
-
-typedef struct {
- int16_t goal_anim_state;
- int16_t num_ranges;
- int16_t range_idx;
-} ANIM_CHANGE;
-
-typedef struct {
- int16_t start_frame;
- int16_t end_frame;
- int16_t link_anim_num;
- int16_t link_frame_num;
-} ANIM_RANGE;
-
typedef struct __unaligned {
int16_t room;
int16_t x;
@@ -874,18 +796,6 @@ typedef struct __unaligned {
uint16_t flags;
} ROOM_INFO;
-typedef struct __unaligned {
- int16_t head_rotation;
- int16_t neck_rotation;
- int16_t maximum_turn;
- uint16_t flags;
- int16_t item_num;
- MOOD_TYPE mood;
- LOT_INFO lot;
- XYZ_32 target;
- ITEM_INFO *enemy;
-} CREATURE_INFO;
-
typedef enum {
CAM_CHASE = 0,
CAM_FIXED = 1,
@@ -1048,86 +958,6 @@ typedef struct __unaligned {
XYZ_32 mic_pos;
} CAMERA_INFO;
-typedef struct __unaligned {
- int16_t *frame_base;
- int16_t frame_num;
- int16_t anim_num;
- int16_t lock;
- struct __unaligned {
- int16_t y;
- int16_t x;
- int16_t z;
- } rot; // TODO: XYZ_16
- int16_t flash_gun;
-} LARA_ARM;
-
-typedef struct __unaligned {
- int32_t ammo;
-} AMMO_INFO;
-
-typedef enum {
- LWS_ABOVE_WATER = 0,
- LWS_UNDERWATER = 1,
- LWS_SURFACE = 2,
- LWS_CHEAT = 3,
- LWS_WADE = 4,
-} LARA_WATER_STATE;
-
-typedef struct __unaligned {
- int16_t item_num;
- int16_t gun_status;
- int16_t gun_type;
- int16_t request_gun_type;
- int16_t last_gun_type;
- int16_t calc_fallspeed;
- int16_t water_status;
- int16_t climb_status;
- int16_t pose_count;
- int16_t hit_frame;
- int16_t hit_direction;
- int16_t air;
- int16_t dive_count;
- int16_t death_timer;
- int16_t current_active;
- int16_t spaz_effect_count;
- int16_t flare_age;
- int16_t skidoo;
- int16_t weapon_item;
- int16_t back_gun;
- int16_t flare_frame;
- uint16_t flare_control_left: 1; // 0x01 1
- uint16_t flare_control_right: 1; // 0x02 2
- uint16_t extra_anim: 1; // 0x04 4
- uint16_t look: 1; // 0x08 8
- uint16_t burn: 1; // 0x10 16
- uint16_t pad: 11;
- int32_t water_surface_dist;
- XYZ_32 last_pos;
- FX_INFO *spaz_effect;
- uint32_t mesh_effects;
- int16_t *mesh_ptrs[15];
- ITEM_INFO *target;
- int16_t target_angles[2];
- int16_t turn_rate;
- int16_t move_angle;
- int16_t head_y_rot;
- int16_t head_x_rot;
- int16_t head_z_rot;
- int16_t torso_y_rot;
- int16_t torso_x_rot;
- int16_t torso_z_rot;
- LARA_ARM left_arm;
- LARA_ARM right_arm;
- AMMO_INFO pistol_ammo;
- AMMO_INFO magnum_ammo;
- AMMO_INFO uzi_ammo;
- AMMO_INFO shotgun_ammo;
- AMMO_INFO harpoon_ammo;
- AMMO_INFO grenade_ammo;
- AMMO_INFO m16_ammo;
- CREATURE_INFO *creature;
-} LARA_INFO;
-
typedef enum {
SFX_LARA_FEET = 0,
SFX_LARA_CLIMB2 = 1,
@@ -1511,14 +1341,6 @@ typedef struct __unaligned {
int16_t roll;
} CINE_FRAME;
-typedef enum {
- IF_ONE_SHOT = 0x0100,
- IF_CODE_BITS = 0x3E00,
- IF_REVERSE = 0x4000,
- IF_INVISIBLE = 0x0100,
- IF_KILLED = 0x8000,
-} ITEM_FLAG;
-
typedef enum {
IS_INACTIVE = 0,
IS_ACTIVE = 1,
@@ -1530,364 +1352,6 @@ typedef struct __unaligned {
uint16_t key[14]; // INPUT_ROLE_NUMBER_OF
} CONTROL_LAYOUT;
-typedef enum {
- LA_RUN = 0,
- LA_WALK_FORWARD = 1,
- LA_WALK_STOP_RIGHT = 2,
- LA_WALK_STOP_LEFT = 3,
- LA_WALK_TO_RUN_RIGHT = 4,
- LA_WALK_TO_RUN_LEFT = 5,
- LA_RUN_START = 6,
- LA_RUN_TO_WALK_RIGHT = 7,
- LA_RUN_TO_STAND_LEFT = 8,
- LA_RUN_TO_WALK_LEFT = 9,
- LA_RUN_TO_STAND_RIGHT = 10,
- LA_STAND_STILL = 11,
- LA_TURN_RIGHT_SLOW = 12,
- LA_TURN_LEFT_SLOW = 13,
- LA_JUMP_FORWARD_LAND_START = 14,
- LA_JUMP_FORWARD_LAND_END_UNUSED = 15,
- LA_RUN_JUMP_RIGHT_START = 16,
- LA_RUN_JUMP_RIGHT_CONTINUE = 17,
- LA_RUN_JUMP_LEFT_START = 18,
- LA_RUN_JUMP_LEFT_CONTINUE = 19,
- LA_WALK_FORWARD_START = 20,
- LA_WALK_FORWARD_START_CONTINUE = 21,
- LA_JUMP_FORWARD_TO_FREEFALL = 22,
- LA_FREEFALL = 23,
- LA_FREEFALL_LAND = 24,
- LA_FREEFALL_LAND_DEATH = 25,
- LA_STAND_TO_JUMP_UP = 26,
- LA_STAND_TO_JUMP_UP_CONTINUE = 27,
- LA_JUMP_UP = 28,
- LA_JUMP_UP_TO_HANG = 29,
- LA_JUMP_UP_TO_FREEFALL = 30,
- LA_JUMP_UP_LAND = 31,
- LA_SMASH_JUMP = 32,
- LA_SMASH_JUMP_CONTINUE = 33,
- LA_FALL_START = 34,
- LA_FALL = 35,
- LA_FALL_TO_FREEFALL = 36,
- LA_HANG_TO_FREEFALL = 37,
- LA_WALK_BACK_END_RIGHT = 38,
- LA_WALK_BACK_END_LEFT = 39,
- LA_WALK_BACK = 40,
- LA_WALK_BACK_START = 41,
- LA_CLIMB_3CLICK = 42,
- LA_CLIMB_3CLICK_END_TO_RUN = 43,
- LA_TURN_RIGHT = 44,
- LA_JUMP_FORWARD_TO_FREEFALL_2 = 45,
- LA_REACH_TO_FREEFALL = 46,
- LA_ROLL_ALTERNATE = 47,
- LA_ROLL_END_ALTERNATE = 48,
- LA_JUMP_FORWARD_END_TO_FREEFALL = 49,
- LA_CLIMB_2CLICK = 50,
- LA_CLIMB_2CLICK_END = 51,
- LA_CLIMB_2CLICK_END_TO_RUN = 52,
- LA_WALL_SMASH_LEFT = 53,
- LA_WALL_SMASH_RIGHT = 54,
- LA_RUN_UP_STEP_RIGHT = 55,
- LA_RUN_UP_STEP_LEFT = 56,
- LA_WALK_UP_STEP_RIGHT = 57,
- LA_WALK_UP_STEP_LEFT = 58,
- LA_WALK_DOWN_LEFT = 59,
- LA_WALK_DOWN_RIGHT = 60,
- LA_WALK_DOWN_BACK_LEFT = 61,
- LA_WALK_DOWN_BACK_RIGHT = 62,
- LA_WALLSWITCH_DOWN = 63,
- LA_WALLSWITCH_UP = 64,
- LA_SIDESTEP_LEFT = 65,
- LA_SIDESTEP_LEFT_END = 66,
- LA_SIDESTEP_RIGHT = 67,
- LA_SIDESTEP_RIGHT_END = 68,
- LA_ROTATE_LEFT = 69,
- LA_SLIDE_FORWARD = 70,
- LA_SLIDE_FORWARD_END = 71,
- LA_SLIDE_FORWARD_STOP = 72,
- LA_STAND_TO_JUMP = 73,
- LA_JUMP_BACK_START = 74,
- LA_JUMP_BACK = 75,
- LA_JUMP_FORWARD_START = 76,
- LA_JUMP_FORWARD = 77,
- LA_JUMP_LEFT_START = 78,
- LA_JUMP_LEFT = 79,
- LA_JUMP_RIGHT_START = 80,
- LA_JUMP_RIGHT = 81,
- LA_LAND = 82,
- LA_JUMP_BACK_TO_FREEFALL = 83,
- LA_JUMP_LEFT_TO_FREEFALL = 84,
- LA_JUMP_RIGHT_TO_FREEFALL = 85,
- LA_UNDERWATER_SWIM_FORWARD = 86,
- LA_UNDERWATER_SWIM_FORWARD_DRIFT = 87,
- LA_SMALL_JUMP_BACK_START = 88,
- LA_SMALL_JUMP_BACK = 89,
- LA_SMALL_JUMP_BACK_END = 90,
- LA_JUMP_UP_START = 91,
- LA_LAND_TO_RUN = 92,
- LA_FALL_BACK = 93,
- LA_JUMP_FORWARD_TO_REACH = 94,
- LA_REACH = 95,
- LA_REACH_TO_HANG = 96,
- LA_CLIMB_ON = 97,
- LA_REACH_TO_FREEFALL_2 = 98,
- LA_FALL_CROUCHING_LANDING = 99,
- LA_JUMP_FORWARD_TO_REACH_LATE = 100,
- LA_JUMP_FORWARD_START_TO_REACH_ALTERNATE = 101,
- LA_CLIMB_ON_END = 102,
- LA_STAND_IDLE = 103,
- LA_SLIDE_BACKWARD_START = 104,
- LA_SLIDE_BACKWARD = 105,
- LA_SLIDE_BACKWARD_END = 106,
- LA_UNDERWATER_SWIM_TO_IDLE = 107,
- LA_UNDERWATER_IDLE = 108,
- LA_UNDERWARER_IDLE_TO_SWIM = 109,
- LA_ONWATER_IDLE = 110,
- LA_ONWATER_TO_STAND_HIGH = 111,
- LA_FREEFALL_TO_UNDERWATER = 112,
- LA_ONWATER_DIVE_ALTERNATE = 113,
- LA_UNDERWATER_TO_ONWATER = 114,
- LA_ONWATER_SWIM_FORWARD_DIVE = 115,
- LA_ONWATER_SWIM_FORWARD = 116,
- LA_ONWATER_SWIM_FORWARD_TO_IDLE = 117,
- LA_ONWATER_IDLE_TO_SWIM_FORWARD = 118,
- LA_ONWATER_DIVE = 119,
- LA_PUSHABLE_GRAB = 120,
- LA_PUSHABLE_RELEASE = 121,
- LA_PUSHABLE_PULL = 122,
- LA_PUSHABLE_PUSH = 123,
- LA_UNDERWATER_DEATH = 124,
- LA_HIT_FRONT = 125,
- LA_HIT_BACK = 126,
- LA_HIT_LEFT = 127,
- LA_HIT_RIGHT = 128,
- LA_UNDERWATER_SWITCH = 129,
- LA_UNDERWATER_PICKUP = 130,
- LA_USE_KEY = 131,
- LA_ONWATER_DEATH = 132,
- LA_RUN_DEATH = 133,
- LA_USE_PUZZLE = 134,
- LA_PICKUP = 135,
- LA_SHIMMY_LEFT = 136,
- LA_SHIMMY_RIGHT = 137,
- LA_STAND_DEATH = 138,
- LA_BOULDER_DEATH = 139,
- LA_ONWATER_IDLE_TO_SWIM_BACK = 140,
- LA_ONWATER_SWIM_BACK = 141,
- LA_ONWATER_SWIM_BACK_TO_IDLE = 142,
- LA_ONWATER_SWIM_LEFT = 143,
- LA_ONWATER_SWIM_RIGHT = 144,
- LA_DEATH_JUMP = 145,
- LA_ROLL_START = 146,
- LA_ROLL_CONTINUE = 147,
- LA_ROLL_END = 148,
- LA_SPIKE_DEATH = 149,
- LA_REACH_TO_THIN_LEDGE = 150,
- LA_SWANDIVE_ROLL = 151,
- LA_SWANDIVE_TO_UNDERWATER = 152,
- LA_FREEFALL_SWANDIVE = 153,
- LA_FREEFALL_SWANDIVE_TO_UNDERWATER = 154,
- LA_SWANDIVE_DEATH = 155,
- LA_SWANDIVE_LEFT = 156,
- LA_SWANDIVE_RIGHT = 157,
- LA_SWANDIVE_START = 158,
- LA_CLIMB_ON_HANDSTAND = 159,
- LA_STAND_TO_LADDER = 160,
- LA_LADDER_UP = 161,
- LA_LADDER_UP_STOP_RIGHT = 162,
- LA_LADDER_UP_STOP_LEFT = 163,
- LA_LADDER_IDLE = 164,
- LA_LADDER_UP_START = 165,
- LA_LADDER_DOWN_STOP_LEFT = 166,
- LA_LADDER_DOWN_STOP_RIGHT = 167,
- LA_LADDER_DOWN = 168,
- LA_LADDER_DOWN_START = 169,
- LA_LADDER_RIGHT = 170,
- LA_LADDER_LEFT = 171,
- LA_LADDER_HANG = 172,
- LA_LADDER_HANG_TO_IDLE = 173,
- LA_LADDER_CLIMB_ON = 174,
- LA_UNKNOWN = 175,
- LA_ONWATER_TO_WADE_SHALLOW = 176,
- LA_WADE = 177,
- LA_RUN_TO_WADE_LEFT = 178,
- LA_RUN_TO_WADE_RIGHT = 179,
- LA_WADE_TO_RUN_LEFT = 180,
- LA_WADE_TO_RUN_RIGHT = 181,
- LA_LADDER_BACKFLIP_START = 182,
- LA_LADDER_BACKFLIP_CONTINUE = 183,
- LA_WADE_TO_STAND_RIGHT = 184,
- LA_WADE_TO_STAND_LEFT = 185,
- LA_STAND_TO_WADE = 186,
- LA_LADDER_UP_HANGING = 187,
- LA_LADDER_DOWN_HANGING = 188,
- LA_FLARE_THROW = 189,
- LA_ONWATER_TO_WADE = 190,
- LA_ONWATER_TO_STAND_MEDIUM = 191,
- LA_UNDERWATER_TO_STAND = 192,
- LA_ONWATER_TO_WADE_LOW = 193,
- LA_LADDER_TO_HANG_DOWN = 194,
- LA_SWITCH_SMALL_DOWN = 195,
- LA_SWITCH_SMALL_UP = 196,
- LA_BUTTON_PUSH = 197,
- LA_UNDERWATER_SWIM_TO_STILL_HUDDLE = 198,
- LA_UNDERWATER_SWIM_TO_STILL_SPRAWL = 199,
- LA_UNDERWATER_SWIM_TO_STILL_MEDIUM = 200,
- LA_LADDER_TO_HANG_RIGHT = 201,
- LA_LADDER_TO_HANG_LEFT = 202,
- LA_UNDERWATER_ROLL_START = 203,
- LA_FLARE_PICKUP = 204,
- LA_UNDERWATER_ROLL_END = 205,
- LA_UNDERWATER_FLARE_PICKUP = 206,
- LA_RUN_JUMP_ROLL_START = 207,
- LA_SOMERSAULT = 208,
- LA_RUN_JUMP_ROLL_END = 209,
- LA_JUMP_FORWARD_ROLL_START = 210,
- LA_JUMP_FORWARD_ROLL_END = 211,
- LA_JUMP_BACK_ROLL_START = 212,
- LA_JUMP_BACK_ROLL_END = 213,
- LA_KICK = 214,
- LA_ZIPLINE_GRAB = 215,
- LA_ZIPLINE_RIDE = 216,
- LA_ZIPLINE_FALL = 217,
-} LARA_ANIMATION;
-
-typedef enum {
- LA_EXTRA_BREATH = 0,
- LA_EXTRA_PLUNGER = 1,
- LA_EXTRA_YETI_KILL = 2,
- LA_EXTRA_SHARK_KILL = 3,
- LA_EXTRA_AIRLOCK = 4,
- LA_EXTRA_GONG_BONG = 5,
- LA_EXTRA_DINO_KILL = 6,
- LA_EXTRA_PULL_DAGGER = 7,
- LA_EXTRA_START_ANIM = 8,
- LA_EXTRA_START_HOUSE = 9,
- LA_EXTRA_FINAL_ANIM = 10,
-} LARA_EXTRA_ANIMATION;
-
-typedef enum {
- LS_WALK = 0,
- LS_RUN = 1,
- LS_STOP = 2,
- LS_FORWARD_JUMP = 3,
- LS_POSE = 4,
- LS_FAST_BACK = 5,
- LS_TURN_RIGHT = 6,
- LS_TURN_LEFT = 7,
- LS_DEATH = 8,
- LS_FAST_FALL = 9,
- LS_HANG = 10,
- LS_REACH = 11,
- LS_SPLAT = 12,
- LS_TREAD = 13,
- LS_LAND = 14,
- LS_COMPRESS = 15,
- LS_BACK = 16,
- LS_SWIM = 17,
- LS_GLIDE = 18,
- LS_NULL = 19,
- LS_FAST_TURN = 20,
- LS_STEP_RIGHT = 21,
- LS_STEP_LEFT = 22,
- LS_HIT = 23,
- LS_SLIDE = 24,
- LS_BACK_JUMP = 25,
- LS_RIGHT_JUMP = 26,
- LS_LEFT_JUMP = 27,
- LS_UP_JUMP = 28,
- LS_FALL_BACK = 29,
- LS_HANG_LEFT = 30,
- LS_HANG_RIGHT = 31,
- LS_SLIDE_BACK = 32,
- LS_SURF_TREAD = 33,
- LS_SURF_SWIM = 34,
- LS_DIVE = 35,
- LS_PUSH_BLOCK = 36,
- LS_PULL_BLOCK = 37,
- LS_PP_READY = 38,
- LS_PICKUP = 39,
- LS_SWITCH_ON = 40,
- LS_SWITCH_OFF = 41,
- LS_USE_KEY = 42,
- LS_USE_PUZZLE = 43,
- LS_UW_DEATH = 44,
- LS_ROLL = 45,
- LS_SPECIAL = 46,
- LS_SURF_BACK = 47,
- LS_SURF_LEFT = 48,
- LS_SURF_RIGHT = 49,
- LS_USE_MIDAS = 50,
- LS_DIE_MIDAS = 51,
- LS_SWAN_DIVE = 52,
- LS_FAST_DIVE = 53,
- LS_GYMNAST = 54,
- LS_WATER_OUT = 55,
- LS_CLIMB_STANCE = 56,
- LS_CLIMBING = 57,
- LS_CLIMB_LEFT = 58,
- LS_CLIMB_END = 59,
- LS_CLIMB_RIGHT = 60,
- LS_CLIMB_DOWN = 61,
- LS_LARA_TEST1 = 62,
- LS_LARA_TEST2 = 63,
- LS_LARA_TEST3 = 64,
- LS_WADE = 65,
- LS_WATER_ROLL = 66,
- LS_FLARE_PICKUP = 67,
- LS_TWIST = 68,
- LS_KICK = 69,
- LS_DEATH_SLIDE = 70,
- LS_DUCK = 71,
- LS_DUCK_ROLL = 72,
- LS_DASH = 73,
- LS_DASH_DIVE = 74,
- LS_MONKEY_SWING = 75,
- LS_MONKEYF = 76,
- LS_LAST = 77,
-} LARA_STATE;
-
-typedef enum {
- LGS_ARMLESS = 0,
- LGS_HANDS_BUSY = 1,
- LGS_DRAW = 2,
- LGS_UNDRAW = 3,
- LGS_READY = 4,
- LGS_SPECIAL = 5,
-} LARA_GUN_STATE;
-
-typedef enum {
- LGT_UNARMED = 0,
- LGT_PISTOLS = 1,
- LGT_MAGNUMS = 2,
- LGT_UZIS = 3,
- LGT_SHOTGUN = 4,
- LGT_M16 = 5,
- LGT_GRENADE = 6,
- LGT_HARPOON = 7,
- LGT_FLARE = 8 ,
- LGT_SKIDOO = 9,
- NUM_WEAPONS = 10,
-} LARA_GUN_TYPE;
-
-typedef enum {
- LM_HIPS = 0,
- LM_THIGH_L = 1,
- LM_CALF_L = 2,
- LM_FOOT_L = 3,
- LM_THIGH_R = 4,
- LM_CALF_R = 5,
- LM_FOOT_R = 6,
- LM_TORSO = 7,
- LM_UARM_R = 8,
- LM_LARM_R = 9,
- LM_HAND_R = 10,
- LM_UARM_L = 11,
- LM_LARM_L = 12,
- LM_HAND_L = 13,
- LM_HEAD = 14,
- LM_NUMBER_OF = 15,
-} LARA_MESH;
-
typedef enum {
MX_INACTIVE = -1,
MX_UNUSED_0 = 0, // 2.mp3
@@ -1984,14 +1448,6 @@ typedef enum {
HT_BIG_SLOPE = 2,
} HEIGHT_TYPE;
-typedef enum {
- DIR_UNKNOWN = -1,
- DIR_NORTH = 0,
- DIR_EAST = 1,
- DIR_SOUTH = 2,
- DIR_WEST = 3,
-} DIRECTION;
-
typedef struct __unaligned {
uint16_t x;
uint16_t y;
diff --git a/src/global/vars_decomp.h b/src/global/vars_decomp.h
index c38aa819..2fd5551a 100644
--- a/src/global/vars_decomp.h
+++ b/src/global/vars_decomp.h
@@ -450,7 +450,7 @@
#define g_IMMatrixStack (*(MATRIX(*)[256])0x005252C0)
#define g_DoorVBuf (*(DOOR_VBUF(*)[4])0x005258C0)
#define g_IMFrac (*(int32_t*)0x005258F0)
-#define g_Anims (*(ANIM_STRUCT **)0x005258F4)
+#define g_Anims (*(ANIM **)0x005258F4)
#define g_BoundRooms (*(int32_t(*)[128])0x00525900)
#define g_OutsideBottom (*(int32_t*)0x00525B00)
#define g_AnimRanges (*(ANIM_RANGE **)0x00525B04)
diff --git a/src/inject_exec.c b/src/inject_exec.c
index 3af86d2d..94045194 100644
--- a/src/inject_exec.c
+++ b/src/inject_exec.c
@@ -22,13 +22,13 @@
#include "game/inventory/common.h"
#include "game/inventory/ring.h"
#include "game/items.h"
-#include "game/lara/lara_cheat.h"
-#include "game/lara/lara_col.h"
-#include "game/lara/lara_control.h"
-#include "game/lara/lara_draw.h"
-#include "game/lara/lara_look.h"
-#include "game/lara/lara_misc.h"
-#include "game/lara/lara_state.h"
+#include "game/lara/cheat.h"
+#include "game/lara/col.h"
+#include "game/lara/control.h"
+#include "game/lara/draw.h"
+#include "game/lara/look.h"
+#include "game/lara/misc.h"
+#include "game/lara/state.h"
#include "game/level.h"
#include "game/los.h"
#include "game/lot.h"
diff --git a/src/specific/s_input.c b/src/specific/s_input.c
index 97936260..b57ffbdc 100644
--- a/src/specific/s_input.c
+++ b/src/specific/s_input.c
@@ -5,7 +5,7 @@
#include "game/gameflow/gameflow_new.h"
#include "game/input.h"
#include "game/inventory/backpack.h"
-#include "game/lara/lara_control.h"
+#include "game/lara/control.h"
#include "global/const.h"
#include "global/funcs.h"
#include "global/vars.h"
diff --git a/subprojects/libtrx b/subprojects/libtrx
index 41cd1a09..c984f369 160000
--- a/subprojects/libtrx
+++ b/subprojects/libtrx
@@ -1 +1 @@
-Subproject commit 41cd1a09e3ea1c445df702cd9fa0d7682761459f
+Subproject commit c984f369d2e7903ec0cd4c5fa5724aeaa8d571b2
diff --git a/tools/generate_funcs b/tools/generate_funcs
index 7bfd2608..08afe5ba 100755
--- a/tools/generate_funcs
+++ b/tools/generate_funcs
@@ -114,7 +114,10 @@ def make_types_h(types: list[str]) -> None:
'#include "const.h"',
"",
"#include ",
+ "#include ",
"#include ",
+ "#include ",
+ "#include ",
"#include ",
"#include ",
"",