mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Backported HOOK_ADJUSTFID from 4.2
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user