diff --git a/CHANGELOG.md b/CHANGELOG.md index 35ae752f0..11a73d77a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - added case insensitive directory and file detection (#845) - added controller detection during runtime (#850) - added an option to allow cancelling Lara's ledge-swinging animation (#856) +- added an option to allow Lara to jump at any point while running, similar to TR2+ (#157) - changed screen resolution option to apply immediately (#114) - changed shaders to use GLSL 1.20 which should fix most issues with OpenGL 2.1 (#327, #685) - fixed sounds stopping instead of pausing if game sounds in inventory are disabled (#717) diff --git a/README.md b/README.md index 16e21ac65..2f28b9464 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,7 @@ Not all options are turned on by default. Refer to `Tomb1Main_ConfigTool.exe` fo - added ability to sidestep like in TR3 - added ability to jump-twist and somersault like in TR2+ - added ability to cancel ledge-swinging animation like in TR2+ +- added ability to jump at any point while running like in TR2+ - added ability to automatically walk to items when nearby - added a pause screen - added a choice whether to play NG or NG+ without having to play the entire game diff --git a/bin/cfg/Tomb1Main_gameflow.json5 b/bin/cfg/Tomb1Main_gameflow.json5 index 1a97f924a..19daa048d 100644 --- a/bin/cfg/Tomb1Main_gameflow.json5 +++ b/bin/cfg/Tomb1Main_gameflow.json5 @@ -41,6 +41,7 @@ "data/backpack.bin", "data/braid.bin", "data/lara_animations.bin", + "data/lara_jumping.bin", "data/uzi_sfx.bin", ], @@ -73,6 +74,7 @@ "data/braid.bin", "data/gym_textures.bin", "data/lara_animations.bin", + "data/lara_jumping.bin", ], // list of actions to execute when this level is played diff --git a/bin/cfg/Tomb1Main_gameflow_ub.json5 b/bin/cfg/Tomb1Main_gameflow_ub.json5 index 9d10664e1..9cd8e4162 100644 --- a/bin/cfg/Tomb1Main_gameflow_ub.json5 +++ b/bin/cfg/Tomb1Main_gameflow_ub.json5 @@ -14,6 +14,7 @@ "data/backpack.bin", "data/braid.bin", "data/lara_animations.bin", + "data/lara_jumping.bin", "data/uzi_sfx.bin", ], diff --git a/bin/data/lara_jumping.bin b/bin/data/lara_jumping.bin new file mode 100644 index 000000000..c245d76ed Binary files /dev/null and b/bin/data/lara_jumping.bin differ diff --git a/src/config.c b/src/config.c index 7d0b5913f..9fe27da57 100644 --- a/src/config.c +++ b/src/config.c @@ -229,6 +229,7 @@ bool Config_ReadFromJSON(const char *cfg_data) READ_INTEGER(camera_speed, 5); READ_BOOL(fix_texture_issues, true); READ_BOOL(enable_swing_cancel, true); + READ_BOOL(enable_tr2_jumping, false); CLAMP(g_Config.start_lara_hitpoints, 1, LARA_HITPOINTS); CLAMP(g_Config.fov_value, 30, 255); @@ -411,6 +412,7 @@ bool Config_Write(void) WRITE_INTEGER(camera_speed); WRITE_BOOL(fix_texture_issues); WRITE_BOOL(enable_swing_cancel); + WRITE_BOOL(enable_tr2_jumping); // User settings WRITE_BOOL(rendering.enable_bilinear_filter); diff --git a/src/config.h b/src/config.h index 541a78238..7a507083c 100644 --- a/src/config.h +++ b/src/config.h @@ -109,6 +109,7 @@ typedef struct { int32_t camera_speed; bool fix_texture_issues; bool enable_swing_cancel; + bool enable_tr2_jumping; struct { int32_t layout; diff --git a/src/game/inject.c b/src/game/inject.c index 25e81f4ce..1cd1e0144 100644 --- a/src/game/inject.c +++ b/src/game/inject.c @@ -14,11 +14,12 @@ #include #define INJECTION_MAGIC MKTAG('T', '1', 'M', 'J') -#define INJECTION_CURRENT_VERSION 2 +#define INJECTION_CURRENT_VERSION 3 typedef enum INJECTION_VERSION { INJ_VERSION_1 = 1, INJ_VERSION_2 = 2, + INJ_VERSION_3 = 3, } INJECTION_VERSION; typedef enum INJECTION_TYPE { @@ -28,6 +29,7 @@ typedef enum INJECTION_TYPE { INJ_UZI_SFX = 3, INJ_FLOOR_DATA = 4, INJ_LARA_ANIMS = 5, + INJ_LARA_JUMPS = 6, } INJECTION_TYPE; typedef struct INJECTION { @@ -100,6 +102,7 @@ static void Inject_TextureData( INJECTION *injection, LEVEL_INFO *level_info, int32_t page_base); static void Inject_MeshData(INJECTION *injection, LEVEL_INFO *level_info); static void Inject_AnimData(INJECTION *injection, LEVEL_INFO *level_info); +static void Inject_AnimRangeEdits(INJECTION *injection); static void Inject_ObjectData( INJECTION *injection, LEVEL_INFO *level_info, uint8_t *palette_map); static void Inject_SFXData(INJECTION *injection, LEVEL_INFO *level_info); @@ -193,6 +196,9 @@ static bool Inject_LoadFromFile(INJECTION *injection, const char *filename) case INJ_TEXTURE_FIX: injection->relevant = g_Config.fix_texture_issues; break; + case INJ_LARA_JUMPS: + injection->relevant = g_Config.enable_tr2_jumping; + break; default: injection->relevant = false; LOG_WARNING("%s is of unknown type %d", filename, injection->type); @@ -243,6 +249,12 @@ static bool Inject_LoadFromFile(INJECTION *injection, const char *filename) info->room_meshes = NULL; } + if (injection->version > INJ_VERSION_2) { + File_Read(&info->anim_range_edit_count, sizeof(int32_t), 1, fp); + } else { + info->anim_range_edit_count = 0; + } + m_Aggregate->texture_page_count += info->texture_page_count; m_Aggregate->texture_count += info->texture_count; m_Aggregate->sprite_info_count += info->sprite_info_count; @@ -300,6 +312,7 @@ bool Inject_AllInjections(LEVEL_INFO *level_info) Inject_FloorDataEdits(injection); Inject_RoomMeshEdits(injection); Inject_RoomDoorEdits(injection); + Inject_AnimRangeEdits(injection); // Realign base indices for the next injection. INJECTION_INFO *inj_info = injection->info; @@ -492,6 +505,72 @@ static void Inject_AnimData(INJECTION *injection, LEVEL_INFO *level_info) } } +static void Inject_AnimRangeEdits(INJECTION *injection) +{ + if (injection->version < INJ_VERSION_3) { + return; + } + + INJECTION_INFO *inj_info = injection->info; + MYFILE *fp = injection->fp; + + GAME_OBJECT_ID object_id; + int32_t edit_count; + int16_t anim_index; + int16_t change_index; + int16_t range_index; + int16_t low_frame; + int16_t high_frame; + + for (int i = 0; i < inj_info->anim_range_edit_count; i++) { + File_Read(&object_id, sizeof(int32_t), 1, fp); + File_Read(&anim_index, sizeof(int16_t), 1, fp); + File_Read(&edit_count, sizeof(int32_t), 1, fp); + + if (object_id < 0 || object_id >= O_NUMBER_OF) { + LOG_WARNING("Object %d is not recognised", object_id); + File_Skip(fp, edit_count * sizeof(int16_t) * 4); + continue; + } + + OBJECT_INFO *object = &g_Objects[object_id]; + if (!object->loaded) { + LOG_WARNING("Object %d is not loaded", object_id); + File_Skip(fp, edit_count * sizeof(int16_t) * 4); + continue; + } + + ANIM_STRUCT *anim = &g_Anims[object->anim_index + anim_index]; + for (int j = 0; j < edit_count; j++) { + File_Read(&change_index, sizeof(int16_t), 1, fp); + File_Read(&range_index, sizeof(int16_t), 1, fp); + File_Read(&low_frame, sizeof(int16_t), 1, fp); + File_Read(&high_frame, sizeof(int16_t), 1, fp); + + if (change_index >= anim->number_changes) { + LOG_WARNING( + "Change %d is invalid for animation %d", change_index, + anim_index); + continue; + } + ANIM_CHANGE_STRUCT *change = + &g_AnimChanges[anim->change_index + change_index]; + + if (range_index >= change->number_ranges) { + LOG_WARNING( + "Range %d is invalid for change %d, animation %d", + range_index, change_index, anim_index); + continue; + } + ANIM_RANGE_STRUCT *range = + &g_AnimRanges[change->range_index + range_index]; + + range->start_frame = low_frame; + range->end_frame = high_frame; + } + } +} + static void Inject_ObjectData( INJECTION *injection, LEVEL_INFO *level_info, uint8_t *palette_map) { diff --git a/src/game/inject.h b/src/game/inject.h index 1321f30d6..037ecbcf9 100644 --- a/src/game/inject.h +++ b/src/game/inject.h @@ -35,6 +35,7 @@ typedef struct INJECTION_INFO { INJECTION_ROOM_MESH *room_meshes; int32_t room_mesh_edit_count; int32_t room_door_edit_count; + int32_t anim_range_edit_count; } INJECTION_INFO; bool Inject_Init( diff --git a/src/game/lara/lara_state.c b/src/game/lara/lara_state.c index 568420026..6c1f5153e 100644 --- a/src/game/lara/lara_state.c +++ b/src/game/lara/lara_state.c @@ -11,6 +11,7 @@ #include "global/vars.h" #include "math/math.h" +#include #include void (*g_LaraStateRoutines[])(ITEM_INFO *item, COLL_INFO *coll) = { @@ -80,6 +81,8 @@ void Lara_State_Walk(ITEM_INFO *item, COLL_INFO *coll) void Lara_State_Run(ITEM_INFO *item, COLL_INFO *coll) { + static bool jump_permitted = true; + if (item->hit_points <= 0) { item->goal_anim_state = LS_DEATH; return; @@ -112,7 +115,21 @@ void Lara_State_Run(ITEM_INFO *item, COLL_INFO *coll) } } - if (g_Input.jump && !item->gravity_status) { + if (g_Config.enable_tr2_jumping) { + int16_t anim = + item->anim_number - g_Objects[item->object_number].anim_index; + if (anim == LA_RUN_START) { + jump_permitted = false; + } else if (anim == LA_RUN) { + if (item->frame_number == LF_JUMP_READY) { + jump_permitted = true; + } + } else { + jump_permitted = true; + } + } + + if (g_Input.jump && jump_permitted && !item->gravity_status) { item->goal_anim_state = LS_JUMP_FORWARD; } else if (g_Input.forward) { item->goal_anim_state = g_Input.slow ? LS_WALK : LS_RUN; diff --git a/src/global/types.h b/src/global/types.h index 24a3dd8cc..91d51bd24 100644 --- a/src/global/types.h +++ b/src/global/types.h @@ -542,6 +542,7 @@ typedef enum MUSIC_TRACK_ID { } MUSIC_TRACK_ID; typedef enum LARA_ANIMATION_FRAME { + LF_JUMP_READY = 4, LF_PICKUPSCION = 44, LF_STOPHANG = 448, LF_FASTFALL = 481, @@ -574,7 +575,9 @@ typedef enum LARA_GUN_ANIMATION_FRAME { } LARA_GUN_ANIMATION_FRAME; typedef enum LARA_ANIMATION { + LA_RUN = 0, LA_WALK_FORWARD = 1, + LA_RUN_START = 6, LA_WALK_BACK = 40, LA_VAULT_12 = 50, LA_VAULT_34 = 42, diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json index 1cef15b65..10431cd58 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json @@ -99,6 +99,10 @@ "Title": "Swing cancels", "Description": "Allows Lara's ledge-swinging animation to be cancelled by letting go and quickly grabbing again, similar to TR2+." }, + "enable_tr2_jumping": { + "Title": "Responsive jumping", + "Description": "Allows Lara to jump at any point while running, similar to TR2+." + }, "enable_numeric_keys": { "Title": "Numeric key quick item use", "Description": "Enables quick weapon draws and medipack usage.\n- 1: Draw pistols\n- 2: Draw shotgun\n- 3: Draw magnums\n- 4: Draw Uzis\n- 8: Use small medipack\n- 9: Use large medipack" diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/es.json b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/es.json index ad6607878..7b3d8a4e8 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/es.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/es.json @@ -187,6 +187,10 @@ "Title": "Cancelación de balanceo", "Description": "Permite que la animación de balanceo de la repisa de Lara se cancele soltándola y agarrándola rápidamente de nuevo, similar a TR2+." }, + "enable_tr2_jumping": { + "Title": "Salto sensible", + "Description": "Permite que Lara salte en cualquier punto mientras corre, similar a TR2+." + }, "enable_music_in_inventory": { "Description": "Permite que los sonidos del juego continúen sonando en la pantalla de inventario.", "Title": "Habilitar sonidos de juegos en el inventario" diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json index 8edcc647a..07e41ecf9 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json @@ -99,6 +99,10 @@ "Title": "Annulation du balancement", "Description": "Permet d'annuler l'animation de balancement à un rebord de Lara en relâchant prise et en saisissant rapidement à nouveau, similaire à TR2+." }, + "enable_tr2_jumping": { + "Title": "Saut réactif", + "Description": "Permet à Lara de sauter à tout moment pendant la course, similaire à TR2+." + }, "enable_numeric_keys": { "Title": "Touches rapide numériques", "Description": "Active les touches rapides numériques en haut du clavier, en raccourci d'équipement d'armes ou d'utilisation de soins.\n- 1: Pistolets\n- 2: Fusil à pompe\n- 3: Magnums\n- 4: Uzis\n- 8: Utiliser une petite trousse de soin\n- 9: Utiliser une grande trousse de soin" diff --git a/tools/config/Tomb1Main_ConfigTool/Resources/specification.json b/tools/config/Tomb1Main_ConfigTool/Resources/specification.json index 2eab42a11..acb136fb4 100644 --- a/tools/config/Tomb1Main_ConfigTool/Resources/specification.json +++ b/tools/config/Tomb1Main_ConfigTool/Resources/specification.json @@ -67,6 +67,11 @@ "DataType": "Bool", "DefaultValue": true }, + { + "Field": "enable_tr2_jumping", + "DataType": "Bool", + "DefaultValue": false + }, { "Field": "enable_numeric_keys", "DataType": "Bool",