mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -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
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user