From e1aefcc1ed031c4b994545ab7fd28ca9f6135241 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Thu, 11 Oct 2018 11:19:22 +0800 Subject: [PATCH] Refactored BonusHtHDamageFix/DisplayBonusDamage code in AmmoMod.cpp (from Mr.Stalin) Fixed DisplayBonusDamage not being applied on Melee Damage stat in the character screen when BonusHtHDamageFix is enabled. Reimplemented INTFACEUSE/INTFACELOOT/BARTER game mode flags, and backported inventory_redraw script function from 4.0. --- artifacts/scripting/headers/sfall.h | 34 ++-- artifacts/scripting/sfall function notes.txt | 4 + sfall/AmmoMod.cpp | 170 +++++++------------ sfall/AnimationsAtOnceLimit.cpp | 8 +- sfall/Bugs.cpp | 22 --- sfall/FalloutEngine.cpp | 27 +++ sfall/FalloutEngine.h | 7 + sfall/HeroAppearance.cpp | 7 - sfall/HeroAppearance.h | 1 - sfall/LoadGameHook.cpp | 35 ++++ sfall/LoadGameHook.h | 35 ++-- sfall/ScriptExtender.cpp | 12 ++ sfall/ScriptOps/InterfaceOp.hpp | 27 +++ sfall/ScriptOps/MetaruleOp.hpp | 1 + 14 files changed, 215 insertions(+), 175 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index b60239c2..d04fbff1 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -1,19 +1,22 @@ //Recognised modes for set_shader_mode and get_game_mode -#define WORLDMAP (0x1) -#define LOCALMAP (0x2) //No point hooking this: would always be 1 at any point at which scripts are running -#define DIALOG (0x4) -#define ESCMENU (0x8) -#define SAVEGAME (0x10) -#define LOADGAME (0x20) -#define COMBAT (0x40) -#define OPTIONS (0x80) -#define HELP (0x100) -#define CHARSCREEN (0x200) -#define PIPBOY (0x400) -#define PCOMBAT (0x800) -#define INVENTORY (0x1000) -#define AUTOMAP (0x2000) -#define SKILLDEX (0x4000) +#define WORLDMAP (0x1) +#define LOCALMAP (0x2) //No point hooking this: would always be 1 at any point at which scripts are running +#define DIALOG (0x4) +#define ESCMENU (0x8) +#define SAVEGAME (0x10) +#define LOADGAME (0x20) +#define COMBAT (0x40) +#define OPTIONS (0x80) +#define HELP (0x100) +#define CHARSCREEN (0x200) +#define PIPBOY (0x400) +#define PCOMBAT (0x800) +#define INVENTORY (0x1000) +#define AUTOMAP (0x2000) +#define SKILLDEX (0x4000) +#define INTFACEUSE (0x8000) +#define INTFACELOOT (0x10000) +#define BARTER (0x20000) //Valid arguments to register_hook #define HOOK_TOHIT (0) @@ -218,6 +221,7 @@ #define intface_is_hidden sfall_func0("intface_is_hidden") #define intface_redraw sfall_func0("intface_redraw") #define intface_show sfall_func0("intface_show") +#define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide) #define item_weight(obj) sfall_func1("item_weight", obj) #define outlined_object sfall_func0("outlined_object") #define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index fabb50bf..a45b96d4 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -433,6 +433,10 @@ Some utility/math functions are available: > int sfall_func0("attack_is_aimed") - returns 1 if the aimed attack mode is selected, 0 otherwise +> void sfall_func1("inventory_redraw", int invSide) +- redraws inventory list in the inventory/use inventory item on/loot/barter screens +- invSide specifies which side needs to be redrawn: 0 - the player, 1 - target (container/NPC in loot/barter screens) + > int sfall_func1("get_current_inven_size", object) - returns the current inventory size of the container or the critter diff --git a/sfall/AmmoMod.cpp b/sfall/AmmoMod.cpp index 0d504aee..56ae3ce3 100644 --- a/sfall/AmmoMod.cpp +++ b/sfall/AmmoMod.cpp @@ -502,119 +502,69 @@ end: jmp DamageFunctionReturn; // Otherwise, exit loop } } +//////////////////////////////////////////////////////////////////////////////// -static const DWORD MeleeDmgDispExit = 0x435C11; -static const DWORD MeleeDmgPrintExit = 0x439926; -static const DWORD MeleeExit = 0x47226D; -static const DWORD UnarmedExit = 0x472556; -static const DWORD FixaEnd = 0x4784B0; -static const DWORD FixbEnd = 0x478553; - -static __declspec(naked) void MeleeDmgDispFix() { +static __declspec(naked) void MeleeDmgDisplayPrintFix_hook() { __asm { - call stat_level_; // Get Melee Damage - mov ecx,eax; // Store value - mov eax,dword ptr ds:[_obj_dude]; // Get pointer to PC - mov edx,PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Get rank of Bonus HtH Damage - shl eax,0x1; // Multiply by 2 - sub ecx,eax; // Subtract from Melee Damage - mov eax,ecx; // Move back to eax in preparation of push - jmp MeleeDmgDispExit; + call stat_level_; // Get Melee Damage + mov ecx, eax; // Store value + mov edx, PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage + mov eax, dword ptr ds:[_obj_dude]; // Get pointer to PC + call perk_level_; // Get rank of Bonus HtH Damage + shl eax, 1; // Multiply by 2 + sub ecx, eax; // Subtract from Melee Damage + mov eax, ecx; // Move back to eax in preparation of push + retn; } } -static __declspec(naked) void MeleeDmgPrintFix() { +static __declspec(naked) void CommonDmgRngDispFix_hook() { __asm { - call stat_level_; // Get Melee Damage - mov ebx,eax; // Store value - mov eax,dword ptr ds:[_obj_dude]; // Get pointer to PC - mov edx,PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Get rank of Bonus HtH Damage - shl eax,0x1; // Multiply by 2 - sub ebx,eax; // Subtract from Melee Damage - mov eax,ebx; // Move back to eax in preparation of push - mov ebx,0x27a; // Facilitates printing to file - jmp MeleeDmgPrintExit; + mov ebx, eax; // Store pointer to critter + call stat_level_; // Get Melee Damage + xchg ebx, eax; // Store Melee Damage value + mov edx, PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage + call perk_level_; // Get rank of Bonus HtH Damage + shl eax, 1; // Multiply by 2 + sub ebx, eax; // Subtract from Melee Damage + mov eax, ebx; // Move back to eax in preparation of push + retn; } } -static __declspec(naked) void MeleeWeapDmgRngDispFix() { +static __declspec(naked) void HtHDamageFix1a_hack() { __asm { - call stat_level_; // Get Melee Damage - mov ebx,eax; // Store Melee Damage value - mov edx,dword ptr ds:[_stack]; // Get pointer to critter - mov eax,dword ptr ds:[_obj_dude]; // Get pointer to PC - cmp eax,edx; // Is PC == critter? - jnz end; // exit if no - mov edx,PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Otherwise, get rank of Bonus HtH Damage - shl eax,0x1; // Multiply by 2 - sub ebx,eax; // Subtract from Melee Damage + xor edx, edx; + cmp ecx, dword ptr ds:[_obj_dude]; // Is the critter == PC? + jnz skip; // Skip if no + mov edx, PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage + mov eax, ecx; // pointer to PC + call perk_level_; // Return Rank_of_Bonus_HtH_Damage_perk + shl eax, 1; // Rank_of_Bonus_HtH_Damage_perk *= 2 + mov edx, eax; // Min_Damage = Rank_of_Bonus_HtH_Damage_perk +skip: + add edx, 1; // Min_Damage += 1 + retn; + } +} + +static __declspec(naked) void HtHDamageFix1b_hook() { + __asm { + call stat_level_; // Get Total_Melee_Damage + cmp ecx, dword ptr ds:[_obj_dude]; // Is the critter == PC? + jnz end; // Skip to exit if no + push eax; + mov edx, PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage + mov eax, ecx; // pointer to PC + call perk_level_; // Return Rank_of_Bonus_HtH_Damage_perk + shl eax, 1; // Rank_of_Bonus_HtH_Damage_perk *= 2 + add dword ptr [esp + 0x24 - 0x20 + 8], eax; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk + pop eax; end: - jmp MeleeExit; + retn; } } -static __declspec(naked) void UnarmedDmgRngDispFix() { - __asm { - mov ebx,eax; // Store Melee Damage value - mov edx,dword ptr ds:[_stack]; // Get pointer to critter - mov eax,dword ptr ds:[_obj_dude]; // Get pointer to PC - cmp eax,edx; // Is PC == critter? - jnz end; // exit if no - mov edx,PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Otherwise, get rank of Bonus HtH Damage - shl eax,0x1; // Multiply by 2 - sub ebx,eax; // Subtract to Melee Damage -end: - mov eax,ebx; // Move back to eax in prepartion of push - add eax,0x2; // Add 2 (max unarmed damage value) - push eax; // push to print string - mov eax,dword ptr ss:[esp+0x98]; - jmp UnarmedExit; - } -} - -static __declspec(naked) void HtHDamageFix1a() { - __asm { - mov eax,ecx; // stat_level_ argument: pointer to critter - mov edx,STAT_melee_dmg; // stat_level_ argument: STAT_melee_dmg - call stat_level_; // Get Total_Melee_Damage - add eax,2; // Total_Melee_Damage += 2 - mov dword ptr ss:[esp],eax; // Max_Damage = Total_Melee_Damage - xor edx,edx; - mov eax,dword ptr ds:[_obj_dude]; // Get pointer to PC - cmp ecx,eax; // Is the critter == PC? - jnz ajmp; // Skip to ajmp if no - mov edx,PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Return Rank_of_Bonus_HtH_Damage_perk - shl eax,0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2 - mov edx, eax; // Min_Damage = Rank_of_Bonus_HtH_Damage_perk -ajmp: - add edx,1; // Min_Damage += 1 - mov dword ptr ss:[esp+0x4],edx; // Store Min_Damage - sub esi,0x8; // Set up for switch statement beyond jump - jmp FixaEnd; - } -} - -static __declspec(naked) void HtHDamageFix1b() { - __asm { - call stat_level_; // Get Total_Melee_Damage - mov ebp, eax; - mov eax, dword ptr ds:[_obj_dude]; // Get pointer to PC - cmp ecx, eax; // Is the critter == PC? - jnz end; // Skip to exit if no - mov edx, PERK_bonus_hth_damage; // perk_level_ argument: PERK_bonus_hth_damage - call perk_level_; // Return Rank_of_Bonus_HtH_Damage_perk - shl eax, 0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2 - add dword ptr ss:[esp+0x4], eax; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk -end: - jmp FixbEnd; - } -} - static void __declspec(naked) DisplayBonusRangedDmg_hook() { __asm { mov edx, PERK_bonus_ranged_damage; @@ -633,7 +583,7 @@ static void __declspec(naked) DisplayBonusHtHDmg1_hook() { mov eax, dword ptr ds:[_stack]; call perk_level_; shl eax, 1; - add dword ptr [esp + 4 * 4], eax; // min_dmg + bonus + add dword ptr [esp + 4 * 4], eax; // min_dmg + perk bonus jmp sprintf_; } } @@ -688,23 +638,23 @@ void AmmoModInit() { int DisplayBonusDmg = GetPrivateProfileIntA("Misc", "DisplayBonusDamage", 0, ini); if (BonusHtHDmgFix) { dlog("Applying Bonus HtH Damage Perk fix.", DL_INIT); - MakeJump(0x435C0C, MeleeDmgDispFix); - MakeJump(0x43991C, MeleeDmgPrintFix); - if (!DisplayBonusDmg) { - MakeJump(0x472266, MeleeWeapDmgRngDispFix); - MakeJump(0x47254B, UnarmedDmgRngDispFix); + if (!DisplayBonusDmg) { // Subtract damage from perk bonus (vanilla displaying) + HookCall(0x435C0C, MeleeDmgDisplayPrintFix_hook); // DisplayFix (ListDrvdStats_) + HookCall(0x439921, MeleeDmgDisplayPrintFix_hook); // PrintFix (Save_as_ASCII_) + HookCall(0x472266, CommonDmgRngDispFix_hook); // MeleeWeap (display_stats_) + HookCall(0x472546, CommonDmgRngDispFix_hook); // Unarmed (display_stats_) } - MakeJump(0x478492, HtHDamageFix1a); - MakeJump(0x47854C, HtHDamageFix1b); + MakeCall(0x478492, HtHDamageFix1a_hack); // Unarmed (item_w_damage_) + HookCall(0x47854C, HtHDamageFix1b_hook); // MeleeWeap (item_w_damage_) dlogr(" Done", DL_INIT); } if (DisplayBonusDmg) { dlog("Applying Display Bonus Damage patch.", DL_INIT); - HookCall(0x4722DD, DisplayBonusRangedDmg_hook); + HookCall(0x4722DD, DisplayBonusRangedDmg_hook); // display_stats_ if (BonusHtHDmgFix) { - HookCall(0x472309, DisplayBonusHtHDmg1_hook); - MakeJump(0x472546, DisplayBonusHtHDmg2_hack); + HookCall(0x472309, DisplayBonusHtHDmg1_hook); // display_stats_ + MakeJump(0x472546, DisplayBonusHtHDmg2_hack); // display_stats_ } dlogr(" Done", DL_INIT); } diff --git a/sfall/AnimationsAtOnceLimit.cpp b/sfall/AnimationsAtOnceLimit.cpp index d9fdf0de..6df75f30 100644 --- a/sfall/AnimationsAtOnceLimit.cpp +++ b/sfall/AnimationsAtOnceLimit.cpp @@ -181,6 +181,8 @@ static DWORD __fastcall CheckSetSad(BYTE openFlag, DWORD valueMul) { return result; } +static const DWORD object_move_back0 = 0x417611; +static const DWORD object_move_back1 = 0x417616; static void __declspec(naked) object_move_hack() { __asm { mov ecx, ds:[ecx + 0x3C]; // openFlag @@ -188,11 +190,9 @@ static void __declspec(naked) object_move_hack() { call CheckSetSad; test eax, eax; jz end; - push 0x417611; // fixed jump - retn; + jmp object_move_back0; // fixed jump end: - push 0x417616; // default - retn; + jmp object_move_back1; // default } } diff --git a/sfall/Bugs.cpp b/sfall/Bugs.cpp index 095a2413..a4f1957a 100644 --- a/sfall/Bugs.cpp +++ b/sfall/Bugs.cpp @@ -590,23 +590,6 @@ skip: } } -// simple hooks from 4.x LoadGameHook.cpp without new game mode flags -static void __declspec(naked) LootContainerWrapper() { - __asm { - call loot_container_; - jmp ResetBodyState; - } -} - -static void __declspec(naked) BarterInventoryWrapper() { - __asm { - push [esp + 4]; - call barter_inventory_; - call ResetBodyState; - retn 4; - } -} - static void __declspec(naked) inven_pickup_hack() { __asm { mov edx, ds:[_pud] @@ -1561,11 +1544,6 @@ void BugsInit() 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); //} diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 0c414997..07525f14 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -614,6 +614,7 @@ const DWORD trait_get_ = 0x4B3B54; const DWORD trait_init_ = 0x4B39F0; const DWORD trait_level_ = 0x4B3BC8; const DWORD trait_set_ = 0x4B3B48; +const DWORD use_inventory_on_ = 0x4717E4; const DWORD _word_wrap_ = 0x4BC6F0; const DWORD win_add_ = 0x4D6238; const DWORD win_delete_ = 0x4D6468; @@ -906,3 +907,29 @@ long __fastcall WordWrap(const char* text, int maxWidth, DWORD* buf, BYTE* count call _word_wrap_ } } + +void __stdcall RedrawWin(DWORD winRef) { + __asm { + mov eax, winRef + call win_draw_ + } +} + +void __stdcall DisplayInventory(long inventoryOffset, long visibleOffset, long mode) { + __asm { + mov ebx, mode + mov edx, visibleOffset + mov eax, inventoryOffset + call display_inventory_ + } +} + +void __stdcall DisplayTargetInventory(long inventoryOffset, long visibleOffset, DWORD* targetInventory, long mode) { + __asm { + mov ecx, mode + mov ebx, targetInventory + mov edx, visibleOffset + mov eax, inventoryOffset + call display_target_inventory_ + } +} diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index bc40907b..fab698cd 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -810,6 +810,7 @@ extern const DWORD trait_get_; extern const DWORD trait_init_; extern const DWORD trait_level_; extern const DWORD trait_set_; +extern const DWORD use_inventory_on_; extern const DWORD _word_wrap_; extern const DWORD win_add_; extern const DWORD win_delete_; @@ -975,3 +976,9 @@ long __stdcall CreateWindowFunc(const char* winName, long x, long y, long width, long __stdcall WinRegisterButton(DWORD winRef, long xPos, long yPos, long width, long height, long hoverOn, long hoverOff, long buttonDown, long buttonUp, BYTE* pictureUp, BYTE* pictureDown, long arg12, long buttonType); long __fastcall WordWrap(const char* text, int maxWidth, DWORD* buf, BYTE* count); + +void __stdcall RedrawWin(DWORD winRef); + +void __stdcall DisplayInventory(long inventoryOffset, long visibleOffset, long mode); + +void __stdcall DisplayTargetInventory(long inventoryOffset, long visibleOffset, DWORD* targetInventory, long mode); diff --git a/sfall/HeroAppearance.cpp b/sfall/HeroAppearance.cpp index 92e518be..2be0d8e6 100644 --- a/sfall/HeroAppearance.cpp +++ b/sfall/HeroAppearance.cpp @@ -577,13 +577,6 @@ void HideWin(int WinRef) { } } */ -//----------------------------------------------------------------------------------------------------------------------- -void RedrawWin(int WinRef) { - __asm { - mov eax, WinRef - call win_draw_ - } -} /////////////////////////////////////////////////////////////////BUTTON FUNCTIONS//////////////////////////////////////////////////////////////////////// diff --git a/sfall/HeroAppearance.h b/sfall/HeroAppearance.h index 9dd952bd..787c0ce3 100644 --- a/sfall/HeroAppearance.h +++ b/sfall/HeroAppearance.h @@ -37,7 +37,6 @@ typedef struct WINinfo { } WINinfo; WINinfo *GetWinStruct(int WinRef); -void RedrawWin(int WinRef); void PrintText(char *DisplayText, BYTE ColourIndex, DWORD Xpos, DWORD Ypos, DWORD TxtWidth, DWORD ToWidth, BYTE *ToSurface); DWORD GetTextWidth(char *TextMsg); DWORD GetMaxCharWidth(); diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index fb42f108..ee207514 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -451,6 +451,36 @@ static void __declspec(naked) HandleInventoryHook() { } } +static void __declspec(naked) UseInventoryOnHook() { + __asm { + or InLoop, INTFACEUSE; + call use_inventory_on_; + and InLoop, (-1 ^ INTFACEUSE); + retn; + } +} + +static void __declspec(naked) LootContainerHook() { + __asm { + or InLoop, INTFACELOOT; + call loot_container_; + and InLoop, (-1 ^ INTFACELOOT); + jmp ResetBodyState; // reset object pointer used in calculating the weight/size of equipped and hidden items on NPCs after exiting loot/barter screens + //retn; + } +} + +static void __declspec(naked) BarterInventoryHook() { + __asm { + or InLoop, BARTER; + push [esp + 4]; + call barter_inventory_; + and InLoop, (-1 ^ BARTER); + call ResetBodyState; + retn 4; + } +} + static void __declspec(naked) AutomapHook() { __asm { or InLoop, AUTOMAP; @@ -526,6 +556,11 @@ void LoadGameHookInit() { HookCall(0x4434AC, SkilldexHook); HookCall(0x44C7BD, SkilldexHook); HookCall(0x443357, HandleInventoryHook); + HookCall(0x44C6FB, UseInventoryOnHook); + HookCall(0x4746EC, LootContainerHook); + HookCall(0x4A4369, LootContainerHook); + HookCall(0x4A4565, LootContainerHook); + HookCall(0x4466C7, BarterInventoryHook); HookCall(0x44396D, AutomapHook); HookCall(0x479519, AutomapHook); } diff --git a/sfall/LoadGameHook.h b/sfall/LoadGameHook.h index 03242b47..1d35cfd5 100644 --- a/sfall/LoadGameHook.h +++ b/sfall/LoadGameHook.h @@ -24,21 +24,24 @@ bool IsMapLoaded(); DWORD InWorldMap(); DWORD InCombat(); -#define WORLDMAP (1<<0) // 0x1 -#define LOCALMAP (1<<1) // 0x2 No point hooking this: would always be 1 at any point at which scripts are running -#define DIALOG (1<<2) // 0x4 -#define ESCMENU (1<<3) // 0x8 -#define SAVEGAME (1<<4) // 0x10 -#define LOADGAME (1<<5) // 0x20 -#define COMBAT (1<<6) // 0x40 -#define OPTIONS (1<<7) // 0x80 -#define HELP (1<<8) // 0x100 -#define CHARSCREEN (1<<9) // 0x200 -#define PIPBOY (1<<10) // 0x400 -#define PCOMBAT (1<<11) // 0x800 -#define INVENTORY (1<<12) // 0x1000 -#define AUTOMAP (1<<13) // 0x2000 -#define SKILLDEX (1<<14) // 0x4000 -#define RESERVED (1<<31) +#define WORLDMAP (1<<0) // 0x1 +#define LOCALMAP (1<<1) // 0x2 No point hooking this: would always be 1 at any point at which scripts are running +#define DIALOG (1<<2) // 0x4 +#define ESCMENU (1<<3) // 0x8 +#define SAVEGAME (1<<4) // 0x10 +#define LOADGAME (1<<5) // 0x20 +#define COMBAT (1<<6) // 0x40 +#define OPTIONS (1<<7) // 0x80 +#define HELP (1<<8) // 0x100 +#define CHARSCREEN (1<<9) // 0x200 +#define PIPBOY (1<<10) // 0x400 +#define PCOMBAT (1<<11) // 0x800 +#define INVENTORY (1<<12) // 0x1000 +#define AUTOMAP (1<<13) // 0x2000 +#define SKILLDEX (1<<14) // 0x4000 +#define INTFACEUSE (1<<15) // 0x8000 +#define INTFACELOOT (1<<16) // 0x10000 +#define BARTER (1<<17) // 0x20000 +#define RESERVED (1<<31) DWORD GetCurrentLoops(); diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index aacdf997..a20c9dc6 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -125,6 +125,17 @@ public: } } + bool asBool() const { + switch (_type) { + case DATATYPE_FLOAT: + return static_cast(_val.f) != 0; + case DATATYPE_INT: + return _val.i != 0; + default: + return true; + } + } + float asFloat() const { switch (_type) { case DATATYPE_FLOAT: @@ -376,6 +387,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = { {sf_get_current_inven_size, "get_current_inven_size", {DATATYPE_MASK_VALID_OBJ}}, {sf_get_flags, "get_flags", {DATATYPE_MASK_VALID_OBJ}}, {sf_get_outline, "get_outline", {DATATYPE_MASK_VALID_OBJ}}, + {sf_inventory_redraw, "inventory_redraw", {DATATYPE_MASK_INT}}, {sf_item_weight, "item_weight", {DATATYPE_MASK_VALID_OBJ}}, {sf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}}, {sf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, diff --git a/sfall/ScriptOps/InterfaceOp.hpp b/sfall/ScriptOps/InterfaceOp.hpp index d4c87c14..0724f2d5 100644 --- a/sfall/ScriptOps/InterfaceOp.hpp +++ b/sfall/ScriptOps/InterfaceOp.hpp @@ -497,6 +497,33 @@ static void sf_display_stats() { } } +static void sf_inventory_redraw() { + int mode = -1; + DWORD loopFlag = GetCurrentLoops(); + if (loopFlag & INVENTORY) { + mode = 0; + } else if (loopFlag & INTFACEUSE) { + mode = 1; + } else if (loopFlag & INTFACELOOT) { + mode = 2; + } else if (loopFlag & BARTER) { + mode = 3; + } else { + return; + } + + if (!opHandler.arg(0).asBool()) { + int* stack_offset = (int*)_stack_offset; + stack_offset[*ptr_curr_stack * 4] = 0; + DisplayInventory(0, -1, mode); + } else if (mode >= 2) { + int* target_stack_offset = (int*)_target_stack_offset; + target_stack_offset[*ptr_target_curr_stack * 4] = 0; + DisplayTargetInventory(0, -1, (DWORD*)*ptr_target_pud, mode); + RedrawWin(*ptr_i_wid); + } +} + static void sf_create_win() { int flags; if (opHandler.numArgs() == 6) { diff --git a/sfall/ScriptOps/MetaruleOp.hpp b/sfall/ScriptOps/MetaruleOp.hpp index a6ce6a8d..b3d93209 100644 --- a/sfall/ScriptOps/MetaruleOp.hpp +++ b/sfall/ScriptOps/MetaruleOp.hpp @@ -119,6 +119,7 @@ static const SfallMetarule metaruleArray[] = { {"intface_is_hidden", sf_intface_is_hidden, 0, 0}, {"intface_redraw", sf_intface_redraw, 0, 0}, {"intface_show", sf_intface_show, 0, 0}, + {"inventory_redraw", sf_inventory_redraw, 1, 1}, {"item_weight", sf_item_weight, 1, 1}, {"outlined_object", sf_outlined_object, 0, 0}, {"set_cursor_mode", sf_set_cursor_mode, 1, 1},