mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed a bug in CheckWeaponAmmoCost (from Mr.Stalin)
It caused NPCs to not switch to other weapons when there is not enough ammo to shoot. Moved CheckWeaponAmmoCost code from Inventory.cpp to Combat.cpp. Now the debug editor starts at the center of the screen. Updated the previous fix in NPC combat control mod.
This commit is contained in:
Generated
+1
@@ -180,6 +180,7 @@
|
||||
this.Controls.Add(this.dataGridView1);
|
||||
this.MinimumSize = new System.Drawing.Size(450, 300);
|
||||
this.Name = "DebugEditor";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "sfall Debug Editor";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DebugEditor_FormClosing);
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
|
||||
|
||||
Generated
+1
@@ -111,6 +111,7 @@
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
this.MinimumSize = new System.Drawing.Size(300, 200);
|
||||
this.Name = "EditorWindow";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Edit Values";
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
Binary file not shown.
@@ -109,8 +109,8 @@ procedure invenwield_handler begin
|
||||
event := get_sfall_arg;
|
||||
|
||||
// Fix weapon duplication when equipping in combat
|
||||
if (event and AllowControl(obj_pid(critter))) then begin
|
||||
set_flags(item, get_flags(item) bwand bwnot(FLAG_LEFT_HAND bwor FLAG_RIGHT_HAND));
|
||||
if (event and slot == INVEN_TYPE_RIGHT_HAND and AllowControl(obj_pid(critter))) then begin
|
||||
set_flags(item, get_flags(item) bwand bwnot(FLAG_LEFT_HAND));
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "..\main.h"
|
||||
#include "..\FalloutEngine\Fallout2.h"
|
||||
#include "HookScripts.h"
|
||||
#include "LoadGameHook.h"
|
||||
#include "Objects.h"
|
||||
|
||||
@@ -48,6 +49,87 @@ static bool hookedAimedShot;
|
||||
static std::vector<DWORD> disabledAS;
|
||||
static std::vector<DWORD> forcedAS;
|
||||
|
||||
static DWORD __fastcall add_check_for_item_ammo_cost(register fo::GameObject* weapon, DWORD hitMode) {
|
||||
DWORD rounds = 1;
|
||||
|
||||
DWORD anim = fo::func::item_w_anim_weap(weapon, hitMode);
|
||||
if (anim == fo::Animation::ANIM_fire_burst || anim == fo::Animation::ANIM_fire_continuous) {
|
||||
rounds = fo::func::item_w_rounds(weapon); // ammo in burst
|
||||
}
|
||||
if (HookScripts::IsInjectHook(HOOK_AMMOCOST)) {
|
||||
AmmoCostHook_Script(1, weapon, &rounds); // get rounds cost from hook
|
||||
} else if (rounds == 1) {
|
||||
fo::func::item_w_compute_ammo_cost(weapon, &rounds);
|
||||
}
|
||||
DWORD currAmmo = fo::func::item_w_curr_ammo(weapon);
|
||||
|
||||
DWORD cost = 1; // default cost
|
||||
if (currAmmo > 0) {
|
||||
cost = rounds / currAmmo;
|
||||
if (rounds % currAmmo) cost++; // round up
|
||||
}
|
||||
return (cost > currAmmo) ? 0 : 1; // 0 - this will force "Out of ammo", 1 - this will force success (enough ammo)
|
||||
}
|
||||
|
||||
// adds check for weapons which require more than 1 ammo for single shot (super cattle prod & mega power fist) and burst rounds
|
||||
static void __declspec(naked) combat_check_bad_shot_hook() {
|
||||
__asm {
|
||||
push edx;
|
||||
push ecx; // weapon
|
||||
mov edx, edi; // hitMode
|
||||
call add_check_for_item_ammo_cost;
|
||||
pop ecx;
|
||||
pop edx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
// check if there is enough ammo to shoot
|
||||
static void __declspec(naked) ai_search_inven_weap_hook() {
|
||||
using namespace fo;
|
||||
__asm {
|
||||
push ecx;
|
||||
mov ecx, eax; // weapon
|
||||
mov edx, ATKTYPE_RWEAPON_PRIMARY; // hitMode
|
||||
call add_check_for_item_ammo_cost;
|
||||
mov ebx, eax; // result
|
||||
mov ecx, esi;
|
||||
mov edx, ATKTYPE_RWEAPON_SECONDARY;
|
||||
call add_check_for_item_ammo_cost;
|
||||
and eax, ebx; // enough ammo?
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD __fastcall divide_burst_rounds_by_ammo_cost(fo::GameObject* weapon, register DWORD currAmmo, DWORD burstRounds) {
|
||||
DWORD rounds = 1; // default multiply
|
||||
|
||||
if (HookScripts::IsInjectHook(HOOK_AMMOCOST)) {
|
||||
rounds = burstRounds; // rounds in burst
|
||||
AmmoCostHook_Script(2, weapon, &rounds);
|
||||
}
|
||||
|
||||
DWORD cost = burstRounds * rounds; // so much ammo is required for this burst
|
||||
if (cost > currAmmo) cost = currAmmo; // if cost ammo more than current ammo, set it to current
|
||||
|
||||
return (cost / rounds); // divide back to get proper number of rounds for damage calculations
|
||||
}
|
||||
|
||||
static void __declspec(naked) compute_spray_hack() {
|
||||
__asm {
|
||||
push edx; // weapon
|
||||
push ecx; // current ammo in weapon
|
||||
xchg ecx, edx;
|
||||
push eax; // eax - rounds in burst attack, need to set ebp
|
||||
call divide_burst_rounds_by_ammo_cost;
|
||||
mov ebp, eax; // overwriten code
|
||||
pop ecx;
|
||||
pop edx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static double ApplyModifiers(std::vector<KnockbackModifier>* mods, fo::GameObject* object, double val) {
|
||||
for (DWORD i = 0; i < mods->size(); i++) {
|
||||
KnockbackModifier* mod = &(*mods)[i];
|
||||
@@ -308,6 +390,11 @@ void Combat::init() {
|
||||
// Actually disables all secondary attacks for the critter, regardless of whether the weapon has a burst attack
|
||||
MakeCall(0x429E44, ai_pick_hit_mode_hack, 1); // NoBurst
|
||||
|
||||
if (GetConfigInt("Misc", "CheckWeaponAmmoCost", 0)) {
|
||||
HookCall(0x4266E9, combat_check_bad_shot_hook);
|
||||
MakeCall(0x4234B3, compute_spray_hack, 1);
|
||||
HookCall(0x429A37, ai_search_inven_weap_hook);
|
||||
}
|
||||
LoadGameHook::OnGameReset() += Combat_OnGameLoad;
|
||||
}
|
||||
|
||||
|
||||
@@ -388,68 +388,6 @@ static void __declspec(naked) inven_ap_cost_hack() {
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD __fastcall add_check_for_item_ammo_cost(register fo::GameObject* weapon, DWORD hitMode) {
|
||||
DWORD rounds = 1;
|
||||
DWORD anim = fo::func::item_w_anim_weap(weapon, hitMode);
|
||||
if (anim == fo::Animation::ANIM_fire_burst || anim == fo::Animation::ANIM_fire_continuous) {
|
||||
rounds = fo::func::item_w_rounds(weapon); // ammo in burst
|
||||
}
|
||||
|
||||
if (HookScripts::IsInjectHook(HOOK_AMMOCOST)) {
|
||||
AmmoCostHook_Script(1, weapon, &rounds); // get rounds cost from hook
|
||||
}
|
||||
|
||||
DWORD currAmmo = fo::func::item_w_curr_ammo(weapon);
|
||||
|
||||
DWORD cost = 1; // default cost
|
||||
if (currAmmo > 0) cost = (DWORD)ceilf((float)rounds / currAmmo);
|
||||
|
||||
return (cost > currAmmo) ? 0 : 1; // 0 - this will force "Out of ammo", 1 - this will force success (enough ammo)
|
||||
}
|
||||
|
||||
// adds check for weapons which require more than 1 ammo for single shot (super cattle prod & mega power fist) and burst rounds
|
||||
static void __declspec(naked) combat_check_bad_shot_hook() {
|
||||
__asm {
|
||||
push edx;
|
||||
push ebx;
|
||||
push ecx; // weapon
|
||||
mov edx, edi; // hitMode
|
||||
call add_check_for_item_ammo_cost;
|
||||
pop ecx;
|
||||
pop ebx;
|
||||
pop edx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD __fastcall divide_burst_rounds_by_ammo_cost(fo::GameObject* weapon, register DWORD currAmmo, DWORD burstRounds) {
|
||||
DWORD rounds = 1; // default multiply
|
||||
|
||||
if (HookScripts::IsInjectHook(HOOK_AMMOCOST)) {
|
||||
rounds = burstRounds; // rounds in burst
|
||||
AmmoCostHook_Script(2, weapon, &rounds);
|
||||
}
|
||||
|
||||
DWORD cost = burstRounds * rounds; // so much ammo is required for this burst
|
||||
if (cost > currAmmo) cost = currAmmo; // if cost ammo more than current ammo, set it to current
|
||||
|
||||
return (cost / rounds); // divide back to get proper number of rounds for damage calculations
|
||||
}
|
||||
|
||||
static void __declspec(naked) compute_spray_hack() {
|
||||
__asm {
|
||||
push edx; // weapon
|
||||
push ecx; // current ammo in weapon
|
||||
xchg ecx, edx;
|
||||
push eax; // eax - rounds in burst attack, need to set ebp
|
||||
call divide_burst_rounds_by_ammo_cost;
|
||||
mov ebp, eax; // overwriten code
|
||||
pop ecx;
|
||||
pop edx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) SetDefaultAmmo() {
|
||||
using namespace fo;
|
||||
using namespace Fields;
|
||||
@@ -783,11 +721,6 @@ void Inventory::init() {
|
||||
MakeCall(0x49C3D9, SuperStimFix);
|
||||
}
|
||||
|
||||
if (GetConfigInt("Misc", "CheckWeaponAmmoCost", 0)) {
|
||||
HookCall(0x4266E9, combat_check_bad_shot_hook);
|
||||
MakeCall(0x4234B3, compute_spray_hack, 1);
|
||||
}
|
||||
|
||||
reloadWeaponKey = GetConfigInt("Input", "ReloadWeaponKey", 0);
|
||||
|
||||
if (GetConfigInt("Misc", "StackEmptyWeapons", 0)) {
|
||||
|
||||
Reference in New Issue
Block a user