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_Error = 0x4C4698;
static const DWORD wmAreaMarkVisitedState_Ret = 0x4C46A2; static const DWORD wmAreaMarkVisitedState_Ret = 0x4C46A2;
static void __declspec(naked) wmAreaMarkVisitedState_hack() { 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 // 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(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 // 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 // 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 // Fix for combat not ending automatically when there are no hostile critters
MakeCall(0x422CF3, combat_should_end_hack); 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 // reimplementation of adjust_fid engine function
// Differences from vanilla: // Differences from vanilla:
// - doesn't use art_vault_guy_num as default art, uses current critter FID instead // - 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 // - invokes onAdjustFid delegate that allows to hook into FID calculation
DWORD __stdcall Inventory::adjust_fid_replacement() { DWORD __stdcall Inventory::adjust_fid_replacement() {
using namespace fo;
DWORD fid; DWORD fid;
if (var::inven_dude->TypeFid() == ObjType::OBJ_TYPE_CRITTER) { if (fo::var::inven_dude->TypeFid() == fo::OBJ_TYPE_CRITTER) {
DWORD frameNum; DWORD frameNum;
DWORD weaponAnimCode = 0; DWORD weaponAnimCode = 0;
if (PartyControl::IsNpcControlled()) { if (PartyControl::IsNpcControlled()) {
// if NPC is under control, use current FID of critter // if NPC is under control, use current FID of critter
frameNum = var::inven_dude->artFid & 0xFFF; frameNum = fo::var::inven_dude->artFid & 0xFFF;
} else { } else {
// vanilla logic: // vanilla logic:
frameNum = var::art_vault_guy_num; frameNum = fo::var::art_vault_guy_num;
auto critterPro = GetProto(var::inven_pid); auto critterPro = fo::GetProto(fo::var::inven_pid);
if (critterPro != nullptr) { if (critterPro != nullptr) {
frameNum = critterPro->fid & 0xFFF; frameNum = critterPro->fid & 0xFFF;
} }
if (var::i_worn != nullptr) { if (fo::var::i_worn != nullptr) {
auto armorPro = GetProto(var::i_worn->protoId); auto armorPro = fo::GetProto(fo::var::i_worn->protoId);
DWORD armorFrameNum = func::stat_level(var::inven_dude, STAT_gender) == GENDER_FEMALE DWORD armorFrameNum = fo::func::stat_level(fo::var::inven_dude, fo::STAT_gender) == fo::GENDER_FEMALE
? armorPro->item.armor.femaleFrameNum ? armorPro->item.armor.femaleFrameNum
: armorPro->item.armor.maleFrameNum; : armorPro->item.armor.maleFrameNum;
@@ -563,23 +593,23 @@ DWORD __stdcall Inventory::adjust_fid_replacement() {
} }
} }
} }
auto itemInHand = func::intface_is_item_right_hand() auto itemInHand = fo::func::intface_is_item_right_hand()
? var::i_rhand ? fo::var::i_rhand
: var::i_lhand; : fo::var::i_lhand;
if (itemInHand != nullptr) { if (itemInHand != nullptr) {
auto itemPro = GetProto(itemInHand->protoId); auto itemPro = fo::GetProto(itemInHand->protoId);
if (itemPro->item.type == item_type_weapon) { if (itemPro->item.type == fo::item_type_weapon) {
weaponAnimCode = itemPro->item.weapon.animationCode; 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 { } else {
fid = var::inven_dude->artFid; fid = fo::var::inven_dude->artFid;
} }
var::i_fid = fid; fo::var::i_fid = fid;
onAdjustFid.invoke(fid); onAdjustFid.invoke(fid);
return var::i_fid; return fo::var::i_fid;
} }
static void __declspec(naked) adjust_fid_hack_replacement() { static void __declspec(naked) adjust_fid_hack_replacement() {
@@ -759,6 +789,11 @@ void Inventory::init() {
MakeCall(0x4759F1, barter_inventory_hack_scroll); MakeCall(0x4759F1, barter_inventory_hack_scroll);
fo::var::max = 100; 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() { Delegate<DWORD>& Inventory::OnAdjustFid() {