/*
* sfall
* Copyright (C) 2008, 2009, 2010 The sfall team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http>.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows>
#include "main.h"
#include "safewrite.h"
static const DWORD get_critter_stat = 0x004AEF48;
static const DWORD has_trait = 0x004B3BC8;
static const DWORD has_perk = 0x00496B78;
static const DWORD FixaEnd = 0x004784B0;
static const DWORD FixbEnd = 0x0047855C;
static _declspec(naked) void HtHDamageFix1a() {
_asm {
mov eax,ecx; // get_critter_stat argument: pointer to
critter
mov edx,0xb; // get_critter_stat argument: STAT_melee_dmg
call get_critter_stat; // Get Total_Melee_Damage
add eax,2; // Total_Melee_Damage += 2
mov dword ptr ss:[esp],eax; // Max_Damage = Total_Melee_Damage
xor edx,edx;
mov eax,dword ptr ds:[0x6610b8]; // Get pointer to PC
cmp ecx,eax; // Is the critter == PC?
jnz ajmp; // Skip to ajmp if no
mov edx,0x2; // has_perk argument: PERK_bonus_hth_damage
mov eax,dword ptr ds:[0x6610b8]; // has_perk argument: pointer to PC
call has_perk; // Return Rank_of_Bonus_HtH_Damage_perk
shl eax,0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2
mov edx,dword ptr ss:[esp+0x4]; // Retrieve Min_Damage
add edx,eax; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk
ajmp:
add edx,1; // Min_Damage += 1
mov dword ptr ss:[esp+0x4],edx; // Store Min_Damage
sub esi,0x8; // Set up for switch statement beyond jump
jmp FixaEnd;
}
}
static _declspec(naked) void HtHDamageFix1b() {
_asm {
add edx,ebp; // Max_Damage += Total_Melee_Damage
mov ebp,dword ptr ds:[0x6610b8]; // Get pointer to PC
cmp ecx,ebp; // Is the critter == PC?
jnz exit; // Exit tweak if no
mov ebp,eax; // Otherwise, store Min_Damage and
Max_Damage...
mov esi,edx; // ...in temp variables (no longer used by rest
of function)
mov edx,0x2; // has_perk argument: PERK_bonus_hth_damage
mov eax,dword ptr ds:[0x6610b8]; // has_perk argument: pointer to PC
call has_perk; // Return Rank_of_Bonus_HtH_Damage_perk
shl eax,0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2
add eax,ebp; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk
mov edx,esi; // Restore Max_Damage from temp variable
exit:
jmp FixbEnd;
}
}
static _declspec(naked) void HtHDamageFix2a() {
_asm {
mov eax,ecx; // get_critter_stat argument: pointer to
critter
mov edx,0xb; // get_critter_stat argument: STAT_melee_dmg
call get_critter_stat; // Get Total_Melee_Damage
add eax,2; // Total_Melee_Damage += 2
mov dword ptr ss:[esp],eax; // Max_Damage = Total_Melee_Damage
xor edx,edx;
mov eax,dword ptr ds:[0x6610b8]; // Get pointer to PC
cmp ecx,eax; // Is the critter == PC?
jnz ajmp; // Skip to ajmp if no
mov eax,0x6; // has_trait argument: TRAIT_heavy_handed
call has_trait; // Heavy_Handed_Bonus = 1 if PC has trait, 0
otherwise
shl eax,0x2; // Heavy_Handed_Bonus *= 4
mov dword ptr ss:[esp+0x4],eax; // Min_Damage = Heavy_Handed_Bonus
mov edx,0x2; // has_perk argument: PERK_bonus_hth_damage
mov eax,dword ptr ds:[0x6610b8]; // has_perk argument: pointer to PC
call has_perk; // Return Rank_of_Bonus_HtH_Damage_perk
shl eax,0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2
mov edx,dword ptr ss:[esp+0x4]; // Retrieve Min_Damage
add edx,eax; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk
ajmp:
add edx,1; // Min_Damage += 1
mov dword ptr ss:[esp+0x4],edx; // Store Min_Damage
sub esi,0x8; // Set up for switch statement beyond jump
jmp FixaEnd;
}
}
static _declspec(naked) void HtHDamageFix2b() {
_asm {
add edx,ebp; // Max_Damage += Total_Melee_Damage
mov ebp,dword ptr ds:[0x6610b8]; // Get pointer to PC
cmp ecx,ebp; // Is the critter == PC?
jnz exit; // Exit tweak if no
mov ebp,eax; // Otherwise, store Min_Damage and
Max_Damage...
mov esi,edx; // ...in temp variables (no longer used by rest
of function)
mov eax,0x6; // has_trait argument: TRAIT_heavy_handed
call has_trait; // Heavy_Handed_Bonus = 1 if PC has trait, 0
otherwise
shl eax,0x2; // Heavy_Handed_Bonus *= 4
add ebp,eax; // Min_Damage += Heavy_Handed_Bonus
mov edx,0x2; // has_perk argument: PERK_bonus_hth_damage
mov eax,dword ptr ds:[0x6610b8]; // has_perk argument: pointer to PC
call has_perk; // Return Rank_of_Bonus_HtH_Damage_perk
shl eax,0x1; // Rank_of_Bonus_HtH_Damage_perk *= 2
add eax,ebp; // Min_Damage += Rank_of_Bonus_HtH_Damage_perk
mov edx,esi; // Restore Max_Damage from temp variable
exit:
jmp FixbEnd;
}
}
void BonusHtHDamageFixInit() {
int formula;
if(formula=GetPrivateProfileInt("Misc", "BonusHtHDamageFix", 1, ini)) {
switch(formula) {
case 1:
MakeCall(0x478492, &HtHDamageFix1a, true);
MakeCall(0x47855a, &HtHDamageFix1b, true);
break;
case 2:
MakeCall(0x478492, &HtHDamageFix2a, true);
MakeCall(0x47855a, &HtHDamageFix2b, true);
break;
default: // Not sure if this is needed for BonusHtHDamageFix=0 setting
break;
}
}
}