Skip to content

Commit

Permalink
Backported the code of AmmoCost hook from 4.x.
Browse files Browse the repository at this point in the history
* Mainly for fixing the issues with CheckWeaponAmmoCost. Because it's
easier to backport the whole set of code than working on the old
implementation. Shouldn't affect the performance much.

Also backported the CheckWeaponAmmoCost code from 4.x.
Updated hookscripts.txt to reflect the change.
Now the debug editor starts at the center of the screen.
  • Loading branch information
NovaRain committed Apr 9, 2019
1 parent 4232be0 commit 564c483
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 142 deletions.
1 change: 1 addition & 0 deletions MPClient/DebugEditor.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions MPClient/EditorWindow.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions artifacts/scripting/hookscripts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,12 @@ HOOK_AMMOCOST (hs_ammocost.int)

Runs when calculating ammo cost for a weapon. Doesn't affect damage, only how much ammo is spent.
By default, weapon will shoot when at least 1 round is left, regardless of ammo cost calculations.
To add proper check for ammo before shooting and proper calculation of number of burst rounds, set Misc.CheckWeaponAmmoCost=1 in ddraw.ini
To add proper check for ammo before shooting and proper calculation of number of burst rounds (hook type 1 and 2 in arg4), set Misc.CheckWeaponAmmoCost=1 in ddraw.ini

Item arg1 - weapon
int arg2 - Number of bullets in burst (1 for single shots)
int arg3 - Ammo cost calculated by original function (this is basically 2 for Super Cattle Prod and Mega Power Fist)
int arg4 - Type of hook (0 - when subtracting ammo after attack, 1 - when checking for "out of ammo" before attack)
int arg4 - Type of hook (0 - when subtracting ammo after single shot attack, 1 - when checking for "out of ammo" before attack, 2 - when calculating number of burst rounds, 3 - when subtracting ammo after burst attack)

int ret1 - new ammo cost value (set to 0 for unlimited ammo)

Expand Down
2 changes: 1 addition & 1 deletion sfall/DebugEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct sArray {
};

static void DEGameWinRedraw() {
__asm call process_bk_;
ProcessBk();
}

static bool SetBlocking(SOCKET s, bool block) {
Expand Down
37 changes: 36 additions & 1 deletion sfall/FalloutEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ const DWORD item_w_anim_code_ = 0x478DA8;
const DWORD item_w_anim_weap_ = 0x47860C;
const DWORD item_w_can_reload_ = 0x478874;
const DWORD item_w_compute_ammo_cost_ = 0x4790AC;
const DWORD item_w_cur_ammo_ = 0x4786A0;
const DWORD item_w_curr_ammo_ = 0x4786A0;
const DWORD item_w_dam_div_ = 0x479294;
const DWORD item_w_dam_mult_ = 0x479230;
const DWORD item_w_damage_ = 0x478448;
Expand Down Expand Up @@ -791,6 +791,10 @@ void InterfaceRedraw() {
__asm call intface_redraw_;
}

void __stdcall ProcessBk() {
__asm call process_bk_;
}

// pops value type from Data stack (must be followed by InterpretPopLong)
DWORD __stdcall InterpretPopShort(TProgram* scriptPtr) {
__asm {
Expand Down Expand Up @@ -981,3 +985,34 @@ long __stdcall QueueFindFirst(TGameObj* object, long qType) {
call queue_find_first_;
}
}

// for the backported AmmoCostHook from 4.x
long __stdcall ItemWAnimWeap(TGameObj* item, DWORD hitMode) {
__asm {
mov edx, hitMode;
mov eax, item;
call item_w_anim_weap_;
}
}

long __stdcall ItemWComputeAmmoCost(TGameObj* item, DWORD* rounds) {
__asm {
mov edx, rounds;
mov eax, item;
call item_w_compute_ammo_cost_;
}
}

long __stdcall ItemWCurrAmmo(TGameObj* item) {
__asm {
mov eax, item;
call item_w_curr_ammo_;
}
}

long __stdcall ItemWRounds(TGameObj* item) {
__asm {
mov eax, item;
call item_w_rounds_;
}
}
67 changes: 28 additions & 39 deletions sfall/FalloutEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,11 @@ extern const DWORD add_bar_box_;
extern const DWORD AddHotLines_;
extern const DWORD adjust_ac_;
extern const DWORD adjust_fid_;
extern const DWORD ai_can_use_weapon_; // (TGameObj *aCritter<eax>, int aWeapon<edx>, int a2Or3<ebx>) returns 1 or 0
extern const DWORD ai_search_inven_armor_;
extern const DWORD ai_try_attack_;
extern const DWORD art_alias_num_;
extern const DWORD art_exists_;
extern const DWORD art_exists_; // eax - frameID, used for critter FIDs
extern const DWORD art_flush_;
extern const DWORD art_frame_data_;
extern const DWORD art_frame_length_;
Expand Down Expand Up @@ -574,7 +575,7 @@ extern const DWORD gdProcess_;
extern const DWORD GetSlotList_;
extern const DWORD get_input_;
extern const DWORD get_time_;
extern const DWORD getmsg_;
extern const DWORD getmsg_; // eax - msg file addr, ebx - message ID, edx - int[4] - loads string from MSG file preloaded in memory
extern const DWORD gmouse_3d_get_mode_;
extern const DWORD gmouse_3d_set_mode_;
extern const DWORD gmouse_is_scrolling_;
Expand All @@ -592,6 +593,8 @@ extern const DWORD handle_inventory_;
extern const DWORD inc_game_time_;
extern const DWORD inc_stat_;
extern const DWORD insert_withdrawal_;
extern const DWORD interface_disable_;
extern const DWORD interface_enable_;
extern const DWORD interpret_; // <eax> - programPtr, <edx> - ??? (-1)
extern const DWORD interpretAddString_;
extern const DWORD interpretFindProcedure_; // get proc number (different for each script) by name: *<eax> - scriptPtr, char* <edx> - proc name
Expand All @@ -602,25 +605,26 @@ extern const DWORD interpretPopShort_;
extern const DWORD interpretPushLong_;
extern const DWORD interpretPushShort_;
extern const DWORD interpretError_;
extern const DWORD intface_get_attack_;
extern const DWORD intface_hide_;
extern const DWORD intface_is_hidden_;
extern const DWORD intface_item_reload_; // no args
extern const DWORD intface_redraw_; // no args
extern const DWORD intface_toggle_item_state_;
extern const DWORD intface_show_;
extern const DWORD intface_toggle_item_state_; // no args
extern const DWORD intface_toggle_items_;
extern const DWORD intface_update_ac_;
extern const DWORD intface_update_hit_points_;
extern const DWORD intface_update_items_;
extern const DWORD intface_update_move_points_;
extern const DWORD intface_use_item_;
extern const DWORD intface_show_;
extern const DWORD intface_hide_;
extern const DWORD intface_is_hidden_;
extern const DWORD intface_get_attack_;
extern const DWORD intface_use_item_; // no args
extern const DWORD invenUnwieldFunc_; // (int critter@<eax>, int slot@<edx>, int a3@<ebx>) - int result (-1 on error, 0 on success)
extern const DWORD invenWieldFunc_; // (int who@<eax>, int item@<edx>, int a3@<ecx>, int slot@<ebx>) - int result (-1 on error, 0 on success)
extern const DWORD inven_display_msg_;
extern const DWORD inven_find_id_;
extern const DWORD inven_left_hand_;
extern const DWORD inven_left_hand_; // eax - object
extern const DWORD inven_pid_is_carried_ptr_;
extern const DWORD inven_right_hand_;
extern const DWORD inven_right_hand_; // eax - object
extern const DWORD inven_unwield_;
extern const DWORD inven_wield_;
extern const DWORD inven_worn_;
Expand Down Expand Up @@ -651,13 +655,13 @@ extern const DWORD item_w_anim_code_;
extern const DWORD item_w_anim_weap_;
extern const DWORD item_w_can_reload_;
extern const DWORD item_w_compute_ammo_cost_; // signed int aWeapon<eax>, int *aRoundsSpent<edx>
extern const DWORD item_w_cur_ammo_;
extern const DWORD item_w_curr_ammo_; // eax - object
extern const DWORD item_w_dam_div_;
extern const DWORD item_w_dam_mult_;
extern const DWORD item_w_damage_;
extern const DWORD item_w_damage_type_;
extern const DWORD item_w_dr_adjust_;
extern const DWORD item_w_max_ammo_;
extern const DWORD item_w_max_ammo_; // eax - object
extern const DWORD item_w_mp_cost_;
extern const DWORD item_w_perk_;
extern const DWORD item_w_range_;
Expand Down Expand Up @@ -721,6 +725,8 @@ extern const DWORD obj_find_first_at_tile_; // <eax>(int elevation<eax>, int ti
extern const DWORD obj_find_next_at_;
extern const DWORD obj_find_next_at_tile_; // no args
extern const DWORD obj_lock_is_jammed_;
extern const DWORD obj_move_to_tile_; // int aObj<eax>, int aTile<edx>, int aElev<ebx>
extern const DWORD obj_new_; // int aObj*<eax>, int aPid<ebx>
extern const DWORD obj_new_sid_inst_;
extern const DWORD obj_outline_object_;
extern const DWORD obj_pid_new_;
Expand All @@ -731,6 +737,7 @@ extern const DWORD obj_set_light_; // <eax>(int aObj<eax>, signed int aDist<edx>
extern const DWORD obj_shoot_blocking_at_;
extern const DWORD obj_sight_blocking_at_;
extern const DWORD obj_top_environment_;
extern const DWORD obj_turn_off_; // int aObj<eax>, int ???<edx>
extern const DWORD obj_unjam_lock_;
extern const DWORD obj_use_book_;
extern const DWORD obj_use_power_on_car_;
Expand Down Expand Up @@ -768,7 +775,7 @@ extern const DWORD process_bk_;
extern const DWORD protinst_use_item_;
extern const DWORD protinst_use_item_on_;
extern const DWORD proto_dude_update_gender_;
extern const DWORD proto_ptr_;
extern const DWORD proto_ptr_; // eax - PID, edx - int** - pointer to a pointer to a proto struct
extern const DWORD pushLongStack_;
extern const DWORD qsort_;
extern const DWORD queue_add_;
Expand Down Expand Up @@ -895,32 +902,6 @@ extern const DWORD xvfprintf_;
* 2) Call _stdcall functions from (1), write those entirely in C++ (with little ASM blocks only to call engine functions, when you are too lazy to add wrapper)
*/

extern const DWORD item_get_type_;
extern const DWORD inven_left_hand_; // eax - object
extern const DWORD inven_right_hand_; // eax - object
extern const DWORD proto_ptr_; // eax - PID, edx - int** - pointer to a pointer to a proto struct
extern const DWORD ai_can_use_weapon_; // (TGameObj *aCritter<eax>, int aWeapon<edx>, int a2Or3<ebx>) returns 1 or 0
extern const DWORD item_w_max_ammo_; // eax - object
extern const DWORD item_w_cur_ammo_; // eax - object


// Interface
extern const DWORD interface_disable_;
extern const DWORD interface_enable_;
extern const DWORD intface_toggle_items_;
extern const DWORD intface_item_reload_; // no args
extern const DWORD intface_toggle_item_state_; // no args
extern const DWORD intface_use_item_; // no args

// objects
extern const DWORD obj_new_; // int aObj*<eax>, int aPid<ebx>
extern const DWORD obj_turn_off_; // int aObj<eax>, int ???<edx>
extern const DWORD obj_move_to_tile_; // int aObj<eax>, int aTile<edx>, int aElev<ebx>

extern const DWORD art_exists_; // eax - frameID, used for critter FIDs

extern const DWORD getmsg_; // eax - msg file addr, ebx - message ID, edx - int[4] - loads string from MSG file preloaded in memory

#define MSG_FILE_COMBAT (0x56D368)
#define MSG_FILE_AI (0x56D510)
#define MSG_FILE_SCRNAME (0x56D754)
Expand Down Expand Up @@ -970,6 +951,8 @@ void SkillSetTags(int* tags, DWORD num);
// redraws the main game interface windows (useful after changing some data like active hand, etc.)
void InterfaceRedraw();

void __stdcall ProcessBk();

// critter worn item (armor)
TGameObj* __stdcall InvenWorn(TGameObj* critter);

Expand Down Expand Up @@ -1024,3 +1007,9 @@ void __stdcall DisplayTargetInventory(long inventoryOffset, long visibleOffset,
long __stdcall StatLevel(TGameObj* critter, long statId);

long __stdcall QueueFindFirst(TGameObj* object, long qType);

// for the backported AmmoCostHook from 4.x
long __stdcall ItemWAnimWeap(TGameObj* item, DWORD hitMode);
long __stdcall ItemWComputeAmmoCost(TGameObj* item, DWORD* rounds);
long __stdcall ItemWCurrAmmo(TGameObj* item);
long __stdcall ItemWRounds(TGameObj* item);
73 changes: 34 additions & 39 deletions sfall/HookScripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -777,51 +777,46 @@ static void __declspec(naked) ItemDamageHook() {
}
}

static void __declspec(naked) AmmoCostHook_internal() {
__asm {
pushad;
mov args[0], eax; //weapon
mov ebx, [edx];
mov args[4], ebx; //rounds in attack
call item_w_compute_ammo_cost_;
cmp eax, -1;
je fail;
mov ebx, [edx];
mov args[8], ebx; //rounds as computed by game
// code backported from 4.x
int __fastcall AmmoCostHook_Script(DWORD hookType, TGameObj* weapon, DWORD* rounds) {
int result = 0;

push HOOK_AMMOCOST;
call RunHookScript;
popad;
cmp cRet, 0;
je end;
mov eax, rets[0];
mov [edx], eax; // override result
xor eax, eax;
jmp end;
fail:
popad;
end:
hookend;
retn;
}
}
BeginHook();
argCount = 4;

static void __declspec(naked) AmmoCostHook() {
__asm {
hookbegin(4);
mov args[12], 0; // type of hook
jmp AmmoCostHook_internal;
args[0] = (DWORD)weapon;
args[1] = *rounds; // rounds in attack
args[3] = hookType;

if (hookType == 2) { // burst hook
*rounds = 1; // set default multiply for check burst attack
} else {
result = ItemWComputeAmmoCost(weapon, rounds);
if (result == -1) goto failed; // failed computed
}
args[2] = *rounds; // rounds as computed by game (cost)

RunHookScript(HOOK_AMMOCOST);

if (cRet > 0) *rounds = rets[0]; // override rounds

failed:
EndHook();
return result;
}

void __declspec(naked) AmmoCostHookWrapper() {
static void __declspec(naked) AmmoCostHook() {
__asm {
hookbegin(4);
push eax;
mov eax, [esp+8]; // hook type
mov args[12], eax;
pop eax;
call AmmoCostHook_internal;
xor ecx, ecx; // type of hook (0)
cmp dword ptr [esp + 0x1C + 4], 46; // ANIM_fire_burst
jl skip;
cmp dword ptr [esp + 0x1C + 4], 47; // ANIM_fire_continuous
jg skip;
mov ecx, 3; // hook type burst
skip:
xchg eax, edx;
push eax; // rounds in attack
call AmmoCostHook_Script; // edx - weapon
retn;
}
}
Expand Down
4 changes: 2 additions & 2 deletions sfall/HookScripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void HookScriptInit();
void HookScriptClear();

extern DWORD InitingHookScripts;
extern void __declspec() AmmoCostHookWrapper();
extern int __fastcall AmmoCostHook_Script(DWORD hookType, TGameObj* weapon, DWORD* rounds);
void _stdcall MouseClickHook(DWORD button, bool pressed);
DWORD _stdcall KeyPressHook(DWORD dxKey, bool pressed, DWORD vKey);
void _stdcall RunHookScriptsAtProc(DWORD procId);
void _stdcall RunHookScriptsAtProc(DWORD procId);
Loading

0 comments on commit 564c483

Please sign in to comment.