Skip to content

Commit

Permalink
inventory: limit item quantities to prevent crashes
Browse files Browse the repository at this point in the history
Resolves #2497.
  • Loading branch information
walkawayy committed Feb 26, 2025
1 parent 6836866 commit 2ae8a17
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 27 deletions.
1 change: 1 addition & 0 deletions docs/tr1/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr1-4.8.3...develop) - ××××-××-××
- added support for custom levels to use `disable_floor` in the gameflow, similar to TR2's Floating Islands (#2541)
- 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 @@ -4,6 +4,7 @@
- fixed smashed windows blocking enemy pathing after loading a save (#2535)
- 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 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 Down Expand Up @@ -41,6 +42,12 @@ void Inv_InsertItem(INVENTORY_ITEM *const inv_item)
source->count++;
}

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

bool Inv_RemoveItem(const GAME_OBJECT_ID obj_id)
{
const GAME_OBJECT_ID inv_obj_id = Inv_GetItemOption(obj_id);
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,13 +1,15 @@
#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);
GAME_OBJECT_ID Inv_GetItemOption(GAME_OBJECT_ID obj_id);
void Inv_InsertItem(INVENTORY_ITEM *inv_item);
void Inv_InsertAmmo(AMMO_INFO *weapon_ammo, int32_t qty);
bool Inv_RemoveItem(GAME_OBJECT_ID obj_id);
int32_t Inv_RequestItem(GAME_OBJECT_ID obj_id);
void Inv_ClearSelection(void);
Expand Down
2 changes: 2 additions & 0 deletions 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
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_InsertAmmo(&g_Lara.shotgun, SHOTGUN_AMMO_QTY);
}
g_Lara.shotgun.ammo += SHOTGUN_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.magnums, UZI_AMMO_QTY);
}
g_Lara.magnums.ammo += MAGNUM_AMMO_QTY;
Inv_InsertAmmo(&g_Lara.magnums, UZI_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_InsertAmmo(&g_Lara.uzis, UZI_AMMO_QTY);
}
g_Lara.uzis.ammo += UZI_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&g_Lara.magnums, UZI_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_InsertAmmo(&g_Lara.uzis, UZI_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_UziAmmo);
}
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_InsertAmmo(&g_Lara.shotgun_ammo, SHOTGUN_AMMO_QTY);
}
g_Lara.shotgun_ammo.ammo += SHOTGUN_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.magnum_ammo, MAGNUM_AMMO_QTY);
}
g_Lara.magnum_ammo.ammo += MAGNUM_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.uzi_ammo, UZI_AMMO_QTY);
}
g_Lara.uzi_ammo.ammo += UZI_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.harpoon_ammo, HARPOON_AMMO_QTY);
}
g_Lara.harpoon_ammo.ammo += HARPOON_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.m16_ammo, M16_AMMO_QTY);
}
g_Lara.m16_ammo.ammo += M16_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&g_Lara.grenade_ammo, GRENADE_AMMO_QTY);
}
g_Lara.grenade_ammo.ammo += GRENADE_AMMO_QTY;
Inv_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&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_InsertAmmo(&g_Lara.grenade_ammo, GRENADE_AMMO_QTY);
} else {
Inv_InsertItem(&g_InvRing_Item_GrenadeAmmo);
}
Expand Down

0 comments on commit 2ae8a17

Please # to comment.