Added FastMoveFromContainer as the auxiliary option for ItemFastMoveKey (from Mr.Stalin)

Refactored the code of StackEmptyWeapons.
Added missing argument validation for backported script functions.
This commit is contained in:
NovaRain
2018-10-10 18:27:54 +08:00
parent dad0860d6e
commit 25554ff0b2
5 changed files with 118 additions and 97 deletions
+4
View File
@@ -161,6 +161,10 @@ ReloadWeaponKey=0
;Set to 0 if you don't want to use a modifier key, or a DX scancode otherwise ;Set to 0 if you don't want to use a modifier key, or a DX scancode otherwise
ItemFastMoveKey=0x1d ItemFastMoveKey=0x1d
;Set to 1 to skip the 'Move Items' window when taking items from containers or corpses and not holding down ItemFastMoveKey
;Requires ItemFastMoveKey to be enabled
FastMoveFromContainer=0
;A key to press to open a debug game editor (requires FalloutClient.exe from the modders pack) ;A key to press to open a debug game editor (requires FalloutClient.exe from the modders pack)
;Set to 0 to disable, or a DX scancode otherwise ;Set to 0 to disable, or a DX scancode otherwise
DebugEditorKey=0 DebugEditorKey=0
+1 -1
View File
@@ -1436,7 +1436,7 @@ static void __declspec(naked) item_w_range_hook() {
call stat_level_; // get ST call stat_level_; // get ST
lea ecx, [eax + ebx]; // ebx - bonus from "Heave Ho!" lea ecx, [eax + ebx]; // ebx - bonus from "Heave Ho!"
sub ecx, 10; // compare ST + bonus <= 10 sub ecx, 10; // compare ST + bonus <= 10
jbe skip; jle skip;
sub ebx, ecx; // cutoff sub ebx, ecx; // cutoff
skip: skip:
retn; retn;
+104 -95
View File
@@ -34,6 +34,7 @@ static DWORD sizeLimitMode;
static DWORD invSizeMaxLimit; static DWORD invSizeMaxLimit;
static DWORD ReloadWeaponKey = 0; static DWORD ReloadWeaponKey = 0;
static DWORD ItemFastMoveKey = 0; static DWORD ItemFastMoveKey = 0;
static DWORD SkipFromContainer = 0;
struct sMessage { struct sMessage {
DWORD number; DWORD number;
@@ -413,20 +414,20 @@ end:
} }
} }
static int invenapcost; static int invenApCost, invenApCostDef;
static char invenapqpreduction; static char invenApQPReduction;
void _stdcall SetInvenApCost(int a) { void _stdcall SetInvenApCost(int cost) {
invenapcost = a; invenApCost = cost;
} }
static const DWORD inven_ap_cost_hook_ret = 0x46E816; static const DWORD inven_ap_cost_hack_ret = 0x46E816;
static void __declspec(naked) inven_ap_cost_hook() { static void __declspec(naked) inven_ap_cost_hack() {
_asm { _asm {
movzx ebx, byte ptr invenapqpreduction; movzx ebx, byte ptr invenApQPReduction;
mul bl; mul bl;
mov edx, invenapcost; mov edx, invenApCost;
sub edx, eax; sub edx, eax;
mov eax, edx; mov eax, edx;
jmp inven_ap_cost_hook_ret; jmp inven_ap_cost_hack_ret;
} }
} }
@@ -434,31 +435,31 @@ static const DWORD add_check_for_item_ammo_cost_back = 0x4266EE;
// adds check for weapons which require more than 1 ammo for single shot (super cattle prod & mega power fist) // adds check for weapons which require more than 1 ammo for single shot (super cattle prod & mega power fist)
static void __declspec(naked) add_check_for_item_ammo_cost() { static void __declspec(naked) add_check_for_item_ammo_cost() {
__asm { __asm {
push edx push edx
push ebx push ebx
sub esp, 4 sub esp, 4
call item_w_cur_ammo_ call item_w_cur_ammo_
mov ebx, eax mov ebx, eax
mov eax, ecx // weapon mov eax, ecx // weapon
mov edx, esp mov edx, esp
mov dword ptr [esp], 1 mov dword ptr [esp], 1
pushad pushad
push 1 // hook type push 1 // hook type
call AmmoCostHookWrapper call AmmoCostHookWrapper
add esp, 4 add esp, 4
popad popad
mov eax, [esp] mov eax, [esp]
cmp eax, ebx cmp eax, ebx
jle enoughammo jle enoughammo
xor eax, eax // this will force "Out of ammo" xor eax, eax // this will force "Out of ammo"
jmp end jmp end
enoughammo: enoughammo:
mov eax, 1 // this will force success mov eax, 1 // this will force success
end: end:
add esp, 4 add esp, 4
pop ebx pop ebx
pop edx pop edx
jmp add_check_for_item_ammo_cost_back; // jump back jmp add_check_for_item_ammo_cost_back; // jump back
} }
} }
@@ -467,74 +468,72 @@ static void __declspec(naked) divide_burst_rounds_by_ammo_cost() {
__asm { __asm {
// ecx - current ammo, eax - burst rounds; need to set ebp // ecx - current ammo, eax - burst rounds; need to set ebp
push edx push edx
sub esp, 4 sub esp, 4
mov ebp, eax mov ebp, eax
mov eax, edx // weapon mov eax, edx // weapon
mov dword ptr [esp], 1 mov dword ptr [esp], 1
mov edx, esp // *rounds mov edx, esp // *rounds
pushad pushad
push 2 push 2
call AmmoCostHookWrapper call AmmoCostHookWrapper
add esp, 4 add esp, 4
popad popad
mov edx, 0 mov edx, 0
mov eax, ebp // rounds in burst mov eax, ebp // rounds in burst
imul dword ptr [esp] // so much ammo is required for this burst imul dword ptr [esp] // so much ammo is required for this burst
cmp eax, ecx cmp eax, ecx
jle skip jle skip
mov eax, ecx // if more than current ammo, set it to current mov eax, ecx // if more than current ammo, set it to current
skip: skip:
idiv dword ptr [esp] // divide back to get proper number of rounds for damage calculations idiv dword ptr [esp] // divide back to get proper number of rounds for damage calculations
mov ebp, eax mov ebp, eax
add esp, 4 add esp, 4
pop edx pop edx
// end overwriten code // end overwriten code
jmp divide_burst_rounds_by_ammo_cost_back; // jump back jmp divide_burst_rounds_by_ammo_cost_back; // jump back
} }
} }
static void __declspec(naked) SetDefaultAmmo() { static void __declspec(naked) SetDefaultAmmo() {
__asm { __asm {
push eax push ecx;
push ebx mov ecx, edx; // ecx = item
push edx mov eax, edx;
xchg eax, edx call item_get_type_;
mov ebx, eax cmp eax, item_type_weapon; // is it item_type_weapon?
call item_get_type_ jne end; // no
cmp eax, item_type_weapon // is it item_type_weapon? cmp dword ptr [ecx + 0x3C], 0; // is there any ammo in the weapon?
jne end // no jne end; // yes
cmp dword ptr [ebx+0x3C], 0 // is there any ammo in the weapon? sub esp, 4;
jne end // yes mov edx, esp;
sub esp, 4 mov eax, [ecx + 0x64]; // eax = weapon pid
mov edx, esp call proto_ptr_;
mov eax, [ebx+0x64] // eax = weapon pid mov edx, [esp];
call proto_ptr_ mov eax, [edx + 0x5C]; // eax = default ammo pid
mov edx, [esp] mov [ecx + 0x40], eax; // set current ammo proto
mov eax, [edx+0x5C] // eax = default ammo pid add esp, 4;
mov [ebx+0x40], eax // set current ammo proto
add esp, 4
end: end:
pop edx pop ecx;
pop ebx retn;
pop eax
retn
} }
} }
static const DWORD inven_action_cursor_hack_End = 0x4736CB;
static void __declspec(naked) inven_action_cursor_hack() { static void __declspec(naked) inven_action_cursor_hack() {
__asm { __asm {
mov edx, [esp+0x1C] mov edx, [esp + 0x6C - 0x50 + 4]; // source_item
call SetDefaultAmmo call SetDefaultAmmo;
cmp dword ptr [esp+0x18], 0 cmp dword ptr [esp + 0x6C - 0x54 + 4], 0; // overwritten engine code
jmp inven_action_cursor_hack_End retn;
} }
} }
static void __declspec(naked) item_add_mult_hook() { static void __declspec(naked) item_add_mult_hook() {
__asm { __asm {
call SetDefaultAmmo push edx;
jmp item_add_force_ call SetDefaultAmmo;
pop edx;
mov eax, ecx; // restore
jmp item_add_force_;
} }
} }
@@ -565,7 +564,7 @@ end:
} }
} }
static void __declspec(naked) loot_container_hack2() { static void __declspec(naked) loot_container_hack_scroll() {
__asm { __asm {
cmp esi, 0x150 // source_down cmp esi, 0x150 // source_down
je scroll je scroll
@@ -603,7 +602,7 @@ end:
} }
} }
static void __declspec(naked) barter_inventory_hack2() { static void __declspec(naked) barter_inventory_hack_scroll() {
__asm { __asm {
push edx push edx
push ecx push ecx
@@ -685,24 +684,31 @@ end:
} }
} }
void __declspec(naked) do_move_timer_hook() { static const DWORD DoMoveTimer_Ret = 0x476920;
static void __declspec(naked) do_move_timer_hook() {
__asm { __asm {
cmp eax, 4; cmp eax, 4;
jnz end; jnz end;
pushad; pushad;
} }
KeyDown(ItemFastMoveKey); KeyDown(ItemFastMoveKey); // check pressed
__asm { __asm {
cmp SkipFromContainer, 0;
jz noSkip;
cmp dword ptr [esp + 0x14 + 36], 0x474A43;
jnz noSkip;
test eax, eax; test eax, eax;
setz al;
noSkip:
test eax, eax; // set if pressed
popad; popad;
jz end; jz end;
mov dword ptr [esp], 0x476920; add esp, 4; // destroy ret
retn; jmp DoMoveTimer_Ret;
end: end:
call setup_move_timer_win_; jmp setup_move_timer_win_;
retn;
} }
} }
@@ -758,9 +764,9 @@ void InventoryInit() {
} }
} }
invenapcost = GetPrivateProfileInt("Misc", "InventoryApCost", 4, ini); invenApCost = invenApCostDef = GetPrivateProfileInt("Misc", "InventoryApCost", 4, ini);
invenapqpreduction = GetPrivateProfileInt("Misc", "QuickPocketsApCostReduction", 2, ini); invenApQPReduction = GetPrivateProfileInt("Misc", "QuickPocketsApCostReduction", 2, ini);
MakeJump(0x46E80B, inven_ap_cost_hook); MakeJump(0x46E80B, inven_ap_cost_hack);
if(GetPrivateProfileInt("Misc", "SuperStimExploitFix", 0, ini)) { if(GetPrivateProfileInt("Misc", "SuperStimExploitFix", 0, ini)) {
GetPrivateProfileString("sfall", "SuperStimExploitMsg", "You cannot use a super stim on someone who is not injured!", SuperStimMsg, 128, translationIni); GetPrivateProfileString("sfall", "SuperStimExploitMsg", "You cannot use a super stim on someone who is not injured!", SuperStimMsg, 128, translationIni);
@@ -775,8 +781,8 @@ void InventoryInit() {
ReloadWeaponKey = GetPrivateProfileInt("Input", "ReloadWeaponKey", 0, ini); ReloadWeaponKey = GetPrivateProfileInt("Input", "ReloadWeaponKey", 0, ini);
if (GetPrivateProfileIntA("Misc", "StackEmptyWeapons", 0, ini)) { if (GetPrivateProfileIntA("Misc", "StackEmptyWeapons", 0, ini)) {
MakeJump(0x4736C6, inven_action_cursor_hack); MakeCall(0x4736C6, inven_action_cursor_hack);
HookCall(0x4772AA, &item_add_mult_hook); HookCall(0x4772AA, item_add_mult_hook);
} }
// Do not call the 'Move Items' window when using drap and drop to reload weapons in the inventory // Do not call the 'Move Items' window when using drap and drop to reload weapons in the inventory
@@ -791,6 +797,8 @@ void InventoryInit() {
ItemFastMoveKey = GetPrivateProfileIntA("Input", "ItemFastMoveKey", DIK_LCONTROL, ini); ItemFastMoveKey = GetPrivateProfileIntA("Input", "ItemFastMoveKey", DIK_LCONTROL, ini);
if (ItemFastMoveKey > 0) { if (ItemFastMoveKey > 0) {
HookCall(0x476897, do_move_timer_hook); HookCall(0x476897, do_move_timer_hook);
// Do not call the 'Move Items' window when taking items from containers or corpses
SkipFromContainer = GetPrivateProfileIntA("Input", "FastMoveFromContainer", 0, ini);
} }
if (GetPrivateProfileIntA("Misc", "ItemCounterDefaultMax", 0, ini)) { if (GetPrivateProfileIntA("Misc", "ItemCounterDefaultMax", 0, ini)) {
@@ -806,11 +814,12 @@ void InventoryInit() {
// Enable mouse scroll control in barter and loot screens when the cursor is hovering over other lists // Enable mouse scroll control in barter and loot screens when the cursor is hovering over other lists
if (UseScrollWheel) { if (UseScrollWheel) {
MakeCall(0x473E66, loot_container_hack2); MakeCall(0x473E66, loot_container_hack_scroll);
MakeCall(0x4759F1, barter_inventory_hack2); MakeCall(0x4759F1, barter_inventory_hack_scroll);
*((DWORD*)_max) = 100; *((DWORD*)_max) = 100;
}; };
} }
void InventoryReset() { void InventoryReset() {
invenapcost=GetPrivateProfileInt("Misc", "InventoryApCost", 4, ini); invenApCost = invenApCostDef;
} }
+1 -1
View File
@@ -18,7 +18,7 @@
#pragma once #pragma once
void _stdcall SetInvenApCost(int a); void _stdcall SetInvenApCost(int cost);
DWORD __stdcall sf_item_total_size(TGameObj* critter); DWORD __stdcall sf_item_total_size(TGameObj* critter);
void InventoryInit(); void InventoryInit();
void InventoryReset(); void InventoryReset();
+8
View File
@@ -373,7 +373,15 @@ static OpcodeHandler opHandler;
static const SfallOpcodeMetadata opcodeMetaArray[] = { static const SfallOpcodeMetadata opcodeMetaArray[] = {
{sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_get_current_inven_size, "get_current_inven_size", {DATATYPE_MASK_VALID_OBJ}},
{sf_get_flags, "get_flags", {DATATYPE_MASK_VALID_OBJ}},
{sf_get_outline, "get_outline", {DATATYPE_MASK_VALID_OBJ}},
{sf_item_weight, "item_weight", {DATATYPE_MASK_VALID_OBJ}},
{sf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}},
{sf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_set_ini_setting, "set_ini_setting", {DATATYPE_MASK_STR, DATATYPE_MASK_INT | DATATYPE_MASK_STR}}, {sf_set_ini_setting, "set_ini_setting", {DATATYPE_MASK_STR, DATATYPE_MASK_INT | DATATYPE_MASK_STR}},
{sf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}}, {sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}},
{sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}}, {sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}},
//{op_message_str_game, {}} //{op_message_str_game, {}}