mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Backported three game hooks from 4.x:
* ROLLCHECK, BESTWEAPON, CANUSEWEAPON Updated documents.
This commit is contained in:
+1
-1
@@ -131,7 +131,7 @@ OverrideMusicDir=1
|
|||||||
;This will slightly increase the startup time of the game on older computers
|
;This will slightly increase the startup time of the game on older computers
|
||||||
AutoSearchSFX=1
|
AutoSearchSFX=1
|
||||||
|
|
||||||
;Uncomment these lines to override the names of sound files for game modes
|
;Uncomment these lines to override the names of sound files used by the engine
|
||||||
;Filenames are limited to 8 characters (without extension)
|
;Filenames are limited to 8 characters (without extension)
|
||||||
;MainMenuMusic=07desert
|
;MainMenuMusic=07desert
|
||||||
;WorldMapMusic=23world
|
;WorldMapMusic=23world
|
||||||
|
|||||||
@@ -70,6 +70,11 @@
|
|||||||
#define HOOK_STDPROCEDURE_END (41)
|
#define HOOK_STDPROCEDURE_END (41)
|
||||||
#define HOOK_TARGETOBJECT (42)
|
#define HOOK_TARGETOBJECT (42)
|
||||||
#define HOOK_ENCOUNTER (43)
|
#define HOOK_ENCOUNTER (43)
|
||||||
|
//#define HOOK_ADJUSTPOISON (44) // unimplemented
|
||||||
|
//#define HOOK_ADJUSTRADS (45) // unimplemented
|
||||||
|
#define HOOK_ROLLCHECK (46)
|
||||||
|
#define HOOK_BESTWEAPON (47)
|
||||||
|
#define HOOK_CANUSEWEAPON (48)
|
||||||
|
|
||||||
// Valid arguments to list_begin
|
// Valid arguments to list_begin
|
||||||
#define LIST_CRITTERS (0)
|
#define LIST_CRITTERS (0)
|
||||||
@@ -261,6 +266,7 @@
|
|||||||
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
||||||
|
|
||||||
// sets the status of an unusable weapon that cannot be used in combat
|
// sets the status of an unusable weapon that cannot be used in combat
|
||||||
|
// use the HOOK_CANUSEWEAPON hook with weapon_is_unusable macro to override the engine value
|
||||||
#define set_weapon_unusable(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwor 0x00000010)
|
#define set_weapon_unusable(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwor 0x00000010)
|
||||||
#define set_weapon_usable(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0xFFFFFFEF)
|
#define set_weapon_usable(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0xFFFFFFEF)
|
||||||
#define weapon_is_unusable(item) (get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0x00000010)
|
#define weapon_is_unusable(item) (get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0x00000010)
|
||||||
|
|||||||
@@ -795,3 +795,62 @@ int arg2 - 1 when the encounter occurs is a special encounter, 0 otherwise
|
|||||||
int ret0 - overrides the map ID, or pass -1 for event type 0 to cancel the encounter and continue traveling
|
int ret0 - overrides the map ID, or pass -1 for event type 0 to cancel the encounter and continue traveling
|
||||||
int ret1 - pass 1 to cancel the encounter and load the specified map from the ret0 (only for event type 0)
|
int ret1 - pass 1 to cancel the encounter and load the specified map from the ret0 (only for event type 0)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_ROLLCHECK (hs_rollcheck.int)`
|
||||||
|
|
||||||
|
Runs when a game event performs a random roll to check the chance of success or failure.
|
||||||
|
|
||||||
|
```
|
||||||
|
int arg0 - event type:
|
||||||
|
1 - checks the chance of an attack hitting the target
|
||||||
|
2 - checks the chance of a bullet from a burst hitting the target (for burst attacks)
|
||||||
|
3 - checks the chance when using skills (not listed below)
|
||||||
|
4 - check the chance of using Repair skill
|
||||||
|
5 - check the chance of using Doctor skill
|
||||||
|
6 - check the chance of using Steal skill for the thief (usually the player)
|
||||||
|
7 - the second Steal skill chance check for the target to catch the thief, in which the target's failure is the thief's success result
|
||||||
|
int arg1 - the value of roll result (see ROLL_* constants), which is calculated as:
|
||||||
|
for ROLL_CRITICAL_SUCCESS: random(1, 100) <= (random_chance / 10) + bonus
|
||||||
|
for ROLL_CRITICAL_FAILURE: random(1, 100) <= -random_chance / 10
|
||||||
|
int arg2 - the chance value
|
||||||
|
int arg3 - the bonus value, used when checking critical success
|
||||||
|
int arg4 - random chance, calculated as: (chance - random(1, 100)), where a negative value is a failure check (ROLL_FAILURE)
|
||||||
|
|
||||||
|
int ret0 - overrides the roll result
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_BESTWEAPON (hs_bestweapon.int)`
|
||||||
|
|
||||||
|
Runs when the AI decides which weapon is the best while searching the inventory for a weapon to equip in combat.\
|
||||||
|
This also runs when the player presses the "Use Best Weapon" button on the party member control panel.
|
||||||
|
|
||||||
|
```
|
||||||
|
Critter arg0 - the critter searching for a weapon
|
||||||
|
Item arg1 - the best weapon chosen from two items
|
||||||
|
Item arg2 - the first choice of weapon
|
||||||
|
Item arg3 - the second choice of weapon
|
||||||
|
Critter arg4 - the target of the critter (can be 0)
|
||||||
|
|
||||||
|
Item ret0 - overrides the chosen best weapon
|
||||||
|
```
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
#### `HOOK_CANUSEWEAPON (hs_canuseweapon.int)`
|
||||||
|
|
||||||
|
Run when the AI checks whether it can use a weapon, or when the game checks whether the player can use an item (weapon) in hand slot.\
|
||||||
|
For AI, this mostly happens when NPCs try to find weapons in their inventory or on the map.\
|
||||||
|
For the player, this happens when the game updates the item data for active item slots on the interface bar.
|
||||||
|
|
||||||
|
```
|
||||||
|
Critter arg0 - the critter doing the check
|
||||||
|
Item arg1 - the item being checked
|
||||||
|
int arg2 - attack type (see ATKTYPE_* constants), or -1 for dude_obj
|
||||||
|
int arg3 - original result of engine function: 1 - can use, 0 - cannot use
|
||||||
|
|
||||||
|
int ret0 - overrides the result of engine function. Any non-zero value allows using the weapon
|
||||||
|
```
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ FUNC(action_use_skill_on_, 0x41255C)
|
|||||||
FUNC(add_bar_box_, 0x4616F0)
|
FUNC(add_bar_box_, 0x4616F0)
|
||||||
FUNC(adjust_ac_, 0x4715F8)
|
FUNC(adjust_ac_, 0x4715F8)
|
||||||
FUNC(adjust_fid_, 0x4716E8)
|
FUNC(adjust_fid_, 0x4716E8)
|
||||||
FUNC(ai_can_use_weapon_, 0x4298EC) // (GameObject *aCritter<eax>, int aWeapon<edx>, int a2Or3<ebx>) returns 1 or 0
|
FUNC(ai_best_weapon_, 0x4293BC)
|
||||||
|
FUNC(ai_can_use_weapon_, 0x4298EC) // (fo::GameObject *aCritter<eax>, int aWeapon<edx>, int a2Or3<ebx>) returns 1 or 0
|
||||||
FUNC(ai_cap_, 0x4280B4)
|
FUNC(ai_cap_, 0x4280B4)
|
||||||
FUNC(ai_check_drugs_, 0x428480)
|
FUNC(ai_check_drugs_, 0x428480)
|
||||||
FUNC(ai_danger_source_, 0x428F4C)
|
FUNC(ai_danger_source_, 0x428F4C)
|
||||||
@@ -630,6 +631,8 @@ FUNC(register_object_turn_towards_, 0x414C50) // int aObj<eax>, int aTile<edx>
|
|||||||
FUNC(remove_bk_process_, 0x4C8DC4)
|
FUNC(remove_bk_process_, 0x4C8DC4)
|
||||||
FUNC(report_explosion_, 0x413144)
|
FUNC(report_explosion_, 0x413144)
|
||||||
FUNC(reset_box_bar_win_, 0x4614A0)
|
FUNC(reset_box_bar_win_, 0x4614A0)
|
||||||
|
FUNC(roll_check_, 0x4A3000)
|
||||||
|
FUNC(roll_check_critical_, 0x4A3030)
|
||||||
FUNC(roll_random_, 0x4A30C0)
|
FUNC(roll_random_, 0x4A30C0)
|
||||||
FUNC(runProgram_, 0x46E154) // eax - programPtr, called once for each program after first loaded - hooks program to game and UI events
|
FUNC(runProgram_, 0x46E154) // eax - programPtr, called once for each program after first loaded - hooks program to game and UI events
|
||||||
FUNC(scr_build_lookup_table_, 0x4A49D0)
|
FUNC(scr_build_lookup_table_, 0x4A49D0)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
changed to stdcall wrappers instead for stability
|
changed to stdcall wrappers instead for stability
|
||||||
*/
|
*/
|
||||||
WRAP_WATCOM_FUNC4(long, _word_wrap, const char*, text, int, maxWidth, DWORD*, buf, BYTE*, count)
|
WRAP_WATCOM_FUNC4(long, _word_wrap, const char*, text, int, maxWidth, DWORD*, buf, BYTE*, count)
|
||||||
|
WRAP_WATCOM_FUNC3(bool, ai_can_use_weapon, fo::GameObject*, critter, fo::GameObject*, item, DWORD, hitMode)
|
||||||
WRAP_WATCOM_FUNC3(long, ai_have_ammo, fo::GameObject*, critter, fo::GameObject*, item, fo::GameObject**, outAmmo)
|
WRAP_WATCOM_FUNC3(long, ai_have_ammo, fo::GameObject*, critter, fo::GameObject*, item, fo::GameObject**, outAmmo)
|
||||||
WRAP_WATCOM_FUNC3(long, ai_pick_hit_mode, fo::GameObject*, source, fo::GameObject*, item, fo::GameObject*, target)
|
WRAP_WATCOM_FUNC3(long, ai_pick_hit_mode, fo::GameObject*, source, fo::GameObject*, item, fo::GameObject*, target)
|
||||||
WRAP_WATCOM_FUNC3(long, ai_magic_hands, fo::GameObject*, source, fo::GameObject*, object, long, msgNumber)
|
WRAP_WATCOM_FUNC3(long, ai_magic_hands, fo::GameObject*, source, fo::GameObject*, object, long, msgNumber)
|
||||||
|
|||||||
@@ -19,7 +19,13 @@ namespace game
|
|||||||
namespace sf = sfall;
|
namespace sf = sfall;
|
||||||
|
|
||||||
static const long aiUseItemAPCost = 2;
|
static const long aiUseItemAPCost = 2;
|
||||||
|
/*
|
||||||
|
// Implementation of ai_can_use_weapon_ engine function with the HOOK_CANUSEWEAPON hook
|
||||||
|
bool CombatAI::ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode) {
|
||||||
|
bool result = fo::func::ai_can_use_weapon(source, weapon, hitMode);
|
||||||
|
return sf::CanUseWeaponHook_Invoke(result, source, weapon, hitMode);
|
||||||
|
}
|
||||||
|
*/
|
||||||
static long drugUsePerfFixMode;
|
static long drugUsePerfFixMode;
|
||||||
|
|
||||||
void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
|
void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class CombatAI {
|
|||||||
public:
|
public:
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
|
//static bool ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode);
|
||||||
|
|
||||||
static void __stdcall ai_check_drugs(fo::GameObject* source);
|
static void __stdcall ai_check_drugs(fo::GameObject* source);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,11 @@ static HooksInjectInfo injectHooks[] = {
|
|||||||
{HOOK_STDPROCEDURE_END, Inject_ScriptProcedureHook2, false},
|
{HOOK_STDPROCEDURE_END, Inject_ScriptProcedureHook2, false},
|
||||||
{HOOK_TARGETOBJECT, Inject_TargetObjectHook, false},
|
{HOOK_TARGETOBJECT, Inject_TargetObjectHook, false},
|
||||||
{HOOK_ENCOUNTER, Inject_EncounterHook, false},
|
{HOOK_ENCOUNTER, Inject_EncounterHook, false},
|
||||||
|
{-1, nullptr, false}, // dummy
|
||||||
|
{-1, nullptr, false}, // dummy
|
||||||
|
{HOOK_ROLLCHECK, Inject_RollCheckHook, false},
|
||||||
|
{HOOK_BESTWEAPON, Inject_BestWeaponHook, false},
|
||||||
|
{HOOK_CANUSEWEAPON, Inject_CanUseWeaponHook, false},
|
||||||
};
|
};
|
||||||
|
|
||||||
void HookScripts::InjectingHook(int hookId) {
|
void HookScripts::InjectingHook(int hookId) {
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ enum HookType
|
|||||||
HOOK_STDPROCEDURE_END = 41,
|
HOOK_STDPROCEDURE_END = 41,
|
||||||
HOOK_TARGETOBJECT = 42,
|
HOOK_TARGETOBJECT = 42,
|
||||||
HOOK_ENCOUNTER = 43,
|
HOOK_ENCOUNTER = 43,
|
||||||
|
// HOOK_ADJUSTPOISON = 44, // unimplemented
|
||||||
|
// HOOK_ADJUSTRADS = 45, // unimplemented
|
||||||
|
HOOK_ROLLCHECK = 46,
|
||||||
|
HOOK_BESTWEAPON = 47,
|
||||||
|
HOOK_CANUSEWEAPON = 48,
|
||||||
HOOK_COUNT
|
HOOK_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,11 @@ static void __fastcall FindTargetHook_Script(DWORD* target, fo::GameObject* atta
|
|||||||
}
|
}
|
||||||
EndHook();
|
EndHook();
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
void FindTargetHook_Invoke(fo::GameObject* targets[], fo::GameObject* attacker) {
|
||||||
|
if (HookScripts::HookHasScript(HOOK_FINDTARGET)) FindTargetHook_Script((DWORD*)targets, attacker);
|
||||||
|
}
|
||||||
|
*/
|
||||||
static void __declspec(naked) FindTargetHook() {
|
static void __declspec(naked) FindTargetHook() {
|
||||||
__asm {
|
__asm {
|
||||||
push eax;
|
push eax;
|
||||||
@@ -426,6 +430,99 @@ default:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fo::GameObject* __stdcall BestWeaponHook_Script(fo::GameObject* bestWeapon, fo::GameObject* source, fo::GameObject* weapon1, fo::GameObject* weapon2, fo::GameObject* target) {
|
||||||
|
BeginHook();
|
||||||
|
argCount = 5;
|
||||||
|
|
||||||
|
args[0] = (DWORD)source;
|
||||||
|
args[1] = (DWORD)bestWeapon;
|
||||||
|
args[2] = (DWORD)weapon1;
|
||||||
|
args[3] = (DWORD)weapon2;
|
||||||
|
args[4] = (DWORD)target;
|
||||||
|
|
||||||
|
RunHookScript(HOOK_BESTWEAPON);
|
||||||
|
|
||||||
|
if (cRet > 0) bestWeapon = (fo::GameObject*)rets[0];
|
||||||
|
|
||||||
|
EndHook();
|
||||||
|
return bestWeapon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) ai_search_inven_weap_hook() {
|
||||||
|
__asm {
|
||||||
|
push ecx; // target
|
||||||
|
push ebx; // weapon2 (secondary)
|
||||||
|
push edx; // weapon1 (primary)
|
||||||
|
push eax; // source
|
||||||
|
call fo::funcoffs::ai_best_weapon_;
|
||||||
|
push eax; // bestWeapon
|
||||||
|
call BestWeaponHook_Script;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
fo::GameObject* BestWeaponHook_Invoke(fo::GameObject* bestWeapon, fo::GameObject* source, fo::GameObject* weapon1, fo::GameObject* weapon2, fo::GameObject* target) {
|
||||||
|
return (HookScripts::HookHasScript(HOOK_BESTWEAPON))
|
||||||
|
? BestWeaponHook_Script(bestWeapon, source, weapon1, weapon2, target)
|
||||||
|
: bestWeapon;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
static bool __stdcall CanUseWeaponHook_Script(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode) {
|
||||||
|
BeginHook();
|
||||||
|
argCount = 4;
|
||||||
|
|
||||||
|
args[0] = (DWORD)source;
|
||||||
|
args[1] = (DWORD)weapon;
|
||||||
|
args[2] = hitMode;
|
||||||
|
args[3] = result;
|
||||||
|
|
||||||
|
RunHookScript(HOOK_CANUSEWEAPON);
|
||||||
|
|
||||||
|
if (cRet > 0) result = (rets[0]) ? true : false;
|
||||||
|
|
||||||
|
EndHook();
|
||||||
|
return result; // only 0 and 1
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) AICanUseWeaponHook() {
|
||||||
|
__asm {
|
||||||
|
push ecx;
|
||||||
|
push ebx; // hitMode
|
||||||
|
push edx; // weapon
|
||||||
|
push eax; // source
|
||||||
|
call fo::funcoffs::ai_can_use_weapon_;
|
||||||
|
push eax; // result
|
||||||
|
call CanUseWeaponHook_Script;
|
||||||
|
//and eax, 1;
|
||||||
|
pop ecx;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) CanUseWeaponHook() {
|
||||||
|
__asm {
|
||||||
|
push ecx;
|
||||||
|
push edx;
|
||||||
|
push -1; // hitMode (indefinite)
|
||||||
|
push eax; // weapon
|
||||||
|
push ds:[FO_VAR_obj_dude]; // source
|
||||||
|
call fo::funcoffs::can_use_weapon_; // 1 - can't use
|
||||||
|
xor al, 1;
|
||||||
|
push eax; // result
|
||||||
|
call CanUseWeaponHook_Script;
|
||||||
|
xor al, 1; // invert
|
||||||
|
pop edx;
|
||||||
|
pop ecx;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
bool CanUseWeaponHook_Invoke(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode) {
|
||||||
|
return (HookScripts::HookHasScript(HOOK_CANUSEWEAPON))
|
||||||
|
? CanUseWeaponHook_Script(result, source, weapon, hitMode)
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void Inject_ToHitHook() {
|
void Inject_ToHitHook() {
|
||||||
@@ -502,6 +599,21 @@ void Inject_TargetObjectHook() {
|
|||||||
SafeWrite8(0x44C26E, 0x17);
|
SafeWrite8(0x44C26E, 0x17);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inject_BestWeaponHook() {
|
||||||
|
HookCall(0x429A59, ai_search_inven_weap_hook);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inject_CanUseWeaponHook() {
|
||||||
|
const DWORD aiCanUseWpnHkAddr[] = {
|
||||||
|
0x429A1B, // ai_search_inven_weap_
|
||||||
|
0x429CF2, // ai_search_environ_
|
||||||
|
0x429E1C // ai_pick_hit_mode_
|
||||||
|
};
|
||||||
|
HookCalls(AICanUseWeaponHook, aiCanUseWpnHkAddr);
|
||||||
|
const DWORD canUseWpnHkAddr[] = {0x45F05E, 0x45F1C1, 0x45F203, 0x45F36A}; // intface_update_items_
|
||||||
|
HookCalls(CanUseWeaponHook, canUseWpnHkAddr);
|
||||||
|
}
|
||||||
|
|
||||||
void InitCombatHookScripts() {
|
void InitCombatHookScripts() {
|
||||||
HookScripts::LoadHookScript("hs_tohit", HOOK_TOHIT);
|
HookScripts::LoadHookScript("hs_tohit", HOOK_TOHIT);
|
||||||
HookScripts::LoadHookScript("hs_afterhitroll", HOOK_AFTERHITROLL);
|
HookScripts::LoadHookScript("hs_afterhitroll", HOOK_AFTERHITROLL);
|
||||||
@@ -512,6 +624,8 @@ void InitCombatHookScripts() {
|
|||||||
HookScripts::LoadHookScript("hs_ammocost", HOOK_AMMOCOST);
|
HookScripts::LoadHookScript("hs_ammocost", HOOK_AMMOCOST);
|
||||||
HookScripts::LoadHookScript("hs_onexplosion", HOOK_ONEXPLOSION);
|
HookScripts::LoadHookScript("hs_onexplosion", HOOK_ONEXPLOSION);
|
||||||
HookScripts::LoadHookScript("hs_targetobject", HOOK_TARGETOBJECT);
|
HookScripts::LoadHookScript("hs_targetobject", HOOK_TARGETOBJECT);
|
||||||
|
HookScripts::LoadHookScript("hs_bestweapon", HOOK_BESTWEAPON);
|
||||||
|
HookScripts::LoadHookScript("hs_canuseweapon", HOOK_CANUSEWEAPON);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,14 @@ void Inject_ItemDamageHook();
|
|||||||
void Inject_AmmoCostHook();
|
void Inject_AmmoCostHook();
|
||||||
void Inject_OnExplosionHook();
|
void Inject_OnExplosionHook();
|
||||||
void Inject_TargetObjectHook();
|
void Inject_TargetObjectHook();
|
||||||
|
void Inject_BestWeaponHook();
|
||||||
|
void Inject_CanUseWeaponHook();
|
||||||
|
|
||||||
int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD &rounds);
|
int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD &rounds);
|
||||||
|
|
||||||
long CalcApCostHook_Invoke(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon);
|
long CalcApCostHook_Invoke(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon);
|
||||||
|
//void FindTargetHook_Invoke(fo::GameObject* targets[], fo::GameObject* attacker);
|
||||||
|
//fo::GameObject* BestWeaponHook_Invoke(fo::GameObject* bestWeapon, fo::GameObject* source, fo::GameObject* weapon1, fo::GameObject* weapon2, fo::GameObject* target);
|
||||||
|
//bool CanUseWeaponHook_Invoke(bool result, fo::GameObject* source, fo::GameObject* weapon, long hitMode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -631,6 +631,66 @@ cancelEnc:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long __stdcall RollCheckHook_Script(long roll, long chance, long bonus, long randomChance, long calledFrom) {
|
||||||
|
long hookType;
|
||||||
|
switch (calledFrom - 5) {
|
||||||
|
case 0x42388E: // compute_attack_
|
||||||
|
case 0x4234D1: // compute_spray_
|
||||||
|
hookType = 1; // single and burst attack hit event
|
||||||
|
break;
|
||||||
|
case 0x42356C: // compute_spray_
|
||||||
|
hookType = 2; // burst attack bullet hit event
|
||||||
|
break;
|
||||||
|
case 0x4AAB29: // skill_result_
|
||||||
|
hookType = 3; // common skill check event
|
||||||
|
break;
|
||||||
|
case 0x4AB3B6: // skill_use_
|
||||||
|
hookType = 4; // SKILL_REPAIR
|
||||||
|
break;
|
||||||
|
case 0x4AB8B5: // skill_use_
|
||||||
|
hookType = 5; // SKILL_DOCTOR
|
||||||
|
break;
|
||||||
|
case 0x4ABC9F: // skill_check_stealing_
|
||||||
|
hookType = 6; // SKILL_STEAL - source stealing check event
|
||||||
|
break;
|
||||||
|
case 0x4ABCE6: // skill_check_stealing_
|
||||||
|
hookType = 7; // SKILL_STEAL - target stealing check event (fail for success stealing)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return roll; // unsupported hook
|
||||||
|
}
|
||||||
|
|
||||||
|
BeginHook();
|
||||||
|
argCount = 5;
|
||||||
|
|
||||||
|
args[0] = hookType;
|
||||||
|
args[1] = roll;
|
||||||
|
args[2] = chance;
|
||||||
|
args[3] = bonus;
|
||||||
|
args[4] = randomChance;
|
||||||
|
|
||||||
|
RunHookScript(HOOK_ROLLCHECK);
|
||||||
|
if (cRet) roll = rets[0];
|
||||||
|
|
||||||
|
EndHook();
|
||||||
|
return roll;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) roll_check_hook() {
|
||||||
|
__asm {
|
||||||
|
push ecx;
|
||||||
|
push [esp + 0xC + 8]; // calledFrom
|
||||||
|
push ebx; // random chance value
|
||||||
|
push esi; // bonus
|
||||||
|
push edi; // chance value
|
||||||
|
call fo::funcoffs::roll_check_critical_;
|
||||||
|
push eax; // roll result
|
||||||
|
call RollCheckHook_Script;
|
||||||
|
pop ecx;
|
||||||
|
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)
|
||||||
@@ -710,6 +770,10 @@ void Inject_EncounterHook() {
|
|||||||
HookCall(0x4C095C, wmRndEncounterOccurred_hook);
|
HookCall(0x4C095C, wmRndEncounterOccurred_hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inject_RollCheckHook() {
|
||||||
|
HookCall(0x4A3020, roll_check_hook);
|
||||||
|
}
|
||||||
|
|
||||||
void InitMiscHookScripts() {
|
void InitMiscHookScripts() {
|
||||||
HookScripts::LoadHookScript("hs_barterprice", HOOK_BARTERPRICE);
|
HookScripts::LoadHookScript("hs_barterprice", HOOK_BARTERPRICE);
|
||||||
HookScripts::LoadHookScript("hs_useskillon", HOOK_USESKILLON);
|
HookScripts::LoadHookScript("hs_useskillon", HOOK_USESKILLON);
|
||||||
@@ -722,6 +786,7 @@ void InitMiscHookScripts() {
|
|||||||
HookScripts::LoadHookScript("hs_resttimer", HOOK_RESTTIMER);
|
HookScripts::LoadHookScript("hs_resttimer", HOOK_RESTTIMER);
|
||||||
HookScripts::LoadHookScript("hs_explosivetimer", HOOK_EXPLOSIVETIMER);
|
HookScripts::LoadHookScript("hs_explosivetimer", HOOK_EXPLOSIVETIMER);
|
||||||
HookScripts::LoadHookScript("hs_encounter", HOOK_ENCOUNTER);
|
HookScripts::LoadHookScript("hs_encounter", HOOK_ENCOUNTER);
|
||||||
|
HookScripts::LoadHookScript("hs_rollcheck", HOOK_ROLLCHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ void Inject_SetGlobalVarHook();
|
|||||||
void Inject_RestTimerHook();
|
void Inject_RestTimerHook();
|
||||||
void Inject_ExplosiveTimerHook();
|
void Inject_ExplosiveTimerHook();
|
||||||
void Inject_EncounterHook();
|
void Inject_EncounterHook();
|
||||||
|
void Inject_RollCheckHook();
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user