mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
inventory: limit max item quantities to fix crashing (#2554)
Resolves #2497.
This commit is contained in:
parent
3ece4b7b29
commit
3808fa7c28
10 changed files with 59 additions and 38 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "game/objects/vars.h"
|
||||
#include "memory.h"
|
||||
#include "strings.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_QTY 999999
|
||||
|
||||
typedef struct {
|
||||
int16_t shape;
|
||||
XYZ_16 pos;
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -69,9 +72,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.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;
|
||||
|
@ -79,7 +82,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
|
|||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -106,9 +109,9 @@ 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;
|
||||
|
@ -116,7 +119,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
|
|||
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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue