Added new HOOK_SUBCOMBATDAMAGE and refactored damage formulas code in AmmoMod.cpp (from Mr.Stalin)

This commit is contained in:
NovaRain
2018-11-27 12:27:48 +08:00
parent 180e743d31
commit 922cdefce6
10 changed files with 188 additions and 164 deletions
+1 -1
View File
@@ -372,7 +372,7 @@ NPCsTryToSpendExtraAP=0
;Note that enabling this option can significantly affect the weapon choice of some NPCs in combat ;Note that enabling this option can significantly affect the weapon choice of some NPCs in combat
AIBestWeaponFix=0 AIBestWeaponFix=0
;Set to 1 to fix NPCs not checking chem_primary_desire setting in AI.txt for drug use preference ;Set to 1 to fix NPCs not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory
AIDrugUsePerfFix=0 AIDrugUsePerfFix=0
;Allows the use of tiles over 80*36 in size. sfall will just split and resave them at startup ;Allows the use of tiles over 80*36 in size. sfall will just split and resave them at startup
@@ -267,4 +267,49 @@
#define WPN_ANIM_MINIGUN (0x09) // (L) #define WPN_ANIM_MINIGUN (0x09) // (L)
#define WPN_ANIM_ROCKET_LAUNCHER (0x0A) // (M) #define WPN_ANIM_ROCKET_LAUNCHER (0x0A) // (M)
// Compute attack result fields
#define C_ATTACK_SOURCE (0x00)
#define C_ATTACK_HIT_MODE (0x04)
#define C_ATTACK_WEAPON (0x08)
#define C_ATTACK_DAMAGE_SOURCE (0x10) // Amount
#define C_ATTACK_FLAGS_SOURCE (0x14) // see DAM_* values in define.h
#define C_ATTACK_ROUNDS (0x18)
#define C_ATTACK_TARGET (0x20)
#define C_ATTACK_BODY_PART (0x28)
#define C_ATTACK_DAMAGE_TARGET (0x2C) // Amount
#define C_ATTACK_FLAGS_TARGET (0x30) // see DAM_*
#define C_ATTACK_KNOCKBACK_VALUE (0x34)
#define C_ATTACK_MAIN_TARGET (0x38)
#define C_ATTACK_AROUND_NUMBER (0x3C) // The number of critters around the target
#define C_ATTACK_TARGET1 (0x40)
#define C_ATTACK_TARGET2 (0x44)
#define C_ATTACK_TARGET3 (0x48)
#define C_ATTACK_TARGET4 (0x4C)
#define C_ATTACK_TARGET5 (0x50)
#define C_ATTACK_TARGET6 (0x54)
#define C_ATTACK_BODY_PART1 (0x58)
#define C_ATTACK_BODY_PART2 (0x5C)
#define C_ATTACK_BODY_PART3 (0x60)
#define C_ATTACK_BODY_PART4 (0x64)
#define C_ATTACK_BODY_PART5 (0x68)
#define C_ATTACK_BODY_PART6 (0x6C)
#define C_ATTACK_DAMAGE_TARGET1 (0x70) // Amount
#define C_ATTACK_DAMAGE_TARGET2 (0x74)
#define C_ATTACK_DAMAGE_TARGET3 (0x78)
#define C_ATTACK_DAMAGE_TARGET4 (0x7C)
#define C_ATTACK_DAMAGE_TARGET5 (0x80)
#define C_ATTACK_DAMAGE_TARGET6 (0x84)
#define C_ATTACK_FLAGS_TARGET1 (0x88) // see DAM_*
#define C_ATTACK_FLAGS_TARGET2 (0x8C)
#define C_ATTACK_FLAGS_TARGET3 (0x90)
#define C_ATTACK_FLAGS_TARGET4 (0x94)
#define C_ATTACK_FLAGS_TARGET5 (0x98)
#define C_ATTACK_FLAGS_TARGET6 (0x9C)
#define C_ATTACK_KNOCKBACK_VALUE1 (0xA0)
#define C_ATTACK_KNOCKBACK_VALUE2 (0xA4)
#define C_ATTACK_KNOCKBACK_VALUE3 (0xA8)
#define C_ATTACK_KNOCKBACK_VALUE4 (0xAC)
#define C_ATTACK_KNOCKBACK_VALUE5 (0xB0)
#define C_ATTACK_KNOCKBACK_VALUE6 (0xB4)
#endif // DEFINE_EXTRA_H #endif // DEFINE_EXTRA_H
+1
View File
@@ -58,6 +58,7 @@
#define HOOK_DESCRIPTIONOBJ (34) #define HOOK_DESCRIPTIONOBJ (34)
#define HOOK_USESKILLON (35) #define HOOK_USESKILLON (35)
#define HOOK_ONEXPLOSION (36) #define HOOK_ONEXPLOSION (36)
#define HOOK_SUBCOMBATDAMAGE (37)
//Valid arguments to list_begin //Valid arguments to list_begin
#define LIST_CRITTERS (0) #define LIST_CRITTERS (0)
+27 -2
View File
@@ -166,7 +166,7 @@ int arg5 - The special effect flags for the target (use bwand DAM_* to chec
int arg6 - The special effect flags for the attacker (use bwand DAM_* to check specific flags) int arg6 - The special effect flags for the attacker (use bwand DAM_* to check specific flags)
int arg7 - The weapon used in the attack int arg7 - The weapon used in the attack
int arg8 - The bodypart that was struck int arg8 - The bodypart that was struck
int arg9 - Damage Multiplier (this is divided by 2, so a value of 3 does 1.5x damage, and 8 does 4x damage. Usually it's 2, but with Silent Death perk and the corresponding attack conditions, it's 4; for critical hits, the value is taken from the critical table) int arg9 - Damage Multiplier (this is divided by 2, so a value of 3 does 1.5x damage, and 8 does 4x damage. Usually it's 2; for critical hits, the value is taken from the critical table; with Silent Death perk and the corresponding attack conditions, the value will be doubled)
int arg10 - Number of bullets actually hit the target (1 for melee attacks) int arg10 - Number of bullets actually hit the target (1 for melee attacks)
int arg11 - The amount of knockback to the target int arg11 - The amount of knockback to the target
int arg12 - Attack Type (see ATKTYPE_* constants) int arg12 - Attack Type (see ATKTYPE_* constants)
@@ -434,7 +434,7 @@ HOOK_INVENWIELD (hs_invenwield.int)
Runs before wielding or unwielding an armor or a weapon by a critter (except when using inventory by PC). Runs before wielding or unwielding an armor or a weapon by a critter (except when using inventory by PC).
An example usage would be to change critter art depending on armor being used or to dynamically customize weapon animations. An example usage would be to change critter art depending on armor being used or to dynamically customize weapon animations.
NOTE: when replacing a previously wielded armor or weapon, the unwielding hook will not be executed. NOTE: when replacing a previously wielded armor or weapon, the unwielding hook will not be executed.
If you need to rely on this, try checking if armor/weapon already equipped when wielding hook is executed. If you need to rely on this, try checking if armor/weapon is already equipped when wielding hook is executed.
Critter arg1 - critter Critter arg1 - critter
Obj arg2 - item being wielded or unwielded (weapon/armor) Obj arg2 - item being wielded or unwielded (weapon/armor)
@@ -578,3 +578,28 @@ Critter arg6 - The target critter, may be 0 or equal to the attacker
int arg7 - 1 when using throwing weapons (e.g. grenades), 0 otherwise int arg7 - 1 when using throwing weapons (e.g. grenades), 0 otherwise
int ret1 - overrides the found object on the checked tile, pass 0 to skip the object int ret1 - overrides the found object on the checked tile, pass 0 to skip the object
-------------------------------------------
HOOK_SUBCOMBATDAMAGE (hs_subcombatdmg.int)
This hook overrides the vanilla damage calculation formula.
Runs when:
1) Before the game calculates how much damage each target will get. This includes primary target as well as all extras (explosions and bursts).
2) AI decides whether it is safe to use area attack (burst, grenades), if he might hit friendlies.
Does not run for misses, non-combat damage like dynamite explosions, or if one of the damage formulas is selected in ddraw.ini.
Critter arg1 - The attacker
Critter arg2 - The target
Obj arg3 - The weapon used in the attack
int arg4 - Attack Type (see ATKTYPE_* constants)
int arg5 - Number of bullets actually hit the target (1 for melee attacks)
int arg6 - Target's Damage Resistance (DR) value (affected by critical hit effects, perks, traits, and special unarmed attacks)
int arg7 - Target's Damage Threshold (DT) value (affected by critical hit effects, perks, traits, and special unarmed attacks)
int arg8 - Bonus ranged damage from the perk
int arg9 - Damage Multiplier (this is divided by 2, so a value of 3 does 1.5x damage, and 8 does 4x damage. Usually it's 2; for critical hits, the value is taken from the critical table; with Silent Death perk and the corresponding attack conditions, the value will be doubled)
int arg10 - Combat Difficulty multiplier (125 - rough, 100 - normal, 75 - wimpy)
int arg11 - The calculated amount of damage (usually 0, required when using multiple hook scripts to calculate damage and using the set_sfall_arg function)
mixed arg12 - Computed attack results (see C_ATTACK_* for offsets and use read_int(arg12 + offset) to get the data)
int ret1 - The returned amount of damage
+4
View File
@@ -56,6 +56,10 @@ WRAP_WATCOM_FUNC1(long, item_w_anim_code, GameObject*, item)
WRAP_WATCOM_FUNC2(long, item_w_anim_weap, GameObject*, item, DWORD, hitMode) WRAP_WATCOM_FUNC2(long, item_w_anim_weap, GameObject*, item, DWORD, hitMode)
WRAP_WATCOM_FUNC2(long, item_w_compute_ammo_cost, GameObject*, item, DWORD*, rounds) WRAP_WATCOM_FUNC2(long, item_w_compute_ammo_cost, GameObject*, item, DWORD*, rounds)
WRAP_WATCOM_FUNC1(long, item_w_curr_ammo, GameObject*, item) WRAP_WATCOM_FUNC1(long, item_w_curr_ammo, GameObject*, item)
WRAP_WATCOM_FUNC2(long, item_w_damage, GameObject*, critter, long, hitMode)
WRAP_WATCOM_FUNC1(long, item_w_dam_div, GameObject*, item)
WRAP_WATCOM_FUNC1(long, item_w_dam_mult, GameObject*, item)
WRAP_WATCOM_FUNC1(long, item_w_dr_adjust, GameObject*, item)
WRAP_WATCOM_FUNC1(long, item_w_rounds, GameObject*, item) WRAP_WATCOM_FUNC1(long, item_w_rounds, GameObject*, item)
WRAP_WATCOM_FUNC1(long, item_w_max_ammo, GameObject*, item) WRAP_WATCOM_FUNC1(long, item_w_max_ammo, GameObject*, item)
WRAP_WATCOM_FUNC1(long, item_weight, GameObject*, item) WRAP_WATCOM_FUNC1(long, item_weight, GameObject*, item)
+105 -160
View File
@@ -20,31 +20,35 @@
#include "..\FalloutEngine\Fallout2.h" #include "..\FalloutEngine\Fallout2.h"
#include "..\Logging.h" #include "..\Logging.h"
#include "HookScripts.h"
#include "AmmoMod.h" #include "AmmoMod.h"
namespace sfall namespace sfall
{ {
using namespace fo; using namespace fo;
int AmmoMod::formula; int AmmoMod::formula;
static const DWORD DamageFunctionReturn = 0x424A63;
// Damage Fix v5 (with v5.1 Damage Multiplier tweak) by Glovz 2014.04.16.xx.xx // Damage Fix v5 (with v5.1 Damage Multiplier tweak) by Glovz 2014.04.16.xx.xx
// TODO: remove or rewrite in C++ // TODO: rewrite in C++
static __declspec(naked) void DamageGlovz() { void AmmoMod::DamageGlovz(fo::ComputeAttackResult &ctd, DWORD* accumulatedDamage, int rounds, int armorDT, int armorDR, int bonusRangedDamage, int multiplyDamage, int difficulty) {
if (rounds <= 0) return;
int ammoY = fo::func::item_w_dam_div(ctd.weapon); // ammoY value (divisor)
int ammoX = fo::func::item_w_dam_mult(ctd.weapon); // ammoX value
int ammoDRM = fo::func::item_w_dr_adjust(ctd.weapon); // ammoDRM value
int mValue;
__asm { __asm {
mov ebx, dword ptr ss:[esp + 0x1C]; // get the number of hits mov esi, ctd;
xor ecx, ecx; // set the loop counter to 0 mov edi, accumulatedDamage;
cmp ebx, 0; // compare the number of hits to 0
jle end; // exit
begin: begin:
mov dword ptr ss:[esp + 0x30], 0; // clear value mov mValue, 0; // clear value
mov edx, dword ptr ds:[esi + 4]; // get pointer to weapon being used by an attacker (I think) mov edx, dword ptr ds:[esi + 4]; // get the hit mode of weapon being used by an attacker
mov eax, dword ptr ds:[esi]; // get pointer to critter attacking mov eax, dword ptr ds:[esi]; // get pointer to critter attacking
call fo::funcoffs::item_w_damage_; // get the raw damage value call fo::funcoffs::item_w_damage_; // get the raw damage value
mov ebx, dword ptr ss:[esp + 0x18]; // get the bonus ranged damage value mov ebx, bonusRangedDamage; // get the bonus ranged damage value
cmp ebx, 0; // compare the range bonus damage value to 0 cmp ebx, 0; // compare the range bonus damage value to 0
jle rdJmp; // if the RB value is less than or equal to 0 then goto rdJmp jle rdJmp; // if the RB value is less than or equal to 0 then goto rdJmp
add eax, ebx; // add the RB value to the RD value add eax, ebx; // add the RB value to the RD value
@@ -52,47 +56,46 @@ rdJmp:
cmp eax, 0; // compare the new damage value to 0 cmp eax, 0; // compare the new damage value to 0
jle noDamageJmp; // goto noDamageJmp jle noDamageJmp; // goto noDamageJmp
mov ebx, eax; // set the ND value mov ebx, eax; // set the ND value
mov edx, dword ptr ss:[esp + 0x28]; // get the armorDT value mov edx, armorDT; // get the armorDT value
cmp edx, 0; // compare the armorDT value to 0 cmp edx, 0; // compare the armorDT value to 0
jle bJmp; // if the armorDT value is less than or equal to 0 then goto bJmp jle bJmp; // if the armorDT value is less than or equal to 0 then goto bJmp
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to critters ammo being used in their weapon (I think) mov eax, dword ptr ammoY; // get the ammoY value
call fo::funcoffs::item_w_dam_div_; // get the ammoY value
cmp eax, 0; // compare the ammoY value to 0 cmp eax, 0; // compare the ammoY value to 0
jg aJmp; // if the ammoY value is greater than 0 then goto aJmp jg aJmp; // if the ammoY value is greater than 0 then goto aJmp
mov eax, 1; // set the ammoY value to 1 mov eax, 1; // set the ammoY value to 1
aJmp: aJmp:
xor ebp, ebp; // clear value xor ecx, ecx; // clear value (old ebp)
cmp edx, eax; // compare the dividend with the divisor cmp edx, eax; // compare the dividend with the divisor
jl lrThan; // the dividend is less than the divisor then goto lrThan jl lrThan; // the dividend is less than the divisor then goto lrThan
jg grThan; // the dividend is greater than the divisor then goto grThan jg grThan; // the dividend is greater than the divisor then goto grThan
jmp setOne; // if the two values are equal then goto setOne jmp setOne; // if the two values are equal then goto setOne
lrThan: lrThan:
mov ebp, edx; // store the dividend value temporarily mov ecx, edx; // store the dividend value temporarily
imul edx, 2; // multiply dividend value by 2 imul edx, 2; // multiply dividend value by 2
sub edx, eax; // subtract divisor value from the dividend value sub edx, eax; // subtract divisor value from the dividend value
cmp edx, 0; // compare the result to 0 cmp edx, 0; // compare the result to 0
jl setZero; // if the result is less than 0 then goto setZero jl setZero; // if the result is less than 0 then goto setZero
jg setOne; // if the result is greater than 0 then goto setOne jg setOne; // if the result is greater than 0 then goto setOne
mov edx, ebp; // restore dividend value mov edx, ecx; // restore dividend value
and edx, 1; // if true (1) then odd if false (0) then even and edx, 1; // if true (1) then odd if false (0) then even
jz setZero; // if the result is equal to 0 then setZero jz setZero; // if the result is equal to 0 then setZero
jmp setOne; // if the result is not 0 then goto setOne jmp setOne; // if the result is not 0 then goto setOne
grThan: grThan:
mov ebp, eax; // assign the divisor value mov ecx, eax; // assign the divisor value
xor eax, eax; // clear value xor eax, eax; // clear value
bbbJmp: bbbJmp:
inc eax; // add 1 to the quotient value inc eax; // add 1 to the quotient value
sub edx, ebp; // subtract the divisor value from the dividend value sub edx, ecx; // subtract the divisor value from the dividend value
cmp edx, ebp; // compare the remainder value to the divisor value cmp edx, ecx; // compare the remainder value to the divisor value
jge bbbJmp; // if the remainder value is greater or equal to the divisor value then goto bbbJmp jge bbbJmp; // if the remainder value is greater or equal to the divisor value then goto bbbJmp
jz endDiv; // if the remainder value is equal to 0 then goto endDiv jz endDiv; // if the remainder value is equal to 0 then goto endDiv
imul edx, 2; // multiply temp remainder value by 2 imul edx, 2; // multiply temp remainder value by 2
sub edx, ebp; // subtract the divisor value from the temp remainder sub edx, ecx; // subtract the divisor value from the temp remainder
cmp edx, 0; // compare the result to 0 cmp edx, 0; // compare the result to 0
jl endDiv; // if the result is less than 0 then goto endDiv jl endDiv; // if the result is less than 0 then goto endDiv
jg addOne; // if the result is greater than 0 then goto addOne jg addOne; // if the result is greater than 0 then goto addOne
mov ebp, eax; // assign the quotient value mov ecx, eax; // assign the quotient value
and ebp, 1; // if true (1) then odd if false (0) then even and ecx, 1; // if true (1) then odd if false (0) then even
jz endDiv; // if the result is equal to zero goto endDiv jz endDiv; // if the result is equal to zero goto endDiv
addOne: addOne:
inc eax; // add 1 to the quotient value inc eax; // add 1 to the quotient value
@@ -103,31 +106,31 @@ setOne:
setZero: setZero:
xor eax, eax; // clear value xor eax, eax; // clear value
endDiv: endDiv:
cmp dword ptr ss:[esp + 0x30], 2; // compare value to 2 cmp mValue, 2; // compare value to 2
je divTwo; // goto divTwo je divTwo; // goto divTwo
cmp dword ptr ss:[esp + 0x30], 3; // compare value to 3 cmp mValue, 3; // compare value to 3
je divThree; // goto divThree je divThree; // goto divThree
cmp dword ptr ss:[esp + 0x30], 4; // compare value to 4 cmp mValue, 4; // compare value to 4
je divFour; // goto divFour je divFour; // goto divFour
cmp dword ptr ss:[esp + 0x30], 5; // compare value to 5 cmp mValue, 5; // compare value to 5
je divFive; // goto divFive je divFive; // goto divFive
cmp dword ptr ss:[esp + 0x30], 6; // compare value to 6 cmp mValue, 6; // compare value to 6
je divSix; // goto divSix je divSix; // goto divSix
cmp dword ptr ss:[esp + 0x30], 7; // compare value to 7 cmp mValue, 7; // compare value to 7 (added for v5.1 tweak)
je divSeven; // goto divSeven je divSeven; // goto divSeven
sub ebx, eax; // subtract the new armorDT value from the RD value sub ebx, eax; // subtract the new armorDT value from the RD value
jmp cJmp; // goto cJmp jmp cJmp; // goto cJmp
bJmp: bJmp:
mov edx, dword ptr ss:[esp + 0x2C]; // get the armorDR value mov edx, armorDR; // get the armorDR value
cmp edx, 0; // compare the armorDR value to 0 cmp edx, 0; // compare the armorDR value to 0
jle dJmp; // if the armorDR value is less than or equal to 0 then goto dJmp jle dJmp; // if the armorDR value is less than or equal to 0 then goto dJmp
cJmp: cJmp:
cmp ebx, 0; // compare the new damage value to 0 cmp ebx, 0; // compare the new damage value to 0
jle noDamageJmp; // goto noDamageJmp jle noDamageJmp; // goto noDamageJmp
mov edx, dword ptr ss:[esp + 0x2C]; // get the armorDR value mov edx, armorDR; // get the armorDR value
cmp edx, 0; // compare the armorDR value to 0 cmp edx, 0; // compare the armorDR value to 0
jle eJmp; // if the armorDR value is less than or equal to 0 then goto eJmp jle eJmp; // if the armorDR value is less than or equal to 0 then goto eJmp
mov eax, dword ptr ss:[esp + 0x20]; // get the CD value mov eax, difficulty; // get the CD value
cmp eax, 100; // compare the CD value to 100 cmp eax, 100; // compare the CD value to 100
jg sdrJmp; // if the CD value is greater than 100 then goto sdrJmp jg sdrJmp; // if the CD value is greater than 100 then goto sdrJmp
je aSubCJmp; // if the CD value is equal to 100 then goto aSubCJmp je aSubCJmp; // if the CD value is equal to 100 then goto aSubCJmp
@@ -136,47 +139,43 @@ cJmp:
sdrJmp: sdrJmp:
sub edx, 20; // subtract 20 from the armorDR value sub edx, 20; // subtract 20 from the armorDR value
aSubCJmp: aSubCJmp:
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to ammo being used in the critters weapon (I think) mov eax, dword ptr ammoDRM; // get the ammoDRM value
call fo::funcoffs::item_w_dr_adjust_; // get the ammoDRM value
cmp eax, 0; // compare the ammoDRM value to 0 cmp eax, 0; // compare the ammoDRM value to 0
jl adrJmp; // if the ammoDRM value is less than 0 then goto adrJmp jl adrJmp; // if the ammoDRM value is less than 0 then goto adrJmp
je bSubCJmp; // if the ammoDRM value is equal to 0 then goto bSubCJmp je bSubCJmp; // if the ammoDRM value is equal to 0 then goto bSubCJmp
xor ebp, ebp; // clear value xor ecx, ecx; // clear value
sub ebp, eax; // subtract ammoDRM value from 0 sub ecx, eax; // subtract ammoDRM value from 0
mov eax, ebp; // set new ammoDRM value mov eax, ecx; // set new ammoDRM value
adrJmp: adrJmp:
add edx, eax; // add the ammoDRM value to the armorDR value add edx, eax; // add the ammoDRM value to the armorDR value
bSubCJmp: bSubCJmp:
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to ammo being used in the critters weapon (I think) mov eax, dword ptr ammoX; // get the ammoX value
call fo::funcoffs::item_w_dam_mult_; // get the ammoX value
cmp eax, 0; // compare the ammoX value to 0 cmp eax, 0; // compare the ammoX value to 0
jg cSubCJmp; // if the ammoX value is greater than 0 then goto cSubCJmp; jg cSubCJmp; // if the ammoX value is greater than 0 then goto cSubCJmp;
mov eax, 1; // set the ammoX value to 1 mov eax, 1; // set the ammoX value to 1
cSubCJmp: cSubCJmp:
mov dword ptr ss:[esp + 0x30], 2; // set value to 2 mov mValue, 2; // set value to 2
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divTwo: divTwo:
mov edx, ebx; // set temp value mov edx, ebx; // set temp value
imul edx, eax; // multiply the ND value by the armorDR value imul edx, eax; // multiply the ND value by the armorDR value
mov eax, 100; // set divisor value to 100 mov eax, 100; // set divisor value to 100
mov dword ptr ss:[esp + 0x30], 3; // set value to 3 mov mValue, 3; // set value to 3
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divThree: divThree:
sub ebx, eax; // subtract the damage resisted value from the ND value sub ebx, eax; // subtract the damage resisted value from the ND value
jmp eJmp; // goto eJmp jmp eJmp; // goto eJmp
dJmp: dJmp:
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to ammo being used in the critters weapon (I think) mov eax, dword ptr ammoX; // get the ammoX value
call fo::funcoffs::item_w_dam_mult_; // get the ammoX value
cmp eax, 1; // compare the ammoX value to 1 cmp eax, 1; // compare the ammoX value to 1
jle bSubDJmp; // if the ammoX value is less than or equal to 1 then goto bSubDJmp; jle bSubDJmp; // if the ammoX value is less than or equal to 1 then goto bSubDJmp;
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to critters ammo being used in their weapon (I think) mov eax, dword ptr ammoY; // get the ammoY value
call fo::funcoffs::item_w_dam_div_; // get the ammoY value
cmp eax, 1; // compare the ammoY value to 1 cmp eax, 1; // compare the ammoY value to 1
jle aSubDJmp; // if the ammoY value is less than or equal to 1 then goto aSubDJmp jle aSubDJmp; // if the ammoY value is less than or equal to 1 then goto aSubDJmp
mov edx, ebx; // set temp value mov edx, ebx; // set temp value
imul edx, 15; // multiply the ND value by 15 imul edx, 15; // multiply the ND value by 15
mov eax, 100; // set divisor value to 100 mov eax, 100; // set divisor value to 100
mov dword ptr ss:[esp + 0x30], 4; // set value to 4 mov mValue, 4; // set value to 4
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divFour: divFour:
add ebx, eax; // add the quotient value to the ND value add ebx, eax; // add the quotient value to the ND value
@@ -185,27 +184,26 @@ aSubDJmp:
mov edx, ebx; // set temp value mov edx, ebx; // set temp value
imul edx, 20; // multiply the ND value by 20 imul edx, 20; // multiply the ND value by 20
mov eax, 100; // set divisor value to 100 mov eax, 100; // set divisor value to 100
mov dword ptr ss:[esp + 0x30], 5; // set value to 5 mov mValue, 5; // set value to 5
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divFive: divFive:
add ebx, eax; // add the quotient value to the ND value add ebx, eax; // add the quotient value to the ND value
jmp eJmp; // goto eJmp jmp eJmp; // goto eJmp
bSubDJmp: bSubDJmp:
mov eax, dword ptr ds:[esi + 0x8]; // get pointer to critters ammo being used in their weapon (I think) mov eax, dword ptr ammoY; // get the ammoY value
call fo::funcoffs::item_w_dam_div_; // get the ammoY value
cmp eax, 1; // compare the ammoY value to 1 cmp eax, 1; // compare the ammoY value to 1
jle eJmp; // goto eJmp jle eJmp; // goto eJmp
mov edx, ebx; // set temp value mov edx, ebx; // set temp value
imul edx, 10; // multiply the ND value by 10 imul edx, 10; // multiply the ND value by 10
mov eax, 100; // set divisor value to 100 mov eax, 100; // set divisor value to 100
mov dword ptr ss:[esp + 0x30], 6; // set value to 6 mov mValue, 6; // set value to 6
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divSix: divSix:
add ebx, eax; // add the quotient value to the ND value add ebx, eax; // add the quotient value to the ND value
eJmp: eJmp:
cmp ebx, 0; // compare the new damage value to 0 cmp ebx, 0; // compare the new damage value to 0
jle noDamageJmp; // goto noDamageJmp jle noDamageJmp; // goto noDamageJmp
mov eax, dword ptr ss:[esp + 0x24]; // get the CM value mov eax, multiplyDamage; // get the Critical Multiplier (CM) value
cmp eax, 2; // compare the CM value to 2 cmp eax, 2; // compare the CM value to 2
jle addNDJmp; // if the CM value is less than or equal to 2 then goto addNDJmp jle addNDJmp; // if the CM value is less than or equal to 2 then goto addNDJmp
cmp AmmoMod::formula, 2; // check selected damage formula (added for v5.1 tweak) cmp AmmoMod::formula, 2; // check selected damage formula (added for v5.1 tweak)
@@ -219,7 +217,7 @@ tweak:
imul edx, eax; // multiply the temp ND value by the CM value imul edx, eax; // multiply the temp ND value by the CM value
imul edx, 25; // multiply the temp ND value by 25 imul edx, 25; // multiply the temp ND value by 25
mov eax, 100; // set divisor value to 100 mov eax, 100; // set divisor value to 100
mov dword ptr ss:[esp + 0x30], 7; // set value to 7 mov mValue, 7; // set value to 7
jmp aJmp; // goto aJmp jmp aJmp; // goto aJmp
divSeven: divSeven:
add ebx, eax; // add the critical damage value to the ND value add ebx, eax; // add the critical damage value to the ND value
@@ -227,108 +225,59 @@ divSeven:
addNDJmp: addNDJmp:
add dword ptr ds:[edi], ebx; // accumulate damage add dword ptr ds:[edi], ebx; // accumulate damage
noDamageJmp: noDamageJmp:
mov eax, dword ptr ss:[esp + 0x1C]; // get the number of hits dec dword ptr rounds; // decrease the hit counter value by one
inc ecx; // the counter value increments by one jnz begin; // compare the number of hits to 0
cmp ecx, eax; // is the counter value less than the number of hits
jl begin; // goto begin
end:
jmp DamageFunctionReturn; // exit
} }
} }
// YAAM // YAAM
// TODO: rewrite in C++ void AmmoMod::DamageYAAM(fo::ComputeAttackResult &ctd, DWORD* accumulatedDamage, int rounds, int armorDT, int armorDR, int bonusRangedDamage,int multiplyDamage, int difficulty) {
static __declspec(naked) void DamageYAAM() { int ammoDiv = fo::func::item_w_dam_div(ctd.weapon); // Retrieve Ammo Divisor
__asm { int ammoMult = fo::func::item_w_dam_mult(ctd.weapon); // Retrieve Ammo Dividend
mov eax, dword ptr ds:[esi + 0x8]; // Get pointer to critter's weapon
mov edx, dword ptr ss:[esp + 0x24]; // Get Critical Multiplier (passed in as argument to function) multiplyDamage *= ammoMult; // Damage Multipler = Critical Multipler * Ammo Dividend
call fo::funcoffs::item_w_dam_mult_; // Retrieve Ammo Dividend int ammoDivisor = 1 * ammoDiv; // Ammo Divisor = 1 * Ammo Divisor
imul edx, eax; // Damage Multipler = Critical Multipler * Ammo Dividend
mov eax, dword ptr ds:[esi + 0x8]; // Get pointer to critter's weapon int ammoDT = fo::func::item_w_dr_adjust(ctd.weapon); // Retrieve ammo DT (well, it's really Retrieve ammo DR, but since we're treating ammo DR as ammo DT...)
call fo::funcoffs::item_w_dam_div_; // Retrieve Ammo Divisor
imul ebp, eax; // Ammo Divisor = 1 * Ammo Divisor (ebp set to 1 earlier in function) // Start of damage calculation loop
mov ebx, dword ptr ss:[esp + 0x1C]; // Get number of hits for (int i = 0; i < rounds; i++) { // Check number of hits
xor ecx, ecx; // Set loop counter to zero int rawDamage = fo::func::item_w_damage(ctd.attacker, ctd.hitMode); // Retrieve Raw Damage
mov dword ptr ss:[esp + 0x24], edx; // Store Damage Multiplier rawDamage += bonusRangedDamage; // Raw Damage = Raw Damage + Bonus Ranged Damage
test ebx, ebx; // Is number of hits <= 0?
jle end; // If yes, jump beyond damage calculation loop int calcDT = armorDT - ammoDT; // DT = armor DT - ammo DT
ajmp: // Start of damage calculation loop if (calcDT < 0) calcDT = 0;
mov edx, dword ptr ds:[esi + 0x4]; // Get pointer to weapon (?)
mov eax, dword ptr ds:[esi]; // Get pointer to critter (?) rawDamage -= calcDT; // Raw Damage = Raw Damage - DT
mov ebx, dword ptr ss:[esp + 0x18]; // Get Bonus Ranged Damage if (rawDamage <= 0) continue; // Is Raw Damage <= 0? If yes, skip damage calculation and go to bottom of loop
call fo::funcoffs::item_w_damage_; // Retrieve Raw Damage
add ebx, eax; // Raw Damage = Raw Damage + Bonus Ranged Damage rawDamage *= multiplyDamage; // Raw Damage = Raw Damage * Damage Multiplier
mov edx, dword ptr ss:[esp + 0x28]; // Get armor DT if (ammoDivisor != 0) { // avoid divide by zero error
mov eax, dword ptr ds:[esi + 0x8]; // Get pointer to critter's weapon rawDamage /= ammoDivisor; // Raw Damage = Raw Damage / Ammo Divisor
call fo::funcoffs::item_w_dr_adjust_; // Retrieve ammo DT (well, it's really Retrieve ammo DR, but since we're treating ammo DR as ammo DT...) }
sub edx, eax; // DT = armor DT - ammo DT rawDamage /= 2; // Raw Damage = Raw Damage / 2 (related to critical hit damage multiplier bonus)
test edx, edx; // Is DT >= 0? rawDamage *= difficulty; // Raw Damage = Raw Damage * combat difficulty setting (75 if wimpy, 100 if normal or if attacker is player, 125 if rough)
jge bjmp; // If yes, skip the next instruction rawDamage /= 100; // Raw Damage = Raw Damage / 100
xor edx, edx; // Otherwise, set DT = 0
bjmp: calcDT = armorDT - ammoDT; // DT = armor DT - ammo DT
sub ebx, edx; // Raw Damage = Raw Damage - DT if (calcDT >= 0) { // Is DT >= 0?
test ebx, ebx; // Is Raw Damage <= 0? calcDT = 0; // If yes, set DT = 0
jle cjmp; // If yes, skip damage calculation and go to bottom of loop } else {
imul ebx, dword ptr ss:[esp + 0x24]; // Otherwise, Raw Damage = Raw Damage * Damage Multiplier calcDT *= 10; // Otherwise, DT = DT * 10 (note that this should be a negative value)
test ebp, ebp; // Is Ammo Divisor == 0? }
je djmp; // If yes, avoid divide by zero error
mov edx, ebx; int calcDR = armorDR + calcDT; // DR = armor DR + DT (note that DT should be less than or equal to zero)
mov eax, ebx; if (calcDR >= 100) { // Is DR >= 100?
sar edx, 31; continue; // If yes, damage will be zero, so stop calculating and go to bottom of loop
idiv ebp; } else if (calcDR < 0) { // Is DR >= 0?
mov ebx, eax; // Otherwise, Raw Damage = Raw Damage / Ammo Divisor calcDR = 0; // If no, set DR = 0
djmp: }
mov edx, ebx;
mov eax, ebx; int resistedDamage = calcDR * rawDamage; // Otherwise, Resisted Damage = DR * Raw Damage
sar edx, 31; resistedDamage /= 100; // Resisted Damage = Resisted Damage / 100
sub eax, edx; rawDamage -= resistedDamage; // Raw Damage = Raw Damage - Resisted Damage
sar eax, 1; // Raw Damage = Raw Damage / 2 (related to critical hit damage multiplier bonus)
mov edx, dword ptr ss:[esp + 0x20]; // Get combat difficulty setting (75 if wimpy, 100 if normal or if attacker is player, 125 if rough) if (rawDamage > 0) *accumulatedDamage += rawDamage; // Accumulated Damage = Accumulated Damage + Raw Damage
imul edx, eax; // Raw Damage = Raw Damage * combat difficulty setting
mov ebx, 100;
mov eax, edx;
sar edx, 31;
idiv ebx;
mov ebx, eax; // Raw Damage = Raw Damage / 100
mov edx, dword ptr ss:[esp + 0x28]; // Get armor DT
mov eax, dword ptr ds:[esi + 0x8]; // Get pointer to critter's weapon
call fo::funcoffs::item_w_dr_adjust_; // Retrieve ammo DT
sub edx, eax; // DT = armor DT - ammo DT
test edx, edx; // Is DT >= 0?
jge ejmp; // If yes, set DT = 0
mov eax, 10;
imul eax, edx; // Otherwise, DT = DT * 10 (note that this should be a negative value)
jmp fjmp;
ejmp:
xor eax, eax;
fjmp:
mov edx, dword ptr ss:[esp + 0x2C]; // Get armor DR
add edx, eax; // DR = armor DR + DT (note that DT should be less than or equal to zero)
test edx, edx; // Is DR >= 0?
jge gjmp;
xor edx, edx; // If no, set DR = 0
jmp hjmp;
gjmp:
cmp edx, 100; // Otherwise, is DR >= 100?
jge ijmp; // If yes, damage will be zero, so stop calculating and go to bottom of loop
hjmp:
imul edx, ebx; // Otherwise, Resisted Damage = DR * Raw Damage
mov dword ptr ss:[esp + 0x30], 100;
mov eax, edx;
sar edx, 31;
idiv dword ptr ss:[esp + 0x30]; // Resisted Damage = Resisted Damage / 100
sub ebx, eax; // Raw Damage = Raw Damage - Resisted Damage
cjmp:
test ebx, ebx; // Is Raw Damage <= 0?
jle ijmp; // If yes, don't accumulate damage
add dword ptr ds:[edi], ebx; // Otherwise, Accumulated Damage = Accumulated Damage + Raw Damage
ijmp:
mov eax, dword ptr ss:[esp + 0x1C]; // Get number of hits
inc ecx; // counter += 1
cmp ecx, eax; // Is counter < number of hits?
jl ajmp; // If yes, go back to start of damage calcuation loop (calculate damage for next hit)
end:
jmp DamageFunctionReturn; // Otherwise, exit loop
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -446,17 +395,13 @@ void AmmoMod::init() {
switch (formula) { switch (formula) {
case 1: case 1:
case 2: case 2:
MakeJump(0x424995, DamageGlovz);
break;
/*case 3:
MakeJump(0x424995, DamageFunction3);
break;
case 4:
MakeJump(0x424995, DamageFunction4);
break;*/
case 5: case 5:
MakeJump(0x424995, DamageYAAM); if (!HookScripts::IsInjectHook(HOOK_SUBCOMBATDAMAGE)) {
HookScripts::InjectingHook(HOOK_SUBCOMBATDAMAGE);
}
break; break;
default:
formula = 0;
} }
} }
+2
View File
@@ -29,6 +29,8 @@ public:
void init(); void init();
static int formula; static int formula;
static void DamageGlovz(fo::ComputeAttackResult &ctd, DWORD* accumulatedDamage, int rounds, int armorDT, int armorDR, int bonusRangedDamage, int multiplyDamage, int difficulty);
static void DamageYAAM(fo::ComputeAttackResult &ctd, DWORD* accumulatedDamage, int rounds, int armorDT, int armorDR, int bonusRangedDamage,int multiplyDamage, int difficulty);
}; };
} }
+1 -1
View File
@@ -2172,7 +2172,7 @@ void BugFixes::init()
// Display a pop-up messages box about death from radiation // Display a pop-up messages box about death from radiation
HookCall(0x42D733, process_rads_hook); HookCall(0x42D733, process_rads_hook);
// Fix for AI not checking chem_primary_desire setting in AI.txt for drug use preference // Fix for AI not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory
if (GetConfigInt("Misc", "AIDrugUsePerfFix", 0)) { if (GetConfigInt("Misc", "AIDrugUsePerfFix", 0)) {
dlog("Applying AI drug use preference fix.", DL_INIT); dlog("Applying AI drug use preference fix.", DL_INIT);
MakeCall(0x42869D, ai_check_drugs_hack_break); MakeCall(0x42869D, ai_check_drugs_hack_break);
+1
View File
@@ -81,6 +81,7 @@ static HooksInjectInfo injectHooks[] = {
{HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false}, {HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false},
{HOOK_USESKILLON, Inject_UseSkillOnHook, false}, {HOOK_USESKILLON, Inject_UseSkillOnHook, false},
{HOOK_ONEXPLOSION, Inject_OnExplosionHook, false}, {HOOK_ONEXPLOSION, Inject_OnExplosionHook, false},
{HOOK_SUBCOMBATDAMAGE, Inject_SubCombatDamageHook, false},
}; };
bool HookScripts::injectAllHooks; bool HookScripts::injectAllHooks;
+1
View File
@@ -63,6 +63,7 @@ enum HookType
HOOK_DESCRIPTIONOBJ = 34, HOOK_DESCRIPTIONOBJ = 34,
HOOK_USESKILLON = 35, HOOK_USESKILLON = 35,
HOOK_ONEXPLOSION = 36, HOOK_ONEXPLOSION = 36,
HOOK_SUBCOMBATDAMAGE = 37,
HOOK_COUNT HOOK_COUNT
}; };