Backported HOOK_ADJUSTFID from 4.2

This commit is contained in:
NovaRain
2021-01-29 23:03:26 +08:00
parent 87af67346e
commit 21b88c3cf0
11 changed files with 178 additions and 95 deletions
+1
View File
@@ -51,6 +51,7 @@
#define HOOK_WITHINPERCEPTION (23) #define HOOK_WITHINPERCEPTION (23)
#define HOOK_INVENTORYMOVE (24) #define HOOK_INVENTORYMOVE (24)
#define HOOK_INVENWIELD (25) #define HOOK_INVENWIELD (25)
#define HOOK_ADJUSTFID (26)
#define HOOK_GAMEMODECHANGE (31) #define HOOK_GAMEMODECHANGE (31)
//Valid arguments to list_begin //Valid arguments to list_begin
+14
View File
@@ -465,6 +465,20 @@ int ret0 - overrides hard-coded handler (-1 - use engine handler, any other
------------------------------------------- -------------------------------------------
HOOK_ADJUSTFID (hs_adjustfid.int)
Runs after calculating character figure FID on the inventory screen, whenever the game decides that character appearance might change.
Also happens on other screens, like barter.
NOTE: FID has following format: 0x0ABBCDDD, where A is object type, BB - animation code (always 0 in this case), C - weapon code, DDD - FRM index in LST file.
int arg0 - the vanilla FID calculated by the engine according to critter base FID and armor/weapon being used
int arg1 - the modified FID calculated by the internal sfall code (like Hero Appearance Mod)
int ret0 - overrides the calculated FID with provided value
-------------------------------------------
HOOK_GAMEMODECHANGE (hs_gamemodechange.int) HOOK_GAMEMODECHANGE (hs_gamemodechange.int)
Runs once every time when the game mode was changed, like opening/closing the inventory, character screen, pipboy, etc. Runs once every time when the game mode was changed, like opening/closing the inventory, character screen, pipboy, etc.
+1
View File
@@ -552,6 +552,7 @@ FUNC(win_register_button_disable_, 0x4D8674)
FUNC(win_register_button_sound_func_, 0x4D87F8) FUNC(win_register_button_sound_func_, 0x4D87F8)
FUNC(win_show_, 0x4D6DAC) FUNC(win_show_, 0x4D6DAC)
FUNC(win_width_, 0x4D7918) FUNC(win_width_, 0x4D7918)
FUNC(windowCheckRegion_, 0x4B6858)
FUNC(windowDisplayBuf_, 0x4B8EF0) FUNC(windowDisplayBuf_, 0x4B8EF0)
FUNC(windowDisplayTransBuf_, 0x4B8F64) FUNC(windowDisplayTransBuf_, 0x4B8F64)
FUNC(windowGetBuffer_, 0x4B82DC) FUNC(windowGetBuffer_, 0x4B82DC)
+1
View File
@@ -118,6 +118,7 @@ WRAP_WATCOM_FUNC2(long, interpretFindProcedure, TProgram*, scriptPtr, const char
WRAP_WATCOM_FUNC1(DWORD, interpretPopShort, TProgram*, scriptPtr) // Pops value type from Data stack (must be followed by InterpretPopLong) WRAP_WATCOM_FUNC1(DWORD, interpretPopShort, TProgram*, scriptPtr) // Pops value type from Data stack (must be followed by InterpretPopLong)
WRAP_WATCOM_FUNC1(DWORD, interpretPopLong, TProgram*, scriptPtr) // Pops value from Data stack (must be preceded by InterpretPopShort) WRAP_WATCOM_FUNC1(DWORD, interpretPopLong, TProgram*, scriptPtr) // Pops value from Data stack (must be preceded by InterpretPopShort)
WRAP_WATCOM_FUNC2(long, intface_get_attack, DWORD*, hitMode, DWORD*, isSecondary) WRAP_WATCOM_FUNC2(long, intface_get_attack, DWORD*, hitMode, DWORD*, isSecondary)
WRAP_WATCOM_FUNC0(long, intface_is_item_right_hand)
WRAP_WATCOM_FUNC0(long, intface_is_hidden) WRAP_WATCOM_FUNC0(long, intface_is_hidden)
WRAP_WATCOM_FUNC0(void, intface_redraw) // Redraws the main game interface windows (useful after changing some data like active hand, etc.) WRAP_WATCOM_FUNC0(void, intface_redraw) // Redraws the main game interface windows (useful after changing some data like active hand, etc.)
WRAP_WATCOM_FUNC0(void, intface_toggle_item_state) WRAP_WATCOM_FUNC0(void, intface_toggle_item_state)
+42 -81
View File
@@ -20,6 +20,7 @@
#include "main.h" #include "main.h"
#include "FalloutEngine.h" #include "FalloutEngine.h"
#include "Inventory.h"
#include "LoadGameHook.h" #include "LoadGameHook.h"
#include "LoadOrder.h" #include "LoadOrder.h"
#include "Message.h" #include "Message.h"
@@ -266,21 +267,12 @@ static void __declspec(naked) AdjustHeroBaseArt() {
} }
// adjust armor art if num below hero art range // adjust armor art if num below hero art range
static void __declspec(naked) AdjustHeroArmorArt() { void __stdcall AdjustHeroArmorArt(DWORD fid) {
__asm { if ((fid & 0xF000000) == (OBJ_TYPE_CRITTER << 24) && !PartyControl_IsNpcControlled()) {
pop ebx; // get ret addr DWORD fidBase = fid & 0xFFF;
mov dword ptr ss:[esp], ebx; // reinsert ret addr in old (push 0) if (fidBase <= critterListSize) {
xor ebx, ebx; *ptr_i_fid += critterListSize;
push 0; }
call art_id_; // call load frm func
mov dx, ax;
and dh, 0x0F; // mask out current weapon flag
cmp edx, critterListSize; // check if critter art in PC range
jg endFunc;
add eax, critterListSize; // shift critter art index up into hero range
endFunc:
//mov dword ptr ds:[FO_VAR_i_fid], eax;
retn;
} }
} }
@@ -367,76 +359,45 @@ static void DrawPC() {
} }
// scan inventory items for armor and weapons currently being worn or wielded and setup matching FrmID for PC // scan inventory items for armor and weapons currently being worn or wielded and setup matching FrmID for PC
void __stdcall RefreshPCArt() { void UpdateHeroArt() {
__asm { TGameObj* iD = *ptr_inven_dude;
call proto_dude_update_gender_; // refresh PC base model art TGameObj* iR = *ptr_i_rhand;
TGameObj* iL = *ptr_i_lhand;
TGameObj* iW = *ptr_i_worn;
push dword ptr ds:[FO_VAR_inven_dude]; *ptr_i_rhand = 0;
push dword ptr ds:[FO_VAR_i_rhand]; // item2 *ptr_i_lhand = 0;
push dword ptr ds:[FO_VAR_i_lhand]; // item1 *ptr_i_worn = 0;
push dword ptr ds:[FO_VAR_i_worn]; // armor
mov eax, dword ptr ds:[FO_VAR_obj_dude]; // PC state struct *ptr_inven_dude = *ptr_obj_dude;
mov dword ptr ds:[FO_VAR_inven_dude], eax; // inventory temp pointer to PC state struct int invenSize = (*ptr_obj_dude)->invenSize;
mov eax, dword ptr ds:[FO_VAR_inven_dude]; //*ptr_pud = invenSize;
lea edx, dword ptr ds:[eax + 0x2C];
mov dword ptr ds:[FO_VAR_pud], edx; // PC inventory
xor eax, eax; for (int itemNum = 0; itemNum < invenSize; itemNum++) {
xor edx, edx; // itemListOffset TGameObj* item = (*ptr_obj_dude)->invenTable[itemNum].object; // PC inventory item list + itemListOffset
xor ebx, ebx; // itemNum
mov dword ptr ds:[FO_VAR_i_rhand], eax; // item2 if (item->flags & ObjectFlag::Right_Hand) {
mov dword ptr ds:[FO_VAR_i_lhand], eax; // item1 *ptr_i_rhand = item;
mov dword ptr ds:[FO_VAR_i_worn], eax; // armor } else if (item->flags & ObjectFlag::Left_Hand) {
jmp LoopStart; *ptr_i_lhand = item;
} else if (item->flags & ObjectFlag::Worn) {
CheckNextItem: *ptr_i_worn = item;
mov eax, dword ptr ds:[eax + 0x8]; // PC inventory item list }
mov eax, dword ptr ds:[edx + eax]; // PC inventory item list + itemListOffset
test byte ptr ds:[eax + 0x27], 1; // if item in item1 slot
jnz IsItem1;
test byte ptr ds:[eax + 0x27], 2; // if item in item2 slot
jnz IsItem2;
test byte ptr ds:[eax + 0x27], 4; // if item in armor slot
jnz IsArmor;
jmp SetNextItem;
IsItem1:
mov dword ptr ds:[FO_VAR_i_lhand], eax; // set item1
test byte ptr ds:[eax + 0x27], 2; // check if same item type also in item2 slot
jz SetNextItem;
IsItem2:
mov dword ptr ds:[FO_VAR_i_rhand], eax; // set item2
jmp SetNextItem;
IsArmor:
mov dword ptr ds:[FO_VAR_i_worn], eax; // set armor
SetNextItem:
inc ebx; // itemNum++
add edx, 8; // itemListOffset + itemsize
LoopStart:
mov eax, dword ptr ds:[FO_VAR_pud]; // PC inventory
cmp ebx, dword ptr ds:[eax]; // size of item list
jl CheckNextItem;
// inventory function - setup pc FrmID and store at address _i_fid
call adjust_fid_;
// copy new FrmID to hero state struct
mov edx, dword ptr ds:[FO_VAR_i_fid];
mov eax, dword ptr ds:[FO_VAR_inven_dude];
mov dword ptr ds:[eax + 0x20], edx;
//call obj_change_fid_;
pop dword ptr ds:[FO_VAR_i_worn]; // armor
pop dword ptr ds:[FO_VAR_i_lhand]; // item1
pop dword ptr ds:[FO_VAR_i_rhand]; // item2
pop dword ptr ds:[FO_VAR_inven_dude];
} }
// inventory function - setup pc FrmID and store at address _i_fid
(*ptr_obj_dude)->artFid = Inventory_adjust_fid(); // adjust_fid_
*ptr_inven_dude = iD;
*ptr_i_rhand = iR;
*ptr_i_lhand = iL;
*ptr_i_worn = iW;
}
void __stdcall RefreshPCArt() {
fo_proto_dude_update_gender(); // refresh PC base model art
UpdateHeroArt();
DrawPC(); DrawPC();
} }
@@ -1462,7 +1423,7 @@ static void EnableHeroAppearanceMod() {
MakeCall(0x49F9DA, AdjustHeroBaseArt); MakeCall(0x49F9DA, AdjustHeroBaseArt);
// Adjust hero art index offset when changing armor (adjust_fid_) // Adjust hero art index offset when changing armor (adjust_fid_)
HookCall(0x4717D1, AdjustHeroArmorArt); /* HookCall(0x4717D1, AdjustHeroArmorArt); - the engine function is replaced by the sfall code */
// Hijack Save Hero State Structure fuction address 9CD54800 // Hijack Save Hero State Structure fuction address 9CD54800
// Return hero art index offset back to normal before saving // Return hero art index offset back to normal before saving
+4
View File
@@ -18,9 +18,13 @@
#pragma once #pragma once
extern bool appModEnabled;
void HeroAppearance_Init(); void HeroAppearance_Init();
void HeroAppearance_Exit(); void HeroAppearance_Exit();
void __stdcall AdjustHeroArmorArt(DWORD fid);
void __stdcall HeroSelectWindow(int raceStyleFlag); void __stdcall HeroSelectWindow(int raceStyleFlag);
void __stdcall SetHeroStyle(int newStyleVal); void __stdcall SetHeroStyle(int newStyleVal);
void __stdcall SetHeroRace(int newRaceVal); void __stdcall SetHeroRace(int newRaceVal);
+17 -1
View File
@@ -1586,6 +1586,21 @@ long __stdcall CorrectFidForRemovedItem_wHook(TGameObj* critter, TGameObj* item,
return result; return result;
} }
// 4.x backport
void __stdcall AdjustFidHook(DWORD vanillaFid) {
BeginHook();
argCount = 2;
args[0] = vanillaFid;
args[1] = *ptr_i_fid; // modified FID by sfall code
RunHookScript(HOOK_ADJUSTFID);
if (cRet > 0) {
*ptr_i_fid = rets[0];
}
EndHook();
}
// 4.x backport // 4.x backport
static unsigned long previousGameMode = 0; static unsigned long previousGameMode = 0;
@@ -1635,7 +1650,7 @@ void __stdcall SetHSReturn(DWORD value) {
} }
void __stdcall RegisterHook(TProgram* script, int id, int procNum, bool specReg) { void __stdcall RegisterHook(TProgram* script, int id, int procNum, bool specReg) {
if (id >= numHooks || (id > HOOK_INVENWIELD && id < HOOK_GAMEMODECHANGE)) return; if (id >= numHooks || (id > HOOK_ADJUSTFID && id < HOOK_GAMEMODECHANGE)) return;
for (std::vector<sHookScript>::iterator it = hooks[id].begin(); it != hooks[id].end(); ++it) { for (std::vector<sHookScript>::iterator it = hooks[id].begin(); it != hooks[id].end(); ++it) {
if (it->prog.ptr == script) { if (it->prog.ptr == script) {
if (procNum == 0) hooks[id].erase(it); // unregister if (procNum == 0) hooks[id].erase(it); // unregister
@@ -1873,6 +1888,7 @@ static void HookScriptInit() {
HookCall(0x45C4F6, op_move_obj_inven_to_obj_hook); HookCall(0x45C4F6, op_move_obj_inven_to_obj_hook);
MakeCall(0x4778AF, item_drop_all_hack, 3); MakeCall(0x4778AF, item_drop_all_hack, 3);
LoadHookScript("hs_adjustfid", HOOK_ADJUSTFID);
LoadHookScript("hs_gamemodechange", HOOK_GAMEMODECHANGE); LoadHookScript("hs_gamemodechange", HOOK_GAMEMODECHANGE);
fo_db_free_file_list(&filenames, 0); fo_db_free_file_list(&filenames, 0);
+5 -1
View File
@@ -46,6 +46,7 @@ enum HookType
HOOK_WITHINPERCEPTION = 23, HOOK_WITHINPERCEPTION = 23,
HOOK_INVENTORYMOVE = 24, HOOK_INVENTORYMOVE = 24,
HOOK_INVENWIELD = 25, HOOK_INVENWIELD = 25,
HOOK_ADJUSTFID = 26, // 4.x backport
HOOK_GAMEMODECHANGE = 31, // 4.x backport HOOK_GAMEMODECHANGE = 31, // 4.x backport
HOOK_COUNT HOOK_COUNT
}; };
@@ -65,17 +66,20 @@ void HookScriptClear();
extern DWORD initingHookScripts; extern DWORD initingHookScripts;
int __fastcall AmmoCostHook_Script(DWORD hookType, TGameObj* weapon, DWORD &rounds);
void __stdcall RunHookScriptsAtProc(DWORD procId); void __stdcall RunHookScriptsAtProc(DWORD procId);
void __stdcall GameModeChangeHook(DWORD exit); void __stdcall GameModeChangeHook(DWORD exit);
void __stdcall KeyPressHook(DWORD* dxKey, bool pressed, DWORD vKey); void __stdcall KeyPressHook(DWORD* dxKey, bool pressed, DWORD vKey);
void __stdcall MouseClickHook(DWORD button, bool pressed); void __stdcall MouseClickHook(DWORD button, bool pressed);
int __fastcall AmmoCostHook_Script(DWORD hookType, TGameObj* weapon, DWORD &rounds);
long __stdcall CorrectFidForRemovedItem_wHook(TGameObj* critter, TGameObj* item, long flags); long __stdcall CorrectFidForRemovedItem_wHook(TGameObj* critter, TGameObj* item, long flags);
void InvenUnwield_HookDrop(); void InvenUnwield_HookDrop();
void InvenUnwield_HookMove(); void InvenUnwield_HookMove();
void __stdcall AdjustFidHook(DWORD vanillaFid);
// Implementation of item_w_mp_cost_ engine function with the hook // Implementation of item_w_mp_cost_ engine function with the hook
long __fastcall sf_item_w_mp_cost(TGameObj* source, long hitMode, long isCalled); long __fastcall sf_item_w_mp_cost(TGameObj* source, long hitMode, long isCalled);
+81 -10
View File
@@ -20,8 +20,11 @@
#include "main.h" #include "main.h"
#include "FalloutEngine.h" #include "FalloutEngine.h"
#include "HeroAppearance.h"
#include "HookScripts.h"
#include "InputFuncs.h" #include "InputFuncs.h"
#include "LoadGameHook.h" #include "LoadGameHook.h"
#include "PartyControl.h"
#include "Inventory.h" #include "Inventory.h"
@@ -58,9 +61,9 @@ void InventoryKeyPressedHook(DWORD dxKey, bool pressed) {
} }
} }
///////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
DWORD __stdcall sf_item_total_size(TGameObj* critter) { DWORD __stdcall Inventory_item_total_size(TGameObj* critter) {
int totalSize = fo_item_c_curr_size(critter); int totalSize = fo_item_c_curr_size(critter);
if (critter->TypeFid() == OBJ_TYPE_CRITTER) { if (critter->TypeFid() == OBJ_TYPE_CRITTER) {
@@ -82,6 +85,70 @@ DWORD __stdcall sf_item_total_size(TGameObj* critter) {
return totalSize; return totalSize;
} }
// Reimplementation of adjust_fid engine function
// Differences from vanilla:
// - doesn't use art_vault_guy_num as default art, uses current critter FID instead
// - calls AdjustFidHook that allows to hook into FID calculation
DWORD __stdcall Inventory_adjust_fid() {
DWORD fid;
if ((*ptr_inven_dude)->TypeFid() == OBJ_TYPE_CRITTER) {
DWORD indexNum;
DWORD weaponAnimCode = 0;
if (PartyControl_IsNpcControlled()) {
// if NPC is under control, use current FID of critter
indexNum = (*ptr_inven_dude)->artFid & 0xFFF;
} else {
// vanilla logic:
indexNum = *ptr_art_vault_guy_num;
auto critterPro = GetProto(*ptr_inven_pid);
if (critterPro != nullptr) {
indexNum = critterPro->fid & 0xFFF;
}
if (*ptr_i_worn != nullptr) {
auto armorPro = GetProto((*ptr_i_worn)->protoId);
DWORD armorFid = fo_stat_level(*ptr_inven_dude, STAT_gender) == GENDER_FEMALE
? armorPro->item.armor.femaleFID
: armorPro->item.armor.maleFID;
if (armorFid != -1) {
indexNum = armorFid;
}
}
}
auto itemInHand = fo_intface_is_item_right_hand()
? *ptr_i_rhand
: *ptr_i_lhand;
if (itemInHand != nullptr) {
auto itemPro = GetProto(itemInHand->protoId);
if (itemPro->item.type == item_type_weapon) {
weaponAnimCode = itemPro->item.weapon.animationCode;
}
}
fid = fo_art_id(OBJ_TYPE_CRITTER, indexNum, 0, weaponAnimCode, 0);
} else {
fid = (*ptr_inven_dude)->artFid;
}
*ptr_i_fid = fid;
// OnAdjustFid
if (appModEnabled) AdjustHeroArmorArt(fid);
AdjustFidHook(fid); // should be called last
return *ptr_i_fid;
}
static void __declspec(naked) adjust_fid_hack() {
__asm {
push ecx;
push edx;
call Inventory_adjust_fid; // return fid
pop edx;
pop ecx;
retn;
}
}
////////////////////////////////////////////////////////////////////////////////
static int __stdcall CritterGetMaxSize(TGameObj* critter) { static int __stdcall CritterGetMaxSize(TGameObj* critter) {
if (critter == *ptr_obj_dude) return invSizeMaxLimit; if (critter == *ptr_obj_dude) return invSizeMaxLimit;
@@ -108,7 +175,7 @@ static __declspec(naked) void critterIsOverloaded_hack() {
jz skip; jz skip;
push ebx; push ebx;
mov ebx, eax; // ebx = MaxSize mov ebx, eax; // ebx = MaxSize
call sf_item_total_size; call Inventory_item_total_size;
cmp eax, ebx; cmp eax, ebx;
setg al; // if CurrSize > MaxSize setg al; // if CurrSize > MaxSize
and eax, 0xFF; and eax, 0xFF;
@@ -122,8 +189,8 @@ end:
static int __fastcall CanAddedItems(TGameObj* critter, TGameObj* item, int count) { static int __fastcall CanAddedItems(TGameObj* critter, TGameObj* item, int count) {
int sizeMax = CritterGetMaxSize(critter); int sizeMax = CritterGetMaxSize(critter);
if (sizeMax > 0) { if (sizeMax > 0) {
int itemsSize = fo_item_size(item) * count; int totalSize = Inventory_item_total_size(critter) + (fo_item_size(item) * count);
if (itemsSize + (int)sf_item_total_size(critter) > sizeMax) return -6; // TODO: Switch this to a lower number, and add custom error messages. if (totalSize > sizeMax) return -6; // TODO: Switch this to a lower number, and add custom error messages.
} }
return 0; return 0;
} }
@@ -168,10 +235,10 @@ static int __fastcall BarterAttemptTransaction(TGameObj* critter, TGameObj* tabl
int size = CritterGetMaxSize(critter); int size = CritterGetMaxSize(critter);
if (size == 0) return 1; if (size == 0) return 1;
int sizeTable = sf_item_total_size(table); int sizeTable = Inventory_item_total_size(table);
if (sizeTable == 0) return 1; if (sizeTable == 0) return 1;
size -= sf_item_total_size(critter); size -= Inventory_item_total_size(critter);
return (sizeTable <= size) ? 1 : 0; return (sizeTable <= size) ? 1 : 0;
} }
@@ -246,7 +313,7 @@ static void __cdecl DisplaySizeStats(TGameObj* critter, const char* &message, DW
} }
sizeMax = limitMax; sizeMax = limitMax;
size = sf_item_total_size(critter); size = Inventory_item_total_size(critter);
const char* msg = MsgSearch(ptr_inventry_message_file, 35); const char* msg = MsgSearch(ptr_inventry_message_file, 35);
message = (msg != nullptr) ? msg : ""; message = (msg != nullptr) ? msg : "";
@@ -312,14 +379,15 @@ static void __declspec(naked) gdControlUpdateInfo_hack() {
call CritterGetMaxSize; call CritterGetMaxSize;
push eax; // sizeMax push eax; // sizeMax
push ebx; push ebx;
call sf_item_total_size; call Inventory_item_total_size;
push eax; // size push eax; // size
mov eax, ebx; mov eax, ebx;
mov edx, STAT_carry_amt; mov edx, STAT_carry_amt;
jmp ControlUpdateInfoRet; jmp ControlUpdateInfoRet;
} }
} }
/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
static char superStimMsg[128]; static char superStimMsg[128];
static int __fastcall SuperStimFix(TGameObj* item, TGameObj* target) { static int __fastcall SuperStimFix(TGameObj* item, TGameObj* target) {
@@ -634,6 +702,9 @@ void InventoryReset() {
} }
void Inventory_Init() { void Inventory_Init() {
// Replace adjust_fid_ function
MakeJump(adjust_fid_, adjust_fid_hack); // 0x4716E8
long widthWeight = 135; long widthWeight = 135;
sizeLimitMode = GetConfigInt("Misc", "CritterInvSizeLimitMode", 0); sizeLimitMode = GetConfigInt("Misc", "CritterInvSizeLimitMode", 0);
+11 -1
View File
@@ -24,4 +24,14 @@ void InventoryKeyPressedHook(DWORD dxKey, bool pressed);
long __stdcall GetInvenApCost(); long __stdcall GetInvenApCost();
void __fastcall SetInvenApCost(int cost); void __fastcall SetInvenApCost(int cost);
DWORD __stdcall sf_item_total_size(TGameObj* critter);
// This function returns the size of the occupied inventory space for the object or critter
// - difference from the item_c_curr_size_ function: includes the size of equipped items for the critter
// - does not return the size of nested items
DWORD __stdcall Inventory_item_total_size(TGameObj* critter);
// Reimplementation of adjust_fid engine function
// Differences from vanilla:
// - doesn't use art_vault_guy_num as default art, uses current critter FID instead
// - calls AdjustFidHook that allows to hook into FID calculation
DWORD __stdcall Inventory_adjust_fid();
+1 -1
View File
@@ -524,7 +524,7 @@ static void mf_set_unjam_locks_time() {
static void mf_get_current_inven_size() { static void mf_get_current_inven_size() {
TGameObj* obj = opHandler.arg(0).asObject(); TGameObj* obj = opHandler.arg(0).asObject();
if (obj) { if (obj) {
opHandler.setReturn(sf_item_total_size(obj)); opHandler.setReturn(Inventory_item_total_size(obj));
} else { } else {
OpcodeInvalidArgs("get_current_inven_size"); OpcodeInvalidArgs("get_current_inven_size");
opHandler.setReturn(0); opHandler.setReturn(0);