mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Code changes to the previous commit
Changed HOOK_CANUSEWEAPON to run for both the player and NPCs. Updated gl_npcarmor script.
This commit is contained in:
Binary file not shown.
@@ -65,7 +65,7 @@ procedure check_weapon_change(variable critter, variable weapon, variable isWiel
|
|||||||
weaponAnimList := npc["WeaponAnims"];
|
weaponAnimList := npc["WeaponAnims"];
|
||||||
if (weaponAnimList != 0) then begin
|
if (weaponAnimList != 0) then begin
|
||||||
foreach (i in string_split(weaponAnimList, ",")) begin
|
foreach (i in string_split(weaponAnimList, ",")) begin
|
||||||
if (newWeaponAnim == atoi(i)) then return -1; // can use (engine default)
|
if (newWeaponAnim == atoi(i) and not(weapon_is_unusable(weapon))) then return -1; // can use (engine default)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return 0; // can't use
|
return 0; // can't use
|
||||||
@@ -226,10 +226,10 @@ end
|
|||||||
procedure canuseweapon_handler begin
|
procedure canuseweapon_handler begin
|
||||||
variable critter, canWield;
|
variable critter, canWield;
|
||||||
critter := get_sfall_arg;
|
critter := get_sfall_arg;
|
||||||
//if (critter) then begin
|
if (critter != dude_obj) then begin
|
||||||
canWield := check_weapon_change(critter, get_sfall_arg, true);
|
canWield := check_weapon_change(critter, get_sfall_arg, true);
|
||||||
// override result
|
// override result
|
||||||
set_sfall_arg(3, canWield);
|
set_sfall_arg(3, canWield);
|
||||||
set_sfall_return(canWield);
|
set_sfall_return(canWield);
|
||||||
//end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -289,9 +289,11 @@
|
|||||||
// checks if the specified PID number exists in the list of registered protos
|
// checks if the specified PID number exists in the list of registered protos
|
||||||
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
#define check_pid(pid) (get_proto_data(pid, 0) != -1)
|
||||||
|
|
||||||
// sets the status of a broken weapon that cannot be used in combat (the hand slot will not be available for use)
|
// sets the status of an unusable weapon that cannot be used in combat
|
||||||
#define set_broken_weapon_state_on(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwor 0x00000010)
|
// use the HOOK_CANUSEWEAPON hook with weapon_is_unusable macro to override the engine value
|
||||||
#define set_broken_weapon_state_off(item) set_object_data(item, OBJ_DATA_MISC_FLAGS, get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0xFFFFFFEF)
|
#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 weapon_is_unusable(item) (get_object_data(item, OBJ_DATA_MISC_FLAGS) bwand 0x00000010)
|
||||||
|
|
||||||
|
|
||||||
/* SFALL_FUNCX MACROS */
|
/* SFALL_FUNCX MACROS */
|
||||||
|
|||||||
@@ -897,13 +897,14 @@ Item ret0 - overrides the chosen best weapon
|
|||||||
|
|
||||||
#### `HOOK_CANUSEWEAPON (hs_canuseweapon.int)`
|
#### `HOOK_CANUSEWEAPON (hs_canuseweapon.int)`
|
||||||
|
|
||||||
Run when the AI checks whether it can use a weapon.
|
Run when the AI checks whether it can use a weapon, or when the game checks whether the player can use a weapon.
|
||||||
This mostly happens when NPCs try to find weapons in their inventory or on the map.
|
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 redraws the interface bar.
|
||||||
|
|
||||||
```
|
```
|
||||||
Critter arg0 - the critter doing the check
|
Critter arg0 - the critter doing the check
|
||||||
Item arg1 - the weapon being checked
|
Item arg1 - the item being checked
|
||||||
int arg2 - attack type (see ATKTYPE_* constants)
|
int arg2 - attack type (see ATKTYPE_* constants), or -1 for dude_obj
|
||||||
int arg3 - original result of engine function: 1 - can use, 0 - can't use
|
int arg3 - original result of engine function: 1 - can use, 0 - can't use
|
||||||
|
|
||||||
int ret0 - overrides the result of engine function. Any non-zero value allows using the weapon
|
int ret0 - overrides the result of engine function. Any non-zero value allows using the weapon
|
||||||
|
|||||||
@@ -616,6 +616,7 @@ FUNC(calculateColor_, 0x4C72B4)
|
|||||||
FUNC(calloc_, 0x4EAFEC)
|
FUNC(calloc_, 0x4EAFEC)
|
||||||
FUNC(can_see_, 0x412BEC)
|
FUNC(can_see_, 0x412BEC)
|
||||||
FUNC(can_talk_to_, 0x413420)
|
FUNC(can_talk_to_, 0x413420)
|
||||||
|
FUNC(can_use_weapon_, 0x477F3C)
|
||||||
FUNC(cget_, 0x4F2250)
|
FUNC(cget_, 0x4F2250)
|
||||||
FUNC(cget_string_, 0x4F0EA1)
|
FUNC(cget_string_, 0x4F0EA1)
|
||||||
FUNC(cgetw_, 0x4F2E5B)
|
FUNC(cgetw_, 0x4F2E5B)
|
||||||
|
|||||||
@@ -626,17 +626,17 @@ static bool __stdcall CanUseWeaponHook_Script(bool result, fo::GameObject* sourc
|
|||||||
args[0] = (DWORD)source;
|
args[0] = (DWORD)source;
|
||||||
args[1] = (DWORD)weapon;
|
args[1] = (DWORD)weapon;
|
||||||
args[2] = hitMode;
|
args[2] = hitMode;
|
||||||
args[3] = 0 | result;
|
args[3] = result;
|
||||||
|
|
||||||
RunHookScript(HOOK_CANUSEWEAPON);
|
RunHookScript(HOOK_CANUSEWEAPON);
|
||||||
|
|
||||||
if (cRet > 0) result = rets[0] ? true : false;
|
if (cRet > 0) result = (rets[0]) ? true : false;
|
||||||
|
|
||||||
EndHook();
|
EndHook();
|
||||||
return result; // only 0 and 1
|
return result; // only 0 and 1
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) CanUseWeaponHook() {
|
static void __declspec(naked) AICanUseWeaponHook() {
|
||||||
__asm {
|
__asm {
|
||||||
push ecx;
|
push ecx;
|
||||||
push ebx; // hitMode
|
push ebx; // hitMode
|
||||||
@@ -645,7 +645,25 @@ static void __declspec(naked) CanUseWeaponHook() {
|
|||||||
call fo::funcoffs::ai_can_use_weapon_;
|
call fo::funcoffs::ai_can_use_weapon_;
|
||||||
push eax; // result
|
push eax; // result
|
||||||
call CanUseWeaponHook_Script;
|
call CanUseWeaponHook_Script;
|
||||||
and eax, 1;
|
//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;
|
pop ecx;
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
@@ -750,11 +768,12 @@ void Inject_BestWeaponHook() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Inject_CanUseWeaponHook() {
|
void Inject_CanUseWeaponHook() {
|
||||||
HookCalls(CanUseWeaponHook, {
|
HookCalls(AICanUseWeaponHook, {
|
||||||
0x429A1B, // ai_search_inven_weap_
|
0x429A1B, // ai_search_inven_weap_
|
||||||
0x429CF2, // ai_search_environ_
|
0x429CF2, // ai_search_environ_
|
||||||
0x429E1C // ai_pick_hit_mode_
|
0x429E1C // ai_pick_hit_mode_
|
||||||
});
|
});
|
||||||
|
HookCalls(CanUseWeaponHook, { 0x45F05E, 0x45F1C1, 0x45F203, 0x45F36A }); // intface_update_items_
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitCombatHookScripts() {
|
void InitCombatHookScripts() {
|
||||||
|
|||||||
@@ -595,25 +595,6 @@ static void __declspec(naked) do_move_timer_hack() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) can_use_weapon_hook() {
|
|
||||||
static const DWORD can_use_weapon_Ret = 0x477F9F;
|
|
||||||
using namespace fo;
|
|
||||||
using namespace fo::Fields;
|
|
||||||
__asm {
|
|
||||||
call fo::funcoffs::item_get_type_;
|
|
||||||
cmp eax, item_type_weapon;
|
|
||||||
je checkFlag;
|
|
||||||
retn; // eax - type
|
|
||||||
checkFlag:
|
|
||||||
test dword ptr [edx + miscFlags], CantUse;
|
|
||||||
jnz cantUse;
|
|
||||||
retn; // eax - type
|
|
||||||
cantUse:
|
|
||||||
add esp, 4;
|
|
||||||
jmp can_use_weapon_Ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int invenApCost, invenApCostDef;
|
static int invenApCost, invenApCostDef;
|
||||||
static char invenApQPReduction;
|
static char invenApQPReduction;
|
||||||
|
|
||||||
@@ -758,11 +739,6 @@ void Inventory::init() {
|
|||||||
// Note: the flag is not checked for the metarule(METARULE_INVEN_UNWIELD_WHO, x) function
|
// Note: the flag is not checked for the metarule(METARULE_INVEN_UNWIELD_WHO, x) function
|
||||||
HookCall(0x45B0CE, op_inven_unwield_hook); // with fix to update interface slot after unwielding
|
HookCall(0x45B0CE, op_inven_unwield_hook); // with fix to update interface slot after unwielding
|
||||||
HookCall(0x45693C, op_wield_obj_critter_hook);
|
HookCall(0x45693C, op_wield_obj_critter_hook);
|
||||||
|
|
||||||
// Add an additional "Can't Use" flag to the misc flags of item objects (offset 0x0038)
|
|
||||||
// Misc Flags:
|
|
||||||
// 0x00000010 - Can't Use (makes the weapon object unusable in combat)
|
|
||||||
HookCall(0x477F4C, can_use_weapon_hook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inventory::InvokeAdjustFid(long fid) {
|
void Inventory::InvokeAdjustFid(long fid) {
|
||||||
|
|||||||
@@ -60,6 +60,57 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) ai_can_use_weapon_hack() {
|
||||||
|
using namespace fo;
|
||||||
|
using namespace Fields;
|
||||||
|
__asm {
|
||||||
|
test dword ptr [esi + miscFlags], CantUse;
|
||||||
|
jnz cantUse;
|
||||||
|
mov eax, [edi + damageFlags];
|
||||||
|
retn;
|
||||||
|
cantUse:
|
||||||
|
mov al, 0xFF;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) can_use_weapon_hook() {
|
||||||
|
static const DWORD cant_use_weapon_Ret = 0x477F9F;
|
||||||
|
using namespace fo;
|
||||||
|
using namespace Fields;
|
||||||
|
__asm {
|
||||||
|
call fo::funcoffs::item_get_type_;
|
||||||
|
cmp eax, item_type_weapon;
|
||||||
|
je checkFlag;
|
||||||
|
retn; // eax - type
|
||||||
|
checkFlag:
|
||||||
|
test dword ptr [edx + miscFlags], CantUse;
|
||||||
|
jnz cantUse;
|
||||||
|
retn; // eax - type
|
||||||
|
cantUse:
|
||||||
|
add esp, 4;
|
||||||
|
jmp cant_use_weapon_Ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: in ai_try_attack_, the attacker will not be able to change unusable weapon, as it happens with crippled arms
|
||||||
|
static void __declspec(naked) combat_check_bad_shot_hack() {
|
||||||
|
static const DWORD combat_check_bad_shot_Ret = 0x42673A;
|
||||||
|
using namespace fo;
|
||||||
|
using namespace Fields;
|
||||||
|
__asm {
|
||||||
|
test dword ptr [ecx + miscFlags], CantUse;
|
||||||
|
jnz cantUse;
|
||||||
|
mov eax, [esi + damageFlags];
|
||||||
|
test al, DAM_CRIP_ARM_LEFT;
|
||||||
|
retn;
|
||||||
|
cantUse:
|
||||||
|
mov eax, 4; // result same as TargetDead
|
||||||
|
add esp, 4;
|
||||||
|
jmp combat_check_bad_shot_Ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __stdcall CombatBlock::SetBlockCombat(long toggle) {
|
void __stdcall CombatBlock::SetBlockCombat(long toggle) {
|
||||||
combatDisabled = toggle != 0;
|
combatDisabled = toggle != 0;
|
||||||
}
|
}
|
||||||
@@ -67,6 +118,13 @@ void __stdcall CombatBlock::SetBlockCombat(long toggle) {
|
|||||||
void CombatBlock::init() {
|
void CombatBlock::init() {
|
||||||
HookCall(0x45F626, intface_use_item_hook); // jnz hook
|
HookCall(0x45F626, intface_use_item_hook); // jnz hook
|
||||||
HookCall(0x4432A6, game_handle_input_hook);
|
HookCall(0x4432A6, game_handle_input_hook);
|
||||||
|
|
||||||
|
// Add an additional "Can't Use" flag to the misc flags of item objects (offset 0x0038)
|
||||||
|
// Misc Flags:
|
||||||
|
// 0x00000010 - Can't Use (makes the weapon object unusable in combat)
|
||||||
|
HookCall(0x477F4C, can_use_weapon_hook);
|
||||||
|
MakeCall(0x4298F4, ai_can_use_weapon_hack);
|
||||||
|
MakeCall(0x426669, combat_check_bad_shot_hack);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user