Changed the fix for AI target selection in commit f0f00a7

* NPCs will reload the weapon in the same turn (and attack if have
enough AP left) if weapon is empty while selecting targets.

Moved some leftover code in main.cpp to KillCounter.cpp & Elevators.cpp.

Misc code edits.
This commit is contained in:
NovaRain
2020-04-27 14:32:39 +08:00
parent 1839790dfb
commit 8b26573073
13 changed files with 91 additions and 52 deletions
+1 -1
View File
@@ -394,7 +394,7 @@ CorpseDeleteTime=6
;Set a number of milliseconds to idle each input loop
;Set to -1 to disable
;Set to 0 to idle only if other processes are waiting for processor time (WinXP/2000: if processes have equal priority)
;Set to 1 (or some higher number if needed, the maximum is 127) to prevent 100% CPU use
;Set to 1 (or some higher number if needed) to prevent 100% CPU use. The maximum is 127
ProcessorIdle=-1
;Set to 1 if using the hero appearance mod
+16 -11
View File
@@ -148,7 +148,7 @@ skip:
}
}
static DWORD RetryCombatMinAP;
static long RetryCombatMinAP;
static void __declspec(naked) RetryCombatHook() {
static DWORD RetryCombatLastAP = 0;
@@ -234,7 +234,7 @@ static void __declspec(naked) ai_danger_source_hook() {
je fix;
retn;
fix: // check result
cmp eax, 2; // exception: 2 - out of range, 1 - no ammo
cmp eax, 1; // exception: 1 - no ammo
setg al; // set 0 for result OK
retn;
}
@@ -262,11 +262,11 @@ static void __declspec(naked) combat_attack_hook() {
}
void AIInit() {
const DWORD combatAttackAddr[] = {
const DWORD combatAttackHkAddr[] = {
0x426A95, // combat_attack_this_
0x42A796 // ai_attack_
};
HookCalls(combat_attack_hook, combatAttackAddr);
HookCalls(combat_attack_hook, combatAttackHkAddr);
RetryCombatMinAP = GetConfigInt("Misc", "NPCsTryToSpendExtraAP", 0);
if (RetryCombatMinAP > 0) {
@@ -284,6 +284,15 @@ void AIInit() {
/////////////////////// Combat AI behavior fixes ///////////////////////
// Fix for duplicate critters being added to the list of potential targets for AI
MakeCall(0x428E75, ai_find_attackers_hack_target2, 2);
MakeCall(0x428EB5, ai_find_attackers_hack_target3);
MakeCall(0x428EE5, ai_find_attackers_hack_target4, 1);
#ifndef NDEBUG
if (iniGetInt("Debugging", "AIBugFixes", 1, ddrawIniDef) == 0) return;
#endif
// Fix to allow fleeing NPC to use drugs
MakeCall(0x42B1DC, combat_ai_hack);
// Fix for AI not checking minimum hp properly for using stimpaks (prevents premature fleeing)
@@ -296,13 +305,9 @@ void AIInit() {
// Disable fleeing when NPC cannot move closer to target
BlockCall(0x42ADF6); // ai_try_attack_
// Fix for duplicate critters being added to the list of potential targets for AI
MakeCall(0x428E75, ai_find_attackers_hack_target2, 2);
MakeCall(0x428EB5, ai_find_attackers_hack_target3);
MakeCall(0x428EE5, ai_find_attackers_hack_target4, 1);
// Fix AI target selection for combat_check_bad_shot_ function returning a no_ammo or out_of_range result
HookCall(0x42918A, ai_danger_source_hook);
// Fix AI target selection for combat_check_bad_shot_ function returning a no_ammo result
const DWORD aiDangerBadShotAddr[] = {0x42903A, 0x42918A};
HookCalls(ai_danger_source_hook, aiDangerBadShotAddr);
}
TGameObj* __stdcall AIGetLastAttacker(TGameObj* target) {
+1 -1
View File
@@ -2643,7 +2643,7 @@ checkTiles:
void BugFixesInit()
{
#ifndef NDEBUG
if (iniGetInt("Debugging", "BugFixes", 1, ddrawIniDef) == 0) return;
if (iniGetInt("Debugging", "BugFixes", 1, ddrawIniDef) == 0) return;
#endif
// Fix vanilla negate operator for float values
+10 -1
View File
@@ -246,7 +246,7 @@ enum Stat : long
};
#define STAT_max_derived STAT_poison_resist
#define STAT_max_stat STAT_current_hp
#define STAT_max_stat STAT_current_hp
// Script data types
#define VAR_TYPE_INT (0xC001)
@@ -288,6 +288,15 @@ enum Skill : long
SKILL_count = 18
};
enum AnimCommand : long
{
RB_UNRESERVED = 0x1,
RB_RESERVED = 0x2,
RB_DONTSTAND = 0x4,
RB_UNKNOWN = 0x100,
RB_END_ANIM = 0x200
};
enum CritterFlags : long
{
CFLG_Sneak = 0x01, // Can sneak ?
+13 -3
View File
@@ -114,13 +114,13 @@ static void __declspec(naked) GetNumButtonsHook3() {
}
}
void ResetElevators() {
static void ResetElevators() {
//memset(&elevators[vanillaElevatorCount], 0, sizeof(sElevator) * (elevatorCount - vanillaElevatorCount));
//memset(&elevatorsFrms[vanillaElevatorCount], 0, sizeof(sElevatorFrms) * (elevatorCount - vanillaElevatorCount));
//for (int i = vanillaElevatorCount; i < elevatorCount; i++) elevatorType[i] = 0;
}
void LoadElevators(const char* elevFile) {
static void LoadElevators(const char* elevFile) {
//ResetElevators();
memcpy(elevators, (void*)_retvals, sizeof(sElevator) * vanillaElevatorCount);
@@ -158,7 +158,7 @@ void LoadElevators(const char* elevFile) {
}
}
void ElevatorsInit() {
static void ElevatorsInit2() {
HookCall(0x43EF83, GetMenuHook);
HookCall(0x43F141, CheckHotKeysHook);
//HookCall(0x43F2D2, UnknownHook2); // unused
@@ -180,3 +180,13 @@ void ElevatorsInit() {
MakeCall(0x43F184, GetNumButtonsHook2, 2);
MakeCall(0x43F1E4, GetNumButtonsHook3, 2);
}
void ElevatorsInit() {
std::string elevPath = GetConfigString("Misc", "ElevatorsFile", "", MAX_PATH);
if (!elevPath.empty()) {
dlog("Applying elevator patch.", DL_INIT);
ElevatorsInit2();
LoadElevators(elevPath.insert(0, ".\\").c_str());
dlogr(" Done", DL_INIT);
}
}
-1
View File
@@ -19,4 +19,3 @@
#pragma once
void ElevatorsInit();
void LoadElevators(const char* elevFile);
+13
View File
@@ -289,6 +289,7 @@ const DWORD barter_inventory_ = 0x4757F0;
const DWORD block_for_tocks_ = 0x4C93B8;
const DWORD buf_to_buf_ = 0x4D36D4;
const DWORD cai_attempt_w_reload_ = 0x42AECC;
const DWORD caiHasWeapPrefType_ = 0x42938C;
const DWORD check_death_ = 0x410814;
const DWORD Check4Keys_ = 0x43F73C;
const DWORD combat_ = 0x422D2C;
@@ -1345,6 +1346,10 @@ long __stdcall BlockForTocks(long ticks) {
WRAP_WATCOM_CALL1(block_for_tocks_, ticks)
}
long __fastcall DetermineToHit(TGameObj* source, TGameObj* target, long bodyPart, long hitMode) {
WRAP_WATCOM_FCALL4(determine_to_hit_, source, target, bodyPart, hitMode)
}
void __fastcall DisplayInventory(long inventoryOffset, long visibleOffset, long mode) {
WRAP_WATCOM_FCALL3(display_inventory_, inventoryOffset, visibleOffset, mode)
}
@@ -1385,6 +1390,10 @@ long __stdcall ObjDestroy(TGameObj* object) {
WRAP_WATCOM_CALL1(obj_destroy_, object)
}
long __stdcall ObjDist(TGameObj* source, TGameObj* target) {
WRAP_WATCOM_CALL2(obj_dist_, source, target)
}
long __stdcall ObjEraseObject(TGameObj* object, BoundRect* boundRect) {
WRAP_WATCOM_CALL2(obj_erase_object_, object, boundRect)
}
@@ -1519,6 +1528,10 @@ long __stdcall ItemWMaxAmmo(TGameObj* item) {
WRAP_WATCOM_CALL1(item_w_max_ammo_, item)
}
long __stdcall ItemWRange(TGameObj* critter, long hitMode) {
WRAP_WATCOM_CALL2(item_w_range_, critter, hitMode)
}
long __stdcall ItemWReload(TGameObj* weapon, TGameObj* ammo) {
WRAP_WATCOM_CALL2(item_w_reload_, weapon, ammo)
}
+6
View File
@@ -550,6 +550,7 @@ extern const DWORD barter_inventory_;
extern const DWORD block_for_tocks_;
extern const DWORD buf_to_buf_;
extern const DWORD cai_attempt_w_reload_;
extern const DWORD caiHasWeapPrefType_;
extern const DWORD check_death_;
extern const DWORD Check4Keys_;
extern const DWORD combat_;
@@ -1253,6 +1254,8 @@ long __stdcall WindowWidth();
long __stdcall BlockForTocks(long ticks);
long __fastcall DetermineToHit(TGameObj* source, TGameObj* target, long bodyPart, long hitMode);
void __fastcall DisplayInventory(long inventoryOffset, long visibleOffset, long mode);
void __fastcall DisplayTargetInventory(long inventoryOffset, long visibleOffset, DWORD* targetInventory, long mode);
@@ -1271,6 +1274,8 @@ TGameObj* __fastcall obj_blocking_at_wrapper(TGameObj* obj, DWORD tile, DWORD el
long __stdcall ObjDestroy(TGameObj* object);
long __stdcall ObjDist(TGameObj* source, TGameObj* target);
long __stdcall ObjEraseObject(TGameObj* object, BoundRect* boundRect);
TGameObj* __stdcall ObjFindFirst();
@@ -1330,6 +1335,7 @@ long __stdcall ItemWAnimWeap(TGameObj* item, DWORD hitMode);
long __stdcall ItemWComputeAmmoCost(TGameObj* item, DWORD* rounds);
long __stdcall ItemWCurrAmmo(TGameObj* item);
long __stdcall ItemWMaxAmmo(TGameObj* item);
long __stdcall ItemWRange(TGameObj* critter, long hitMode);
long __stdcall ItemWReload(TGameObj* weapon, TGameObj* ammo);
long __stdcall ItemWRounds(TGameObj* item);
long __stdcall ItemWeight(TGameObj* item);
+9 -1
View File
@@ -37,7 +37,7 @@ static void __declspec(naked) IncKillCounter() {
}
}
void KillCounterInit() {
static void KillCounterInit2() {
usingExtraKillTypes = true;
// Overwrite the critter_kill_count_ function that reads the kill counter
@@ -66,3 +66,11 @@ void KillCounterInit() {
bool UsingExtraKillTypes() {
return usingExtraKillTypes;
}
void KillCounterInit() {
if (GetConfigInt("Misc", "ExtraKillTypes", 0)) {
dlog("Applying extra kill types patch.", DL_INIT);
KillCounterInit2();
dlogr(" Done", DL_INIT);
}
}
+6 -6
View File
@@ -53,6 +53,8 @@
static DWORD inLoop = 0;
static DWORD saveInCombatFix;
static bool disableHorrigan = false;
static bool pipBoyAvailableAtGameStart = false;
static bool gameLoaded = false;
// True if game was started, false when on the main menu
@@ -320,12 +322,11 @@ static void NewGame2() {
gameLoaded = true;
}
static bool DisableHorrigan = false;
static void __declspec(naked) NewGame() {
__asm {
pushad;
call NewGame2;
mov al, DisableHorrigan;
mov al, disableHorrigan;
mov byte ptr ds:[_Meet_Frank_Horrigan], al;
popad;
jmp main_game_loop_;
@@ -337,13 +338,12 @@ static void ReadExtraGameMsgFilesIfNeeded() {
ReadExtraGameMsgFiles();
}
static bool PipBoyAvailableAtGameStart = false;
static void __declspec(naked) MainMenuHook() {
__asm {
pushad;
push 0;
call ResetState;
mov al, PipBoyAvailableAtGameStart;
mov al, pipBoyAvailableAtGameStart;
mov byte ptr ds:[_gmovie_played_list + 0x3], al;
call ReadExtraGameMsgFilesIfNeeded;
popad;
@@ -623,7 +623,7 @@ void LoadGameHookInit() {
switch (GetConfigInt("Misc", "PipBoyAvailableAtGameStart", 0)) {
case 1:
PipBoyAvailableAtGameStart = true;
pipBoyAvailableAtGameStart = true;
break;
case 2:
SafeWrite8(0x497011, 0xEB); // skip the vault suit movie check
@@ -631,7 +631,7 @@ void LoadGameHookInit() {
}
if (GetConfigInt("Misc", "DisableHorrigan", 0)) {
DisableHorrigan = true;
disableHorrigan = true;
SafeWrite8(0x4C06D8, 0xEB); // skip the Horrigan encounter check
}
+4 -6
View File
@@ -458,9 +458,9 @@ void PartyControl_OnGameLoad() {
void PartyControlInit() {
Mode = GetConfigInt("Misc", "ControlCombat", 0);
if (Mode > 2)
Mode = 0;
if (Mode > 2) Mode = 0;
if (Mode > 0) {
dlogr("Initializing party control...", DL_INIT);
char pidbuf[512];
pidbuf[511] = 0;
if (GetConfigString("Misc", "ControlCombatPIDList", "", pidbuf, 511)) {
@@ -468,8 +468,7 @@ void PartyControlInit() {
char* comma;
while (true) {
comma = strchr(ptr, ',');
if (!comma)
break;
if (!comma) break;
*comma = 0;
if (strlen(ptr) > 0)
Chars.push_back((WORD)strtoul(ptr, 0, 0));
@@ -495,8 +494,7 @@ void PartyControlInit() {
// WARNING: Handling dude perks/traits in the engine code while controlling another NPC remains impossible, this requires serious hacking of the engine code
HookCall(0x458242, GetRealDudePerk); // op_has_trait_
HookCall(0x458326, GetRealDudeTrait); // op_has_trait_
} else
dlogr(" Disabled.", DL_INIT);
}
MakeCall(0x45F47C, intface_toggle_items_hack);
+6 -6
View File
@@ -291,7 +291,7 @@ skip:
}
}
void WorldLimitsPatches() {
static void WorldLimitsPatches() {
DWORD data = GetConfigInt("Misc", "LocalMapXLimit", 0);
if (data) {
dlog("Applying local map x limit patch.", DL_INIT);
@@ -314,7 +314,7 @@ void WorldLimitsPatches() {
//}
}
void TimeLimitPatch() {
static void TimeLimitPatch() {
int limit = GetConfigInt("Misc", "TimeLimit", 13);
if (limit == -2 || limit == -3) {
addYear = true;
@@ -341,7 +341,7 @@ void TimeLimitPatch() {
}
}
void WorldmapFpsPatch() {
static void WorldmapFpsPatch() {
bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16);
if (GetConfigInt("Misc", "WorldMapFPSPatch", 0)) {
dlog("Applying world map fps patch.", DL_INIT);
@@ -376,7 +376,7 @@ void WorldmapFpsPatch() {
}
}
void PathfinderFixInit() {
static void PathfinderFixInit() {
//if (GetConfigInt("Misc", "PathfinderFix", 0)) {
dlog("Applying Pathfinder patch.", DL_INIT);
SafeWrite16(0x4C1FF6, 0x9090); // wmPartyWalkingStep_
@@ -386,7 +386,7 @@ void PathfinderFixInit() {
//}
}
void StartingStatePatches() {
static void StartingStatePatches() {
int date = GetConfigInt("Misc", "StartYear", -1);
if (date >= 0) {
dlog("Applying starting year patch.", DL_INIT);
@@ -442,7 +442,7 @@ void StartingStatePatches() {
if (ViewportX != -1 || ViewportY != -1) HookCall(0x4BCF07, ViewportHook); // game_reset_
}
void PipBoyAutomapsPatch() {
static void PipBoyAutomapsPatch() {
dlog("Applying Pip-Boy automaps patch.", DL_INIT);
MakeCall(0x4BF931, wmMapInit_hack, 2);
SafeWrite32(0x41B8B7, (DWORD)AutomapPipboyList);
+6 -15
View File
@@ -369,9 +369,8 @@ static void DllMain2() {
dlogr("Running MoviesInit().", DL_INIT);
MoviesInit();
dlog("Applying main menu patches.", DL_INIT);
dlogr("Running MainMenuInit().", DL_INIT);
MainMenuInit();
dlogr(" Done", DL_INIT);
dlogr("Running InterfaceInit().", DL_INIT);
InterfaceInit();
@@ -455,7 +454,7 @@ static void DllMain2() {
dlogr("Running InventoryInit().", DL_INIT);
InventoryInit();
dlogr("Initializing party control...", DL_INIT);
dlogr("Running PartyControlInit().", DL_INIT);
PartyControlInit();
dlogr("Running BurstModsInit().", DL_INIT);
@@ -467,19 +466,11 @@ static void DllMain2() {
dlogr("Running ExplosionInit().", DL_INIT);
ExplosionInit();
std::string elevPath = GetConfigString("Misc", "ElevatorsFile", "", MAX_PATH);
if (!elevPath.empty()) {
dlog("Applying elevator patch.", DL_INIT);
ElevatorsInit();
LoadElevators(elevPath.insert(0, ".\\").c_str());
dlogr(" Done", DL_INIT);
}
dlogr("Running ElevatorsInit().", DL_INIT);
ElevatorsInit();
if (GetConfigInt("Misc", "ExtraKillTypes", 0)) {
dlog("Applying extra kill types patch.", DL_INIT);
KillCounterInit();
dlogr(" Done", DL_INIT);
}
dlogr("Running KillCounterInit().", DL_INIT);
KillCounterInit();
dlogr("Running AIInit().", DL_INIT);
AIInit();