Added class to most of modules

Added missing ReplacementFuncs.h.
This commit is contained in:
NovaRain
2021-11-15 22:03:40 +08:00
parent 81f112063e
commit 53c0517268
124 changed files with 1704 additions and 1414 deletions
+2 -2
View File
@@ -90,7 +90,7 @@ bool CRC(const char* filepath) {
DWORD size = GetFileSize(h, 0);
if (size != ExpectedSize && GetIntDefaultConfig("Debugging", "SkipSizeCheck", 0) == 0) {
if (size != ExpectedSize && IniReader::GetIntDefaultConfig("Debugging", "SkipSizeCheck", 0) == 0) {
CloseHandle(h);
sprintf_s(buf, "You're trying to use sfall with an incompatible version of Fallout.\n"
"Was expecting '" TARGETVERSION "'.\n\n"
@@ -113,7 +113,7 @@ bool CRC(const char* filepath) {
bool matchedCRC = false;
std::vector<std::string> extraCrcList = GetListDefaultConfig("Debugging", "ExtraCRC", "", 512, ',');
std::vector<std::string> extraCrcList = IniReader::GetListDefaultConfig("Debugging", "ExtraCRC", "", 512, ',');
if (!extraCrcList.empty()) {
matchedCRC = std::any_of(extraCrcList.begin(), extraCrcList.end(), [crc](const std::string& testCrcStr) -> bool {
DWORD testedCrc = strtoul(testCrcStr.c_str(), 0, 16);
+1 -1
View File
@@ -196,7 +196,7 @@ void CombatAI::init() {
sf::SafeWrite8(0x429BE9, sf::CodeType::JumpNZ); // jz > jnz
sf::SafeWrite8(0x429BF1, sf::CodeType::JumpShort); // jnz > jmp
drugUsePerfFixMode = sf::GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
drugUsePerfFixMode = sf::IniReader::GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
if (drugUsePerfFixMode > 0) sf::dlogr("Applying AI drug use preference fix.", DL_FIX);
}
+2 -2
View File
@@ -122,7 +122,7 @@ DWORD __stdcall Inventory::adjust_fid() {
if ((*fo::ptr::inven_dude)->TypeFid() == fo::OBJ_TYPE_CRITTER) {
DWORD indexNum;
DWORD weaponAnimCode = 0;
if (sf::PartyControl_IsNpcControlled()) {
if (sf::PartyControl::IsNpcControlled()) {
// if NPC is under control, use current FID of critter
indexNum = (*fo::ptr::inven_dude)->artFid & 0xFFF;
} else {
@@ -159,7 +159,7 @@ DWORD __stdcall Inventory::adjust_fid() {
}
*fo::ptr::i_fid = fid;
// OnAdjustFid
if (sf::appModEnabled) sf::AdjustHeroArmorArt(fid);
if (sf::HeroAppearance::appModEnabled) sf::AdjustHeroArmorArt(fid);
sf::AdjustFidHook(fid); // should be called last
return *fo::ptr::i_fid;
}
+4 -4
View File
@@ -101,7 +101,7 @@ long __stdcall Items::item_weapon_range(fo::GameObject* source, fo::GameObject*
long heaveHoMod = Stats::perk_level(source, fo::Perk::PERK_heave_ho);
long stRange = fo::func::stat_level(source, fo::Stat::STAT_st);
if (sf::perkHeaveHoModTweak) {
if (sf::Perks::perkHeaveHoModTweak) {
stRange *= 3;
if (stRange > range) stRange = range;
return stRange + (heaveHoMod * 6);
@@ -129,7 +129,7 @@ static long __stdcall item_w_mp_cost_sub(fo::GameObject* source, fo::GameObject*
long type = fo::func::item_w_subtype(item, hitMode);
if (source->protoId == fo::ProtoID::PID_Player && sf::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) {
if (source->protoId == fo::ProtoID::PID_Player && sf::Perks::DudeHasTrait(fo::Trait::TRAIT_fast_shot)) {
// Alternative behaviors of the Fast Shot trait
if (item && fastShotTweak > 2) { // Fallout 1 behavior (allowed for all weapons)
cost--;
@@ -217,7 +217,7 @@ long __fastcall Items::item_w_mp_cost(fo::GameObject* source, fo::AttackType hit
// unarmed hits
long cost = unarmedAPCost;
if (hitMode == fo::AttackType::ATKTYPE_PUNCH || hitMode == fo::AttackType::ATKTYPE_KICK || hitMode >= fo::AttackType::ATKTYPE_STRONGPUNCH) {
cost = sf::Unarmed_GetHitAPCost(hitMode);
cost = sf::Unarmed::GetHitAPCost(hitMode);
}
// return cost
@@ -248,7 +248,7 @@ void Items::init() {
// Replace the item_w_mp_cost_ function with the sfall implementation
sf::MakeJump(fo::funcoffs::item_w_mp_cost_ + 1, item_w_mp_cost_hack); // 0x478B25
fastShotTweak = sf::GetConfigInt("Misc", "FastShotFix", 0);
fastShotTweak = sf::IniReader::GetConfigInt("Misc", "FastShotFix", 0);
}
}
+5 -5
View File
@@ -29,7 +29,7 @@ static void __stdcall Draw(fo::Window* win, BYTE* surface, long width, long heig
}
if (!win->randY) return;
surface = &sf::WinRender_GetOverlaySurface(win)[rect.left - win->rect.x] + ((rect.top - win->rect.y) * win->width);
surface = &sf::WindowRender::GetOverlaySurface(win)[rect.left - win->rect.x] + ((rect.top - win->rect.y) * win->width);
if (toBuffer) {
fo::func::trans_buf_to_buf(surface, width, height, widthFrom, &toBuffer[rect.left - updateRect->left] + ((rect.top - updateRect->top) * toWidth), toWidth);
@@ -58,7 +58,7 @@ void __fastcall Render::GNW_win_refresh(fo::Window* win, RECT* updateRect, BYTE*
}*/
int h = (updateRect->bottom - updateRect->top) + 1;
sf::UpdateDDSurface(GetBuffer(), w, h, w, updateRect); // update the entire rectangle area
sf::Graphics::UpdateDDSurface(GetBuffer(), w, h, w, updateRect); // update the entire rectangle area
} else {
fo::func::mouse_show(); // for updating background cursor area
@@ -81,7 +81,7 @@ void __fastcall Render::GNW_win_refresh(fo::Window* win, RECT* updateRect, BYTE*
int wRect = (rects->wRect.right - rects->wRect.left) + 1;
int hRect = (rects->wRect.bottom - rects->wRect.top) + 1;
sf::UpdateDDSurface(&GetBuffer()[rects->wRect.left - updateRect->left] + (rects->wRect.top - updateRect->top) * w, wRect, hRect, w, &rects->wRect);
sf::Graphics::UpdateDDSurface(&GetBuffer()[rects->wRect.left - updateRect->left] + (rects->wRect.top - updateRect->top) * w, wRect, hRect, w, &rects->wRect);
fo::RectList* free = rects;
rects = rects->nextRect;
@@ -117,7 +117,7 @@ void __fastcall Render::GNW_win_refresh(fo::Window* win, RECT* updateRect, BYTE*
}
int widthFrom = win->width;
int toWidth = (toBuffer) ? (updateRect->right - updateRect->left) + 1 : sf::Gfx_GetGameWidthRes();
int toWidth = (toBuffer) ? (updateRect->right - updateRect->left) + 1 : sf::Graphics::GetGameWidthRes();
fo::func::win_clip(win, &rects, toBuffer);
@@ -153,7 +153,7 @@ void __fastcall Render::GNW_win_refresh(fo::Window* win, RECT* updateRect, BYTE*
int height = (rects->rect.offy - rects->rect.y) + 1;
int widthFrom = toWidth;
sf::UpdateDDSurface(&GetBuffer()[rects->rect.x] + (rects->rect.y * widthFrom), width, height, widthFrom, &rects->wRect);
sf::Graphics::UpdateDDSurface(&GetBuffer()[rects->rect.x] + (rects->rect.y * widthFrom), width, height, widthFrom, &rects->wRect);
}
fo::RectList* next = rects->nextRect;
fo::util::rect_free(rects);
+5 -5
View File
@@ -20,14 +20,14 @@ namespace sf = sfall;
int __stdcall Skills::trait_adjust_skill(DWORD skillID) {
int result = 0;
if (sf::TraitsModEnable()) {
if (fo::ptr::pc_trait[0] != -1) result += sf::GetTraitSkillBonus(skillID, 0);
if (fo::ptr::pc_trait[1] != -1) result += sf::GetTraitSkillBonus(skillID, 1);
if (sf::Perks::TraitsModEnable()) {
if (fo::ptr::pc_trait[0] != -1) result += sf::Perks::GetTraitSkillBonus(skillID, 0);
if (fo::ptr::pc_trait[1] != -1) result += sf::Perks::GetTraitSkillBonus(skillID, 1);
}
if (sf::DudeHasTrait(fo::TRAIT_gifted)) result -= 10;
if (sf::Perks::DudeHasTrait(fo::TRAIT_gifted)) result -= 10;
if (sf::DudeHasTrait(fo::TRAIT_good_natured)) {
if (sf::Perks::DudeHasTrait(fo::TRAIT_good_natured)) {
if (skillID <= fo::SKILL_THROWING) {
result -= 10;
} else if (skillID == fo::SKILL_FIRST_AID || skillID == fo::SKILL_DOCTOR || skillID == fo::SKILL_CONVERSANT || skillID == fo::SKILL_BARTER) {
+5 -5
View File
@@ -19,7 +19,7 @@ namespace sf = sfall;
static bool smallFrameTraitFix = false;
int __stdcall Stats::trait_level(DWORD traitID) {
return sf::DudeHasTrait(traitID);
return sf::Perks::DudeHasTrait(traitID);
}
// Wrapper of perk_level_ function, for quickly skipping other critters
@@ -36,9 +36,9 @@ int __stdcall Stats::trait_adjust_stat(DWORD statID) {
if (statID > fo::STAT_max_derived) return 0;
int result = 0;
if (sf::TraitsModEnable()) {
if (fo::ptr::pc_trait[0] != -1) result += sf::GetTraitStatBonus(statID, 0);
if (fo::ptr::pc_trait[1] != -1) result += sf::GetTraitStatBonus(statID, 1);
if (sf::Perks::TraitsModEnable()) {
if (fo::ptr::pc_trait[0] != -1) result += sf::Perks::GetTraitStatBonus(statID, 0);
if (fo::ptr::pc_trait[1] != -1) result += sf::Perks::GetTraitStatBonus(statID, 1);
}
switch (statID) {
@@ -124,7 +124,7 @@ void Stats::init() {
sf::MakeJump(fo::funcoffs::trait_adjust_stat_, trait_adjust_stat_replacement); // 0x4B3C7C
// Fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points
smallFrameTraitFix = (sf::GetConfigInt("Misc", "SmallFrameFix", 0) != 0);
smallFrameTraitFix = (sf::IniReader::GetConfigInt("Misc", "SmallFrameFix", 0) != 0);
}
}
+17 -17
View File
@@ -23,7 +23,7 @@
namespace sfall
{
DWORD modifiedIni;
DWORD IniReader::modifiedIni;
static const char* ddrawIni = ".\\ddraw.ini";
static char ini[65] = ".\\";
@@ -50,67 +50,67 @@ static std::vector<std::string> __stdcall getList(const char* section, const cha
return list;
}
const char* GetConfigFile() {
const char* IniReader::GetConfigFile() {
return ini;
}
void SetDefaultConfigFile() {
void IniReader::SetDefaultConfigFile() {
std::strcpy(&ini[2], &ddrawIni[2]);
}
void SetConfigFile(const char* iniFile) {
void IniReader::SetConfigFile(const char* iniFile) {
strcat_s(ini, iniFile);
}
int __stdcall GetIntDefaultConfig(const char* section, const char* setting, int defaultValue) {
int __stdcall IniReader::GetIntDefaultConfig(const char* section, const char* setting, int defaultValue) {
return getInt(section, setting, defaultValue, ddrawIni);
}
std::vector<std::string> __stdcall GetListDefaultConfig(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter) {
std::vector<std::string> __stdcall IniReader::GetListDefaultConfig(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter) {
return getList(section, setting, defaultValue, bufSize, delimiter, ddrawIni);
}
int __stdcall GetConfigInt(const char* section, const char* setting, int defaultValue) {
int __stdcall IniReader::GetConfigInt(const char* section, const char* setting, int defaultValue) {
return getInt(section, setting, defaultValue, ini);
}
std::string __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, size_t bufSize) {
std::string __stdcall IniReader::GetConfigString(const char* section, const char* setting, const char* defaultValue, size_t bufSize) {
return trim(getString(section, setting, defaultValue, bufSize, ini));
}
size_t __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize) {
size_t __stdcall IniReader::GetConfigString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize) {
return getString(section, setting, defaultValue, buf, bufSize, ini);
}
std::vector<std::string> __stdcall GetConfigList(const char* section, const char* setting, const char* defaultValue, size_t bufSize) {
std::vector<std::string> __stdcall IniReader::GetConfigList(const char* section, const char* setting, const char* defaultValue, size_t bufSize) {
return getList(section, setting, defaultValue, bufSize, ',', ini);
}
int __stdcall IniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile) {
int __stdcall IniReader::GetInt(const char* section, const char* setting, int defaultValue, const char* iniFile) {
return getInt(section, setting, defaultValue, iniFile);
}
size_t __stdcall IniGetString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize, const char* iniFile) {
size_t __stdcall IniReader::GetString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize, const char* iniFile) {
return getString(section, setting, defaultValue, buf, bufSize, iniFile);
}
std::string __stdcall IniGetString(const char* section, const char* setting, const char* defaultValue, size_t bufSize, const char* iniFile) {
std::string __stdcall IniReader::GetString(const char* section, const char* setting, const char* defaultValue, size_t bufSize, const char* iniFile) {
return getString(section, setting, defaultValue, bufSize, iniFile);
}
std::vector<std::string> __stdcall IniGetList(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter, const char* iniFile) {
std::vector<std::string> __stdcall IniReader::GetList(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter, const char* iniFile) {
return getList(section, setting, defaultValue, bufSize, delimiter, iniFile);
}
int __stdcall SetConfigInt(const char* section, const char* setting, int value) {
int __stdcall IniReader::SetConfigInt(const char* section, const char* setting, int value) {
char buf[33];
_itoa_s(value, buf, 33, 10);
int result = WritePrivateProfileStringA(section, setting, buf, ini);
return result;
}
void IniReader_Init() {
modifiedIni = GetConfigInt("Main", "ModifiedIni", 0);
void IniReader::init() {
modifiedIni = IniReader::GetConfigInt("Main", "ModifiedIni", 0);
}
}
+29 -26
View File
@@ -21,44 +21,47 @@
namespace sfall
{
extern DWORD modifiedIni;
class IniReader {
public:
static void init();
void IniReader_Init();
static DWORD modifiedIni;
const char* GetConfigFile();
void SetDefaultConfigFile();
void SetConfigFile(const char* iniFile);
static const char* GetConfigFile();
static void SetDefaultConfigFile();
static void SetConfigFile(const char* iniFile);
// Gets the integer value from the default config (i.e. ddraw.ini)
int __stdcall GetIntDefaultConfig(const char* section, const char* setting, int defaultValue);
// Gets the integer value from the default config (i.e. ddraw.ini)
static int __stdcall GetIntDefaultConfig(const char* section, const char* setting, int defaultValue);
// Gets a list of values separated by the delimiter from the default config (i.e. ddraw.ini)
std::vector<std::string> __stdcall GetListDefaultConfig(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter);
// Gets a list of values separated by the delimiter from the default config (i.e. ddraw.ini)
static std::vector<std::string> __stdcall GetListDefaultConfig(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter);
// Gets the integer value from sfall configuration INI file
int __stdcall GetConfigInt(const char* section, const char* setting, int defaultValue);
// Gets the integer value from sfall configuration INI file
static int __stdcall GetConfigInt(const char* section, const char* setting, int defaultValue);
// Gets the string value from sfall configuration INI file with trim function
std::string __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, size_t bufSize = 128);
// Gets the string value from sfall configuration INI file with trim function
static std::string __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, size_t bufSize = 128);
// Loads the string value from sfall configuration INI file into the provided buffer
size_t __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, char* buffer, size_t bufSize = 128);
// Loads the string value from sfall configuration INI file into the provided buffer
static size_t __stdcall GetConfigString(const char* section, const char* setting, const char* defaultValue, char* buffer, size_t bufSize = 128);
// Parses the comma-separated list from the settings from sfall configuration INI file
std::vector<std::string> __stdcall GetConfigList(const char* section, const char* setting, const char* defaultValue, size_t bufSize = 128);
// Parses the comma-separated list from the settings from sfall configuration INI file
static std::vector<std::string> __stdcall GetConfigList(const char* section, const char* setting, const char* defaultValue, size_t bufSize = 128);
// Gets the integer value from given INI file
int __stdcall IniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile);
// Gets the integer value from given INI file
static int __stdcall GetInt(const char* section, const char* setting, int defaultValue, const char* iniFile);
// Gets the string value from given INI file
size_t __stdcall IniGetString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize, const char* iniFile);
// Gets the string value from given INI file
static size_t __stdcall GetString(const char* section, const char* setting, const char* defaultValue, char* buf, size_t bufSize, const char* iniFile);
// Gets the string value from given INI file
std::string __stdcall IniGetString(const char* section, const char* setting, const char* defaultValue, size_t bufSize, const char* iniFile);
// Gets the string value from given INI file
static std::string __stdcall GetString(const char* section, const char* setting, const char* defaultValue, size_t bufSize, const char* iniFile);
// Parses the comma-separated list setting from given INI file
std::vector<std::string> __stdcall IniGetList(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter, const char* iniFile);
// Parses the comma-separated list setting from given INI file
static std::vector<std::string> __stdcall GetList(const char* section, const char* setting, const char* defaultValue, size_t bufSize, char delimiter, const char* iniFile);
int __stdcall SetConfigInt(const char* section, const char* setting, int value);
static int __stdcall SetConfigInt(const char* section, const char* setting, int value);
};
}
+10 -10
View File
@@ -194,7 +194,7 @@ public:
// Only called for the mouse
HRESULT __stdcall GetDeviceState(DWORD a, LPVOID b) {
Gfx_RefreshGraphics();
Graphics::RefreshGraphics();
if (DeviceType != kDeviceType_MOUSE) {
return RealDevice->GetDeviceState(a, b);
}
@@ -301,8 +301,8 @@ public:
keysDown[buf[i].dwOfs] = state;
}
// OnKeyPressed
InventoryKeyPressedHook(buf[i].dwOfs, (state > 0));
DebugEditorKeyPressedHook(buf[i].dwOfs, (state > 0));
Inventory::KeyPressedHook(buf[i].dwOfs, (state > 0));
DebugEditor::KeyPressedHook(buf[i].dwOfs, (state > 0));
}
return hr;
}
@@ -428,20 +428,20 @@ public:
};
inline void InitInputFeatures() {
reverseMouse = GetConfigInt("Input", "ReverseMouseButtons", 0) != 0;
useScrollWheel = GetConfigInt("Input", "UseScrollWheel", 1) != 0;
wheelMod = GetConfigInt("Input", "ScrollMod", 0);
reverseMouse = IniReader::GetConfigInt("Input", "ReverseMouseButtons", 0) != 0;
useScrollWheel = IniReader::GetConfigInt("Input", "UseScrollWheel", 1) != 0;
wheelMod = IniReader::GetConfigInt("Input", "ScrollMod", 0);
long MouseSpeed = GetConfigInt("Input", "MouseSensitivity", 100);
long MouseSpeed = IniReader::GetConfigInt("Input", "MouseSensitivity", 100);
if (MouseSpeed != 100) {
adjustMouseSpeed = true;
mouseSpeedMod = ((double)MouseSpeed) / 100.0;
}
middleMouseKey = GetConfigInt("Input", "MiddleMouse", DIK_B);
middleMouseKey = IniReader::GetConfigInt("Input", "MiddleMouse", DIK_B);
backgroundKeyboard = GetConfigInt("Input", "BackgroundKeyboard", 0) != 0;
backgroundMouse = GetConfigInt("Input", "BackgroundMouse", 0) != 0;
backgroundKeyboard = IniReader::GetConfigInt("Input", "BackgroundKeyboard", 0) != 0;
backgroundMouse = IniReader::GetConfigInt("Input", "BackgroundMouse", 0) != 0;
keyboardLayout = GetKeyboardLayout(0);
}
+5 -5
View File
@@ -80,19 +80,19 @@ void devlog_f(...) {}
void LoggingInit() {
Log.open("sfall-log.txt", std::ios_base::out | std::ios_base::trunc);
if (GetIntDefaultConfig("Debugging", "Init", 0)) {
if (IniReader::GetIntDefaultConfig("Debugging", "Init", 0)) {
DebugTypes |= DL_INIT;
}
if (GetIntDefaultConfig("Debugging", "Hook", 0)) {
if (IniReader::GetIntDefaultConfig("Debugging", "Hook", 0)) {
DebugTypes |= DL_HOOK;
}
if (GetIntDefaultConfig("Debugging", "Script", 0)) {
if (IniReader::GetIntDefaultConfig("Debugging", "Script", 0)) {
DebugTypes |= DL_SCRIPT;
}
if (GetIntDefaultConfig("Debugging", "Criticals", 0)) {
if (IniReader::GetIntDefaultConfig("Debugging", "Criticals", 0)) {
DebugTypes |= DL_CRITICALS;
}
if (GetIntDefaultConfig("Debugging", "Fixes", 0)) {
if (IniReader::GetIntDefaultConfig("Debugging", "Fixes", 0)) {
DebugTypes |= DL_FIX;
}
}
+15 -15
View File
@@ -40,7 +40,7 @@ static std::tr1::unordered_map<fo::GameObject*, fo::GameObject*> sources;
////////////////////////////////// AI HELPERS //////////////////////////////////
// Returns the friendly critter or any blocking object in the line of fire
fo::GameObject* __stdcall AIHelpers_CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team) {
fo::GameObject* __stdcall AIHelpers::CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team) {
if (object && object->IsCritter() && object->critter.teamNum != team) { // is not friendly fire
long objTile = object->tile;
if (objTile == targetTile) return nullptr;
@@ -54,26 +54,26 @@ fo::GameObject* __stdcall AIHelpers_CheckShootAndFriendlyInLineOfFire(fo::GameOb
fo::GameObject* obj = object; // for ignoring the object (multihex) when building the path
fo::func::make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = AIHelpers_CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
object = CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
}
return object; // friendly critter, any object or null
}
// Returns the friendly critter in the line of fire
fo::GameObject* __stdcall AIHelpers_CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
fo::GameObject* __stdcall AIHelpers::CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
fo::GameObject* object = nullptr;
fo::func::make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = AIHelpers_CheckShootAndFriendlyInLineOfFire(object, target->tile, attacker->critter.teamNum);
object = CheckShootAndFriendlyInLineOfFire(object, target->tile, attacker->critter.teamNum);
return (object && object->IsCritter()) ? object : nullptr; // 0 - if there are no friendly critters
}
bool __stdcall AIHelpers_AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance) {
bool __stdcall AIHelpers::AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance) {
if (game::Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY) >= distance) return true;
return (game::Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_SECONDARY) >= distance);
}
bool __stdcall AIHelpers_AttackInRange(fo::GameObject* source, fo::GameObject* weapon, fo::GameObject* target) {
return AIHelpers_AttackInRange(source, weapon, fo::func::obj_dist(source, target));
bool __stdcall AIHelpers::AttackInRange(fo::GameObject* source, fo::GameObject* weapon, fo::GameObject* target) {
return AIHelpers::AttackInRange(source, weapon, fo::func::obj_dist(source, target));
}
////////////////////////////////////////////////////////////////////////////////
@@ -289,7 +289,7 @@ static long __fastcall ai_try_attack_switch_fix(fo::GameObject* target, long &hi
// is using a close range weapon?
long wType = fo::func::item_w_subtype(item, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY);
if (wType <= fo::AttackSubType::MELEE) { // unarmed and melee weapons, check the distance before switching
if (!AIHelpers_AttackInRange(source, item, target)) return -1; // target out of range, exit ai_try_attack_
if (!AIHelpers::AttackInRange(source, item, target)) return -1; // target out of range, exit ai_try_attack_
}
return 1; // all good, execute vanilla behavior of ai_switch_weapons_ function
}
@@ -534,7 +534,7 @@ fix:
////////////////////////////////////////////////////////////////////////////////
static bool __fastcall RollFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
if (AIHelpers_CheckFriendlyFire(target, attacker)) {
if (AIHelpers::CheckFriendlyFire(target, attacker)) {
long dice = fo::func::roll_random(1, 10);
return (fo::func::stat_level(attacker, fo::STAT_iq) >= dice); // true - is friendly
}
@@ -612,19 +612,19 @@ static void __declspec(naked) combat_attack_hook() {
}
}
void AICombatClear() {
void AI::AICombatClear() {
targets.clear();
sources.clear();
}
void AI_Init() {
void AI::init() {
const DWORD combatAttackAddr[] = {
0x426A95, // combat_attack_this_
0x42A796 // ai_attack_
};
HookCalls(combat_attack_hook, combatAttackAddr);
RetryCombatMinAP = GetConfigInt("Misc", "NPCsTryToSpendExtraAP", 0);
RetryCombatMinAP = IniReader::GetConfigInt("Misc", "NPCsTryToSpendExtraAP", 0);
if (RetryCombatMinAP > 0) {
dlog("Applying retry combat patch.", DL_INIT);
HookCall(0x422B94, RetryCombatHook); // combat_turn_
@@ -633,7 +633,7 @@ void AI_Init() {
/////////////////////// Combat behavior AI fixes ///////////////////////
#ifndef NDEBUG
if (GetIntDefaultConfig("Debugging", "AIFixes", 1) == 0) return;
if (IniReader::GetIntDefaultConfig("Debugging", "AIFixes", 1) == 0) return;
#endif
// Fix for NPCs not fully reloading a weapon if it has an ammo capacity more than a box of ammo
@@ -708,12 +708,12 @@ void AI_Init() {
MakeCall(0x42A8D9, ai_try_attack_hack_check_safe_weapon);
}
fo::GameObject* __stdcall AIGetLastAttacker(fo::GameObject* target) {
fo::GameObject* __stdcall AI::AIGetLastAttacker(fo::GameObject* target) {
iter itr = sources.find(target);
return (itr != sources.end()) ? itr->second : 0;
}
fo::GameObject* __stdcall AIGetLastTarget(fo::GameObject* source) {
fo::GameObject* __stdcall AI::AIGetLastTarget(fo::GameObject* source) {
iter itr = targets.find(source);
return (itr != targets.end()) ? itr->second : 0;
}
+18 -10
View File
@@ -23,19 +23,27 @@
namespace sfall
{
void AI_Init();
void AICombatClear();
class AI {
public:
static const char* name() { return "AI"; }
static void init();
// Returns the friendly critter or any blocking object in the line of fire
fo::GameObject* __stdcall AIHelpers_CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team);
static void AICombatClear();
// Returns the friendly critter in the line of fire
fo::GameObject* __stdcall AIHelpers_CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker);
static fo::GameObject* __stdcall AIGetLastAttacker(fo::GameObject* target);
static fo::GameObject* __stdcall AIGetLastTarget(fo::GameObject* source);
};
bool __stdcall AIHelpers_AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance);
bool __stdcall AIHelpers_AttackInRange(fo::GameObject* source, fo::GameObject* weapon, fo::GameObject* target);
class AIHelpers {
public:
// Returns the friendly critter or any blocking object in the line of fire
static fo::GameObject* __stdcall CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team);
fo::GameObject* __stdcall AIGetLastAttacker(fo::GameObject* target);
fo::GameObject* __stdcall AIGetLastTarget(fo::GameObject* source);
// Returns the friendly critter in the line of fire
static fo::GameObject* __stdcall CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker);
static bool __stdcall AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance);
static bool __stdcall AttackInRange(fo::GameObject* source, fo::GameObject* weapon, fo::GameObject* target);
};
}
+11 -7
View File
@@ -392,13 +392,13 @@ isLock:
}
}
void ClearAllLockAnimSets() {
static void ClearAllLock() {
std::fill(lockAnimSet.begin(), lockAnimSet.end(), 0);
}
static void __declspec(naked) anim_stop_hack() {
__asm {
call ClearAllLockAnimSets;
call ClearAllLock;
mov edx, 1;
retn;
}
@@ -507,7 +507,7 @@ notDude:
}
}
void ApplyAnimationsAtOncePatches(signed char aniMax) {
static void ApplyAnimationsAtOncePatches(signed char aniMax) {
//allocate memory to store larger animation struct arrays
sf_anim_set.resize(aniMax + 1); // include a dummy
sf_sad.resize(aniMax + 1); // -8?
@@ -562,8 +562,12 @@ void ApplyAnimationsAtOncePatches(signed char aniMax) {
SafeWriteBatch<DWORD>((DWORD)&animSad->pathData[0].tile, sad_28);
}
void Animations_Init() {
animationLimit = GetConfigInt("Misc", "AnimationsAtOnceLimit", 32);
void Animations::OnGameLoad() {
ClearAllLock();
}
void Animations::init() {
animationLimit = IniReader::GetConfigInt("Misc", "AnimationsAtOnceLimit", 32);
if (animationLimit < 32) animationLimit = 32;
if (animationLimit > 32) {
if (animationLimit > 127) animationLimit = 127;
@@ -610,7 +614,7 @@ void Animations_Init() {
MakeCall(0x419A17, art_alias_fid_hack);
// Fix for grave type containers in the open state not executing the use_p_proc procedure
if (GetConfigInt("Misc", "GraveContainersFix", 0)) {
if (IniReader::GetConfigInt("Misc", "GraveContainersFix", 0)) {
dlog("Applying grave type containers fix.", DL_INIT);
HookCall(0x49CFAC, obj_use_container_hook);
SafeWrite16(0x4122D9, 0x9090); // action_get_an_object_
@@ -618,7 +622,7 @@ void Animations_Init() {
}
}
//void Animations_Exit() {
//void Animations::exit() {
//}
}
+8 -3
View File
@@ -21,8 +21,13 @@
namespace sfall
{
void Animations_Init();
//void Animations_Exit();
void ClearAllLockAnimSets();
class Animations {
public:
static const char* name() { return "Animations"; }
static void init();
//static void exit();
static void OnGameLoad();
};
}
+24 -24
View File
@@ -25,7 +25,7 @@
namespace sfall
{
static int boxCount; // current box count
int BarBoxes::boxCount; // current box count
static int totalBoxCount, actualBoxCount; // total boxes and w/o vanilla
static int initCount = 5; // init config counter (5 - vanilla box)
static int sizeBox, setBoxIndex = 5;
@@ -165,11 +165,7 @@ static void ResetBoxes() {
//SafeWriteBytes(0x461243, restoreData, 5);
}
int __stdcall BarBoxes_MaxBox() {
return boxCount - 1;
}
void __stdcall BarBoxes_SetText(int box, const char* text, DWORD color) {
void __stdcall BarBoxes::SetText(int box, const char* text, DWORD color) {
setBoxIndex = box;
boxes[box].colour = color;
box -= 5;
@@ -227,8 +223,8 @@ static void SetEngine(int count) {
}
}
long BarBoxes_SetMaxSlots() {
long scrWidth = Gfx_GetGameWidthRes();
static long SetMaxSlots() {
long scrWidth = Graphics::GetGameWidthRes();
int slots = scrWidth / 127;
if (++slots > 16) {
@@ -247,7 +243,7 @@ long BarBoxes_SetMaxSlots() {
static long __fastcall GetOffsetX(int width) {
int x_offset = 0;
if (BarBoxes_SetMaxSlots() > 640 && width > ifaceWidth) {
if (SetMaxSlots() > 640 && width > ifaceWidth) {
x_offset -= (width - ifaceWidth) / 2;
}
return x_offset;
@@ -264,7 +260,11 @@ static void __declspec(naked) refresh_box_bar_win_hack() {
}
}
void BarBoxes_OnGameLoad() {
void BarBoxes::OnAfterGameInit() {
SetMaxSlots();
}
void BarBoxes::OnGameLoad() {
ResetBoxes();
if (initCount != totalBoxCount) {
boxCount = initCount;
@@ -272,8 +272,8 @@ void BarBoxes_OnGameLoad() {
}
}
void BarBoxes_Init() {
initCount += GetConfigInt("Misc", "BoxBarCount", 5);
void BarBoxes::init() {
initCount += IniReader::GetConfigInt("Misc", "BoxBarCount", 5);
if (initCount < 5) initCount = 5; // exclude the influence of negative values from the config
if (initCount > 100) initCount = 100;
@@ -287,7 +287,7 @@ void BarBoxes_Init() {
boxes[i].msg = 100 + i;
}
std::string boxBarColors = GetConfigString("Misc", "BoxBarColours", "", actualBoxCount + 1);
std::string boxBarColors = IniReader::GetConfigString("Misc", "BoxBarColours", "", actualBoxCount + 1);
for (size_t i = 0; i < boxBarColors.size(); i++) {
if (boxBarColors[i] == '1') {
boxes[i + 5].colour = 1; // red color
@@ -306,15 +306,15 @@ void BarBoxes_Init() {
MakeCall(0x4615FA, refresh_box_bar_win_hack);
SafeWriteBatch<DWORD>((DWORD)newBoxSlot, bboxSlotAddr); // _bboxslot
ifaceWidth = IniGetInt("IFACE", "IFACE_BAR_WIDTH", 640, ".\\f2_res.ini");
ifaceWidth = IniReader::GetInt("IFACE", "IFACE_BAR_WIDTH", 640, ".\\f2_res.ini");
if (ifaceWidth < 640) ifaceWidth = 640;
}
long __stdcall BarBoxes_AddExtraBox() {
long __stdcall BarBoxes::AddExtraBox() {
if (boxCount < totalBoxCount) {
actualBoxCount++;
boxCount++;
return BarBoxes_MaxBox(); // just return the number of the previously added box
return MaxBox(); // just return the number of the previously added box
}
if (totalBoxCount > 126) return -1; // limit is exceeded
@@ -346,27 +346,27 @@ long __stdcall BarBoxes_AddExtraBox() {
actualBoxCount++;
SetEngine(totalBoxCount);
return BarBoxes_MaxBox(); // current number of added box
return MaxBox(); // current number of added box
}
bool __stdcall BarBoxes_GetBox(int i) {
if (i < 5 || i > BarBoxes_MaxBox()) return false;
bool __stdcall BarBoxes::GetBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return false;
return boxText[i - 5].isActive;
}
void __stdcall BarBoxes_AddBox(int i) {
if (i < 5 || i > BarBoxes_MaxBox()) return;
void __stdcall BarBoxes::AddBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return;
boxText[i - 5].isActive = true;
__asm call fo::funcoffs::refresh_box_bar_win_;
}
void __stdcall BarBoxes_RemoveBox(int i) {
if (i < 5 || i > BarBoxes_MaxBox()) return;
void __stdcall BarBoxes::RemoveBox(int i) {
if (i < 5 || i > BarBoxes::MaxBox()) return;
boxText[i - 5].isActive = false;
__asm call fo::funcoffs::refresh_box_bar_win_;
}
void BarBoxes_Exit() {
void BarBoxes::exit() {
delete[] boxes;
delete[] boxText;
}
+18 -10
View File
@@ -3,17 +3,25 @@
namespace sfall
{
void BarBoxes_Init();
void BarBoxes_Exit();
void BarBoxes_OnGameLoad();
long BarBoxes_SetMaxSlots();
class BarBoxes {
private:
static int boxCount;
int __stdcall BarBoxes_MaxBox();
void __stdcall BarBoxes_SetText(int box, const char* text, DWORD color);
public:
static const char* name() { return "BarBoxes"; }
static void init();
static void exit();
bool __stdcall BarBoxes_GetBox(int i);
void __stdcall BarBoxes_AddBox(int i);
void __stdcall BarBoxes_RemoveBox(int i);
long __stdcall BarBoxes_AddExtraBox();
static void OnGameLoad();
static void OnAfterGameInit();
static int MaxBox() { return boxCount - 1; }
static void __stdcall SetText(int box, const char* text, DWORD color);
static bool __stdcall GetBox(int i);
static void __stdcall AddBox(int i);
static void __stdcall RemoveBox(int i);
static long __stdcall AddExtraBox();
};
}
+8 -8
View File
@@ -85,16 +85,16 @@ static void LoadVanillaBooks() {
books[4].skill = 17;
}
void Books_Init() {
std::string booksFile = GetConfigString("Misc", "BooksFile", "", MAX_PATH);
void Books::init() {
std::string booksFile = IniReader::GetConfigString("Misc", "BooksFile", "", MAX_PATH);
if (!booksFile.empty()) {
dlog("Applying books patch...", DL_INIT);
const char* iniBooks = booksFile.insert(0, ".\\").c_str();
bool includeVanilla = (IniGetInt("main", "overrideVanilla", 0, iniBooks) == 0);
bool includeVanilla = (IniReader::GetInt("main", "overrideVanilla", 0, iniBooks) == 0);
if (includeVanilla) BooksCount = 5;
int count = IniGetInt("main", "count", 0, iniBooks);
int count = IniReader::GetInt("main", "count", 0, iniBooks);
int n = 0;
if (count > 0) {
@@ -106,9 +106,9 @@ void Books_Init() {
char section[4];
for (int i = 1; i <= count; i++) {
_itoa_s(i, section, 10);
if (books[BooksCount].bookPid = IniGetInt(section, "PID", 0, iniBooks)) {
books[BooksCount].msgID = IniGetInt(section, "TextID", 0, iniBooks);
books[BooksCount].skill = IniGetInt(section, "Skill", 0, iniBooks);
if (books[BooksCount].bookPid = IniReader::GetInt(section, "PID", 0, iniBooks)) {
books[BooksCount].msgID = IniReader::GetInt(section, "TextID", 0, iniBooks);
books[BooksCount].skill = IniReader::GetInt(section, "Skill", 0, iniBooks);
BooksCount++;
n++;
}
@@ -121,7 +121,7 @@ void Books_Init() {
}
}
void Books_Exit() {
void Books::exit() {
if (books) delete[] books;
}
+6 -2
View File
@@ -21,7 +21,11 @@
namespace sfall
{
void Books_Init();
void Books_Exit();
class Books {
public:
static const char* name() { return "Books"; }
static void init();
static void exit();
};
}
+57 -57
View File
@@ -41,7 +41,7 @@ static int __fastcall DrugPidPop() {
return pid;
}
void BugFixes_DrugsSaveFix(HANDLE file) {
void BugFixes::DrugsSaveFix(HANDLE file) {
DWORD sizeWrite, count = drugsPid.size();
WriteFile(file, &count, 4, &sizeWrite, 0);
if (!count) return;
@@ -53,7 +53,7 @@ void BugFixes_DrugsSaveFix(HANDLE file) {
return;
}
bool BugFixes_DrugsLoadFix(HANDLE file) {
bool BugFixes::DrugsLoadFix(HANDLE file) {
DWORD count, sizeRead;
ReadFile(file, &count, 4, &sizeRead, 0);
if (sizeRead != 4) return false;
@@ -73,7 +73,7 @@ void ResetBodyState() {
__asm mov weightOnBody, 0;
}
void BugFixes_Initialization() {
static void Initialization() {
// Restore calling original engine functions from HRP hacks (there is no difference in HRP functions)
__int64 data = 0xC189565153;
SafeWriteBytes(0x4D78CC, (BYTE*)&data, 5); // win_get_top_win_
@@ -83,9 +83,9 @@ void BugFixes_Initialization() {
static std::vector<fo::AIcap> aiCapsBackup;
void combat_ai_init_backup() {
static void combat_ai_init_backup() {
long num_caps = *fo::ptr::num_caps;
AIcap* caps = *fo::ptr::cap;
fo::AIcap* caps = *fo::ptr::cap;
aiCapsBackup.resize(num_caps);
std::memcpy(&aiCapsBackup[0], caps, num_caps * sizeof(fo::AIcap));
@@ -93,7 +93,7 @@ void combat_ai_init_backup() {
static void combat_ai_reset() {
long num_caps = *fo::ptr::num_caps;
AIcap* caps = *fo::ptr::cap;
fo::AIcap* caps = *fo::ptr::cap;
std::memcpy(caps, &aiCapsBackup[0], num_caps * sizeof(fo::AIcap));
}
@@ -2533,7 +2533,7 @@ static void __declspec(naked) wmAreaMarkVisitedState_hack() {
//static const DWORD wmAreaMarkVisitedState_Error = 0x4C4698;
static long isNoRadius;
isNoRadius = Worldmap_AreaMarkStateIsNoRadius(); // F1 behavior radius
isNoRadius = Worldmap::AreaMarkStateIsNoRadius(); // F1 behavior radius
__asm {
mov [ecx + 0x40], esi; // wmAreaInfoList.visited
test esi, esi; // mark "unknown" state
@@ -3109,7 +3109,7 @@ static void __declspec(naked) op_create_object_sid_hack() {
mov eax, esi;
retn;
init:
call IsMapLoading;
call LoadGameHook::IsMapLoading;
test al, al;
jnz end; // yes - initialization will be performed by engine functions
cmp createObjectSidStartFix, 0;
@@ -3135,25 +3135,25 @@ noObject:
jmp end;
}
}
/*
// Missing game initialization
void BugFixes_OnBeforeGameInit() {
void BugFixes::OnBeforeGameInit() {
Initialization();
}
void BugFixes_OnAfterGameInit() {
void BugFixes::OnAfterGameInit() {
combat_ai_init_backup();
}
*/
void BugFixes_OnGameLoad() {
void BugFixes::OnGameLoad() {
dudeIsAnimDeath = false;
combat_ai_reset();
}
void BugFixes_Init()
void BugFixes::init()
{
#ifndef NDEBUG
if (GetIntDefaultConfig("Debugging", "BugFixes", 1) == 0) return;
if (IniReader::GetIntDefaultConfig("Debugging", "BugFixes", 1) == 0) return;
#endif
// Fix vanilla negate operator for float values
@@ -3169,19 +3169,19 @@ void BugFixes_Init()
SafeWrite16(0x46A4E7, 0x04DB);
// Fix for vanilla division operator treating negative integers as unsigned
if (GetConfigInt("Misc", "DivisionOperatorFix", 1)) {
if (IniReader::GetConfigInt("Misc", "DivisionOperatorFix", 1)) {
dlog("Applying division operator fix.", DL_FIX);
SafeWrite32(0x46A51D, 0xFBF79990); // xor edx, edx; div ebx > cdq; idiv ebx
dlogr(" Done", DL_FIX);
}
//if (GetConfigInt("Misc", "SpecialUnarmedAttacksFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "SpecialUnarmedAttacksFix", 1)) {
dlog("Applying Special Unarmed Attacks fix.", DL_FIX);
//MakeJump(0x42394D, compute_attack_hack); - implementation moved to Unarmed module
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "SharpshooterFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "SharpshooterFix", 1)) {
dlog("Applying Sharpshooter patch.", DL_FIX);
// https://www.nma-fallout.com/threads/fo2-engine-tweaks-sfall.178390/page-119#post-4050162
// by Slider2k
@@ -3205,7 +3205,7 @@ void BugFixes_Init()
// Fix for "Too Many Items" bug
// http://fforum.kochegarov.com/index.php?showtopic=29288&view=findpost&p=332242
//if (GetConfigInt("Misc", "TooManyItemsBugFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "TooManyItemsBugFix", 1)) {
dlog("Applying preventive patch for \"Too Many Items\" bug.", DL_FIX);
const DWORD writeScriptNodeAddr[] = {0x4A596A, 0x4A59C1};
HookCalls(scr_write_ScriptNode_hook, writeScriptNodeAddr);
@@ -3216,7 +3216,7 @@ void BugFixes_Init()
MakeCall(0x49BE70, obj_use_power_on_car_hack);
// Fix for being able to charge the car by using cells on other scenery/critters
if (GetConfigInt("Misc", "CarChargingFix", 1)) {
if (IniReader::GetConfigInt("Misc", "CarChargingFix", 1)) {
dlog("Applying car charging fix.", DL_FIX);
MakeJump(0x49C36D, protinst_default_use_item_hack);
dlogr(" Done", DL_FIX);
@@ -3236,7 +3236,7 @@ void BugFixes_Init()
// Evil bug! If party member has the same armor type in inventory as currently equipped, then
// on level up he loses Armor Class equal to the one received from this armor.
// The same happens if you just order NPC to remove the armor through dialogue.
//if (GetConfigInt("Misc", "ArmorCorruptsNPCStatsFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "ArmorCorruptsNPCStatsFix", 1)) {
dlog("Applying fix for armor reducing NPC original stats when removed.", DL_FIX);
HookCall(0x495F3B, partyMemberCopyLevelInfo_hook_stat_level);
HookCall(0x45419B, correctFidForRemovedItem_hook_adjust_ac);
@@ -3255,7 +3255,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
// Allow 9 options (lines of text) to be displayed correctly in a dialog window
//if (GetConfigInt("Misc", "DialogOptions9Lines", 1)) {
//if (IniReader::GetConfigInt("Misc", "DialogOptions9Lines", 1)) {
dlog("Applying 9 dialog options patch.", DL_FIX);
MakeCall(0x447021, gdProcessUpdate_hack, 1);
dlogr(" Done", DL_FIX);
@@ -3280,7 +3280,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
// Fix for not counting in the weight/size of equipped items on NPC when stealing or bartering
//if (GetConfigInt("Misc", "NPCWeightFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "NPCWeightFix", 1)) {
dlog("Applying fix for not counting in weight of equipped items on NPC.", DL_FIX);
MakeCall(0x473B4E, loot_container_hack);
HookCall(0x4758AB, barter_inventory_hook);
@@ -3296,7 +3296,7 @@ void BugFixes_Init()
// Corrects the max text width of the player name in inventory to be 140 (was 80), which matches the width for item name
SafeWrite32(0x471E48, 140);
//if (GetConfigInt("Misc", "InventoryDragIssuesFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "InventoryDragIssuesFix", 1)) {
dlog("Applying inventory reverse order issues fix.", DL_FIX);
// Fix for minor visual glitch when picking up solo item from the top of inventory
// and there is multiple item stack at the bottom of inventory
@@ -3310,7 +3310,7 @@ void BugFixes_Init()
//}
// Enable party members with level 6 protos to reach level 6
//if (GetConfigInt("Misc", "NPCStage6Fix", 1)) {
//if (IniReader::GetConfigInt("Misc", "NPCStage6Fix", 1)) {
dlog("Applying NPC Stage 6 Fix.", DL_FIX);
MakeJump(0x493CE9, NPCStage6Fix1); // partyMember_init_
MakeJump(0x494224, NPCStage6Fix2); // partyMemberGetAIOptions_
@@ -3319,32 +3319,32 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "NPCLevelFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "NPCLevelFix", 1)) {
dlog("Applying NPC level fix.", DL_FIX);
HookCall(0x495BC9, (void*)0x495E51); // jz 0x495E7F > jz 0x495E51
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "BlackSkilldexFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "BlackSkilldexFix", 1)) {
dlog("Applying black Skilldex patch.", DL_FIX);
HookCall(0x497D0F, PipStatus_AddHotLines_hook);
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "FixWithdrawalPerkDescCrash", 1)) {
//if (IniReader::GetConfigInt("Misc", "FixWithdrawalPerkDescCrash", 1)) {
dlog("Applying withdrawal perk description crash fix.", DL_FIX);
HookCall(0x47A501, perform_withdrawal_start_display_print_hook);
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "JetAntidoteFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "JetAntidoteFix", 1)) {
dlog("Applying Jet Antidote fix.", DL_FIX);
// Fix for Jet antidote not being removed after removing the addiction effect (when using the item)
MakeJump(0x47A013, (void*)0x47A168); // item_d_take_drug_
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "NPCDrugAddictionFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "NPCDrugAddictionFix", 1)) {
dlog("Applying NPC's drug addiction fix.", DL_FIX);
// proper checks for NPC's addiction instead of always using global vars
const DWORD itemTakeDrugHkAddr[] = {0x479FBC, 0x47A0AE};
@@ -3356,13 +3356,13 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "ShivPatch", 1)) {
//if (IniReader::GetConfigInt("Misc", "ShivPatch", 1)) {
dlog("Applying shiv patch.", DL_FIX);
SafeWrite8(0x477B2B, CodeType::JumpShort);
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "ImportedProcedureFix", 0)) {
//if (IniReader::GetConfigInt("Misc", "ImportedProcedureFix", 0)) {
dlog("Applying imported procedure patch.", DL_FIX);
// http://teamx.ru/site_arc/smf/index.php-topic=398.0.htm
SafeWrite16(0x46B35B, 0x1C60); // Fix problems with the temporary stack
@@ -3376,14 +3376,14 @@ void BugFixes_Init()
SafeWrite8(0x46C7AC, 0x76); // jb > jbe
// Update the AC counter
//if (GetConfigInt("Misc", "WieldObjCritterFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "WieldObjCritterFix", 1)) {
dlog("Applying wield_obj_critter fix.", DL_FIX);
SafeWrite8(0x456912, 0x1E); // jnz 0x456931
HookCall(0x45697F, op_wield_obj_critter_adjust_ac_hook);
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "MultiHexPathingFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "MultiHexPathingFix", 1)) {
dlog("Applying MultiHex Pathing Fix.", DL_FIX);
HookCall(0x416144, make_path_func_hook); // Fix for building the path to the central hex of a multihex object
//const DWORD multiHexPathAddr[] = {0x42901F, 0x429170};
@@ -3398,7 +3398,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "DodgyDoorsFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "DodgyDoorsFix", 1)) {
dlog("Applying Dodgy Door Fix.", DL_FIX);
MakeCall(0x4113D3, action_melee_hack, 2);
MakeCall(0x411BC9, action_ranged_hack, 2);
@@ -3419,7 +3419,7 @@ void BugFixes_Init()
// Fix for "NPC turns into a container" bug
// https://www.nma-fallout.com/threads/fo2-engine-tweaks-sfall.178390/page-123#post-4065716
//if (GetConfigInt("Misc", "NPCTurnsIntoContainerFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "NPCTurnsIntoContainerFix", 1)) {
dlog("Applying fix for \"NPC turns into a container\" bug.", DL_FIX);
MakeJump(0x42E46E, critter_wake_clear_hack);
MakeCall(0x488EF3, obj_load_func_hack, 1);
@@ -3442,7 +3442,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
// Fix for being unable to sell used geiger counters or stealth boys
if (GetConfigInt("Misc", "CanSellUsedGeiger", 1)) {
if (IniReader::GetConfigInt("Misc", "CanSellUsedGeiger", 1)) {
dlog("Applying fix for being unable to sell used geiger counters or stealth boys.", DL_FIX);
const DWORD itemQueuedAddr[] = {0x478115, 0x478138}; // item_queued_ (will return the found item)
SafeWriteBatch<BYTE>(0xBA, itemQueuedAddr);
@@ -3466,20 +3466,20 @@ void BugFixes_Init()
// Fix for checking the horizontal position on the y-axis instead of x when setting coordinates on the world map
SafeWrite8(0x4C4743, 0xC6); // cmp esi, eax
//if (GetConfigInt("Misc", "PrintToFileFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "PrintToFileFix", 1)) {
dlog("Applying print to file fix.", DL_FIX);
MakeCall(0x4C67D4, db_get_file_list_hack);
dlogr(" Done", DL_FIX);
//}
// Fix for display issues when calling gdialog_mod_barter with critters with no "Barter" flag set
//if (GetConfigInt("Misc", "gdBarterDispFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "gdBarterDispFix", 1)) {
dlog("Applying gdialog_mod_barter display fix.", DL_FIX);
HookCall(0x448250, gdActivateBarter_hook);
dlogr(" Done", DL_FIX);
//}
//if (GetConfigInt("Misc", "BagBackpackFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "BagBackpackFix", 1)) {
dlog("Applying fix for bag/backpack bugs.", DL_FIX);
// Fix for items disappearing from inventory when you try to drag them to bag/backpack in the inventory list
// and are overloaded
@@ -3510,7 +3510,7 @@ void BugFixes_Init()
HookCall(0x4211C0, combat_load_hook_item);
// Fix for Bonus Move APs being replenished when you save and load the game in combat
//if (GetConfigInt("Misc", "BonusMoveFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "BonusMoveFix", 1)) {
dlog("Applying fix for Bonus Move exploit.", DL_FIX);
HookCall(0x420E93, combat_load_hook);
MakeCall(0x422A06, combat_turn_hack);
@@ -3525,7 +3525,7 @@ void BugFixes_Init()
MakeCall(0x424CD2, apply_damage_hack);
// Fix for the double damage effect of Silent Death perk not being applied to critical hits
//if (GetConfigInt("Misc", "SilentDeathFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "SilentDeathFix", 1)) {
dlog("Applying Silent Death patch.", DL_FIX);
SafeWrite8(0x4238DF, 0x8C); // jl loc_423A0D
HookCall(0x423A99, compute_attack_hook);
@@ -3567,7 +3567,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
// Display full item description for weapon/ammo in the barter screen
showItemDescription = (GetConfigInt("Misc", "FullItemDescInBarter", 0) != 0);
showItemDescription = (IniReader::GetConfigInt("Misc", "FullItemDescInBarter", 0) != 0);
if (showItemDescription) {
dlog("Applying full item description in barter patch.", DL_FIX);
HookCall(0x49B452, obj_examine_func_hack_weapon); // it's jump
@@ -3575,7 +3575,7 @@ void BugFixes_Init()
}
// Display experience points with the bonus from Swift Learner perk when gained from non-scripted situations
if (GetConfigInt("Misc", "DisplaySwiftLearnerExp", 1)) {
if (IniReader::GetConfigInt("Misc", "DisplaySwiftLearnerExp", 1)) {
dlog("Applying Swift Learner exp display patch.", DL_FIX);
MakeCall(0x4AFAEF, statPCAddExperienceCheckPMs_hack);
HookCall(0x4221E2, combat_give_exps_hook);
@@ -3591,7 +3591,7 @@ void BugFixes_Init()
SafeWrite16(0x456B76, 0x23EB); // jmp loc_456B9B (skip unused engine code)
// Fix broken obj_can_hear_obj function
if (GetConfigInt("Misc", "ObjCanHearObjFix", 0)) {
if (IniReader::GetConfigInt("Misc", "ObjCanHearObjFix", 0)) {
dlog("Applying obj_can_hear_obj fix.", DL_FIX);
SafeWrite8(0x4583D8, 0x3B); // jz loc_458414
SafeWrite8(0x4583DE, CodeType::JumpZ); // jz loc_458414
@@ -3599,7 +3599,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
}
if (GetConfigInt("Misc", "AIBestWeaponFix", 1)) {
if (IniReader::GetConfigInt("Misc", "AIBestWeaponFix", 1)) {
dlog("Applying AI best weapon choice fix.", DL_FIX);
// Fix for the incorrect item being checked for the presence of weapon perks
HookCall(0x42954B, ai_best_weapon_hook);
@@ -3640,7 +3640,7 @@ void BugFixes_Init()
dlogr(" Done", DL_FIX);
// Fix for the "mood" argument of start_gdialog function being ignored for talking heads
if (GetConfigInt("Misc", "StartGDialogFix", 0)) {
if (IniReader::GetConfigInt("Misc", "StartGDialogFix", 0)) {
dlog("Applying start_gdialog argument fix.", DL_FIX);
MakeCall(0x456F08, op_start_gdialog_hack);
dlogr(" Done", DL_FIX);
@@ -3657,9 +3657,9 @@ void BugFixes_Init()
// Radiation fixes
MakeCall(0x42D6C3, process_rads_hack, 1); // prevents player's death if a stat is less than 1 when removing radiation effects
HookCall(0x42D67A, process_rads_hook); // fix for the same effect message being displayed when removing radiation effects
radEffectsMsgNum = GetConfigInt("Misc", "RadEffectsRemovalMsg", radEffectsMsgNum);
radEffectsMsgNum = IniReader::GetConfigInt("Misc", "RadEffectsRemovalMsg", radEffectsMsgNum);
// Display messages about radiation for the active geiger counter
if (GetConfigInt("Misc", "ActiveGeigerMsgs", 1)) {
if (IniReader::GetConfigInt("Misc", "ActiveGeigerMsgs", 1)) {
dlog("Applying active geiger counter messages patch.", DL_FIX);
const DWORD activeGeigerAddr[] = {0x42D424, 0x42D444};
SafeWriteBatch<BYTE>(CodeType::JumpZ, activeGeigerAddr); // jnz > jz
@@ -3668,7 +3668,7 @@ void BugFixes_Init()
// Display a pop-up message box about death from radiation
HookCall(0x42D733, process_rads_hook_msg);
//int drugUsePerfFix = GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
//int drugUsePerfFix = IniReader::GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
//if (drugUsePerfFix > 0) {
// dlog("Applying AI drug use preference fix.", DL_FIX);
// if (drugUsePerfFix == 1) {
@@ -3696,7 +3696,7 @@ void BugFixes_Init()
// Fix and repurpose the unused called_shot/num_attack arguments of attack_complex function
// called_shot - additional damage when hitting the target
// num_attacks - the number of free action points on the first turn only
if (GetConfigInt("Misc", "AttackComplexFix", 0)) {
if (IniReader::GetConfigInt("Misc", "AttackComplexFix", 0)) {
dlog("Applying attack_complex arguments fix.", DL_FIX);
HookCall(0x456D4A, op_attack_hook);
SafeWrite8(0x456D61, 0x74); // mov [gcsd.free_move], esi
@@ -3803,7 +3803,7 @@ void BugFixes_Init()
// up an item due to not enough space in the inventory
HookCall(0x49B6E7, obj_pickup_hook);
HookCall(0x49B71C, obj_pickup_hook_message);
Translate_Get("sfall", "NPCPickupFail", "%s cannot pick up the item.", pickupMessage, 65);
Translate::Get("sfall", "NPCPickupFail", "%s cannot pick up the item.", pickupMessage, 65);
// Fix for anim_move_to_tile_ engine function ignoring the distance argument for the player
HookCall(0x416D44, anim_move_to_tile_hook);
@@ -3814,7 +3814,7 @@ void BugFixes_Init()
MakeCall(0x411DF7, action_climb_ladder_hack); // bug caused by anim_move_to_tile_ fix
// Partial fix for incorrect positioning after exiting small/medium locations (e.g. Ghost Farm)
//if (GetConfigInt("Misc", "SmallLocExitFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "SmallLocExitFix", 1)) {
dlog("Applying fix for incorrect positioning after exiting small/medium locations.", DL_FIX);
MakeJump(0x4C5A41, wmTeleportToArea_hack);
dlogr(" Done", DL_FIX);
@@ -3830,7 +3830,7 @@ void BugFixes_Init()
MakeCall(0x4C03AA, wmWorldMap_hack, 2);
// Fix to prevent using number keys to enter unvisited areas on a town map
if (GetConfigInt("Misc", "TownMapHotkeysFix", 1)) {
if (IniReader::GetConfigInt("Misc", "TownMapHotkeysFix", 1)) {
dlog("Applying town map hotkeys patch.", DL_FIX);
MakeCall(0x4C495A, wmTownMapFunc_hack, 1);
dlogr(" Done", DL_FIX);
@@ -3842,7 +3842,7 @@ void BugFixes_Init()
// Fix for the car being lost when entering a location via the Town/World button and then leaving on foot
// (sets GVAR_CAR_PLACED_TILE (633) to -1 on exit to the world map)
if (GetConfigInt("Misc", "CarPlacedTileFix", 1)) {
if (IniReader::GetConfigInt("Misc", "CarPlacedTileFix", 1)) {
dlog("Applying car placed tile fix.", DL_FIX);
MakeCall(0x4C2367, wmInterfaceInit_hack);
dlogr(" Done", DL_FIX);
@@ -3860,7 +3860,7 @@ void BugFixes_Init()
HookCall(0x458B3D, op_critter_add_trait_hook);
// Fix to prevent corpses from blocking line of fire
//if (GetConfigInt("Misc", "CorpseLineOfFireFix", 1)) {
//if (IniReader::GetConfigInt("Misc", "CorpseLineOfFireFix", 1)) {
dlog("Applying fix for corpses blocking line of fire.", DL_FIX);
MakeJump(0x48B994, obj_shoot_blocking_at_hack0);
MakeJump(0x48BA04, obj_shoot_blocking_at_hack1);
@@ -3962,7 +3962,7 @@ void BugFixes_Init()
HookCall(0x4B6C13, checkAllRegions_hook);
// Fix for the script attached to an object not being initialized properly upon object creation
createObjectSidStartFix = (GetConfigInt("Misc", "CreateObjectSidFix", 0) != 0);
createObjectSidStartFix = (IniReader::GetConfigInt("Misc", "CreateObjectSidFix", 0) != 0);
MakeCall(0x4551C0, op_create_object_sid_hack, 1);
// Fix the error handling in create_object_sid function to prevent a crash when the proto is missing
SafeWrite8(0x45507B, 0x51); // jz 0x4550CD

Some files were not shown because too many files have changed in this diff Show More