Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lara: add responsive jumping #864

Merged
merged 4 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions bin/cfg/Tomb1Main_gameflow.json5
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"data/backpack.bin",
"data/braid.bin",
"data/lara_animations.bin",
"data/lara_jumping.bin",
"data/uzi_sfx.bin",
],

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions bin/cfg/Tomb1Main_gameflow_ub.json5
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"data/backpack.bin",
"data/braid.bin",
"data/lara_animations.bin",
"data/lara_jumping.bin",
"data/uzi_sfx.bin",
],

Expand Down
Binary file added bin/data/lara_jumping.bin
Binary file not shown.
2 changes: 2 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/game/game/game_demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ void Game_Demo(void)
// changing the controls affects negatively the original game demo data,
// so temporarily turn off all the T1M enhancements
int8_t old_enhanced_look = g_Config.enable_enhanced_look;
int8_t old_tr2_jumping = g_Config.enable_tr2_jumping;
g_Config.enable_enhanced_look = 0;
g_Config.enable_tr2_jumping = 0;

if (Level_Initialise(m_DemoLevel)) {
Game_Demo_LoadLaraPos();
Expand All @@ -140,4 +142,5 @@ void Game_Demo(void)
}

g_Config.enable_enhanced_look = old_enhanced_look;
g_Config.enable_tr2_jumping = old_tr2_jumping;
}
81 changes: 80 additions & 1 deletion src/game/inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
#include <stddef.h>

#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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down
1 change: 1 addition & 0 deletions src/game/inject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
15 changes: 14 additions & 1 deletion src/game/lara/lara_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "global/vars.h"
#include "math/math.h"

#include <stdbool.h>
#include <stdint.h>

void (*g_LaraStateRoutines[])(ITEM_INFO *item, COLL_INFO *coll) = {
Expand All @@ -36,6 +37,8 @@ void (*g_LaraStateRoutines[])(ITEM_INFO *item, COLL_INFO *coll) = {
Lara_State_Twist,
};

static bool m_JumpPermitted = true;

static int16_t Lara_FloorFront(ITEM_INFO *item, PHD_ANGLE ang, int32_t dist);

static int16_t Lara_FloorFront(ITEM_INFO *item, PHD_ANGLE ang, int32_t dist)
Expand Down Expand Up @@ -112,7 +115,17 @@ 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) {
m_JumpPermitted = false;
} else if (anim != LA_RUN || item->frame_number == LF_JUMP_READY) {
m_JumpPermitted = true;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this boolean logic can be simplified, I'll follow up tomorrow

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this work?

    if (g_Config.enable_tr2_jumping) {
        int16_t anim = item->anim_number - g_Objects[item->object_number].anim_index;
        if (anim == LA_RUN_START) {
            m_JumpPermitted = false;
        } else if (anim != LA_RUN || item->frame_number == LF_JUMP_READY) {
            m_JumpPermitted = true;
        }
    }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks much better - I'll test it out tomorrow. Thanks.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An ideal outcome would be to forgo introducing a new global variable and set it always in the local scope. But I don't think that's possible since frame number resets to 0 and cycles, so even comparing it with >= will work in an unintended way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is a shame but thankfully this is a short snippet of code now so looks much tidier. I've tested it out and all is good 👍


if (g_Input.jump && m_JumpPermitted && !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;
Expand Down
3 changes: 3 additions & 0 deletions src/global/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions tools/config/Tomb1Main_ConfigTool/Resources/Lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions tools/config/Tomb1Main_ConfigTool/Resources/Lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions tools/config/Tomb1Main_ConfigTool/Resources/Lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
"DataType": "Bool",
"DefaultValue": true
},
{
"Field": "enable_tr2_jumping",
"DataType": "Bool",
"DefaultValue": false
},
{
"Field": "enable_numeric_keys",
"DataType": "Bool",
Expand Down