mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
+28
-26
@@ -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)) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user