From 1a17ac5ac8f627eaf3d3c154359e84853957fc5c Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 30 Mar 2020 21:15:19 +0800 Subject: [PATCH] Added ActiveGeigerMsgs option and radiation fixes Changed "Radiated" to be highlighted in red color when the player is under the influence of negative effects of radiation. Some edits to macros in HookScripts.cpp. --- artifacts/ddraw.ini | 3 ++ sfall/BugFixes.cpp | 106 +++++++++++++++++++++++++-------------- sfall/FalloutEngine.cpp | 79 +++++++++++++++++++---------- sfall/FalloutEngine.h | 30 +++++++---- sfall/FalloutStructs.h | 7 ++- sfall/HookScripts.cpp | 75 ++++++++++++++------------- sfall/ScriptExtender.cpp | 2 +- sfall/main.cpp | 26 +++++++++- 8 files changed, 215 insertions(+), 113 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index a1933c2b..29b06868 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -654,6 +654,9 @@ DontTurnOffSneakIfYouRun=0 ;Set to 0 to disable switching. (Default is 3) UseWalkDistance=3 +;Set to 1 to display messages about radiation for the active geiger counter +ActiveGeigerMsgs=1 + ;Set to 1 to fix the bug of being unable to sell used geiger counters or stealth boys CanSellUsedGeiger=1 diff --git a/sfall/BugFixes.cpp b/sfall/BugFixes.cpp index de5c5d5a..54c0b382 100644 --- a/sfall/BugFixes.cpp +++ b/sfall/BugFixes.cpp @@ -1085,37 +1085,31 @@ skip: } static void __declspec(naked) combat_ctd_init_hack() { + static const DWORD combat_ctd_init_Ret = 0x422F11; __asm { - mov [esi+0x24], eax // ctd.targetTile - mov eax, [ebx+0x54] // pobj.who_hit_me - inc eax - jnz end - mov [ebx+0x54], eax // pobj.who_hit_me + mov [esi + 0x24], eax; // ctd.targetTile + mov eax, [ebx + 0x54]; // pobj.who_hit_me + inc eax; + jnz end; // jump if whoHitMe != -1 + mov [ebx + 0x54], eax; // pobj.who_hit_me = 0 end: - push 0x422F11 - retn + jmp combat_ctd_init_Ret; } } static void __declspec(naked) obj_save_hack() { - __asm { - inc eax - jz end - dec eax - mov edx, [esp+0x1C] // combat_data - mov eax, [eax+0x68] // pobj.who_hit_me.cid - test byte ptr ds:[_combat_state], 1 // in combat? - jz clear // No - cmp dword ptr [edx], 0 // in combat? - jne skip // Yes + __asm { // edx - combat_data + mov eax, [eax + 0x68]; // pobj.who_hit_me.cid + test byte ptr ds:[_combat_state], 1; // in combat? + jz clear; // No + cmp dword ptr [edx], 0; // in combat? + jne skip; // Yes clear: - xor eax, eax - dec eax + xor eax, eax; + dec eax; // -1 skip: - mov [edx+0x18], eax // combat_data.who_hit_me -end: - push 0x489422 - retn + mov [edx + 0x18], eax; // combat_data.who_hit_me + retn; } } @@ -1497,11 +1491,14 @@ static void __declspec(naked) ResetPlayer_hook() { } } -static const DWORD obj_move_to_tile_Ret = 0x48A74E; static void __declspec(naked) obj_move_to_tile_hack() { + static const DWORD obj_move_to_tile_Ret = 0x48A74E; __asm { - cmp dword ptr ds:[_map_state], 0; // map number, -1 exit to worldmap + cmp ds:[_loadingGame], 0; + jnz skip; + cmp dword ptr ds:[_map_state], 0; // map number, -1 exit to worldmap (probably redundant) jz mapLeave; +skip: add esp, 4; jmp obj_move_to_tile_Ret; mapLeave: @@ -1854,7 +1851,32 @@ noRange: } } +static void __declspec(naked) process_rads_hack() { + static const DWORD process_rads_Ret = 0x42D708; + __asm { + test ebp, ebp; + jl fix; + test byte ptr [ecx + 0x44], DAM_DEAD; + jnz fix; + retn; +fix: + add esp, 4; + jmp process_rads_Ret; + } +} + static void __declspec(naked) process_rads_hook() { + __asm { + test ebp, ebp; + jg skip; + mov esi, 999; // msg number + mov [esp + 0x20 - 0x20 + 4], esi; +skip: + jmp message_search_; + } +} + +static void __declspec(naked) process_rads_hook_msg() { __asm { push eax; // death message for DialogOut call display_print_; @@ -2771,6 +2793,16 @@ void BugFixesInit() dlogr(" Done", DL_INIT); //} + // Enable party members with level 6 protos to reach level 6 + //if (GetConfigInt("Misc", "NPCStage6Fix", 1)) { + dlog("Applying NPC Stage 6 Fix.", DL_INIT); + MakeJump(0x493CE9, NPCStage6Fix1); // partyMember_init_ + MakeJump(0x494224, NPCStage6Fix2); // partyMemberGetAIOptions_ + SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage (partyMember_init_) + SafeWrite8(0x4940BB, 204); // move pointer by 204 bytes instead of 200 + dlogr(" Done", DL_INIT); + //} + //if (GetConfigInt("Misc", "NPCLevelFix", 1)) { dlog("Applying NPC level fix.", DL_INIT); HookCall(0x495BC9, (void*)0x495E51); // jz 0x495E7F > jz 0x495E51 @@ -2831,16 +2863,6 @@ void BugFixesInit() dlogr(" Done", DL_INIT); //} - // Enable party members with level 6 protos to reach level 6 - //if (GetConfigInt("Misc", "NPCStage6Fix", 1)) { - dlog("Applying NPC Stage 6 Fix.", DL_INIT); - MakeJump(0x493CE9, NPCStage6Fix1); // partyMember_init_ - MakeJump(0x494224, NPCStage6Fix2); // partyMemberGetAIOptions_ - SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage (partyMember_init_) - SafeWrite8(0x4940BB, 204); // move pointer by 204 bytes instead of 200 - dlogr(" Done", DL_INIT); - //} - //if (GetConfigInt("Misc", "MultiHexPathingFix", 1)) { dlog("Applying MultiHex Pathing Fix.", DL_INIT); MakeCall(0x42901F, MultiHexFix); @@ -2876,7 +2898,7 @@ void BugFixesInit() dlog("Applying fix for explosives bugs.", DL_INIT); // Fix crashes when killing critters with explosives MakeJump(0x422F05, combat_ctd_init_hack); - MakeJump(0x489413, obj_save_hack); + MakeCall(0x48941C, obj_save_hack, 1); // Fix for destroy_p_proc not being called if the critter is killed by explosives when you leave the map MakeCall(0x4130C3, action_explode_hack); MakeCall(0x4130E5, action_explode_hack1); @@ -3089,8 +3111,18 @@ void BugFixesInit() // Fix for determine_to_hit_func_ engine function taking distance into account when called from determine_to_hit_no_range_ HookCall(0x4244C3, determine_to_hit_func_hook); + // Radiation fixes + MakeCall(0x42D6C3, process_rads_hack, 1); // prevents player's death if a stat is less than 1 when removing radiation effects + HookCall(0x42D67A, process_rads_hook); // fix for the same message being displayed when removing radiation effects + // Display messages about radiation for the active geiger counter + if (GetConfigInt("Misc", "ActiveGeigerMsgs", 1)) { + dlog("Applying active geiger counter messages patch.", DL_INIT); + SafeWrite8(0x42D424, 0x74); // jnz > jz + SafeWrite8(0x42D444, 0x74); + dlogr(" Done", DL_INIT); + } // Display a pop-up messages box about death from radiation - HookCall(0x42D733, process_rads_hook); + HookCall(0x42D733, process_rads_hook_msg); // Fix for AI not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory if (GetConfigInt("Misc", "AIDrugUsePerfFix", 0)) { diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 2c394cbf..3837105c 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -315,6 +315,7 @@ const DWORD critter_can_obj_dude_rest_ = 0x42E564; const DWORD critter_compute_ap_from_distance_ = 0x42E62C; const DWORD critter_flag_check_ = 0x42E6AC; const DWORD critter_get_hits_ = 0x42D18C; +const DWORD critter_get_rads_ = 0x42D38C; const DWORD critter_is_dead_ = 0x42DD18; const DWORD critter_kill_ = 0x42DA64; const DWORD critter_kill_count_type_ = 0x42D920; @@ -990,30 +991,6 @@ long __stdcall ScrPtr(long scriptId, TScript** scriptPtr) { WRAP_WATCOM_CALL2(scr_ptr_, scriptId, scriptPtr) } -long __stdcall RegisterObjectAnimateAndHide(TGameObj* object, long anim, long delay) { - WRAP_WATCOM_CALL3(register_object_animate_and_hide_, object, anim, delay) -} - -long __stdcall RegisterObjectChangeFid(TGameObj* object, long artFid, long delay) { - WRAP_WATCOM_CALL3(register_object_change_fid_, object, artFid, delay) -} - -long __stdcall RegisterObjectLight(TGameObj* object, long lightRadius, long delay) { - WRAP_WATCOM_CALL3(register_object_light_, object, lightRadius, delay) -} - -long __stdcall RegisterObjectMustErase(TGameObj* object) { - WRAP_WATCOM_CALL1(register_object_must_erase_, object) -} - -long __stdcall RegisterObjectTakeOut(TGameObj* object, long holdFrameId, long nothing) { - WRAP_WATCOM_CALL3(register_object_take_out_, object, holdFrameId, nothing) -} - -long __stdcall RegisterObjectTurnTowards(TGameObj* object, long tileNum, long nothing) { - WRAP_WATCOM_CALL3(register_object_turn_towards_, object, tileNum, nothing) -} - long __stdcall ScrNew(long* scriptID, long sType) { WRAP_WATCOM_CALL2(scr_new_, scriptID, sType) } @@ -1051,6 +1028,10 @@ void __stdcall IntfaceRedraw() { WRAP_WATCOM_CALL0(intface_redraw_) } +long __stdcall PickDeath(TGameObj* attacker, TGameObj* target, TGameObj* weapon, long amount, long anim, long hitFromBack) { + WRAP_WATCOM_CALL6(pick_death_, attacker, target, weapon, amount, anim, hitFromBack) +} + void __stdcall ProcessBk() { WRAP_WATCOM_CALL0(process_bk_) } @@ -1059,6 +1040,38 @@ void __stdcall ProtoDudeUpdateGender() { WRAP_WATCOM_CALL0(proto_dude_update_gender_) } +long* __stdcall QueueFindFirst(TGameObj* object, long qType) { + WRAP_WATCOM_CALL2(queue_find_first_, object, qType) +} + +long* __stdcall QueueFindNext(TGameObj* object, long qType) { + WRAP_WATCOM_CALL2(queue_find_next_, object, qType) +} + +long __stdcall RegisterObjectAnimateAndHide(TGameObj* object, long anim, long delay) { + WRAP_WATCOM_CALL3(register_object_animate_and_hide_, object, anim, delay) +} + +long __stdcall RegisterObjectChangeFid(TGameObj* object, long artFid, long delay) { + WRAP_WATCOM_CALL3(register_object_change_fid_, object, artFid, delay) +} + +long __stdcall RegisterObjectLight(TGameObj* object, long lightRadius, long delay) { + WRAP_WATCOM_CALL3(register_object_light_, object, lightRadius, delay) +} + +long __stdcall RegisterObjectMustErase(TGameObj* object) { + WRAP_WATCOM_CALL1(register_object_must_erase_, object) +} + +long __stdcall RegisterObjectTakeOut(TGameObj* object, long holdFrameId, long nothing) { + WRAP_WATCOM_CALL3(register_object_take_out_, object, holdFrameId, nothing) +} + +long __stdcall RegisterObjectTurnTowards(TGameObj* object, long tileNum, long nothing) { + WRAP_WATCOM_CALL3(register_object_turn_towards_, object, tileNum, nothing) +} + // pops value type from Data stack (must be followed by InterpretPopLong) DWORD __stdcall InterpretPopShort(TProgram* scriptPtr) { WRAP_WATCOM_CALL1(interpretPopShort_, scriptPtr) @@ -1358,8 +1371,8 @@ TGameObj* __fastcall obj_blocking_at_wrapper(TGameObj* obj, DWORD tile, DWORD el } } -long* __stdcall QueueFindFirst(TGameObj* object, long qType) { - WRAP_WATCOM_CALL2(queue_find_first_, object, qType) +long __stdcall ObjEraseObject(TGameObj* object, BoundRect* boundRect) { + WRAP_WATCOM_CALL2(obj_erase_object_, object, boundRect) } TGameObj* __stdcall ObjFindFirst() { @@ -1378,6 +1391,10 @@ TGameObj* __stdcall ObjFindNextAtTile() { WRAP_WATCOM_CALL0(obj_find_next_at_tile_) } +long __stdcall ObjPidNew(TGameObj* object, long pid) { + WRAP_WATCOM_CALL2(obj_pid_new_, object, pid) +} + long __stdcall ObjLockIsJammed(TGameObj* object) { WRAP_WATCOM_CALL1(obj_lock_is_jammed_, object) } @@ -1651,6 +1668,16 @@ __declspec(noinline) TGameObj* __stdcall GetItemPtrSlot(TGameObj* critter, long return itemPtr; } +// Checks whether the player is under the influence of negative effects of radiation +long __fastcall IsRadInfluence() { + QueueRadiation* queue = (QueueRadiation*)QueueFindFirst(*ptr_obj_dude, radiation_event); + while (queue) { + if (queue->init && queue->level >= 2) return 1; + queue = (QueueRadiation*)QueueFindNext(*ptr_obj_dude, radiation_event); + } + return 0; +} + // Returns the number of local variables of the object script long GetScriptLocalVars(long sid) { TScript* script = nullptr; diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 4f8b0ffe..d6e376cb 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -291,6 +291,7 @@ #define _GoodColor 0x6AB4EF #define _GreenColor 0x6A3CB0 #define _LIGHT_GREY_Color 0x6A76BF +#define _LIGHT_RED_Color 0x6AB61A #define _PeanutButter 0x6A82F3 #define _RedColor 0x6AB4D0 #define _WhiteColor 0x6AB8CF @@ -575,6 +576,7 @@ extern const DWORD critter_can_obj_dude_rest_; extern const DWORD critter_compute_ap_from_distance_; extern const DWORD critter_flag_check_; extern const DWORD critter_get_hits_; +extern const DWORD critter_get_rads_; extern const DWORD critter_is_dead_; // eax - critter extern const DWORD critter_kill_; extern const DWORD critter_kill_count_type_; @@ -1131,13 +1133,6 @@ TGameObj* __stdcall ScrFindObjFromProgram(TProgram* program); // Returns 0 on success, -1 on failure. long __stdcall ScrPtr(long scriptId, TScript** scriptPtr); -long __stdcall RegisterObjectAnimateAndHide(TGameObj* object, long anim, long delay); -long __stdcall RegisterObjectChangeFid(TGameObj* object, long artFid, long delay); -long __stdcall RegisterObjectLight(TGameObj* object, long lightRadius, long delay); -long __stdcall RegisterObjectMustErase(TGameObj* object); -long __stdcall RegisterObjectTakeOut(TGameObj* object, long holdFrameId, long nothing); -long __stdcall RegisterObjectTurnTowards(TGameObj* object, long tileNum, long nothing); - long __stdcall ScrNew(long* scriptID, long sType); long __stdcall ScrRemove(long scriptID); @@ -1156,10 +1151,22 @@ long __stdcall IntfaceIsHidden(); // redraws the main game interface windows (useful after changing some data like active hand, etc.) void __stdcall IntfaceRedraw(); +long __stdcall PickDeath(TGameObj* attacker, TGameObj* target, TGameObj* weapon, long amount, long anim, long hitFromBack); + void __stdcall ProcessBk(); void __stdcall ProtoDudeUpdateGender(); +long* __stdcall QueueFindFirst(TGameObj* object, long qType); +long* __stdcall QueueFindNext(TGameObj* object, long qType); + +long __stdcall RegisterObjectAnimateAndHide(TGameObj* object, long anim, long delay); +long __stdcall RegisterObjectChangeFid(TGameObj* object, long artFid, long delay); +long __stdcall RegisterObjectLight(TGameObj* object, long lightRadius, long delay); +long __stdcall RegisterObjectMustErase(TGameObj* object); +long __stdcall RegisterObjectTakeOut(TGameObj* object, long holdFrameId, long nothing); +long __stdcall RegisterObjectTurnTowards(TGameObj* object, long tileNum, long nothing); + // critter worn item (armor) TGameObj* __stdcall InvenWorn(TGameObj* critter); @@ -1244,12 +1251,12 @@ long __stdcall PerkLevel(TGameObj* critter, long perkId); long __stdcall TraitLevel(long traitID); -long* __stdcall QueueFindFirst(TGameObj* object, long qType); - void __fastcall make_straight_path_func_wrapper(TGameObj* objFrom, DWORD tileFrom, DWORD tileTo, void* rotationPtr, DWORD* result, long flags, void* func); TGameObj* __fastcall obj_blocking_at_wrapper(TGameObj* obj, DWORD tile, DWORD elevation, void* func); +long __stdcall ObjEraseObject(TGameObj* object, BoundRect* boundRect); + TGameObj* __stdcall ObjFindFirst(); TGameObj* __stdcall ObjFindFirstAtTile(long elevation, long tileNum); @@ -1258,6 +1265,8 @@ TGameObj* __stdcall ObjFindNext(); TGameObj* __stdcall ObjFindNextAtTile(); +long __stdcall ObjPidNew(TGameObj* object, long pid); + // checks/unjams jammed locks long __stdcall ObjLockIsJammed(TGameObj* object); void __stdcall ObjUnjamLock(TGameObj* object); @@ -1375,6 +1384,9 @@ void SkillSetTags(long* tags, long num); __declspec(noinline) TGameObj* __stdcall GetItemPtrSlot(TGameObj* critter, long slot); +// Checks whether the player is under the influence of negative effects of radiation +long __fastcall IsRadInfluence(); + // Returns the number of local variables of the object script long GetScriptLocalVars(long sid); diff --git a/sfall/FalloutStructs.h b/sfall/FalloutStructs.h index dc0c7a30..027fc995 100644 --- a/sfall/FalloutStructs.h +++ b/sfall/FalloutStructs.h @@ -333,7 +333,12 @@ struct Queue { DWORD time; long type; TGameObj* object; - long data; + DWORD* data; Queue* next; }; + +struct QueueRadiation { + long level; + long init; // 1 - for removing effect +}; #pragma pack(pop) diff --git a/sfall/HookScripts.cpp b/sfall/HookScripts.cpp index b62a6221..59b5f9db 100644 --- a/sfall/HookScripts.cpp +++ b/sfall/HookScripts.cpp @@ -70,12 +70,11 @@ static struct HooksPositionInfo { bool hasHsScript; } hooksInfo[HOOK_COUNT]; -#define hookbegin(a) pushadc __asm call BeginHook popadc __asm mov argCount, a -#define hookend pushadc __asm call EndHook popadc - #define HookBegin pushadc __asm call BeginHook popadc #define HookEnd pushadc __asm call EndHook popadc +#define HookBeginArgs(a) HookBegin __asm mov argCount, a + static void _stdcall BeginHook() { if (callDepth && callDepth <= maxDepth) { // save all values of the current hook if another hook was called during the execution of the current hook @@ -241,7 +240,7 @@ static void __declspec(naked) AfterHitRollHook() { static void __declspec(naked) CalcApCostHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; mov args[4], edx; mov args[8], ebx; @@ -255,7 +254,7 @@ static void __declspec(naked) CalcApCostHook() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } @@ -263,7 +262,7 @@ end: // this is for using non-weapon items, always 2 AP in vanilla static void __declspec(naked) CalcApCostHook2() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], ecx; // critter mov args[4], edx; // attack type (to determine hand) mov args[8], ebx; @@ -277,18 +276,18 @@ static void __declspec(naked) CalcApCostHook2() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) CalcDeathAnimHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[24], ebx; test ebx, ebx; jz noweap - mov ebx, [ebx+0x64]; + mov ebx, [ebx + 0x64]; and ebx, 0xFFF; jmp weapend; noweap: @@ -318,8 +317,8 @@ weapend: mov args[24], eax; end1: popad; - mov eax, [esp+8]; - mov ebx, [esp+4]; + mov eax, [esp + 8]; + mov ebx, [esp + 4]; push eax; push ebx; mov eax, args[4]; @@ -347,20 +346,20 @@ skip2: call obj_erase_object_; aend: pop eax; - hookend; + HookEnd; retn 8; } } static void __declspec(naked) CalcDeathAnimHook2() { __asm { - hookbegin(5); + HookBeginArgs(5); call check_death_; // call original function mov args[0], -1; // weaponPid, -1 - mov ebx, [esp+60]; + mov ebx, [esp + 60]; mov args[4], ebx; // attacker mov args[8], esi; // target - mov ebx, [esp+12] + mov ebx, [esp + 12] mov args[12], ebx; // dmgAmount mov args[16], eax; // calculated animID pushad; @@ -373,7 +372,7 @@ static void __declspec(naked) CalcDeathAnimHook2() { mov args[16], eax; skip: mov eax, args[16]; - hookend; + HookEnd; retn; } } @@ -499,7 +498,7 @@ static void __declspec(naked) FindTargetHook() { static void __declspec(naked) UseObjOnHook() { __asm { - hookbegin(3); + HookBeginArgs(3); mov args[0], edx; // target mov args[4], eax; // user mov args[8], ebx; // object @@ -516,14 +515,14 @@ static void __declspec(naked) UseObjOnHook() { defaulthandler: call protinst_use_item_on_; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) UseObjOnHook_item_d_take_drug() { __asm { - hookbegin(3); + HookBeginArgs(3); mov args[0], eax; // target mov args[4], eax; // user mov args[8], edx; // object @@ -540,14 +539,14 @@ static void __declspec(naked) UseObjOnHook_item_d_take_drug() { defaulthandler: call item_d_take_drug_; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) UseObjHook() { __asm { - hookbegin(2); + HookBeginArgs(2); mov args[0], eax; // user mov args[4], edx; // object pushad; @@ -563,7 +562,7 @@ static void __declspec(naked) UseObjHook() { defaulthandler: call protinst_use_item_; end: - hookend; + HookEnd; retn; } } @@ -686,7 +685,7 @@ static void __declspec(naked) OverrideCost_BarterPriceHook() { static void __declspec(naked) MoveCostHook() { __asm { - hookbegin(3); + HookBeginArgs(3); mov args[0], eax; mov args[4], edx; call critter_compute_ap_from_distance_; @@ -699,7 +698,7 @@ static void __declspec(naked) MoveCostHook() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } @@ -707,7 +706,7 @@ end: static const DWORD _obj_blocking_at = 0x48B84E; static void __declspec(naked) HexMBlockingHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; mov args[4], edx; mov args[8], ebx; @@ -728,14 +727,14 @@ next: jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) HexABlockingHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; mov args[4], edx; mov args[8], ebx; @@ -749,14 +748,14 @@ static void __declspec(naked) HexABlockingHook() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) HexShootBlockingHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; mov args[4], edx; mov args[8], ebx; @@ -770,14 +769,14 @@ static void __declspec(naked) HexShootBlockingHook() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) HexSightBlockingHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; mov args[4], edx; mov args[8], ebx; @@ -791,14 +790,14 @@ static void __declspec(naked) HexSightBlockingHook() { jl end; mov eax, rets[0]; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) ItemDamageHook() { __asm { - hookbegin(6); + HookBeginArgs(6); mov args[0], eax; //min mov args[4], edx; //max mov args[8], edi; //weapon @@ -822,7 +821,7 @@ skip: runrandom: call roll_random_; end: - hookend; + HookEnd; retn; } } @@ -902,7 +901,7 @@ void _stdcall MouseClickHook(DWORD button, bool pressed) { static void __declspec(naked) UseSkillHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; // user mov args[4], edx; // target mov args[8], ebx; // skill id @@ -920,14 +919,14 @@ static void __declspec(naked) UseSkillHook() { defaulthandler: call skill_use_; end: - hookend; + HookEnd; retn; } } static void __declspec(naked) StealCheckHook() { __asm { - hookbegin(4); + HookBeginArgs(4); mov args[0], eax; // thief mov args[4], edx; // target mov args[8], ebx; // item @@ -945,7 +944,7 @@ static void __declspec(naked) StealCheckHook() { defaulthandler: call skill_check_stealing_; end: - hookend; + HookEnd; retn; } } diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 8845f37b..524202be 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -1018,7 +1018,7 @@ static void __declspec(naked) CombatLoopHook() { //pop eax; pop edx; call get_input_; - pop ecx; // prevent the combat turn from being skipped after pressing Alt-Tab + pop ecx; // fix to prevent the combat turn from being skipped after using Alt+Tab retn; } } diff --git a/sfall/main.cpp b/sfall/main.cpp index 2fd6ab5c..7e367631 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -335,6 +335,26 @@ playWalkMovie: } } +static void __declspec(naked) ListDrvdStats_hook() { + static const DWORD ListDrvdStats_Ret = 0x4354D9; + __asm { + call IsRadInfluence; + test eax, eax; + jnz influence; + mov eax, ds:[_obj_dude]; + jmp critter_get_rads_; +influence: + xor ecx, ecx; + mov cl, ds:[_RedColor]; + cmp dword ptr [esp], 0x4354BE + 5; + jne skip; + mov cl, 131; // color index for selected +skip: + add esp, 4; + jmp ListDrvdStats_Ret; + } +} + static void __declspec(naked) op_display_msg_hook() { __asm { cmp dword ptr ds:_debug_func, 0; @@ -790,6 +810,10 @@ static void DllMain2() { dlogr(" Done", DL_INIT); } + // Highlight "Radiated" in red color when the player is under the influence of negative effects of radiation + HookCall(0x43549C, ListDrvdStats_hook); + HookCall(0x4354BE, ListDrvdStats_hook); + // Increase the max text width of the information card in the character screen SafeWrite8(0x43ACD5, 145); // 136 SafeWrite8(0x43DD37, 145); // 133 @@ -834,8 +858,8 @@ static void __declspec(naked) OnExitFunc() { } } -static const DWORD loadFunc = 0x4FE1D0; static void LoadHRPModule() { + static const DWORD loadFunc = 0x4FE1D0; HMODULE dll; __asm call loadFunc; // get HRP loading address __asm mov dll, eax;