mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Backported CritterInvSizeLimitMode related fixes/improvements from the develop branch:
* Changed item_total_weight/item_c_curr_size engine functions to return the weight and size of equipped(hidden) items on NPCs when exchanging/bartering items. * Fixed CritterInvSizeLimitMode not properly checking the weight of equipped items when mode is set to 4+. * Added inventory size check to "Take All" button. * Added additional note to CritterInvSizeLimitMode in ddraw.ini, and changed CritterInvSizeLimit to its default value.
This commit is contained in:
+2
-2
@@ -468,10 +468,10 @@ BoostScriptDialogLimit=0
|
||||
|
||||
;These options modify the checks to see if a critter can carry an additional item, changing which items are counted towards the weight limit and adding an additional size check
|
||||
;Set the mode to 0 to disable the size check, 1 to apply to the PC only, 2 to apply to the PC and party members, or 3 to apply to all critters
|
||||
;Only the PC uses CritterInvSizeLimit. Other critters will use the extra unused stat (STAT_unused = 10)
|
||||
;Only the PC uses CritterInvSizeLimit. Other critters will use the unused stat (STAT_unused = 10) or have the size limit of 100 if the stat is not set
|
||||
;Add 4 to the mode to limit the weight check to used items only
|
||||
CritterInvSizeLimitMode=0
|
||||
CritterInvSizeLimit=200
|
||||
CritterInvSizeLimit=100
|
||||
|
||||
;Some bit flags to alter behaviour of the motion sensor
|
||||
;1 - Allow sensor use on automap when motion sensor is in pack rather than hands
|
||||
|
||||
+136
-61
@@ -5,7 +5,15 @@
|
||||
#include "FalloutEngine.h"
|
||||
#include "ScriptExtender.h"
|
||||
|
||||
DWORD WeightOnBody = 0;
|
||||
static DWORD critterBody = 0;
|
||||
static DWORD sizeOnBody = 0;
|
||||
static DWORD weightOnBody = 0;
|
||||
|
||||
void ResetBodyState() {
|
||||
_asm mov critterBody, 0;
|
||||
_asm mov sizeOnBody, 0;
|
||||
_asm mov weightOnBody, 0;
|
||||
}
|
||||
|
||||
static void __declspec(naked) SharpShooterFix() {
|
||||
__asm {
|
||||
@@ -394,84 +402,145 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate weight & size of equipped items
|
||||
static void __declspec(naked) loot_container_hack() {
|
||||
__asm {
|
||||
mov eax, [esp+0x114+0x4]
|
||||
test eax, eax
|
||||
jz noLeftWeapon
|
||||
call item_weight_
|
||||
mov critterBody, ebp; // target
|
||||
push esi;
|
||||
mov esi, [esp + 0x114 + 8]; // item lhand
|
||||
mov sizeOnBody, esi;
|
||||
mov eax, esi;
|
||||
test esi, esi;
|
||||
jz noLeftWeapon;
|
||||
call item_size_;
|
||||
mov sizeOnBody, eax;
|
||||
mov eax, esi;
|
||||
call item_weight_;
|
||||
noLeftWeapon:
|
||||
mov WeightOnBody, eax
|
||||
mov eax, [esp+0x118+0x4]
|
||||
test eax, eax
|
||||
jz noRightWeapon
|
||||
call item_weight_
|
||||
mov weightOnBody, eax;
|
||||
mov esi, [esp + 0x118 + 8]; // item rhand
|
||||
test esi, esi;
|
||||
jz noRightWeapon;
|
||||
mov eax, esi;
|
||||
call item_size_;
|
||||
add sizeOnBody, eax;
|
||||
mov eax, esi;
|
||||
call item_weight_;
|
||||
add weightOnBody, eax;
|
||||
noRightWeapon:
|
||||
add WeightOnBody, eax
|
||||
mov eax, [esp+0x11C+0x4]
|
||||
test eax, eax
|
||||
jz noArmor
|
||||
call item_weight_
|
||||
mov esi, [esp + 0x11C + 8]; // item armor
|
||||
test esi, esi;
|
||||
jz noArmor;
|
||||
mov eax, esi;
|
||||
call item_size_;
|
||||
add sizeOnBody, eax;
|
||||
mov eax, esi;
|
||||
call item_weight_;
|
||||
add weightOnBody, eax;
|
||||
noArmor:
|
||||
add WeightOnBody, eax
|
||||
xor eax, eax
|
||||
inc eax
|
||||
inc eax
|
||||
retn
|
||||
mov esi, [esp + 0xF8 + 8]; // check JESSE_CONTAINER
|
||||
mov eax, esi;
|
||||
call item_c_curr_size_;
|
||||
add sizeOnBody, eax;
|
||||
mov eax, esi;
|
||||
call item_total_weight_;
|
||||
add weightOnBody, eax;
|
||||
pop esi;
|
||||
mov eax, 2; // overwritten code
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) barter_inventory_hack() {
|
||||
static void __declspec(naked) barter_inventory_hook() {
|
||||
__asm {
|
||||
mov eax, [esp+0x20+0x4]
|
||||
test eax, eax
|
||||
jz noArmor
|
||||
call item_weight_
|
||||
mov critterBody, eax; // target
|
||||
call item_move_all_hidden_;
|
||||
push esi;
|
||||
mov esi, [esp + 0x20 + 8]; // armor
|
||||
mov sizeOnBody, esi;
|
||||
mov eax, esi;
|
||||
test eax, eax;
|
||||
jz noArmor;
|
||||
call item_size_;
|
||||
mov sizeOnBody, eax
|
||||
mov eax, esi;
|
||||
call item_weight_;
|
||||
noArmor:
|
||||
mov WeightOnBody, eax
|
||||
mov eax, [esp+0x1C+0x4]
|
||||
test eax, eax
|
||||
jnz haveWeapon
|
||||
cmp dword ptr ds:[_dialog_target_is_party], eax
|
||||
jne end // This is a party member
|
||||
mov eax, [esp+0x18+0x4]
|
||||
test eax, eax
|
||||
jz end
|
||||
mov weightOnBody, eax;
|
||||
mov esi, [esp + 0x1C + 8]; // weapon
|
||||
test esi, esi;
|
||||
jnz haveWeapon;
|
||||
cmp ds:[_dialog_target_is_party], esi; // esi = 0
|
||||
jne skip; // This is a party member
|
||||
mov eax, [esp + 0x18 + 8]; // item_weapon
|
||||
test eax, eax;
|
||||
jz skip;
|
||||
haveWeapon:
|
||||
call item_weight_
|
||||
add WeightOnBody, eax
|
||||
end:
|
||||
mov ebx, PID_JESSE_CONTAINER
|
||||
retn
|
||||
mov eax, esi;
|
||||
call item_size_;
|
||||
add sizeOnBody, eax;
|
||||
mov eax, esi;
|
||||
call item_weight_;
|
||||
add weightOnBody, eax;
|
||||
skip:
|
||||
mov esi, [esp + 0x10 + 8]; // check JESSE_CONTAINER
|
||||
mov eax, esi;
|
||||
call item_c_curr_size_;
|
||||
add sizeOnBody, eax
|
||||
mov eax, esi;
|
||||
call item_total_weight_;
|
||||
add weightOnBody, eax
|
||||
pop esi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) barter_attempt_transaction_hook() {
|
||||
// Add weightOnBody to item_total_weight_ function
|
||||
static void __declspec(naked) item_total_weight_hack() {
|
||||
__asm {
|
||||
call stat_level_ // eax = Max weight
|
||||
sub eax, WeightOnBody // Accounting for weight of target's equipped armor and weapon
|
||||
retn
|
||||
xor edx, edx;
|
||||
mov ebx, [edi]; // Inventory.inv_size
|
||||
xor esi, esi;
|
||||
//------
|
||||
cmp eax, dword ptr ds:[_obj_dude]; // eax - source
|
||||
jz skip;
|
||||
cmp critterBody, eax; // if condition is true, then now it's exchanging/bartering with source object
|
||||
cmovz esi, weightOnBody; // take the weight of target's equipped items into account
|
||||
skip:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD Looting = 0;
|
||||
static void __declspec(naked) move_inventory_hook() {
|
||||
// Add sizeOnBody to item_c_curr_size_ function
|
||||
static void __declspec(naked) item_c_curr_size_hack() {
|
||||
__asm {
|
||||
inc Looting
|
||||
call move_inventory_
|
||||
dec Looting
|
||||
retn
|
||||
xor esi, esi;
|
||||
mov edx, [ecx]; // Inventory.inv_size
|
||||
xor edi, edi;
|
||||
//------
|
||||
cmp eax, dword ptr ds:[_obj_dude]; // eax - source
|
||||
jz skip;
|
||||
cmp critterBody, eax; // if condition is true, then now it's exchanging/bartering with source object
|
||||
cmovz edi, sizeOnBody; // take the size of target's equipped items into account
|
||||
skip:
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) item_add_mult_hook() {
|
||||
// simple hooks from 4.x LoadGameHook.cpp without new game mode flags
|
||||
static void __declspec(naked) LootContainerWrapper() {
|
||||
__asm {
|
||||
call stat_level_ // eax = Max weight
|
||||
cmp Looting, 0
|
||||
je end
|
||||
sub eax, WeightOnBody // Accounting for weight of target's equipped armor and weapon
|
||||
end:
|
||||
retn
|
||||
call loot_container_;
|
||||
jmp ResetBodyState;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) BarterInventoryWrapper() {
|
||||
__asm {
|
||||
push [esp + 4];
|
||||
call barter_inventory_;
|
||||
call ResetBodyState;
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1336,14 +1405,20 @@ void BugsInit()
|
||||
HookCall(0x437B26, &StatButtonDown_hook);
|
||||
dlogr(" Done", DL_INIT);
|
||||
|
||||
// Fix for not counting in the weight of equipped items on NPC when stealing or bartering
|
||||
// Fix for not counting in the weight/size of equipped items on NPC when stealing or bartering
|
||||
//if (GetPrivateProfileIntA("Misc", "NPCWeightFix", 1, ini)) {
|
||||
dlog("Applying fix for not counting in weight of equipped items on NPC.", DL_INIT);
|
||||
MakeCall(0x473B4E, loot_container_hack);
|
||||
MakeCall(0x47588A, barter_inventory_hack);
|
||||
HookCall(0x474CB8, &barter_attempt_transaction_hook);
|
||||
HookCall(0x4742AD, &move_inventory_hook);
|
||||
HookCall(0x4771B5, &item_add_mult_hook);
|
||||
HookCall(0x4758AB, barter_inventory_hook);
|
||||
MakeCall(0x477EAB, item_total_weight_hack);
|
||||
SafeWrite8(0x477EB0, 0x90);
|
||||
MakeCall(0x479A2F, item_c_curr_size_hack);
|
||||
SafeWrite8(0x479A34, 0x90);
|
||||
// Reset object pointer after exiting loot/barter screens
|
||||
HookCall(0x4746EC, LootContainerWrapper);
|
||||
HookCall(0x4A4369, LootContainerWrapper);
|
||||
HookCall(0x4A4565, LootContainerWrapper);
|
||||
HookCall(0x4466C7, BarterInventoryWrapper);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
extern DWORD WeightOnBody;
|
||||
extern void ResetBodyState();
|
||||
|
||||
void BugsInit();
|
||||
|
||||
@@ -247,6 +247,7 @@ const DWORD art_ptr_unlock_ = 0x419260;
|
||||
const DWORD attack_crit_success_ = 0x423EB4;
|
||||
const DWORD automap_ = 0x41B8BC;
|
||||
const DWORD barter_compute_value_ = 0x474B2C;
|
||||
const DWORD barter_inventory_ = 0x4757F0;
|
||||
const DWORD buf_to_buf_ = 0x4D36D4;
|
||||
const DWORD check_death_ = 0x410814;
|
||||
const DWORD Check4Keys_ = 0x43F73C;
|
||||
@@ -396,6 +397,7 @@ const DWORD item_m_cell_pid_ = 0x479454;
|
||||
const DWORD item_m_dec_charges_ = 0x4795A4;
|
||||
const DWORD item_m_turn_off_ = 0x479898;
|
||||
const DWORD item_move_all_ = 0x4776AC;
|
||||
const DWORD item_move_all_hidden_ = 0x4776E0;
|
||||
const DWORD item_move_force_ = 0x4776A4;
|
||||
const DWORD item_mp_cost_ = 0x478040;
|
||||
const DWORD item_remove_mult_ = 0x477490;
|
||||
@@ -429,6 +431,7 @@ const DWORD loadColorTable_ = 0x4C78E4;
|
||||
const DWORD LoadGame_ = 0x47C640;
|
||||
const DWORD loadProgram_ = 0x4A3B74;
|
||||
const DWORD LoadSlot_ = 0x47DC68;
|
||||
const DWORD loot_container_ = 0x473904;
|
||||
const DWORD main_game_loop_ = 0x480E48;
|
||||
const DWORD main_menu_hide_ = 0x481A00;
|
||||
const DWORD main_menu_loop_ = 0x481AEC;
|
||||
|
||||
@@ -426,6 +426,7 @@ extern const DWORD art_ptr_unlock_;
|
||||
extern const DWORD attack_crit_success_;
|
||||
extern const DWORD automap_;
|
||||
extern const DWORD barter_compute_value_;
|
||||
extern const DWORD barter_inventory_;
|
||||
extern const DWORD buf_to_buf_;
|
||||
extern const DWORD check_death_;
|
||||
extern const DWORD Check4Keys_;
|
||||
@@ -574,6 +575,7 @@ extern const DWORD item_m_cell_pid_;
|
||||
extern const DWORD item_m_dec_charges_;
|
||||
extern const DWORD item_m_turn_off_;
|
||||
extern const DWORD item_move_all_;
|
||||
extern const DWORD item_move_all_hidden_;
|
||||
extern const DWORD item_move_force_;
|
||||
extern const DWORD item_mp_cost_;
|
||||
extern const DWORD item_remove_mult_;
|
||||
@@ -607,6 +609,7 @@ extern const DWORD loadColorTable_;
|
||||
extern const DWORD LoadGame_;
|
||||
extern const DWORD loadProgram_; // loads script from scripts/ folder by file name and returns pointer to it: char* <eax> - file name (w/o extension)
|
||||
extern const DWORD LoadSlot_;
|
||||
extern const DWORD loot_container_;
|
||||
extern const DWORD main_game_loop_;
|
||||
extern const DWORD main_menu_hide_;
|
||||
extern const DWORD main_menu_loop_;
|
||||
|
||||
+36
-33
@@ -92,32 +92,8 @@ void InventoryKeyPressedHook(DWORD dxKey, bool pressed, DWORD vKey) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static DWORD _stdcall item_total_size(void* critter) {
|
||||
//TODO: Don't really want to be overwriting stuff like this after init. Rewrite properly.
|
||||
HookCall(0x477EBD, (void*)0x477B68);
|
||||
HookCall(0x477EF6, (void*)0x477B68);
|
||||
HookCall(0x477F12, (void*)0x477B68);
|
||||
HookCall(0x477F2A, (void*)0x477B68);
|
||||
|
||||
DWORD result;
|
||||
__asm {
|
||||
mov eax, critter;
|
||||
call item_total_weight_;
|
||||
mov result, eax;
|
||||
}
|
||||
|
||||
HookCall(0x477EBD, (void*)0x477B88);
|
||||
HookCall(0x477EF6, (void*)0x477B88);
|
||||
HookCall(0x477F12, (void*)0x477B88);
|
||||
HookCall(0x477F2A, (void*)0x477B88);
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
static DWORD __stdcall sf_item_total_size(TGameObj* critter) {
|
||||
|
||||
int totalSize;
|
||||
__asm {
|
||||
mov eax, critter;
|
||||
@@ -127,17 +103,17 @@ static DWORD __stdcall sf_item_total_size(TGameObj* critter) {
|
||||
|
||||
if ((critter->artFID & 0xF000000) == (OBJ_TYPE_CRITTER << 24)) {
|
||||
TGameObj* item = InvenRightHand(critter);
|
||||
if (item && !(item->flags & OBJFLAG_HELD_IN_RIGHT << 8)) {
|
||||
if (item && !(item->flags & 0x2000000)) {
|
||||
totalSize += ItemSize(item);
|
||||
}
|
||||
|
||||
TGameObj* itemL = InvenLeftHand(critter);
|
||||
if (itemL && item != itemL && !(itemL->flags & OBJFLAG_HELD_IN_LEFT << 8)) {
|
||||
if (itemL && item != itemL && !(itemL->flags & 0x1000000)) {
|
||||
totalSize += ItemSize(itemL);
|
||||
}
|
||||
|
||||
item = InvenWorn(critter);
|
||||
if (item && !(item->flags & OBJFLAG_WORN << 8)) {
|
||||
if (item && !(item->flags & 0x4000000)) {
|
||||
totalSize += ItemSize(item);
|
||||
}
|
||||
}
|
||||
@@ -240,11 +216,11 @@ fail:
|
||||
}
|
||||
}
|
||||
|
||||
static int __fastcall BarterAttemptTransaction(TGameObj* critter, TGameObj* targetTable) {
|
||||
static int __fastcall BarterAttemptTransaction(TGameObj* critter, TGameObj* table) {
|
||||
int size = CritterGetMaxSize(critter);
|
||||
if (size == 0) return 1;
|
||||
|
||||
int sizeTable = sf_item_total_size(targetTable);
|
||||
int sizeTable = sf_item_total_size(table);
|
||||
if (sizeTable == 0) return 1;
|
||||
|
||||
size -= sf_item_total_size(critter);
|
||||
@@ -258,8 +234,8 @@ static __declspec(naked) void barter_attempt_transaction_hack_pc() {
|
||||
/* cmp eax, edx */
|
||||
jg fail; // if there's no available weight
|
||||
//------
|
||||
mov ecx, edi;
|
||||
mov edx, ebp;
|
||||
mov ecx, edi; // source (pc)
|
||||
mov edx, ebp; // npc table
|
||||
call BarterAttemptTransaction;
|
||||
test eax, eax;
|
||||
jz fail;
|
||||
@@ -277,8 +253,8 @@ static __declspec(naked) void barter_attempt_transaction_hack_pm() {
|
||||
/* cmp eax, edx */
|
||||
jg fail; // if there's no available weight
|
||||
//------
|
||||
mov ecx, ebx;
|
||||
mov edx, esi;
|
||||
mov ecx, ebx; // target (npc)
|
||||
mov edx, esi; // pc table
|
||||
call BarterAttemptTransaction;
|
||||
test eax, eax;
|
||||
jz fail;
|
||||
@@ -289,6 +265,26 @@ fail:
|
||||
}
|
||||
}
|
||||
|
||||
static __declspec(naked) void loot_container_hook_btn() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push edx; // source current weight
|
||||
mov edx, eax; // target
|
||||
mov ecx, [esp + 0x150 - 0x1C + 12]; // source
|
||||
call BarterAttemptTransaction;
|
||||
pop edx;
|
||||
pop ecx;
|
||||
test eax, eax;
|
||||
jz fail;
|
||||
mov eax, ebp; // target
|
||||
jmp item_total_weight_;
|
||||
fail:
|
||||
mov eax, edx;
|
||||
inc eax; // weight + 1
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static char InvenFmt[32];
|
||||
static const char* InvenFmt1 = "%s %d/%d %s %d/%d";
|
||||
static const char* InvenFmt2 = "%s %d/%d";
|
||||
@@ -716,7 +712,11 @@ void InventoryInit() {
|
||||
if (sizeLimitMode > 0 && sizeLimitMode <= 7) {
|
||||
if (sizeLimitMode >= 4) {
|
||||
sizeLimitMode -= 4;
|
||||
// item_total_weight_ patch
|
||||
SafeWrite8(0x477EB3, 0xEB);
|
||||
SafeWrite8(0x477EF5, 0);
|
||||
SafeWrite8(0x477F11, 0);
|
||||
SafeWrite8(0x477F29, 0);
|
||||
}
|
||||
invSizeMaxLimit = GetPrivateProfileInt("Misc", "CritterInvSizeLimit", 100, ini);
|
||||
|
||||
@@ -730,6 +730,9 @@ void InventoryInit() {
|
||||
SafeWrite16(0x474C7A, 0x9090);
|
||||
MakeJump(0x474C7C, barter_attempt_transaction_hack_pc);
|
||||
|
||||
// Check player's capacity when using "Take All" button
|
||||
HookCall(0x47410B, loot_container_hook_btn);
|
||||
|
||||
// Display total weight/size on the inventory screen
|
||||
MakeJump(0x4725E0, display_stats_hack);
|
||||
SafeWrite32(0x4725FF, (DWORD)&InvenFmt);
|
||||
|
||||
@@ -52,11 +52,11 @@ bool IsMapLoaded() {
|
||||
}
|
||||
|
||||
DWORD InWorldMap() {
|
||||
return (InLoop&WORLDMAP) ? 1 : 0;
|
||||
return (InLoop & WORLDMAP) ? 1 : 0;
|
||||
}
|
||||
|
||||
DWORD InCombat() {
|
||||
return (InLoop&COMBAT) ? 1 : 0;
|
||||
return (InLoop & COMBAT) ? 1 : 0;
|
||||
}
|
||||
|
||||
DWORD GetCurrentLoops() {
|
||||
|
||||
Reference in New Issue
Block a user