mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Backported game hooks from 4.0.x
* COMBATTURN is not implemented. Updated documents.
This commit is contained in:
@@ -146,7 +146,7 @@
|
|||||||
//#define RMOBJ_AI_USE_DRUG_ON_2 4360176 // same as RMOBJ_AI_USE_DRUG_ON (obsolete, use only for sfall before 4.3.1/3.8.31)
|
//#define RMOBJ_AI_USE_DRUG_ON_2 4360176 // same as RMOBJ_AI_USE_DRUG_ON (obsolete, use only for sfall before 4.3.1/3.8.31)
|
||||||
#define RMOBJ_BARTER_ARMOR 4675656 // removing armor from NPC's slot before entering the barter screen
|
#define RMOBJ_BARTER_ARMOR 4675656 // removing armor from NPC's slot before entering the barter screen
|
||||||
#define RMOBJ_BARTER_WEAPON 4675722 // removing weapon from NPC's slot before entering the barter screen
|
#define RMOBJ_BARTER_WEAPON 4675722 // removing weapon from NPC's slot before entering the barter screen
|
||||||
#define RMOBJ_INVEN_DROP_CAPS 4667295 // if money/caps are dropped manually by the player from the inventory screen
|
#define RMOBJ_INVEN_DROP_CAPS 4667295 // if multiple money/caps are dropped manually by the player from the inventory screen
|
||||||
#define RMOBJ_DROP_INTO_CONTAINER 4678833 // when dropping items into a container item (bag/backpack)
|
#define RMOBJ_DROP_INTO_CONTAINER 4678833 // when dropping items into a container item (bag/backpack)
|
||||||
// old defines
|
// old defines
|
||||||
#define RMOBJ_RM_MULT_OBJS RMOBJ_ITEM_REMOVED_MULTI
|
#define RMOBJ_RM_MULT_OBJS RMOBJ_ITEM_REMOVED_MULTI
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
#define HOOK_INVENTORYMOVE (24)
|
#define HOOK_INVENTORYMOVE (24)
|
||||||
#define HOOK_INVENWIELD (25)
|
#define HOOK_INVENWIELD (25)
|
||||||
#define HOOK_ADJUSTFID (26)
|
#define HOOK_ADJUSTFID (26)
|
||||||
|
//#define HOOK_COMBATTURN (27) // unimplemented
|
||||||
|
#define HOOK_CARTRAVEL (28)
|
||||||
|
#define HOOK_SETGLOBALVAR (29)
|
||||||
|
#define HOOK_RESTTIMER (30)
|
||||||
#define HOOK_GAMEMODECHANGE (31)
|
#define HOOK_GAMEMODECHANGE (31)
|
||||||
|
|
||||||
// Valid arguments to list_begin
|
// Valid arguments to list_begin
|
||||||
|
|||||||
@@ -582,6 +582,48 @@ int ret0 - overrides the calculated FID with provided value
|
|||||||
|
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_CARTRAVEL (hs_cartravel.int)`
|
||||||
|
|
||||||
|
Runs continuously during worldmap travel on car.
|
||||||
|
|
||||||
|
```
|
||||||
|
int arg0 - vanilla car speed (between 3 and 8 "steps")
|
||||||
|
int arg1 - vanilla fuel consumption (100 and below)
|
||||||
|
|
||||||
|
int ret0 - car speed override (pass -1 if you just want to override fuel consumption)
|
||||||
|
int ret1 - fuel consumption override
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_SETGLOBALVAR (hs_setglobalvar.int)`
|
||||||
|
|
||||||
|
Runs when setting the value of a global variable.
|
||||||
|
|
||||||
|
```
|
||||||
|
int arg0 - the index number of the global variable being set
|
||||||
|
int arg1 - the set value of the global variable
|
||||||
|
|
||||||
|
int ret0 - overrides the value of the global variable
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_RESTTIMER (hs_resttimer.int)`
|
||||||
|
|
||||||
|
Runs continuously while the player is resting (using pipboy alarm clock).
|
||||||
|
|
||||||
|
```
|
||||||
|
int arg0 - the game time in ticks
|
||||||
|
int arg1 - event type: 1 - when the resting ends normally, -1 - when pressing ESC to cancel the timer, 0 - otherwise
|
||||||
|
int arg2 - the hour part of the length of resting time
|
||||||
|
int arg3 - the minute part of the length of resting time
|
||||||
|
|
||||||
|
int ret0 - pass 1 to interrupt the resting, pass 0 to continue the rest if it was interrupted by pressing ESC key
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
#### `HOOK_GAMEMODECHANGE (hs_gamemodechange.int)`
|
#### `HOOK_GAMEMODECHANGE (hs_gamemodechange.int)`
|
||||||
|
|
||||||
Runs once every time when the game mode was changed, like opening/closing the inventory, character screen, pipboy, etc.
|
Runs once every time when the game mode was changed, like opening/closing the inventory, character screen, pipboy, etc.
|
||||||
|
|||||||
@@ -732,6 +732,7 @@ FUNC(windowOutput_, 0x4B80A4)
|
|||||||
FUNC(windowShow_, 0x4B7648)
|
FUNC(windowShow_, 0x4B7648)
|
||||||
FUNC(windowWidth_, 0x4B7734)
|
FUNC(windowWidth_, 0x4B7734)
|
||||||
FUNC(windowWrapLineWithSpacing_, 0x4B8854)
|
FUNC(windowWrapLineWithSpacing_, 0x4B8854)
|
||||||
|
FUNC(wmCarUseGas_, 0x4C4DA4)
|
||||||
FUNC(wmDrawCursorStopped_, 0x4C41EC)
|
FUNC(wmDrawCursorStopped_, 0x4C41EC)
|
||||||
FUNC(wmEvalTileNumForPlacement_, 0x4C1A64)
|
FUNC(wmEvalTileNumForPlacement_, 0x4C1A64)
|
||||||
FUNC(wmFindCurSubTileFromPos_, 0x4C0C00)
|
FUNC(wmFindCurSubTileFromPos_, 0x4C0C00)
|
||||||
|
|||||||
@@ -58,8 +58,6 @@ WRAP_WATCOM_FFUNC4(void, register_object_call, long*, target, long*, source, voi
|
|||||||
WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value)
|
WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value)
|
||||||
WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value)
|
WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value)
|
||||||
WRAP_WATCOM_FFUNC6(long, text_object_create, fo::GameObject*, object, const char*, text, long, font, long, colorText, long, colorOutline, fo::BoundRect*, rect)
|
WRAP_WATCOM_FFUNC6(long, text_object_create, fo::GameObject*, object, const char*, text, long, font, long, colorText, long, colorOutline, fo::BoundRect*, rect)
|
||||||
WRAP_WATCOM_FFUNC3(long, tile_coord, long, tile, long*, outX, long*, outY) // the fourth argument of the function is not used
|
|
||||||
WRAP_WATCOM_FFUNC3(long, tile_num_in_direction, long, tile, long, rotation, long, distance)
|
|
||||||
WRAP_WATCOM_FFUNC8(void, trans_cscale, void*, fromBuff, long, width, long, height, long, fromPitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch)
|
WRAP_WATCOM_FFUNC8(void, trans_cscale, void*, fromBuff, long, width, long, height, long, fromPitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch)
|
||||||
WRAP_WATCOM_FFUNC3(void, win_clip, fo::Window*, window, fo::RectList**, rects, void*, buffer)
|
WRAP_WATCOM_FFUNC3(void, win_clip, fo::Window*, window, fo::RectList**, rects, void*, buffer)
|
||||||
WRAP_WATCOM_FFUNC6(void, win_print, long, winID, const char*, text, long, textWidth, long, xPos, long, yPos, long, colorFlags)
|
WRAP_WATCOM_FFUNC6(void, win_print, long, winID, const char*, text, long, textWidth, long, xPos, long, yPos, long, colorFlags)
|
||||||
@@ -99,6 +97,7 @@ WRAP_WATCOM_FUNC2(void, executeProcedure, fo::Program*, sptr, long, procNum)
|
|||||||
WRAP_WATCOM_FUNC1(long, folder_print_line, const char*, text)
|
WRAP_WATCOM_FUNC1(long, folder_print_line, const char*, text)
|
||||||
WRAP_WATCOM_FUNC1(const char*, findCurrentProc, fo::Program*, program) // Returns the name of current procedure by program pointer
|
WRAP_WATCOM_FUNC1(const char*, findCurrentProc, fo::Program*, program) // Returns the name of current procedure by program pointer
|
||||||
WRAP_WATCOM_FUNC1(long, FMtext_width, const char*, text)
|
WRAP_WATCOM_FUNC1(long, FMtext_width, const char*, text)
|
||||||
|
WRAP_WATCOM_FUNC1(long, game_get_global_var, long, globalVar)
|
||||||
WRAP_WATCOM_FUNC0(long, get_input)
|
WRAP_WATCOM_FUNC0(long, get_input)
|
||||||
// Searches for message ID in given message file and places result in result argument
|
// Searches for message ID in given message file and places result in result argument
|
||||||
WRAP_WATCOM_FUNC3(const char*, getmsg, const fo::MessageList*, fileAddr, fo::MessageNode*, result, long, messageId)
|
WRAP_WATCOM_FUNC3(const char*, getmsg, const fo::MessageList*, fileAddr, fo::MessageNode*, result, long, messageId)
|
||||||
@@ -222,9 +221,11 @@ WRAP_WATCOM_FUNC2(void, skill_set_tags, long*, tags, long, num)
|
|||||||
WRAP_WATCOM_FUNC2(long, stat_level, fo::GameObject*, critter, long, statId)
|
WRAP_WATCOM_FUNC2(long, stat_level, fo::GameObject*, critter, long, statId)
|
||||||
WRAP_WATCOM_FUNC1(void, stat_pc_add_experience, long, amount) // Adds experience points to PC
|
WRAP_WATCOM_FUNC1(void, stat_pc_add_experience, long, amount) // Adds experience points to PC
|
||||||
WRAP_WATCOM_FUNC1(long, text_font, long, fontNum)
|
WRAP_WATCOM_FUNC1(long, text_font, long, fontNum)
|
||||||
|
WRAP_WATCOM_FUNC3(long, tile_coord, long, tile, long*, outX, long*, outY) // the fourth argument of the function is not used
|
||||||
WRAP_WATCOM_FUNC2(long, tile_dist, long, scrTile, long, dstTile)
|
WRAP_WATCOM_FUNC2(long, tile_dist, long, scrTile, long, dstTile)
|
||||||
WRAP_WATCOM_FUNC2(long, tile_dir, long, scrTile, long, dstTile)
|
WRAP_WATCOM_FUNC2(long, tile_dir, long, scrTile, long, dstTile)
|
||||||
WRAP_WATCOM_FUNC2(long, tile_idistance, long, sourceTile, long, targetTile)
|
WRAP_WATCOM_FUNC2(long, tile_idistance, long, sourceTile, long, targetTile)
|
||||||
|
WRAP_WATCOM_FUNC3(long, tile_num_in_direction, long, tile, long, rotation, long, distance)
|
||||||
WRAP_WATCOM_FUNC1(long, tile_on_edge, long, tile)
|
WRAP_WATCOM_FUNC1(long, tile_on_edge, long, tile)
|
||||||
WRAP_WATCOM_FUNC0(void, tile_refresh_display) // Redraws the whole screen
|
WRAP_WATCOM_FUNC0(void, tile_refresh_display) // Redraws the whole screen
|
||||||
WRAP_WATCOM_FUNC2(void, tile_refresh_rect, fo::BoundRect*, boundRect, long, elevation) // Redraws the given rectangle on screen
|
WRAP_WATCOM_FUNC2(void, tile_refresh_rect, fo::BoundRect*, boundRect, long, elevation) // Redraws the given rectangle on screen
|
||||||
@@ -237,7 +238,9 @@ WRAP_WATCOM_FUNC1(BYTE*, win_get_buf, DWORD, winRef)
|
|||||||
WRAP_WATCOM_FUNC1(void, win_hide, DWORD, winRef)
|
WRAP_WATCOM_FUNC1(void, win_hide, DWORD, winRef)
|
||||||
WRAP_WATCOM_FUNC1(void, win_show, DWORD, winRef)
|
WRAP_WATCOM_FUNC1(void, win_show, DWORD, winRef)
|
||||||
WRAP_WATCOM_FUNC0(long, windowWidth)
|
WRAP_WATCOM_FUNC0(long, windowWidth)
|
||||||
|
WRAP_WATCOM_FUNC1(void, wmCarUseGas, long, gasAmount)
|
||||||
WRAP_WATCOM_FUNC1(long, wmEvalTileNumForPlacement, long, tile)
|
WRAP_WATCOM_FUNC1(long, wmEvalTileNumForPlacement, long, tile)
|
||||||
|
WRAP_WATCOM_FUNC0(void, wmPartyWalkingStep)
|
||||||
WRAP_WATCOM_FUNC1(void, wmRefreshInterfaceOverlay, long, isRedraw)
|
WRAP_WATCOM_FUNC1(void, wmRefreshInterfaceOverlay, long, isRedraw)
|
||||||
|
|
||||||
/* Database functions */
|
/* Database functions */
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ static HooksInjectInfo injectHooks[] = {
|
|||||||
{HOOK_INVENWIELD, Inject_InvenWieldHook, false},
|
{HOOK_INVENWIELD, Inject_InvenWieldHook, false},
|
||||||
{HOOK_ADJUSTFID, nullptr, true}, // always embedded to the engine
|
{HOOK_ADJUSTFID, nullptr, true}, // always embedded to the engine
|
||||||
{-1, nullptr, false}, // dummy
|
{-1, nullptr, false}, // dummy
|
||||||
{-1, nullptr, false}, // dummy
|
{HOOK_CARTRAVEL, Inject_CarTravelHook, false},
|
||||||
{-1, nullptr, false}, // dummy
|
{HOOK_SETGLOBALVAR, Inject_SetGlobalVarHook, false},
|
||||||
{-1, nullptr, false}, // dummy
|
{HOOK_RESTTIMER, Inject_RestTimerHook, false},
|
||||||
{HOOK_GAMEMODECHANGE, nullptr, true}, // always embedded to the engine
|
{HOOK_GAMEMODECHANGE, nullptr, true}, // always embedded to the engine
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,12 @@ enum HookType
|
|||||||
HOOK_WITHINPERCEPTION = 23,
|
HOOK_WITHINPERCEPTION = 23,
|
||||||
HOOK_INVENTORYMOVE = 24,
|
HOOK_INVENTORYMOVE = 24,
|
||||||
HOOK_INVENWIELD = 25,
|
HOOK_INVENWIELD = 25,
|
||||||
HOOK_ADJUSTFID = 26, // 4.x backport
|
HOOK_ADJUSTFID = 26,
|
||||||
HOOK_GAMEMODECHANGE = 31, // 4.x backport
|
HOOK_COMBATTURN = 27, // unimplemented
|
||||||
|
HOOK_CARTRAVEL = 28,
|
||||||
|
HOOK_SETGLOBALVAR = 29,
|
||||||
|
HOOK_RESTTIMER = 30,
|
||||||
|
HOOK_GAMEMODECHANGE = 31,
|
||||||
HOOK_COUNT
|
HOOK_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,20 @@ void __stdcall HookCommon::SetHSReturn(DWORD value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List of hooks that are not allowed to be called recursively
|
||||||
|
static bool CheckRecursiveHooks(DWORD hook) {
|
||||||
|
if (hook == currentRunHook) {
|
||||||
|
switch (hook) {
|
||||||
|
case HOOK_SETGLOBALVAR:
|
||||||
|
// case HOOK_SETLIGHTING:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
if (isDebug) fo::func::debug_printf("\nWARNING: A recursive hook with ID %d was running.", hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void __stdcall BeginHook() {
|
void __stdcall BeginHook() {
|
||||||
if (callDepth && callDepth <= maxDepth) {
|
if (callDepth && callDepth <= maxDepth) {
|
||||||
// save all values of the current hook if another hook was called during the execution of the current hook
|
// save all values of the current hook if another hook was called during the execution of the current hook
|
||||||
@@ -97,10 +111,12 @@ static void __stdcall RunSpecificHookScript(HookScript *hook) {
|
|||||||
void __stdcall RunHookScript(DWORD hook) {
|
void __stdcall RunHookScript(DWORD hook) {
|
||||||
cRet = 0;
|
cRet = 0;
|
||||||
if (!hooks[hook].empty()) {
|
if (!hooks[hook].empty()) {
|
||||||
if (callDepth > 8) {
|
if (callDepth > 1) {
|
||||||
fo::func::debug_printf("\n[SFALL] The hook ID: %d cannot be executed.", hook);
|
if (CheckRecursiveHooks(hook) || callDepth > 8) {
|
||||||
dlog_f("The hook %d cannot be executed due to exceeding depth limit\n", DL_MAIN, hook);
|
fo::func::debug_printf("\n[SFALL] The hook ID: %d cannot be executed.", hook);
|
||||||
return;
|
dlog_f("The hook %d cannot be executed due to exceeding depth limit or disallowed recursive calls\n", DL_MAIN, hook);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currentRunHook = hook;
|
currentRunHook = hook;
|
||||||
size_t hooksCount = hooks[hook].size();
|
size_t hooksCount = hooks[hook].size();
|
||||||
|
|||||||
@@ -226,6 +226,167 @@ static void __declspec(naked) PerceptionSearchTargetHook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const long maxGasAmount = 80000;
|
||||||
|
|
||||||
|
static void CarTravelHook_Script() {
|
||||||
|
BeginHook();
|
||||||
|
argCount = 2;
|
||||||
|
|
||||||
|
// calculate vanilla speed
|
||||||
|
int carSpeed = 3;
|
||||||
|
if (fo::func::game_get_global_var(fo::GVAR_CAR_BLOWER)) {
|
||||||
|
carSpeed += 1;
|
||||||
|
}
|
||||||
|
if (fo::func::game_get_global_var(fo::GVAR_NEW_RENO_CAR_UPGRADE)) {
|
||||||
|
carSpeed += 1;
|
||||||
|
}
|
||||||
|
if (fo::func::game_get_global_var(fo::GVAR_NEW_RENO_SUPER_CAR)) {
|
||||||
|
carSpeed += 3;
|
||||||
|
}
|
||||||
|
// calculate vanilla fuel consumption
|
||||||
|
int originalGas = *fo::ptr::carGasAmount;
|
||||||
|
*fo::ptr::carGasAmount = maxGasAmount;
|
||||||
|
fo::func::wmCarUseGas(100);
|
||||||
|
int consumption = maxGasAmount - *fo::ptr::carGasAmount;
|
||||||
|
|
||||||
|
// run script
|
||||||
|
args[0] = carSpeed;
|
||||||
|
args[1] = consumption;
|
||||||
|
RunHookScript(HOOK_CARTRAVEL);
|
||||||
|
|
||||||
|
// override travel speed
|
||||||
|
if (cRet > 0 && static_cast<long>(rets[0]) >= 0) {
|
||||||
|
carSpeed = rets[0];
|
||||||
|
}
|
||||||
|
// move car on map
|
||||||
|
for (int i = 0; i < carSpeed; ++i) {
|
||||||
|
fo::func::wmPartyWalkingStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fuel consumption
|
||||||
|
if (cRet > 1) {
|
||||||
|
consumption = static_cast<long>(rets[1]);
|
||||||
|
}
|
||||||
|
// consume fuel
|
||||||
|
*fo::ptr::carGasAmount = max(0, originalGas - consumption); // Note: the reverse breaks the result in VS2010
|
||||||
|
|
||||||
|
EndHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) CarTravelHack() {
|
||||||
|
static const DWORD CarTravelHack_back = 0x4BFF43;
|
||||||
|
__asm {
|
||||||
|
pushad;
|
||||||
|
call CarTravelHook_Script;
|
||||||
|
popad;
|
||||||
|
jmp CarTravelHack_back;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long __fastcall GlobalVarHook_Script(register DWORD number, register int value) {
|
||||||
|
int old = (*fo::ptr::game_global_vars)[number];
|
||||||
|
|
||||||
|
if (IsGameLoaded() && HookScripts::HookHasScript(HOOK_SETGLOBALVAR)) { // IsGameLoaded - don't execute hook until loading sfall scripts
|
||||||
|
BeginHook();
|
||||||
|
argCount = 2;
|
||||||
|
args[0] = number;
|
||||||
|
args[1] = value;
|
||||||
|
|
||||||
|
RunHookScript(HOOK_SETGLOBALVAR);
|
||||||
|
if (cRet > 0) value = rets[0];
|
||||||
|
EndHook();
|
||||||
|
}
|
||||||
|
if (number == fo::GVAR_PLAYER_REPUTATION && displayKarmaChanges) {
|
||||||
|
int diff = value - old;
|
||||||
|
if (diff != 0) Karma::DisplayKarma(diff);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) SetGlobalVarHook() {
|
||||||
|
__asm {
|
||||||
|
push eax;
|
||||||
|
push ecx;
|
||||||
|
push edx;
|
||||||
|
mov ecx, eax; // number
|
||||||
|
call GlobalVarHook_Script; // edx - value
|
||||||
|
pop edx;
|
||||||
|
pop ecx;
|
||||||
|
cmp eax, edx; // if return value != set value
|
||||||
|
cmovne edx, eax;
|
||||||
|
pop eax;
|
||||||
|
jmp fo::funcoffs::game_set_global_var_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int restTicks;
|
||||||
|
|
||||||
|
static long __fastcall RestTimerHook_Script(DWORD hours, DWORD minutes, DWORD gameTime, DWORD addrHook) {
|
||||||
|
addrHook -= 5;
|
||||||
|
|
||||||
|
BeginHook();
|
||||||
|
argCount = 4;
|
||||||
|
|
||||||
|
args[0] = gameTime;
|
||||||
|
args[2] = hours;
|
||||||
|
args[3] = minutes;
|
||||||
|
|
||||||
|
if (addrHook == 0x499CA1 || addrHook == 0x499B63) {
|
||||||
|
args[0] = restTicks;
|
||||||
|
args[1] = -1;
|
||||||
|
} else {
|
||||||
|
restTicks = args[0];
|
||||||
|
args[1] = (addrHook == 0x499DF2 || (args[2] == 0 && addrHook == 0x499BE0)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
RunHookScript(HOOK_RESTTIMER);
|
||||||
|
|
||||||
|
long result = -1;
|
||||||
|
if (cRet > 0) {
|
||||||
|
result = (rets[0] != 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
EndHook();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) RestTimerLoopHook() {
|
||||||
|
__asm {
|
||||||
|
pushadc;
|
||||||
|
mov edx, [esp + 16 + 0x44]; // minutes_
|
||||||
|
mov ecx, [esp + 16 + 0x40]; // hours_
|
||||||
|
push [esp + 12]; // addrHook
|
||||||
|
push eax; // gameTime
|
||||||
|
call RestTimerHook_Script;
|
||||||
|
pop ecx;
|
||||||
|
pop edx;
|
||||||
|
test eax, eax; // result >= 0
|
||||||
|
cmovge edi, eax; // return 1 to interrupt resting
|
||||||
|
pop eax;
|
||||||
|
jmp fo::funcoffs::set_game_time_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) RestTimerEscapeHook() {
|
||||||
|
__asm {
|
||||||
|
mov edi, 1; // engine code
|
||||||
|
cmp eax, 0x1B; // ESC ASCII code
|
||||||
|
jnz skip;
|
||||||
|
pushadc;
|
||||||
|
mov edx, [esp + 16 + 0x44]; // minutes_
|
||||||
|
mov ecx, [esp + 16 + 0x40]; // hours_
|
||||||
|
push [esp + 12]; // addrHook
|
||||||
|
push eax; // gameTime
|
||||||
|
call RestTimerHook_Script;
|
||||||
|
pop ecx;
|
||||||
|
pop edx;
|
||||||
|
test eax, eax; // result >= 0
|
||||||
|
cmovge edi, eax; // return 0 for cancel ESC key
|
||||||
|
pop eax;
|
||||||
|
skip:
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Inject_BarterPriceHook() {
|
void Inject_BarterPriceHook() {
|
||||||
const DWORD barterPriceHkAddr[] = {
|
const DWORD barterPriceHkAddr[] = {
|
||||||
0x474D4C, // barter_attempt_transaction_ (offers button)
|
0x474D4C, // barter_attempt_transaction_ (offers button)
|
||||||
@@ -261,11 +422,30 @@ void Inject_WithinPerceptionHook() {
|
|||||||
HookCall(0x458403, PerceptionRangeHearHook);
|
HookCall(0x458403, PerceptionRangeHearHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inject_CarTravelHook() {
|
||||||
|
MakeJump(0x4BFEF1, CarTravelHack);
|
||||||
|
BlockCall(0x4BFF6E); // vanilla wmCarUseGas(100) call
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inject_SetGlobalVarHook() {
|
||||||
|
HookCall(0x455A6D, SetGlobalVarHook);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inject_RestTimerHook() {
|
||||||
|
const DWORD restTimerLoopHkAddr[] = {0x499B4B, 0x499BE0, 0x499D2C, 0x499DF2};
|
||||||
|
HookCalls(RestTimerLoopHook, restTimerLoopHkAddr);
|
||||||
|
const DWORD restTimerEscHkAddr[] = {0x499B63, 0x499CA1};
|
||||||
|
MakeCalls(RestTimerEscapeHook, restTimerEscHkAddr);
|
||||||
|
}
|
||||||
|
|
||||||
void InitMiscHookScripts() {
|
void InitMiscHookScripts() {
|
||||||
HookScripts::LoadHookScript("hs_barterprice", HOOK_BARTERPRICE);
|
HookScripts::LoadHookScript("hs_barterprice", HOOK_BARTERPRICE);
|
||||||
HookScripts::LoadHookScript("hs_useskill", HOOK_USESKILL);
|
HookScripts::LoadHookScript("hs_useskill", HOOK_USESKILL);
|
||||||
HookScripts::LoadHookScript("hs_steal", HOOK_STEAL);
|
HookScripts::LoadHookScript("hs_steal", HOOK_STEAL);
|
||||||
HookScripts::LoadHookScript("hs_withinperception", HOOK_WITHINPERCEPTION);
|
HookScripts::LoadHookScript("hs_withinperception", HOOK_WITHINPERCEPTION);
|
||||||
|
HookScripts::LoadHookScript("hs_cartravel", HOOK_CARTRAVEL);
|
||||||
|
HookScripts::LoadHookScript("hs_setglobalvar", HOOK_SETGLOBALVAR);
|
||||||
|
HookScripts::LoadHookScript("hs_resttimer", HOOK_RESTTIMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ void Inject_BarterPriceHook();
|
|||||||
void Inject_UseSkillHook();
|
void Inject_UseSkillHook();
|
||||||
void Inject_StealCheckHook();
|
void Inject_StealCheckHook();
|
||||||
void Inject_WithinPerceptionHook();
|
void Inject_WithinPerceptionHook();
|
||||||
|
void Inject_CarTravelHook();
|
||||||
|
void Inject_SetGlobalVarHook();
|
||||||
|
void Inject_RestTimerHook();
|
||||||
|
|
||||||
long PerceptionRangeHook_Invoke(fo::GameObject* watcher, fo::GameObject* target, long type, long result);
|
long PerceptionRangeHook_Invoke(fo::GameObject* watcher, fo::GameObject* target, long type, long result);
|
||||||
|
|
||||||
|
|||||||
+7
-20
@@ -23,6 +23,8 @@
|
|||||||
#include "..\FalloutEngine\Fallout2.h"
|
#include "..\FalloutEngine\Fallout2.h"
|
||||||
#include "..\Translate.h"
|
#include "..\Translate.h"
|
||||||
|
|
||||||
|
#include "HookScripts.h"
|
||||||
|
|
||||||
#include "Karma.h"
|
#include "Karma.h"
|
||||||
|
|
||||||
namespace sfall
|
namespace sfall
|
||||||
@@ -37,6 +39,7 @@ static std::vector<KarmaFrmSetting> karmaFrms;
|
|||||||
|
|
||||||
static char karmaGainMsg[128];
|
static char karmaGainMsg[128];
|
||||||
static char karmaLossMsg[128];
|
static char karmaLossMsg[128];
|
||||||
|
bool displayKarmaChanges;
|
||||||
|
|
||||||
static DWORD __stdcall DrawCard() {
|
static DWORD __stdcall DrawCard() {
|
||||||
int reputation = (*fo::ptr::game_global_vars)[fo::GVAR_PLAYER_REPUTATION];
|
int reputation = (*fo::ptr::game_global_vars)[fo::GVAR_PLAYER_REPUTATION];
|
||||||
@@ -64,7 +67,7 @@ skip:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __stdcall SetKarma(int value) {
|
void Karma::DisplayKarma(int value) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
sprintf_s(buf, karmaGainMsg, value);
|
sprintf_s(buf, karmaGainMsg, value);
|
||||||
@@ -74,29 +77,13 @@ static void __stdcall SetKarma(int value) {
|
|||||||
fo::func::display_print(buf);
|
fo::func::display_print(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) SetGlobalVarWrapper() {
|
|
||||||
__asm {
|
|
||||||
test eax, eax; // Gvar number
|
|
||||||
jnz end;
|
|
||||||
pushadc;
|
|
||||||
call fo::funcoffs::game_get_global_var_;
|
|
||||||
sub edx, eax; // value -= old
|
|
||||||
jz skip;
|
|
||||||
push edx;
|
|
||||||
call SetKarma;
|
|
||||||
skip:
|
|
||||||
popadc;
|
|
||||||
end:
|
|
||||||
jmp fo::funcoffs::game_set_global_var_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ApplyDisplayKarmaChangesPatch() {
|
static void ApplyDisplayKarmaChangesPatch() {
|
||||||
if (IniReader::GetConfigInt("Misc", "DisplayKarmaChanges", 0)) {
|
displayKarmaChanges = IniReader::GetConfigInt("Misc", "DisplayKarmaChanges", 0) != 0;
|
||||||
|
if (displayKarmaChanges) {
|
||||||
dlog("Applying display karma changes patch.", DL_INIT);
|
dlog("Applying display karma changes patch.", DL_INIT);
|
||||||
Translate::Get("sfall", "KarmaGain", "You gained %d karma.", karmaGainMsg);
|
Translate::Get("sfall", "KarmaGain", "You gained %d karma.", karmaGainMsg);
|
||||||
Translate::Get("sfall", "KarmaLoss", "You lost %d karma.", karmaLossMsg);
|
Translate::Get("sfall", "KarmaLoss", "You lost %d karma.", karmaLossMsg);
|
||||||
HookCall(0x455A6D, SetGlobalVarWrapper);
|
HookScripts::InjectingHook(HOOK_SETGLOBALVAR);
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ class Karma {
|
|||||||
public:
|
public:
|
||||||
static const char* name() { return "Karma"; }
|
static const char* name() { return "Karma"; }
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
|
static void DisplayKarma(int value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern bool displayKarmaChanges;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user