// Jim's Formula
static __declspec(naked) void DamageFunction5() {
__asm {
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)
call GetAmmoDividend; // Retrieve Ammo Dividend
imul edx,eax; // Damage Multipler = Critical Multipler * Ammo Dividend
mov eax,dword ptr ds:[esi+0x8]; // Get pointer to critter's weapon
call GetAmmoDivisor; // Retrieve Ammo Divisor
imul ebp,eax; // Ammo Divisor = 1 * Ammo Divisor (ebp set to 1 earlier in function)
mov ebx,dword ptr ss:[esp+0x1c]; // Get number of hits
xor ecx,ecx; // Set loop counter to zero
mov dword ptr ss:[esp+0x24],edx; // Store Damage Multiplier
test ebx,ebx; // Is number of hits smaller than= 0?
jle end; // If yes, jump beyond damage calculation loop
ajmp: // Start of damage calculation loop
mov edx,dword ptr ds:[esi+0x4]; // Get pointer to weapon (?)
mov eax,dword ptr ds:[esi]; // Get pointer to critter (?)
mov ebx,dword ptr ss:[esp+0x18]; // Get Bonus Ranged Damage
call DamageFunctionSub1; // Retrieve Raw Damage
add ebx,eax; // Raw Damage = Raw Damage + Bonus Ranged Damage
imul ebx,0x64; //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 GetAmmoDTMod; // Retrieve ammo AM (Armor Modifier: adds or removes a percentage of the DT and DR)
imul edx,eax; // DT modifier = armor DT * ammo AM
mov edx,dword ptr ss:[esp+0x28]; // Get armor DT
imul edx,0x64; //DT = DT*100
add edx,eax; // DT = DT + DT modifier (can be negative)
test edx,edx; // Is DT >= 0?
jge bjmp; // If yes, skip the next instruction
xor edx,edx; // Otherwise, set DT = 0
bjmp:
sub ebx,edx; // Raw Damage = Raw Damage - DT
test ebx,ebx; // Is Raw Damage smaller than= 0?
jle cjmp; // If yes, skip damage calculation and go to bottom of loop
imul ebx,dword ptr ss:[esp+0x24]; // Otherwise, Raw Damage = Raw Damage * Damage Multiplier
test ebp,ebp; // Is Ammo Divisor == 0?
je djmp; // If yes, avoid divide by zero error
mov edx,ebx;
mov eax,ebx;
sar edx,0x1f;
idiv ebp;
mov ebx,eax; // Otherwise, Raw Damage = Raw Damage / Ammo Divisor
djmp:
mov edx,ebx;
mov eax,ebx;
sar edx,0x1f;
sub eax,edx;
sar eax,0x1; // Raw Damage = Raw Damage / 2 (related to critical hit damage multiplier bonus)
jmp fjmp;
fjmp:
mov dword ptr ss:[esp+0x30],0x64; //sets some variable to 100
mov eax,ebx; //(not sure if I have to do this, but Haen does it)
mov edx,ebx;
sar edx,0x1f; // makes Raw Damage modifier the dividend
idiv dword ptr ss:[esp+0x30]; // Raw Damage = Raw Damage / 100
mov ebx,eax;
mov edx,dword ptr ss:[esp+0x2c]; // Get armor DR
mov eax,dword ptr ds:[esi+0x8]; // Get pointer to critter's weapon
call GetAmmoDTMod; // Retrieve ammo AM
imul edx,eax; // DR modifier = armor DR * ammo AM
mov dword ptr ss:[esp+0x30],0x64; //sets some variable to 100
mov eax,edx; //(not sure if I have to do this, but Haen does it)
sar edx,0x1f; // makes DR modifier the dividend
idiv dword ptr ss:[esp+0x30]; // DR modifier = DR modifier / 100
mov edx,dword ptr ss:[esp+0x2c]; // Get armor DR
add edx,eax; // DR = DR + DR modifier (can be negative)
test edx,edx; // Is DR >= 0?
jge gjmp;
xor edx,edx; // If no, set DR = 0
jmp hjmp;
gjmp:
cmp edx,0x64; // 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],0x64;
mov eax,edx;
sar edx,0x1f;
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 smaller than= 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 smaller than 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
}
}