Added a check for the DAM_KNOCKED_OUT flag

to wield_obj_critter/inven_unwield script functions.

Added climbing ladders to "interrupted player's movement in combat" fix.
This commit is contained in:
NovaRain
2019-07-03 12:09:39 +08:00
parent d8d3bade94
commit 274e141277
2 changed files with 63 additions and 19 deletions
+10 -1
View File
@@ -2121,6 +2121,14 @@ static void __declspec(naked) action_use_an_item_on_object_hack() {
}
}
static void __declspec(naked) action_climb_ladder_hack() {
__asm {
add ecx, ds:[FO_VAR_combat_free_move];
mov eax, 2; // RB_RESERVED
retn;
}
}
//static const DWORD wmAreaMarkVisitedState_Error = 0x4C4698;
static const DWORD wmAreaMarkVisitedState_Ret = 0x4C46A2;
static void __declspec(naked) wmAreaMarkVisitedState_hack() {
@@ -2771,6 +2779,7 @@ void BugFixes::init()
// Fix for the player's movement in combat being interrupted when trying to use objects with Bonus Move APs available
MakeCall(0x411FD6, action_use_an_item_on_object_hack);
MakeCall(0x411DF7, action_climb_ladder_hack);
// Fix for Scout perk being taken into account when setting the visibility of locations with mark_area_known function
// also fix the incorrect coordinates for small/medium location circles that the engine uses to highlight their sub-tiles
@@ -2783,7 +2792,7 @@ void BugFixes::init()
// Fix for combat not ending automatically when there are no hostile critters
MakeCall(0x422CF3, combat_should_end_hack);
SafeWrite16(0x422CEA, 0x0C74); // jz 0x422CF8
SafeWrite16(0x422CEA, 0x0C74); // jz 0x422CF8 (skip party members)
}
}
+53 -18
View File
@@ -531,30 +531,60 @@ skip:
}
}
static void __declspec(naked) op_inven_unwield_hook() {
using namespace fo;
using namespace Fields;
__asm {
mov ecx, [eax + protoId];
and ecx, 0x0F000000;
cmp ecx, OBJ_TYPE_CRITTER << 24;
jne skip;
test byte ptr [eax + damageFlags], DAM_KNOCKED_OUT;
jz skip;
push 0x505AFC; // "But is already Inactive (Dead/Stunned/Invisible)"
call fo::funcoffs::debug_printf_;
add esp, 4;
retn;
skip:
jmp fo::funcoffs::inven_unwield_;
}
}
static void __declspec(naked) op_wield_obj_critter_hook() {
using namespace fo;
using namespace Fields;
__asm {
test byte ptr [eax + damageFlags], DAM_KNOCKED_OUT;
jz skip;
mov eax, -1;
retn;
skip:
jmp fo::funcoffs::inven_wield_;
}
}
// reimplementation of adjust_fid engine function
// Differences from vanilla:
// - doesn't use art_vault_guy_num as default art, uses current critter FID instead
// - invokes onAdjustFid delegate that allows to hook into FID calculation
DWORD __stdcall Inventory::adjust_fid_replacement() {
using namespace fo;
DWORD fid;
if (var::inven_dude->TypeFid() == ObjType::OBJ_TYPE_CRITTER) {
if (fo::var::inven_dude->TypeFid() == fo::OBJ_TYPE_CRITTER) {
DWORD frameNum;
DWORD weaponAnimCode = 0;
if (PartyControl::IsNpcControlled()) {
// if NPC is under control, use current FID of critter
frameNum = var::inven_dude->artFid & 0xFFF;
frameNum = fo::var::inven_dude->artFid & 0xFFF;
} else {
// vanilla logic:
frameNum = var::art_vault_guy_num;
auto critterPro = GetProto(var::inven_pid);
frameNum = fo::var::art_vault_guy_num;
auto critterPro = fo::GetProto(fo::var::inven_pid);
if (critterPro != nullptr) {
frameNum = critterPro->fid & 0xFFF;
}
if (var::i_worn != nullptr) {
auto armorPro = GetProto(var::i_worn->protoId);
DWORD armorFrameNum = func::stat_level(var::inven_dude, STAT_gender) == GENDER_FEMALE
if (fo::var::i_worn != nullptr) {
auto armorPro = fo::GetProto(fo::var::i_worn->protoId);
DWORD armorFrameNum = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE
? armorPro->item.armor.femaleFrameNum
: armorPro->item.armor.maleFrameNum;
@@ -563,23 +593,23 @@ DWORD __stdcall Inventory::adjust_fid_replacement() {
}
}
}
auto itemInHand = func::intface_is_item_right_hand()
? var::i_rhand
: var::i_lhand;
auto itemInHand = fo::func::intface_is_item_right_hand()
? fo::var::i_rhand
: fo::var::i_lhand;
if (itemInHand != nullptr) {
auto itemPro = GetProto(itemInHand->protoId);
if (itemPro->item.type == item_type_weapon) {
auto itemPro = fo::GetProto(itemInHand->protoId);
if (itemPro->item.type == fo::item_type_weapon) {
weaponAnimCode = itemPro->item.weapon.animationCode;
}
}
fid = func::art_id(OBJ_TYPE_CRITTER, frameNum, 0, weaponAnimCode, 0);
fid = fo::func::art_id(fo::OBJ_TYPE_CRITTER, frameNum, 0, weaponAnimCode, 0);
} else {
fid = var::inven_dude->artFid;
fid = fo::var::inven_dude->artFid;
}
var::i_fid = fid;
fo::var::i_fid = fid;
onAdjustFid.invoke(fid);
return var::i_fid;
return fo::var::i_fid;
}
static void __declspec(naked) adjust_fid_hack_replacement() {
@@ -759,6 +789,11 @@ void Inventory::init() {
MakeCall(0x4759F1, barter_inventory_hack_scroll);
fo::var::max = 100;
};
// Check the DAM_KNOCKED_OUT flag for wield_obj_critter/inven_unwield script functions
// Note: the flag is not checked for the metarule(METARULE_INVEN_UNWIELD_WHO, x) function
HookCall(0x45B0CE, op_inven_unwield_hook);
HookCall(0x45693C, op_wield_obj_critter_hook);
}
Delegate<DWORD>& Inventory::OnAdjustFid() {