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"];
if (weaponAnimList != 0) then 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
return 0; // can't use
@@ -226,10 +226,10 @@ end
procedure canuseweapon_handler begin
variable critter, canWield;
critter := get_sfall_arg;
//if (critter) then begin
if (critter != dude_obj) then begin
canWield := check_weapon_change(critter, get_sfall_arg, true);
// override result
set_sfall_arg(3, canWield);
set_sfall_return(canWield);
//end
end
end
+5 -3
View File
@@ -289,9 +289,11 @@
// checks if the specified PID number exists in the list of registered protos
#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)
#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)
#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)
// 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_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 */
+5 -4
View File
@@ -897,13 +897,14 @@ Item ret0 - overrides the chosen best weapon
#### `HOOK_CANUSEWEAPON (hs_canuseweapon.int)`
Run when the AI checks whether it can use a weapon.
This mostly happens when NPCs try to find weapons in their inventory or on the map.
Run when the AI checks whether it can use a weapon, or when the game checks whether the player can use a weapon.
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
Item arg1 - the weapon being checked
int arg2 - attack type (see ATKTYPE_* constants)
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 - can't use
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(can_see_, 0x412BEC)
FUNC(can_talk_to_, 0x413420)
FUNC(can_use_weapon_, 0x477F3C)
FUNC(cget_, 0x4F2250)
FUNC(cget_string_, 0x4F0EA1)
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[1] = (DWORD)weapon;
args[2] = hitMode;
args[3] = 0 | result;
args[3] = result;
RunHookScript(HOOK_CANUSEWEAPON);
if (cRet > 0) result = rets[0] ? true : false;
if (cRet > 0) result = (rets[0]) ? true : false;
EndHook();
return result; // only 0 and 1
}
static void __declspec(naked) CanUseWeaponHook() {
static void __declspec(naked) AICanUseWeaponHook() {
__asm {
push ecx;
push ebx; // hitMode
@@ -645,7 +645,25 @@ static void __declspec(naked) CanUseWeaponHook() {
call fo::funcoffs::ai_can_use_weapon_;
push eax; // result
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;
retn;
}
@@ -750,11 +768,12 @@ void Inject_BestWeaponHook() {
}
void Inject_CanUseWeaponHook() {
HookCalls(CanUseWeaponHook, {
HookCalls(AICanUseWeaponHook, {
0x429A1B, // ai_search_inven_weap_
0x429CF2, // ai_search_environ_
0x429E1C // ai_pick_hit_mode_
});
HookCalls(CanUseWeaponHook, { 0x45F05E, 0x45F1C1, 0x45F203, 0x45F36A }); // intface_update_items_
}
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 char invenApQPReduction;
@@ -758,11 +739,6 @@ void Inventory::init() {
// 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(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) {
+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) {
combatDisabled = toggle != 0;
}
@@ -67,6 +118,13 @@ void __stdcall CombatBlock::SetBlockCombat(long toggle) {
void CombatBlock::init() {
HookCall(0x45F626, intface_use_item_hook); // jnz 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);
}
}