diff --git a/include/libtrx/game/items.h b/include/libtrx/game/items.h new file mode 100644 index 0000000..43da3fa --- /dev/null +++ b/include/libtrx/game/items.h @@ -0,0 +1,96 @@ +#pragma once + +#include "objects.h" + +#include +#include +#include "math.h" + +#pragma pack(push, 1) + +#if TR_VERSION == 1 +typedef enum { + DS_CARRIED = 0, + DS_FALLING = 1, + DS_DROPPED = 2, + DS_COLLECTED = 3, +} DROP_STATUS; + +typedef struct CARRIED_ITEM { + GAME_OBJECT_ID object_id; + int16_t spawn_num; + XYZ_32 pos; + XYZ_16 rot; + int16_t room_num; + int16_t fall_speed; + DROP_STATUS status; + struct CARRIED_ITEM *next_item; +} CARRIED_ITEM; +#endif + +typedef struct { + int32_t floor; + uint32_t touch_bits; + uint32_t mesh_bits; +#if TR_VERSION == 1 + GAME_OBJECT_ID object_id; +#elif TR_VERSION == 2 + int16_t object_id; +#endif + int16_t current_anim_state; + int16_t goal_anim_state; + int16_t required_anim_state; + int16_t anim_num; + int16_t frame_num; + int16_t room_num; + int16_t next_item; + int16_t next_active; + int16_t speed; + int16_t fall_speed; + int16_t hit_points; + int16_t box_num; + int16_t timer; + uint16_t flags; + +#if TR_VERSION == 1 + int16_t shade; + void *data; + void *priv; + CARRIED_ITEM *carried_item; +#elif TR_VERSION == 2 + int16_t shade1; + int16_t shade2; + int16_t carried_item; + void *data; +#endif + + XYZ_32 pos; + XYZ_16 rot; + + uint16_t active : 1; // 0x0001 + uint16_t status : 2; // 0x0002…0x0004 + uint16_t gravity : 1; // 0x0008 + uint16_t hit_status : 1; // 0x0010 + uint16_t collidable : 1; // 0x0020 + uint16_t looked_at : 1; // 0x0040 +#if TR_VERSION == 1 + uint16_t pad : 9; // 0x0080…0x8000 +#elif TR_VERSION == 2 + uint16_t dynamic_light : 1; // 0x0080 + uint16_t killed : 1; // 0x0100 + uint16_t pad : 7; // 0x0200…0x8000 +#endif + +#if TR_VERSION == 1 + struct { + struct { + XYZ_32 pos; + XYZ_16 rot; + } result, prev; + } interp; +#endif +} ITEM_INFO; + +#pragma pack(pop) + +void Item_TakeDamage(ITEM_INFO *item, int16_t damage, bool hit_status); diff --git a/include/libtrx/game/math.h b/include/libtrx/game/math.h new file mode 100644 index 0000000..c7a1280 --- /dev/null +++ b/include/libtrx/game/math.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#pragma pack(push, 1) + +typedef struct { + int32_t x; + int32_t y; + int32_t z; +} XYZ_32; + +typedef struct { + int16_t x; + int16_t y; + int16_t z; +} XYZ_16; + +#pragma pack(pop) diff --git a/include/libtrx/game/objects.h b/include/libtrx/game/objects.h new file mode 100644 index 0000000..5a3ee08 --- /dev/null +++ b/include/libtrx/game/objects.h @@ -0,0 +1,467 @@ +#pragma once + +typedef enum { +#if TR_VERSION == 1 + NO_OBJECT = -1, + O_LARA = 0, + O_PISTOL_ANIM = 1, + O_SHOTGUN_ANIM = 2, + O_MAGNUM_ANIM = 3, + O_UZI_ANIM = 4, + O_LARA_EXTRA = 5, + O_BACON_LARA = 6, + O_WOLF = 7, + O_BEAR = 8, + O_BAT = 9, + O_CROCODILE = 10, + O_ALLIGATOR = 11, + O_LION = 12, + O_LIONESS = 13, + O_PUMA = 14, + O_APE = 15, + O_RAT = 16, + O_VOLE = 17, + O_TREX = 18, + O_RAPTOR = 19, + O_WARRIOR1 = 20, // flying mutant + O_WARRIOR2 = 21, + O_WARRIOR3 = 22, + O_CENTAUR = 23, + O_MUMMY = 24, + O_DINO_WARRIOR = 25, + O_FISH = 26, + O_LARSON = 27, + O_PIERRE = 28, + O_SKATEBOARD = 29, + O_SKATEKID = 30, + O_COWBOY = 31, + O_BALDY = 32, + O_NATLA = 33, + O_TORSO = 34, // a.k.a. Abortion, Adam or Evil Natla + O_FALLING_BLOCK = 35, + O_PENDULUM = 36, + O_SPIKES = 37, + O_ROLLING_BALL = 38, + O_DARTS = 39, + O_DART_EMITTER = 40, + O_DRAW_BRIDGE = 41, + O_TEETH_TRAP = 42, + O_DAMOCLES_SWORD = 43, + O_THORS_HANDLE = 44, + O_THORS_HEAD = 45, + O_LIGHTNING_EMITTER = 46, + O_MOVING_BAR = 47, + O_MOVABLE_BLOCK = 48, + O_MOVABLE_BLOCK2 = 49, + O_MOVABLE_BLOCK3 = 50, + O_MOVABLE_BLOCK4 = 51, + O_SLIDING_PILLAR = 52, + O_FALLING_CEILING1 = 53, + O_FALLING_CEILING2 = 54, + O_SWITCH_TYPE1 = 55, + O_SWITCH_TYPE2 = 56, + O_DOOR_TYPE1 = 57, + O_DOOR_TYPE2 = 58, + O_DOOR_TYPE3 = 59, + O_DOOR_TYPE4 = 60, + O_DOOR_TYPE5 = 61, + O_DOOR_TYPE6 = 62, + O_DOOR_TYPE7 = 63, + O_DOOR_TYPE8 = 64, + O_TRAPDOOR = 65, + O_TRAPDOOR2 = 66, + O_BIGTRAPDOOR = 67, + O_BRIDGE_FLAT = 68, + O_BRIDGE_TILT1 = 69, + O_BRIDGE_TILT2 = 70, + O_PASSPORT_OPTION = 71, + O_MAP_OPTION = 72, + O_PHOTO_OPTION = 73, + O_COG_1 = 74, + O_COG_2 = 75, + O_COG_3 = 76, + O_PLAYER_1 = 77, + O_PLAYER_2 = 78, + O_PLAYER_3 = 79, + O_PLAYER_4 = 80, + O_PASSPORT_CLOSED = 81, + O_MAP_CLOSED = 82, + O_SAVEGAME_ITEM = 83, + O_PISTOL_ITEM = 84, + O_SHOTGUN_ITEM = 85, + O_MAGNUM_ITEM = 86, + O_UZI_ITEM = 87, + O_PISTOL_AMMO_ITEM = 88, + O_SG_AMMO_ITEM = 89, + O_MAG_AMMO_ITEM = 90, + O_UZI_AMMO_ITEM = 91, + O_EXPLOSIVE_ITEM = 92, + O_MEDI_ITEM = 93, + O_BIGMEDI_ITEM = 94, + O_DETAIL_OPTION = 95, + O_SOUND_OPTION = 96, + O_CONTROL_OPTION = 97, + O_GAMMA_OPTION = 98, + O_PISTOL_OPTION = 99, + O_SHOTGUN_OPTION = 100, + O_MAGNUM_OPTION = 101, + O_UZI_OPTION = 102, + O_PISTOL_AMMO_OPTION = 103, + O_SG_AMMO_OPTION = 104, + O_MAG_AMMO_OPTION = 105, + O_UZI_AMMO_OPTION = 106, + O_EXPLOSIVE_OPTION = 107, + O_MEDI_OPTION = 108, + O_BIGMEDI_OPTION = 109, + O_PUZZLE_ITEM1 = 110, + O_PUZZLE_ITEM2 = 111, + O_PUZZLE_ITEM3 = 112, + O_PUZZLE_ITEM4 = 113, + O_PUZZLE_OPTION1 = 114, + O_PUZZLE_OPTION2 = 115, + O_PUZZLE_OPTION3 = 116, + O_PUZZLE_OPTION4 = 117, + O_PUZZLE_HOLE1 = 118, + O_PUZZLE_HOLE2 = 119, + O_PUZZLE_HOLE3 = 120, + O_PUZZLE_HOLE4 = 121, + O_PUZZLE_DONE1 = 122, + O_PUZZLE_DONE2 = 123, + O_PUZZLE_DONE3 = 124, + O_PUZZLE_DONE4 = 125, + O_LEADBAR_ITEM = 126, + O_LEADBAR_OPTION = 127, + O_MIDAS_TOUCH = 128, + O_KEY_ITEM1 = 129, + O_KEY_ITEM2 = 130, + O_KEY_ITEM3 = 131, + O_KEY_ITEM4 = 132, + O_KEY_OPTION1 = 133, + O_KEY_OPTION2 = 134, + O_KEY_OPTION3 = 135, + O_KEY_OPTION4 = 136, + O_KEY_HOLE1 = 137, + O_KEY_HOLE2 = 138, + O_KEY_HOLE3 = 139, + O_KEY_HOLE4 = 140, + O_PICKUP_ITEM1 = 141, + O_PICKUP_ITEM2 = 142, + O_SCION_ITEM = 143, + O_SCION_ITEM2 = 144, + O_SCION_ITEM3 = 145, + O_SCION_ITEM4 = 146, + O_SCION_HOLDER = 147, + O_PICKUP_OPTION1 = 148, + O_PICKUP_OPTION2 = 149, + O_SCION_OPTION = 150, + O_EXPLOSION1 = 151, + O_EXPLOSION2 = 152, + O_SPLASH1 = 153, + O_SPLASH2 = 154, + O_BUBBLES1 = 155, + O_BUBBLES2 = 156, + O_BUBBLE_EMITTER = 157, + O_BLOOD1 = 158, + O_BLOOD2 = 159, + O_DART_EFFECT = 160, + O_STATUE = 161, + O_PORTACABIN = 162, + O_PODS = 163, + O_RICOCHET1 = 164, + O_TWINKLE = 165, + O_GUN_FLASH = 166, + O_DUST = 167, + O_BODY_PART = 168, + O_CAMERA_TARGET = 169, + O_WATERFALL = 170, + O_MISSILE1 = 171, + O_MISSILE2 = 172, + O_MISSILE3 = 173, + O_MISSILE4 = 174, + O_MISSILE5 = 175, + O_LAVA = 176, + O_LAVA_EMITTER = 177, + O_FLAME = 178, + O_FLAME_EMITTER = 179, + O_LAVA_WEDGE = 180, + O_BIG_POD = 181, + O_BOAT = 182, + O_EARTHQUAKE = 183, + O_SKYBOX = 184, + O_TEMP6 = 185, + O_TEMP7 = 186, + O_TEMP8 = 187, + O_TEMP9 = 188, + O_TEMP10 = 189, + O_HAIR = O_TEMP10, + O_ALPHABET = 190, +#else + O_NONE = -1, + O_LARA = 0, + O_LARA_PISTOLS = 1, + O_LARA_HAIR = 2, + O_LARA_SHOTGUN = 3, + O_LARA_MAGNUMS = 4, + O_LARA_UZIS = 5, + O_LARA_M16 = 6, + O_LARA_GRENADE = 7, + O_LARA_HARPOON = 8, + O_LARA_FLARE = 9, + O_LARA_SKIDOO = 10, + O_LARA_BOAT = 11, + O_LARA_EXTRA = 12, + O_SKIDOO_FAST = 13, + O_BOAT = 14, + O_DOG = 15, + O_CULT_1 = 16, + O_CULT_1A = 17, + O_CULT_1B = 18, + O_CULT_2 = 19, + O_CULT_3 = 20, + O_MOUSE = 21, + O_DRAGON_FRONT = 22, + O_DRAGON_BACK = 23, + O_GONDOLA = 24, + O_SHARK = 25, + O_EEL = 26, + O_BIG_EEL = 27, + O_BARRACUDA = 28, + O_DIVER = 29, + O_WORKER_1 = 30, + O_WORKER_2 = 31, + O_WORKER_3 = 32, + O_WORKER_4 = 33, + O_WORKER_5 = 34, + O_JELLY = 35, + O_SPIDER = 36, + O_BIG_SPIDER = 37, + O_CROW = 38, + O_TIGER = 39, + O_BARTOLI = 40, + O_XIAN_SPEARMAN = 41, + O_XIAN_SPEARMAN_STATUE = 42, + O_XIAN_KNIGHT = 43, + O_XIAN_KNIGHT_STATUE = 44, + O_YETI = 45, + O_GIANT_YETI = 46, + O_EAGLE = 47, + O_BANDIT_1 = 48, + O_BANDIT_2 = 49, + O_BANDIT_2B = 50, + O_SKIDOO_ARMED = 51, + O_SKIDMAN = 52, + O_MONK_1 = 53, + O_MONK_2 = 54, + O_FALLING_BLOCK_1 = 55, + O_FALLING_BLOCK_2 = 56, + O_FALLING_BLOCK_3 = 57, + O_PENDULUM_1 = 58, + O_SPIKES = 59, + O_ROLLING_BALL_1 = 60, + O_DARTS = 61, + O_DART_EMITTER = 62, + O_DRAW_BRIDGE = 63, + O_TEETH_TRAP = 64, + O_LIFT = 65, + O_GENERAL = 66, + O_MOVABLE_BLOCK_1 = 67, + O_MOVABLE_BLOCK_2 = 68, + O_MOVABLE_BLOCK_3 = 69, + O_MOVABLE_BLOCK_4 = 70, + O_BIG_BOWL = 71, + O_WINDOW_1 = 72, + O_WINDOW_2 = 73, + O_WINDOW_3 = 74, + O_WINDOW_4 = 75, + O_PROPELLER_1 = 76, + O_POWER_SAW = 77, + O_HOOK = 78, + O_FALLING_CEILING = 79, + O_SPINNING_BLADE = 80, + O_BLADE = 81, + O_KILLER_STATUE = 82, + O_ROLLING_BALL_2 = 83, + O_ICICLE = 84, + O_SPIKE_WALL = 85, + O_SPRING_BOARD = 86, + O_CEILING_SPIKES = 87, + O_BELL = 88, + O_WATER_SPRITE = 89, + O_SNOW_SPRITE = 90, + O_SKIDOO_LARA = 91, + O_SWITCH_TYPE_1 = 92, + O_SWITCH_TYPE_2 = 93, + O_PROPELLER_2 = 94, + O_PROPELLER_3 = 95, + O_PENDULUM_2 = 96, + O_MESH_SWAP_1 = 97, + O_MESH_SWAP_2 = 98, + O_LARA_SWAP = 99, + O_TEXT_BOX = 100, + O_ROLLING_BALL_3 = 101, + O_DEATH_SLIDE = 102, + O_SWITCH_TYPE_3 = 103, + O_SWITCH_TYPE_4 = 104, + O_SWITCH_TYPE_5 = 105, + O_DOOR_TYPE_1 = 106, + O_DOOR_TYPE_2 = 107, + O_DOOR_TYPE_3 = 108, + O_DOOR_TYPE_4 = 109, + O_DOOR_TYPE_5 = 110, + O_DOOR_TYPE_6 = 111, + O_DOOR_TYPE_7 = 112, + O_DOOR_TYPE_8 = 113, + O_TRAPDOOR_TYPE_1 = 114, + O_TRAPDOOR_TYPE_2 = 115, + O_TRAPDOOR_TYPE_3 = 116, + O_BRIDGE_FLAT = 117, + O_BRIDGE_TILT_1 = 118, + O_BRIDGE_TILT_2 = 119, + O_PASSPORT_OPTION = 120, + O_COMPASS_OPTION = 121, + O_PHOTO_OPTION = 122, + O_PLAYER_1 = 123, + O_PLAYER_2 = 124, + O_PLAYER_3 = 125, + O_PLAYER_4 = 126, + O_PLAYER_5 = 127, + O_PLAYER_6 = 128, + O_PLAYER_7 = 129, + O_PLAYER_8 = 130, + O_PLAYER_9 = 131, + O_PLAYER_10 = 132, + O_PASSPORT_CLOSED = 133, + O_COMPASS_ITEM = 134, + O_PISTOL_ITEM = 135, + O_SHOTGUN_ITEM = 136, + O_MAGNUM_ITEM = 137, + O_UZI_ITEM = 138, + O_HARPOON_ITEM = 139, + O_M16_ITEM = 140, + O_GRENADE_ITEM = 141, + O_PISTOL_AMMO_ITEM = 142, + O_SHOTGUN_AMMO_ITEM = 143, + O_MAGNUM_AMMO_ITEM = 144, + O_UZI_AMMO_ITEM = 145, + O_HARPOON_AMMO_ITEM = 146, + O_M16_AMMO_ITEM = 147, + O_GRENADE_AMMO_ITEM = 148, + O_SMALL_MEDIPACK_ITEM = 149, + O_LARGE_MEDIPACK_ITEM = 150, + O_FLARES_ITEM = 151, + O_FLARE_ITEM = 152, + O_DETAIL_OPTION = 153, + O_SOUND_OPTION = 154, + O_CONTROL_OPTION = 155, + O_GAMMA_OPTION = 156, + O_PISTOL_OPTION = 157, + O_SHOTGUN_OPTION = 158, + O_MAGNUM_OPTION = 159, + O_UZI_OPTION = 160, + O_HARPOON_OPTION = 161, + O_M16_OPTION = 162, + O_GRENADE_OPTION = 163, + O_PISTOL_AMMO_OPTION = 164, + O_SHOTGUN_AMMO_OPTION = 165, + O_MAGNUM_AMMO_OPTION = 166, + O_UZI_AMMO_OPTION = 167, + O_HARPOON_AMMO_OPTION = 168, + O_M16_AMMO_OPTION = 169, + O_GRENADE_AMMO_OPTION = 170, + O_SMALL_MEDIPACK_OPTION = 171, + O_LARGE_MEDIPACK_OPTION = 172, + O_FLARES_OPTION = 173, + O_PUZZLE_ITEM_1 = 174, + O_PUZZLE_ITEM_2 = 175, + O_PUZZLE_ITEM_3 = 176, + O_PUZZLE_ITEM_4 = 177, + O_PUZZLE_OPTION_1 = 178, + O_PUZZLE_OPTION_2 = 179, + O_PUZZLE_OPTION_3 = 180, + O_PUZZLE_OPTION_4 = 181, + O_PUZZLE_HOLE_1 = 182, + O_PUZZLE_HOLE_2 = 183, + O_PUZZLE_HOLE_3 = 184, + O_PUZZLE_HOLE_4 = 185, + O_PUZZLE_DONE_1 = 186, + O_PUZZLE_DONE_2 = 187, + O_PUZZLE_DONE_3 = 188, + O_PUZZLE_DONE_4 = 189, + O_SECRET_1 = 190, + O_SECRET_2 = 191, + O_SECRET_3 = 192, + O_KEY_ITEM_1 = 193, + O_KEY_ITEM_2 = 194, + O_KEY_ITEM_3 = 195, + O_KEY_ITEM_4 = 196, + O_KEY_OPTION_1 = 197, + O_KEY_OPTION_2 = 198, + O_KEY_OPTION_3 = 199, + O_KEY_OPTION_4 = 200, + O_KEY_HOLE_1 = 201, + O_KEY_HOLE_2 = 202, + O_KEY_HOLE_3 = 203, + O_KEY_HOLE_4 = 204, + O_PICKUP_ITEM_1 = 205, + O_PICKUP_ITEM_2 = 206, + O_PICKUP_OPTION_1 = 207, + O_PICKUP_OPTION_2 = 208, + O_SPHERE_OF_DOOM_1 = 209, + O_SPHERE_OF_DOOM_2 = 210, + O_SPHERE_OF_DOOM_3 = 211, + O_ALARM_SOUND = 212, + O_BIRD_TWEETER_1 = 213, + O_DINO = 214, + O_BIRD_TWEETER_2 = 215, + O_CLOCK_CHIMES = 216, + O_DRAGON_BONES_1 = 217, + O_DRAGON_BONES_2 = 218, + O_DRAGON_BONES_3 = 219, + O_HOT_LIQUID = 220, + O_BOAT_BITS = 221, + O_MINE = 222, + O_INV_BACKGROUND = 223, + O_FX_RESERVED = 224, + O_GONG_BONGER = 225, + O_DETONATOR_1 = 226, + O_DETONATOR_2 = 227, + O_COPTER = 228, + O_EXPLOSION = 229, + O_SPLASH = 230, + O_BUBBLES = 231, + O_BUBBLE_EMITTER = 232, + O_BLOOD = 233, + O_DART_EFFECT = 234, + O_FLARE_FIRE = 235, + O_GLOW = 236, + O_GLOW_RESERVED = 237, + O_RICOCHET = 238, + O_TWINKLE = 239, + O_GUN_FLASH = 240, + O_M16_FLASH = 241, + O_BODY_PART = 242, + O_CAMERA_TARGET = 243, + O_WATERFALL = 244, + O_MISSILE_HARPOON = 245, + O_MISSILE_FLAME = 246, + O_MISSILE_KNIFE = 247, + O_GRENADE = 248, + O_HARPOON_BOLT = 249, + O_LAVA = 250, + O_LAVA_EMITTER = 251, + O_FLAME = 252, + O_FLAME_EMITTER = 253, + O_SKYBOX = 254, + O_ALPHABET = 255, + O_DYING_MONK = 256, + O_DING_DONG = 257, + O_LARA_ALARM = 258, + O_MINI_COPTER = 259, + O_WINSTON = 260, + O_ASSAULT_DIGITS = 261, + O_FINAL_LEVEL_COUNTER = 262, + O_CUT_SHOTGUN = 263, + O_EARTHQUAKE = 264, +#endif + O_NUMBER_OF, +} GAME_OBJECT_ID; diff --git a/meson.build b/meson.build index 7003da9..401f60f 100644 --- a/meson.build +++ b/meson.build @@ -52,6 +52,7 @@ sources = [ 'src/engine/audio_stream.c', 'src/engine/image.c', 'src/enum_str.c', + 'src/game/items.c', 'src/filesystem.c', 'src/json/bson_parse.c', 'src/json/bson_write.c', diff --git a/src/game/items.c b/src/game/items.c new file mode 100644 index 0000000..c4f2177 --- /dev/null +++ b/src/game/items.c @@ -0,0 +1,20 @@ +#include "game/items.h" + +#include "utils.h" + +void Item_TakeDamage( + ITEM_INFO *const item, const int16_t damage, const bool hit_status) +{ +#if TR_VERSION == 1 + if (item->hit_points == DONT_TARGET) { + return; + } +#endif + + item->hit_points -= damage; + CLAMPL(item->hit_points, 0); + + if (hit_status) { + item->hit_status = 1; + } +}