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:
NovaRain
2021-09-02 11:23:24 +08:00
parent 428cf42c7d
commit 569bde5fab
8 changed files with 96 additions and 39 deletions
Binary file not shown.
+3 -3
View File
@@ -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
+5 -3
View File
@@ -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 */
+5 -4
View File
@@ -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)
+24 -5
View File
@@ -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() {
-24
View File
@@ -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) {
+58
View File
@@ -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);
} }
} }