Rewrote the score calculation in AIBestWeaponFix (#370)

Changed FastShotFix to be disabled by default.
This commit is contained in:
NovaRain
2021-04-29 11:54:20 +08:00
parent 52af67ad3d
commit 7df0407798
5 changed files with 40 additions and 33 deletions
+7 -8
View File
@@ -438,10 +438,9 @@ SkipOpeningMovies=0
;Set to 0 to disable
NPCsTryToSpendExtraAP=0
;Set to 1 to fix NPCs not checking weapon perks properly when choosing the best weapon in combat
;Set to 2 to change the priority multiplier for having weapon perk to 3x (the original is 5x)
;Note that enabling this option can significantly affect the weapon of choice for some NPCs
AIBestWeaponFix=0
;Set to 1 to fix the priority score calculation for choosing the best weapon for NPCs
;Note that enabling this option can affect the weapon of choice for some NPCs
AIBestWeaponFix=1
;Set to 1 to fix NPCs not taking chem_primary_desire in AI.txt as drug use preference when using drugs in their inventory
;Set to 2 to allow NPCs to use only the drugs listed in chem_primary_desire and healing drugs (stimpaks and healing powder)
@@ -546,11 +545,11 @@ RemoveCriticalTimelimits=0
;MainMenuBigFontColour=0x3C
;Alternative behaviors to the Fast Shot trait
;0 - Fallout 2 original behavior: -1 AP cost for ranged weapons; aimed attacks are disabled
;1 - Haenlomal's fix: aimed attacks are enabled for melee/unarmed weapons and HtH attacks
;0 - Fallout 2 original behavior: -1 AP cost for ranged weapons. Aimed attacks are disabled
;1 - Haenlomal's tweak: aimed attacks are enabled for melee/unarmed weapons and HtH attacks
;2 - Alternative behavior: apply -1 AP cost to melee/unarmed weapons and HtH attacks
;3 - Fallout 1 original behavior: -1 AP cost for all weapons; aimed attacks are disabled
FastShotFix=1
;3 - Fallout 1 original behavior: -1 AP cost for all weapons. Aimed attacks are disabled
FastShotFix=0
;Set to 1 to fix the carry weight penalty of the Small Frame trait not being applied to bonus Strength points
SmallFrameFix=0
+12 -12
View File
@@ -66,11 +66,11 @@ void __declspec(naked) Tilemap::obj_path_blocking_at_() {
}
}
static std::vector<int> buildLineTiles;
//static std::vector<int> buildLineTiles;
static bool TileExists(long tile) {
return (std::find(buildLineTiles.cbegin(), buildLineTiles.cend(), tile) != buildLineTiles.cend());
}
//static bool TileExists(long tile) {
// return (std::find(buildLineTiles.cbegin(), buildLineTiles.cend(), tile) != buildLineTiles.cend());
//}
// Fixed and improved implementation of tile_num_beyond_ engine function
// - correctly gets the tile from the constructed line
@@ -78,11 +78,11 @@ static bool TileExists(long tile) {
long __fastcall Tilemap::tile_num_beyond(long sourceTile, long targetTile, long maxRange) {
if (maxRange <= 0 || sourceTile == targetTile) return sourceTile;
if (buildLineTiles.empty()) {
/*if (buildLineTiles.empty()) {
buildLineTiles.reserve(100);
} else {
buildLineTiles.clear();
}
}*/
long currentRange = fo::func::tile_dist(sourceTile, targetTile);
//fo::func::debug_printf("\ntile_dist: %d", currentRange);
@@ -121,11 +121,11 @@ long __fastcall Tilemap::tile_num_beyond(long sourceTile, long targetTile, long
long tile = fo::func::tile_num(target_X, target_Y);
//fo::func::debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
if (tile != lastTile) {
if (!TileExists(tile)) {
//if (!TileExists(tile)) {
long dist = fo::func::tile_dist(targetTile, tile);
if ((dist + currentRange) >= maxRange || fo::func::tile_on_edge(tile)) return tile;
buildLineTiles.push_back(tile);
}
// buildLineTiles.push_back(tile);
//}
lastTile = tile;
}
stepCounter = 0;
@@ -155,11 +155,11 @@ long __fastcall Tilemap::tile_num_beyond(long sourceTile, long targetTile, long
long tile = fo::func::tile_num(target_X, target_Y);
//fo::func::debug_printf("\ntile_num: %d [x:%d y:%d]", tile, target_X, target_Y);
if (tile != lastTile) {
if (!TileExists(tile)) {
//if (!TileExists(tile)) {
long dist = fo::func::tile_dist(targetTile, tile);
if ((dist + currentRange) >= maxRange || fo::func::tile_on_edge(tile)) return tile;
buildLineTiles.push_back(tile);
}
// buildLineTiles.push_back(tile);
//}
lastTile = tile;
}
stepCounter = 0;
+16 -7
View File
@@ -1824,6 +1824,15 @@ static void __declspec(naked) op_obj_can_hear_obj_hack() {
}
}
static void __declspec(naked) ai_best_weapon_hack() {
__asm {
sar edx, 31;
sub eax, edx
sar eax, 1;
retn;
}
}
static void __declspec(naked) ai_best_weapon_hook() {
__asm {
mov eax, [esp + 0xF4 - 0x10 + 4]; // prev.item
@@ -3445,15 +3454,15 @@ void BugFixes::init()
dlogr(" Done", DL_FIX);
}
// Fix for AI not checking weapon perks properly when searching for the best weapon
int bestWeaponPerkFix = IniReader::GetConfigInt("Misc", "AIBestWeaponFix", 0);
if (bestWeaponPerkFix > 0) {
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);
// also change the priority multiplier for having weapon perk to 3x (the original is 5x)
if (bestWeaponPerkFix > 1) {
SafeWriteBatch<BYTE>(0x55, {0x42955E, 0x4296E7}); // lea eax, [edx * 2];
}
// Corrects the calculation of the weapon score to: (maxDmg + minDmg) / 4
SafeWriteBatch<BYTE>(0x01, {0x4294E2, 0x429675}); // sub > add
MakeCalls(ai_best_weapon_hack, {0x4294E6, 0x429679});
// Corrects the weapon score multiplier for having perks to 2x (was 5x)
SafeWriteBatch<BYTE>(0x15, {0x42955E, 0x4296E7}); // lea eax, [edx*4] > lea eax, [edx]
dlogr(" Done", DL_FIX);
}
-1
View File
@@ -70,7 +70,6 @@ static long heroIsFemale = -1;
// Searches the special character in the text and removes the text depending on the player's gender
// example: <MaleText^FemaleText>
static long __fastcall ReplaceGenderWord(fo::MessageNode* msgData, DWORD* msgFile) {
if (!InDialog() || msgData->flags & MSG_GENDER_CHECK_FLG) return 1;
if (heroIsFemale < 0) heroIsFemale = fo::HeroIsFemale();
+5 -5
View File
@@ -1139,7 +1139,7 @@ checkType:
}
}
// Haenlomal's fix
// Haenlomal's tweak
static void __declspec(naked) item_w_called_shot_hack() {
static const DWORD FastShotTraitFix_End = 0x478E7F;
using namespace fo;
@@ -1169,18 +1169,18 @@ cantUse:
}
static void FastShotTraitFix() {
switch (IniReader::GetConfigInt("Misc", "FastShotFix", 1)) {
switch (IniReader::GetConfigInt("Misc", "FastShotFix", 0)) {
case 1:
dlog("Applying Fast Shot trait patch. (Haenlomal's fix)", DL_INIT);
dlog("Applying Fast Shot trait patch (Haenlomal's tweak).", DL_INIT);
MakeJump(0x478E79, item_w_called_shot_hack);
goto fix;
case 2:
dlog("Applying Fast Shot trait patch. (Alternative behavior)", DL_INIT);
dlog("Applying Fast Shot trait patch (Alternative behavior).", DL_INIT);
SafeWrite16(0x478C9F, 0x9090);
HookCalls((void*)0x478C7D, {0x478BB8, 0x478BC7, 0x478BD6, 0x478BEA, 0x478BF9, 0x478C08, 0x478C2F});
goto done;
case 3:
dlog("Applying Fast Shot trait patch. (Fallout 1 behavior)", DL_INIT);
dlog("Applying Fast Shot trait patch (Fallout 1 behavior).", DL_INIT);
HookCall(0x478C97, (void*)fo::funcoffs::item_hit_with_);
SafeWrite16(0x478C9E, CodeType::JumpZ << 8); // ignore all unarmed attacks (cmp eax, 0; jz)
goto done;