mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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.
This commit is contained in:
@@ -662,6 +662,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
|
||||
|
||||
|
||||
@@ -144,6 +144,16 @@ long CheckAddictByPid(fo::GameObject* critter, long pid) {
|
||||
/* keyword 'return' is not needed, the compiler will do everything correctly */
|
||||
}
|
||||
|
||||
// Checks whether the player is under the influence of negative effects of radiation
|
||||
long __fastcall IsRadInfluence() {
|
||||
fo::QueueRadiation* queue = (fo::QueueRadiation*)fo::func::queue_find_first(fo::var::obj_dude, fo::radiation_event);
|
||||
while (queue) {
|
||||
if (queue->init && queue->level >= 2) return 1;
|
||||
queue = (fo::QueueRadiation*)fo::func::queue_find_next(fo::var::obj_dude, fo::radiation_event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ToggleNpcFlag(fo::GameObject* npc, long flag, bool set) {
|
||||
Proto* protoPtr;
|
||||
if (fo::func::proto_ptr(npc->protoId, &protoPtr) != -1) {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Functions.h"
|
||||
|
||||
@@ -66,6 +67,9 @@ bool HeroIsFemale();
|
||||
|
||||
long CheckAddictByPid(fo::GameObject* critter, long pid);
|
||||
|
||||
// Checks whether the player is under the influence of negative effects of radiation
|
||||
long __fastcall IsRadInfluence();
|
||||
|
||||
void ToggleNpcFlag(fo::GameObject* npc, long flag, bool set);
|
||||
|
||||
// Returns the number of party members in the existing table (begins from 1)
|
||||
|
||||
@@ -117,7 +117,7 @@ struct GameObject {
|
||||
long damageLastTurn;
|
||||
long aiPacket;
|
||||
long teamNum;
|
||||
long whoHitMe;
|
||||
GameObject* whoHitMe;
|
||||
long health;
|
||||
long rads;
|
||||
long poison;
|
||||
@@ -791,10 +791,15 @@ struct Queue {
|
||||
DWORD time;
|
||||
long type;
|
||||
GameObject* object;
|
||||
long data;
|
||||
DWORD* data;
|
||||
Queue* next;
|
||||
};
|
||||
|
||||
struct QueueRadiation {
|
||||
long level;
|
||||
long init; // 1 - for removing effect
|
||||
};
|
||||
|
||||
struct QueueDrug {
|
||||
DWORD pid;
|
||||
fo::Stat stat0;
|
||||
@@ -806,7 +811,7 @@ struct QueueDrug {
|
||||
};
|
||||
|
||||
struct QueueAddict {
|
||||
long init; // 1 = perk is not active yet
|
||||
long init; // 1 - perk is not active yet
|
||||
DWORD drugPid;
|
||||
fo::Perk perkId; // effect of addiction
|
||||
};
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
#define FO_VAR_GoodColor 0x6AB4EF
|
||||
#define FO_VAR_GreenColor 0x6A3CB0
|
||||
#define FO_VAR_LIGHT_GREY_Color 0x6A76BF
|
||||
#define FO_VAR_LIGHT_RED_Color 0x6AB61A
|
||||
#define FO_VAR_PeanutButter 0x6A82F3
|
||||
#define FO_VAR_RedColor 0x6AB4D0
|
||||
#define FO_VAR_WhiteColor 0x6AB8CF
|
||||
|
||||
+69
-38
@@ -1098,37 +1098,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 + whoHitMe] // pobj.who_hit_me
|
||||
inc eax
|
||||
jnz end
|
||||
mov [ebx + whoHitMe], eax // pobj.who_hit_me
|
||||
mov [esi + 0x24], eax; // ctd.targetTile
|
||||
mov eax, [ebx + whoHitMe]; // pobj.who_hit_me
|
||||
inc eax;
|
||||
jnz end; // jump if whoHitMe != -1
|
||||
mov [ebx + whoHitMe], 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 + cid] // pobj.who_hit_me.cid
|
||||
test byte ptr ds:[FO_VAR_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 + cid]; // pobj.who_hit_me.cid
|
||||
test byte ptr ds:[FO_VAR_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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1511,11 +1505,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:[FO_VAR_map_state], 0; // map number, -1 exit to worldmap
|
||||
cmp ds:[FO_VAR_loadingGame], 0;
|
||||
jnz skip;
|
||||
cmp dword ptr ds:[FO_VAR_map_state], 0; // map number, -1 exit to worldmap (probably redundant)
|
||||
jz mapLeave;
|
||||
skip:
|
||||
add esp, 4;
|
||||
jmp obj_move_to_tile_Ret;
|
||||
mapLeave:
|
||||
@@ -1868,7 +1865,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 + damageFlags], 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 fo::funcoffs::message_search_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) process_rads_hook_msg() {
|
||||
__asm {
|
||||
push eax; // death message for DialogOut
|
||||
call fo::funcoffs::display_print_;
|
||||
@@ -2789,6 +2811,16 @@ void BugFixes::init()
|
||||
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
|
||||
@@ -2849,16 +2881,6 @@ void BugFixes::init()
|
||||
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);
|
||||
MakeCalls(MultiHexFix, {0x42901F, 0x429170});
|
||||
@@ -2893,7 +2915,7 @@ void BugFixes::init()
|
||||
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);
|
||||
@@ -3105,8 +3127,17 @@ void BugFixes::init()
|
||||
// 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);
|
||||
|
||||
// Display a pop-up messages box about death from radiation
|
||||
HookCall(0x42D733, process_rads_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);
|
||||
SafeWriteBatch<BYTE>(0x74, {0x42D424, 0x42D444}); // jnz > jz
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
// Display a pop-up message box about death from radiation
|
||||
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)) {
|
||||
|
||||
@@ -45,7 +45,7 @@ static void __declspec(naked) CombatLoopHook() {
|
||||
//pop eax;
|
||||
pop edx;
|
||||
call fo::funcoffs::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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +264,26 @@ playWalkMovie:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) ListDrvdStats_hook() {
|
||||
static const DWORD ListDrvdStats_Ret = 0x4354D9;
|
||||
__asm {
|
||||
call fo::IsRadInfluence;
|
||||
test eax, eax;
|
||||
jnz influence;
|
||||
mov eax, ds:[FO_VAR_obj_dude];
|
||||
jmp fo::funcoffs::critter_get_rads_;
|
||||
influence:
|
||||
xor ecx, ecx;
|
||||
mov cl, ds:[FO_VAR_RedColor];
|
||||
cmp dword ptr [esp], 0x4354BE + 5;
|
||||
jne skip;
|
||||
mov cl, 131; // color index for selected
|
||||
skip:
|
||||
add esp, 4;
|
||||
jmp ListDrvdStats_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
void AdditionalWeaponAnimsPatch() {
|
||||
if (GetConfigInt("Misc", "AdditionalWeaponAnims", 0)) {
|
||||
dlog("Applying additional weapon animations patch.", DL_INIT);
|
||||
@@ -689,6 +709,9 @@ void MiscPatches::init() {
|
||||
dlogr(" Done", DL_INIT);
|
||||
}
|
||||
|
||||
// Highlight "Radiated" in red color when the player is under the influence of negative effects of radiation
|
||||
HookCalls(ListDrvdStats_hook, { 0x43549C, 0x4354BE });
|
||||
|
||||
// Increase the max text width of the information card in the character screen
|
||||
SafeWriteBatch<BYTE>(145, {0x43ACD5, 0x43DD37}); // 136, 133
|
||||
|
||||
|
||||
Reference in New Issue
Block a user