Added a fix for unable to sell/give items to the other in barter screen when the player/party member is overloaded (from Mr.Stalin)

Added a variant of MakeCall/Jump with 3 arguments to replace some SafeWrite 0x90 code for trailing NOPs.
This commit is contained in:
NovaRain
2018-11-30 11:25:11 +08:00
parent 17be216a11
commit db2c366376
17 changed files with 71 additions and 76 deletions
+28 -26
View File
@@ -954,6 +954,17 @@ found:
}
}
static void __declspec(naked) barter_attempt_transaction_hook_weight() {
__asm {
call fo::funcoffs::item_total_weight_;
test eax, eax;
jnz skip;
xor edx, edx;
skip:
retn;
}
}
static void __declspec(naked) item_m_turn_off_hook() {
__asm {
and byte ptr [eax+0x25], 0xDF // Rest flag of used items
@@ -1197,7 +1208,6 @@ static void __declspec(naked) Save_as_ASCII_hack() {
__asm {
mov edx, STAT_sequence;
mov ebx, 626; // line index in EDITOR.MSG
push 0x4396FC; // call stat_level_
retn;
}
}
@@ -1275,7 +1285,6 @@ static void __declspec(naked) partyMemberGetCurLevel_hack() {
__asm {
mov esi, 0xFFFFFFFF; // initialize party member index
mov edi, dword ptr ds:[FO_VAR_partyMemberMaxCount];
push 0x495FFC;
retn;
}
}
@@ -1842,16 +1851,14 @@ void BugFixes::init()
dlog("Applying fix for not counting in weight of equipped items on NPC.", DL_INIT);
MakeCall(0x473B4E, loot_container_hack);
HookCall(0x4758AB, barter_inventory_hook);
MakeCall(0x477EAB, item_total_weight_hack);
SafeWrite8(0x477EB0, 0x90);
MakeCall(0x479A2F, item_c_curr_size_hack);
SafeWrite8(0x479A34, 0x90);
MakeCall(0x477EAB, item_total_weight_hack, 1);
MakeCall(0x479A2F, item_c_curr_size_hack, 1);
dlogr(" Done", DL_INIT);
//}
// Corrects the max text width of the item weight in trading interface to be 64 (was 80), which matches the table width
SafeWrite32(0x475541, 64);
SafeWrite32(0x475789, 64);
SafeWrite8(0x475541, 64);
SafeWrite8(0x475789, 64);
// Corrects the max text width of the player name in inventory to be 140 (was 80), which matches the width for item name
SafeWrite32(0x471E48, 140);
@@ -1930,10 +1937,8 @@ void BugFixes::init()
dlog("Applying MultiHex Pathing Fix.", DL_INIT);
MakeCalls(MultiHexFix, {0x42901F, 0x429170});
// Fix for multihex critters moving too close and overlapping their targets in combat
MakeCall(0x42A14F, MultiHexCombatRunFix);
SafeWrite8(0x42A154, 0x90);
MakeCall(0x42A178, MultiHexCombatMoveFix);
SafeWrite8(0x42A17D, 0x90);
MakeCall(0x42A14F, MultiHexCombatRunFix, 1);
MakeCall(0x42A178, MultiHexCombatMoveFix, 1);
dlogr(" Done", DL_INIT);
//}
@@ -2016,12 +2021,9 @@ void BugFixes::init()
// Fix for the engine not checking player's inventory properly when putting items into the bag/backpack in the hands
MakeJump(0x4715DB, switch_hand_hack);
// Fix to ignore player's equipped items when opening bag/backpack
MakeCall(0x471B7F, inven_item_wearing); // inven_right_hand_
SafeWrite8(0x471B84, 0x90); // nop
MakeCall(0x471BCB, inven_item_wearing); // inven_left_hand_
SafeWrite8(0x471BD0, 0x90); // nop
MakeCall(0x471C17, inven_item_wearing); // inven_worn_
SafeWrite8(0x471C1C, 0x90); // nop
MakeCall(0x471B7F, inven_item_wearing, 1); // inven_right_hand_
MakeCall(0x471BCB, inven_item_wearing, 1); // inven_left_hand_
MakeCall(0x471C17, inven_item_wearing, 1); // inven_worn_
// Fix crash when trying to open bag/backpack on the table in the bartering interface
MakeCall(0x473191, inven_action_cursor_hack);
dlogr(" Done", DL_INIT);
@@ -2034,7 +2036,7 @@ void BugFixes::init()
MakeJump(0x47808C, ItemCountFix); // replacing item_count_ function
// Fix for Sequence stat value not being printed correctly when using "print to file" option
MakeJump(0x4396F5, Save_as_ASCII_hack);
MakeCall(0x4396F5, Save_as_ASCII_hack, 2);
// Fix for Bonus Move APs being replenished when you save and load the game in combat
//if (GetConfigInt("Misc", "BonusMoveFix", 1)) {
@@ -2059,7 +2061,7 @@ void BugFixes::init()
//}
// Fix crash when calling partyMemberGetCurLevel_ on a critter that has no data in party.txt
MakeJump(0x495FF6, partyMemberGetCurLevel_hack);
MakeCall(0x495FF6, partyMemberGetCurLevel_hack, 1);
// Fix for player's base EMP DR not being properly initialized when creating a new character and then starting the game
HookCall(0x4A22DF, &ResetPlayer_hook);
@@ -2085,8 +2087,7 @@ void BugFixes::init()
MakeCalls(obj_examine_func_hack_ammo0, {0x49B4AD, 0x49B504});
SafeWrite16(0x49B4B2, 0x9090);
SafeWrite16(0x49B509, 0x9090);
MakeCall(0x49B563, obj_examine_func_hack_ammo1);
SafeWrite16(0x49B568, 0x9090);
MakeCall(0x49B563, obj_examine_func_hack_ammo1, 2);
dlogr(" Done", DL_INIT);
// Display full item description for weapon/ammo in barter screen
@@ -2118,8 +2119,7 @@ void BugFixes::init()
dlog("Applying obj_can_hear_obj fix.", DL_INIT);
SafeWrite8(0x4583D8, 0x3B); // jz loc_458414
SafeWrite8(0x4583DE, 0x74); // jz loc_458414
MakeCall(0x4583E0, op_obj_can_hear_obj_hack);
SafeWrite8(0x4583E5, 0x90);
MakeCall(0x4583E0, op_obj_can_hear_obj_hack, 1);
dlogr(" Done", DL_INIT);
}
@@ -2135,9 +2135,11 @@ void BugFixes::init()
SafeWrite8(0x4C1015, 0x90);
HookCall(0x4C1042, wmSetupRandomEncounter_hook);
// Fix for unable to sell/give items in barter screen when the player/party member is overloaded
HookCalls(barter_attempt_transaction_hook_weight, {0x474C73, 0x474CCA});
// Fix for the underline position in the inventory display window when the item name is longer than one line
MakeCall(0x472F5F, inven_obj_examine_func_hack);
SafeWrite8(0x472F64, 0x90);
MakeCall(0x472F5F, inven_obj_examine_func_hack, 1);
// Fix for the exploit that allows you to gain excessive skill points from Tag! perk before leaving the character screen
//if (GetConfigInt("Misc", "TagPerkFix", 1)) {
+6 -9
View File
@@ -73,7 +73,6 @@ static void __declspec(naked) GetNumButtonsHook1() {
lea esi, menus;
mov eax, [esi+edi*4];
mov eax, [FO_VAR_btncnt + eax*4];
push 0x43F064;
retn;
}
}
@@ -83,7 +82,6 @@ static void __declspec(naked) GetNumButtonsHook2() {
lea edx, menus;
mov eax, [edx+edi*4];
mov eax, [FO_VAR_btncnt + eax*4];
push 0x43F18B;
retn;
}
}
@@ -93,7 +91,6 @@ static void __declspec(naked) GetNumButtonsHook3() {
lea eax, menus;
mov eax, [eax+edi*4];
mov eax, [FO_VAR_btncnt+eax*4];
push 0x43F1EB;
retn;
}
}
@@ -124,9 +121,11 @@ void ResetElevators() {
void ElevatorsInit(const char* file) {
strcpy_s(elevFile, ".\\");
strcat_s(elevFile, file);
HookCall(0x43EF83, GetMenuHook);
HookCall(0x43F141, UnknownHook);
HookCall(0x43F2D2, UnknownHook2);
SafeWrite8(0x43EF76, (BYTE)elevatorCount);
SafeWrite32(0x43EFA4, (DWORD)elevatorExits);
SafeWrite32(0x43EFB9, (DWORD)elevatorExits);
@@ -135,12 +134,10 @@ void ElevatorsInit(const char* file) {
SafeWrite32(0x43F309, (DWORD)&elevatorExits[0][0].elevation);
SafeWrite32(0x43F315, (DWORD)&elevatorExits[0][0].tile);
SafeWrite8(0x43F05D, 0xe9);
HookCall(0x43F05D, GetNumButtonsHook1);
SafeWrite8(0x43F184, 0xe9);
HookCall(0x43F184, GetNumButtonsHook2);
SafeWrite8(0x43F1E4, 0xe9);
HookCall(0x43F1E4, GetNumButtonsHook3);
MakeCall(0x43F05D, GetNumButtonsHook1, 2);
MakeCall(0x43F184, GetNumButtonsHook2, 2);
MakeCall(0x43F1E4, GetNumButtonsHook3, 2);
ResetElevators();
}
+2 -4
View File
@@ -314,10 +314,8 @@ static void apply_expl_hack() {
MakeCall(0x49BCC7, obj_use_explosive_hack); // check explosives
MakeCall(0x49BD56, obj_use_explosive_active_hack); // set active explosive
MakeCall(0x4A2865, queue_do_explosion_hack); // set damage explosive
MakeCall(0x4737F2, inven_action_cursor_drop_hack); // check drop explosives
SafeWrite8(0x4737F7, 0x90);
MakeCall(0x49C005, protinstTestDroppedExplosive_hack); // check drop explosives
SafeWrite8(0x49C00A, 0x90);
MakeCall(0x4737F2, inven_action_cursor_drop_hack, 1); // check drop explosives
MakeCall(0x49C005, protinstTestDroppedExplosive_hack, 1); // check drop explosives
}
void Explosions::AddToExplosives(DWORD pid, DWORD activePid, DWORD minDmg, DWORD maxDmg) {
+1 -2
View File
@@ -491,8 +491,7 @@ void ExtraSaveSlots::init() {
}
if (extraSaveSlots) {
MakeCall(0x47B923, SaveGame_hack1);
SafeWrite8(0x47B928, 0x90);
MakeCall(0x47B923, SaveGame_hack1, 1);
} else {
SafeWrite8(0x47B923, 0x89);
SafeWrite32(0x47B924, 0x5193B83D); // mov [slot_cursor], edi(0)
+4 -7
View File
@@ -129,10 +129,7 @@ DWORD _stdcall GetHSArgCount() {
}
DWORD _stdcall GetHSArg() {
if (cArg == argCount)
return 0;
else
return args[cArg++];
return (cArg == argCount) ? 0 : args[cArg++];
}
void _stdcall SetHSArg(DWORD id, DWORD value) {
@@ -143,9 +140,9 @@ DWORD* _stdcall GetHSArgs() {
return args;
}
void _stdcall SetHSReturn(DWORD d) {
if (cRetTmp < 8) {
rets[cRetTmp++] = d;
void _stdcall SetHSReturn(DWORD value) {
if (cRetTmp < maxRets) {
rets[cRetTmp++] = value;
}
if (cRetTmp > cRet) {
cRet = cRetTmp;
+3
View File
@@ -13,6 +13,9 @@ namespace sfall
// Number of types of hooks
constexpr int numHooks = HOOK_COUNT;
// Maximum number of return values
const int maxRets = 8;
// Struct for registered hook script
struct HookScript {
ScriptProgram prog;
+1 -2
View File
@@ -400,8 +400,7 @@ void Inject_InventoryMoveHook() {
0x473851, 0x47386F,
0x47379A // caps multi drop
});
MakeCall(0x473807, InvenActionExplosiveDropHack); // drop active explosives
SafeWrite8(0x47380C, 0x90);
MakeCall(0x473807, InvenActionExplosiveDropHack, 1); // drop active explosives
}
void Inject_InvenWieldHook() {
+1 -2
View File
@@ -528,8 +528,7 @@ void Inject_ExplosiveTimerHook() {
void Inject_UseSkillOnHook() {
HookCalls(UseSkillOnHook, { 0x44C3CA, 0x44C81C });
MakeCall(0x4127BA, UseSkillOnHack);
SafeWrite8(0x4127BF, 0x90);
MakeCall(0x4127BA, UseSkillOnHack, 1);
MakeCalls(skill_use_hack, {0x4AB05D, 0x4AB558, 0x4ABA60}); // fix checking obj_dude's target
// replace source skill user
SafeWriteBatch<DWORD>((DWORD)&sourceSkillOn, {0x4AAF47, 0x4AB051, 0x4AB3FB, 0x4AB550, 0x4AB8FA, 0x4ABA54});
+1 -2
View File
@@ -803,8 +803,7 @@ void Inventory::init() {
if (GetConfigInt("Misc", "CheckWeaponAmmoCost", 0)) {
HookCall(0x4266E9, combat_check_bad_shot_hook);
MakeCall(0x4234B3, compute_spray_hack);
SafeWrite8(0x4234B8, 0x90);
MakeCall(0x4234B3, compute_spray_hack, 1);
}
reloadWeaponKey = GetConfigInt("Input", "ReloadWeaponKey", 0);
+2 -4
View File
@@ -350,8 +350,7 @@ static void Knockback_OnGameLoad() {
}
void Knockback::init() {
MakeCall(0x424B76, compute_damage_hack); // KnockbackMod
SafeWrite16(0x424B7B, 0x9090);
MakeCall(0x424B76, compute_damage_hack, 2); // KnockbackMod
MakeJump(0x4136D3, compute_dmg_damage_hack); // for op_critter_dmg
MakeCall(0x424791, determine_to_hit_func_hack); // HitChanceMod
@@ -362,8 +361,7 @@ void Knockback::init() {
SafeWrite32(0x4ABC6B, 0x90909090);
// Actually disables all secondary attacks for the critter, regardless of whether the weapon has a burst attack
MakeCall(0x429E44, ai_pick_hit_mode_hack); // NoBurst
SafeWrite8(0x429E49, 0x90);
MakeCall(0x429E44, ai_pick_hit_mode_hack, 1); // NoBurst
LoadGameHook::OnGameReset() += Knockback_OnGameLoad;
}
+1 -2
View File
@@ -105,8 +105,7 @@ void MainMenu::init() {
MakeJump(0x481844, MainMenuButtonYHook);
}
if (MainMenuTextOffset) {
SafeWrite8(0x481933, 0x90);
MakeCall(0x481934, MainMenuTextYHook);
MakeCall(0x481933, MainMenuTextYHook, 1);
}
MakeJump(0x4817AB, MainMenuTextHook);
+2 -4
View File
@@ -492,8 +492,7 @@ void DebugModePatch() {
SafeWrite16(0x4C6E75, 0x66EB); // jmps 0x4C6EDD
SafeWrite8(0x4C6EF2, 0xEB);
SafeWrite8(0x4C7034, 0x0);
MakeCall(0x4DC319, win_debug_hook);
SafeWrite16(0x4DC31E, 0x9090);
MakeCall(0x4DC319, win_debug_hook, 2);
}
} else {
SafeWrite32(0x4C6D9C, (DWORD)debugGnw);
@@ -869,8 +868,7 @@ void DisplaySecondWeaponRangePatch() {
void KeepWeaponSelectModePatch() {
if (GetConfigInt("Misc", "KeepWeaponSelectMode", 1)) {
dlog("Applying keep weapon select mode patch.", DL_INIT);
MakeCall(0x4714EC, switch_hand_hack);
SafeWrite8(0x4714F1, 0x90);
MakeCall(0x4714EC, switch_hand_hack, 1);
dlogr(" Done", DL_INIT);
}
}
+1 -2
View File
@@ -796,8 +796,7 @@ void Movies::init() {
HookCalls(gmovie_play_hook_pause, {0x44E816});
HookCalls(gmovie_play_hook_unpause, {0x44EA84});
MakeCall(0x450525, gsound_background_volume_set_hack);
MakeCall(0x4503CA, gsound_master_volume_set_hack);
SafeWrite8(0x4503CF, 0x90);
MakeCall(0x4503CA, gsound_master_volume_set_hack, 1);
if (allowDShowSound > 1) {
HookCall(0x450851, gsound_background_play_hook);
}
+3 -6
View File
@@ -459,13 +459,10 @@ skip:
void QuestListPatch() {
MakeCall(0x4974E4, StartPipboy_hack);
MakeCall(0x497173, pipboy_hack_action);
SafeWrite8(0x497178, 0x90);
MakeCall(0x497173, pipboy_hack_action, 1);
MakeCall(0x4971B2, pipboy_hack_press0);
SafeWrite8(0x4971B7, 0x90);
MakeCall(0x497183, pipboy_hack_press1);
SafeWrite8(0x497188, 0x90);
MakeCall(0x4971B2, pipboy_hack_press0, 1);
MakeCall(0x497183, pipboy_hack_press1, 1);
MakeCall(0x4971D9, pipboy_hack_back);
HookCall(0x497219, pipboy_hook);
+3 -4
View File
@@ -198,11 +198,10 @@ void Stats::init() {
};
MakeJump(0x4AEF4D, stat_level_hack);
MakeJump(0x4AF3AF, stat_level_hack_check);
SafeWrite16(0x4AF3B4, 0x9090);
MakeJump(0x4AF3AF, stat_level_hack_check, 2);
MakeJump(0x4AF571, stat_set_base_hack_check);
MakeCall(0x4AF09C, CalcApToAcBonus); // stat_level_
SafeMemSet(0x4AF0A1, 0x90, 3);
MakeCall(0x4AF09C, CalcApToAcBonus, 3); // stat_level_
auto xpTableList = GetConfigList("Misc", "XPTable", "", 2048);
size_t numLevels = xpTableList.size();
+10
View File
@@ -73,11 +73,21 @@ void MakeCall(DWORD addr, void* func) {
HookCall(addr, func);
}
void MakeCall(DWORD addr, void* func, int len) {
SafeMemSet(addr + 5, 0x90, len);
MakeCall(addr, func);
}
void MakeJump(DWORD addr, void* func) {
SafeWrite8(addr, 0xE9);
HookCall(addr, func);
}
void MakeJump(DWORD addr, void* func, int len) {
SafeMemSet(addr + 5, 0x90, len);
MakeJump(addr, func);
}
void HookCalls(void* func, std::initializer_list<DWORD> addrs) {
for (auto addr : addrs) {
HookCall(addr, func);
+2
View File
@@ -36,7 +36,9 @@ void _stdcall SafeWriteBatch(T data, std::initializer_list<DWORD> addrs) {
void _stdcall SafeWriteStr(DWORD addr, const char* data);
void HookCall(DWORD addr, void* func);
void MakeCall(DWORD addr, void* func);
void MakeCall(DWORD addr, void* func, int len);
void MakeJump(DWORD addr, void* func);
void MakeJump(DWORD addr, void* func, int len);
void BlockCall(DWORD addr);
void SafeMemSet(DWORD addr, BYTE val, int len);
void SafeWriteBytes(DWORD addr, BYTE* data, int count);