Skip to content

Commit

Permalink
inventory: limit max item quantities to fix crashing (#2554)
Browse files Browse the repository at this point in the history
Resolves #2497.
  • Loading branch information
walkawayy authored Mar 1, 2025
1 parent 3ece4b7 commit 3808fa7
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 38 deletions.
1 change: 1 addition & 0 deletions docs/tr1/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- changed the Controls screen to hide the reset and unbind texts when changing a key (#2103)
- fixed several instances of the camera going out of bounds (#1034)
- fixed the bear AI fix option being applied in the Vilcabamba demo (#2559, regression from 4.8)
- fixed extremely large item quantities crashing the game (#2497, regression from 0.3)

## [4.8.3](https://github.com/LostArtefacts/TRX/compare/tr1-4.8.2...tr1-4.8.3) - 2025-02-17
- fixed some of Lara's speech in the gym not playing in response to player action (#2514, regression from 4.8)
Expand Down
1 change: 1 addition & 0 deletions docs/tr2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- fixed a rare issue whereby Lara would be unable to move after disposing a flare (#2545, regression from 0.9)
- fixed flare pickups only adding one flare to Lara's inventory rather than six (#2551, regression from 0.9)
- fixed play any level causing the game to hang when no gym level is present (#2560, regression from 0.9)
- fixed extremely large item quantities crashing the game (#2497, regression from 0.3)

## [0.9.2](https://github.com/LostArtefacts/TRX/compare/tr2-0.9.1...tr2-0.9.2) - 2025-02-19
- fixed secret rewards not handed out after loading a save (#2528, regression from 0.8)
Expand Down
2 changes: 2 additions & 0 deletions src/libtrx/game/console/cmd/give_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "game/objects/vars.h"
#include "memory.h"
#include "strings.h"
#include "utils.h"

#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -49,6 +50,7 @@ static COMMAND_RESULT M_Entrypoint(const COMMAND_CONTEXT *const ctx)
if (args == nullptr) {
return CR_BAD_INVOCATION;
}
CLAMPG(num, MAX_QTY);
args++;
}

Expand Down
7 changes: 7 additions & 0 deletions src/libtrx/game/inventory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "game/inventory_ring/vars.h"
#include "game/objects/vars.h"
#include "utils.h"

bool Inv_AddItemNTimes(const GAME_OBJECT_ID obj_id, const int32_t qty)
{
Expand All @@ -12,6 +13,12 @@ bool Inv_AddItemNTimes(const GAME_OBJECT_ID obj_id, const int32_t qty)
return result;
}

void Inv_AddAmmo(AMMO_INFO *const weapon_ammo, int32_t qty)
{
weapon_ammo->ammo += qty;
CLAMPG(weapon_ammo->ammo, MAX_QTY);
}

GAME_OBJECT_ID Inv_GetItemOption(const GAME_OBJECT_ID obj_id)
{
if (Object_IsType(obj_id, g_InvObjects)) {
Expand Down
2 changes: 2 additions & 0 deletions src/libtrx/include/libtrx/game/inventory.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#pragma once

#include "inventory_ring/types.h"
#include "lara/types.h"
#include "objects/ids.h"

#include <stdint.h>

bool Inv_AddItemNTimes(GAME_OBJECT_ID obj_id, int32_t qty);
void Inv_AddAmmo(AMMO_INFO *weapon_ammo, int32_t qty);
GAME_OBJECT_ID Inv_GetItemOption(GAME_OBJECT_ID obj_id);
void Inv_InsertItem(INVENTORY_ITEM *inv_item);
bool Inv_RemoveItem(GAME_OBJECT_ID obj_id);
Expand Down
4 changes: 3 additions & 1 deletion src/libtrx/include/libtrx/game/inventory_ring/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <stdint.h>

#define MAX_QTY 999999

typedef struct {
int16_t shape;
XYZ_16 pos;
Expand Down Expand Up @@ -74,7 +76,7 @@ typedef struct {
typedef struct {
int16_t current;
int16_t count;
int16_t qtys[24];
int32_t qtys[24];
INVENTORY_ITEM *items[24];
} INV_RING_SOURCE;

Expand Down
21 changes: 12 additions & 9 deletions src/tr1/game/inventory.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "global/types.h"
#include "global/vars.h"

#include <libtrx/utils.h>

#include <stdint.h>

bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
Expand All @@ -32,6 +34,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
for (int32_t i = 0; i < source->count; i++) {
if (source->items[i]->object_id == inv_obj_id) {
source->qtys[i]++;
CLAMPG(source->qtys[i], MAX_QTY);
return true;
}
}
Expand All @@ -47,9 +50,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_SHOTGUN_OPTION:
for (int32_t i = Inv_RequestItem(O_SG_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_SG_AMMO_ITEM);
g_Lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
Inv_AddAmmo(&g_Lara.shotgun, SHOTGUN_AMMO_QTY);
}
g_Lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
Inv_AddAmmo(&g_Lara.shotgun, SHOTGUN_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Shotgun);
Item_GlobalReplace(O_SHOTGUN_ITEM, O_SG_AMMO_ITEM);
return false;
Expand All @@ -58,9 +61,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_MAGNUM_OPTION:
for (int32_t i = Inv_RequestItem(O_MAG_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_MAG_AMMO_ITEM);
g_Lara.magnums.ammo += MAGNUM_AMMO_QTY;
Inv_AddAmmo(&g_Lara.magnums, MAGNUM_AMMO_QTY);
}
g_Lara.magnums.ammo += MAGNUM_AMMO_QTY;
Inv_AddAmmo(&g_Lara.magnums, MAGNUM_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Magnum);
Item_GlobalReplace(O_MAGNUM_ITEM, O_MAG_AMMO_ITEM);
return false;
Expand All @@ -69,17 +72,17 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_UZI_OPTION:
for (int32_t i = Inv_RequestItem(O_UZI_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_UZI_AMMO_ITEM);
g_Lara.uzis.ammo += UZI_AMMO_QTY;
Inv_AddAmmo(&g_Lara.uzis, UZI_AMMO_QTY);
}
g_Lara.uzis.ammo += UZI_AMMO_QTY;
Inv_AddAmmo(&g_Lara.uzis, UZI_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Uzi);
Item_GlobalReplace(O_UZI_ITEM, O_UZI_AMMO_ITEM);
return false;

case O_SG_AMMO_ITEM:
case O_SG_AMMO_OPTION:
if (Inv_RequestItem(O_SHOTGUN_ITEM)) {
g_Lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
Inv_AddAmmo(&g_Lara.shotgun, SHOTGUN_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_ShotgunAmmo);
}
Expand All @@ -88,7 +91,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_MAG_AMMO_ITEM:
case O_MAG_AMMO_OPTION:
if (Inv_RequestItem(O_MAGNUM_ITEM)) {
g_Lara.magnums.ammo += MAGNUM_AMMO_QTY;
Inv_AddAmmo(&g_Lara.magnums, MAGNUM_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_MagnumAmmo);
}
Expand All @@ -97,7 +100,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_UZI_AMMO_ITEM:
case O_UZI_AMMO_OPTION:
if (Inv_RequestItem(O_UZI_ITEM)) {
g_Lara.uzis.ammo += UZI_AMMO_QTY;
Inv_AddAmmo(&g_Lara.uzis, UZI_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_UziAmmo);
}
Expand Down
8 changes: 4 additions & 4 deletions src/tr1/game/overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,18 +622,18 @@ static void M_DrawAmmoInfo(void)
return;
}

char ammo_string[80] = "";
char ammo_string[128] = "";
switch (g_Lara.gun_type) {
case LGT_PISTOLS:
return;
case LGT_SHOTGUN:
sprintf(ammo_string, "%5d A", g_Lara.shotgun.ammo / SHOTGUN_AMMO_CLIP);
sprintf(ammo_string, "%6d A", g_Lara.shotgun.ammo / SHOTGUN_AMMO_CLIP);
break;
case LGT_UZIS:
sprintf(ammo_string, "%5d C", g_Lara.uzis.ammo);
sprintf(ammo_string, "%6d C", g_Lara.uzis.ammo);
break;
case LGT_MAGNUMS:
sprintf(ammo_string, "%5d B", g_Lara.magnums.ammo);
sprintf(ammo_string, "%6d B", g_Lara.magnums.ammo);
break;
default:
return;
Expand Down
39 changes: 21 additions & 18 deletions src/tr2/game/inventory.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "game/objects/vars.h"
#include "global/vars.h"

#include <libtrx/utils.h>

bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
{
const GAME_OBJECT_ID inv_obj_id = Inv_GetItemOption(obj_id);
Expand All @@ -21,6 +23,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
const int32_t qty =
obj_id == O_FLARES_ITEM ? FLARE_AMMO_QTY : 1;
source->qtys[i] += qty;
CLAMPG(source->qtys[i], MAX_QTY);
return true;
}
}
Expand All @@ -45,9 +48,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_SHOTGUN_OPTION:
for (int32_t i = Inv_RequestItem(O_SHOTGUN_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_SHOTGUN_AMMO_ITEM);
g_Lara.shotgun_ammo.ammo += SHOTGUN_AMMO_QTY;
Inv_AddAmmo(&g_Lara.shotgun_ammo, SHOTGUN_AMMO_QTY);
}
g_Lara.shotgun_ammo.ammo += SHOTGUN_AMMO_QTY;
Inv_AddAmmo(&g_Lara.shotgun_ammo, SHOTGUN_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Shotgun);
if (g_Lara.last_gun_type == LGT_UNARMED) {
g_Lara.last_gun_type = LGT_SHOTGUN;
Expand All @@ -62,9 +65,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_MAGNUM_OPTION:
for (int32_t i = Inv_RequestItem(O_MAGNUM_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_MAGNUM_AMMO_ITEM);
g_Lara.magnum_ammo.ammo += MAGNUM_AMMO_QTY;
Inv_AddAmmo(&g_Lara.magnum_ammo, MAGNUM_AMMO_QTY);
}
g_Lara.magnum_ammo.ammo += MAGNUM_AMMO_QTY;
Inv_AddAmmo(&g_Lara.magnum_ammo, MAGNUM_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Magnums);
Item_GlobalReplace(O_MAGNUM_ITEM, O_MAGNUM_AMMO_ITEM);
return false;
Expand All @@ -73,9 +76,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_UZI_OPTION:
for (int32_t i = Inv_RequestItem(O_UZI_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_UZI_AMMO_ITEM);
g_Lara.uzi_ammo.ammo += UZI_AMMO_QTY;
Inv_AddAmmo(&g_Lara.uzi_ammo, UZI_AMMO_QTY);
}
g_Lara.uzi_ammo.ammo += UZI_AMMO_QTY;
Inv_AddAmmo(&g_Lara.uzi_ammo, UZI_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Uzis);
Item_GlobalReplace(O_UZI_ITEM, O_UZI_AMMO_ITEM);
return false;
Expand All @@ -84,9 +87,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_HARPOON_OPTION:
for (int32_t i = Inv_RequestItem(O_HARPOON_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_HARPOON_AMMO_ITEM);
g_Lara.harpoon_ammo.ammo += HARPOON_AMMO_QTY;
Inv_AddAmmo(&g_Lara.harpoon_ammo, HARPOON_AMMO_QTY);
}
g_Lara.harpoon_ammo.ammo += HARPOON_AMMO_QTY;
Inv_AddAmmo(&g_Lara.harpoon_ammo, HARPOON_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Harpoon);
Item_GlobalReplace(O_HARPOON_ITEM, O_HARPOON_AMMO_ITEM);
return false;
Expand All @@ -95,9 +98,9 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_M16_OPTION:
for (int32_t i = Inv_RequestItem(O_M16_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_M16_AMMO_ITEM);
g_Lara.m16_ammo.ammo += M16_AMMO_QTY;
Inv_AddAmmo(&g_Lara.m16_ammo, M16_AMMO_QTY);
}
g_Lara.m16_ammo.ammo += M16_AMMO_QTY;
Inv_AddAmmo(&g_Lara.m16_ammo, M16_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_M16);
Item_GlobalReplace(O_M16_ITEM, O_M16_AMMO_ITEM);
return false;
Expand All @@ -106,17 +109,17 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_GRENADE_OPTION:
for (int32_t i = Inv_RequestItem(O_GRENADE_AMMO_ITEM); i > 0; i--) {
Inv_RemoveItem(O_GRENADE_AMMO_ITEM);
g_Lara.grenade_ammo.ammo += GRENADE_AMMO_QTY;
Inv_AddAmmo(&g_Lara.grenade_ammo, GRENADE_AMMO_QTY);
}
g_Lara.grenade_ammo.ammo += GRENADE_AMMO_QTY;
Inv_AddAmmo(&g_Lara.grenade_ammo, GRENADE_AMMO_QTY);
Inv_InsertItem(&g_InvRing_Item_Grenade);
Item_GlobalReplace(O_GRENADE_ITEM, O_GRENADE_AMMO_ITEM);
return false;

case O_SHOTGUN_AMMO_ITEM:
case O_SHOTGUN_AMMO_OPTION:
if (Inv_RequestItem(O_SHOTGUN_ITEM)) {
g_Lara.shotgun_ammo.ammo += 12;
Inv_AddAmmo(&g_Lara.shotgun_ammo, SHOTGUN_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_ShotgunAmmo);
}
Expand All @@ -125,7 +128,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_MAGNUM_AMMO_ITEM:
case O_MAGNUM_AMMO_OPTION:
if (Inv_RequestItem(O_MAGNUM_ITEM)) {
g_Lara.magnum_ammo.ammo += 40;
Inv_AddAmmo(&g_Lara.magnum_ammo, MAGNUM_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_MagnumAmmo);
}
Expand All @@ -134,7 +137,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_UZI_AMMO_ITEM:
case O_UZI_AMMO_OPTION:
if (Inv_RequestItem(O_UZI_ITEM)) {
g_Lara.uzi_ammo.ammo += 80;
Inv_AddAmmo(&g_Lara.uzi_ammo, UZI_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_UziAmmo);
}
Expand All @@ -143,7 +146,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_HARPOON_AMMO_ITEM:
case O_HARPOON_AMMO_OPTION:
if (Inv_RequestItem(O_HARPOON_ITEM)) {
g_Lara.harpoon_ammo.ammo += 3;
Inv_AddAmmo(&g_Lara.harpoon_ammo, HARPOON_AMMO_CLIP);
} else {
Inv_InsertItem(&g_InvRing_Item_HarpoonAmmo);
}
Expand All @@ -152,7 +155,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_M16_AMMO_ITEM:
case O_M16_AMMO_OPTION:
if (Inv_RequestItem(O_M16_ITEM)) {
g_Lara.m16_ammo.ammo += 40;
Inv_AddAmmo(&g_Lara.m16_ammo, M16_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_M16Ammo);
}
Expand All @@ -161,7 +164,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
case O_GRENADE_AMMO_ITEM:
case O_GRENADE_AMMO_OPTION:
if (Inv_RequestItem(O_GRENADE_ITEM)) {
g_Lara.grenade_ammo.ammo += 2;
Inv_AddAmmo(&g_Lara.grenade_ammo, GRENADE_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_GrenadeAmmo);
}
Expand Down
12 changes: 6 additions & 6 deletions src/tr2/game/overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,27 +266,27 @@ static void M_DrawAmmoInfo(void)
char buffer[128] = "";
switch (g_Lara.gun_type) {
case LGT_MAGNUMS:
sprintf(buffer, "%5d", g_Lara.magnum_ammo.ammo);
sprintf(buffer, "%6d", g_Lara.magnum_ammo.ammo);
break;

case LGT_UZIS:
sprintf(buffer, "%5d", g_Lara.uzi_ammo.ammo);
sprintf(buffer, "%6d", g_Lara.uzi_ammo.ammo);
break;

case LGT_SHOTGUN:
sprintf(buffer, "%5d", g_Lara.shotgun_ammo.ammo / 6);
sprintf(buffer, "%6d", g_Lara.shotgun_ammo.ammo / 6);
break;

case LGT_M16:
sprintf(buffer, "%5d", g_Lara.m16_ammo.ammo);
sprintf(buffer, "%6d", g_Lara.m16_ammo.ammo);
break;

case LGT_GRENADE:
sprintf(buffer, "%5d", g_Lara.grenade_ammo.ammo);
sprintf(buffer, "%6d", g_Lara.grenade_ammo.ammo);
break;

case LGT_HARPOON:
sprintf(buffer, "%5d", g_Lara.harpoon_ammo.ammo);
sprintf(buffer, "%6d", g_Lara.harpoon_ammo.ammo);
break;

default:
Expand Down

0 comments on commit 3808fa7

Please sign in to comment.