Added combat rating check to "Snipe" distance preference fix

Added a fix to reduce friendly fire in burst attacks.
Updated the info of TGameObj struct.
This commit is contained in:
NovaRain
2020-05-01 08:01:24 +08:00
parent 7f3de8d19a
commit 24c9499021
7 changed files with 77 additions and 5 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ AllowDShowSound=0
;Set to 1 to override the music path used by default (i.e. data\sound\music\) if not present in the cfg
;Set to 2 to overwrite all occurances of the music path
OverrideMusicDir=2
OverrideMusicDir=1
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Input]
+55
View File
@@ -28,6 +28,23 @@ typedef std::tr1::unordered_map<TGameObj*, TGameObj*>::const_iterator iter;
static std::tr1::unordered_map<TGameObj*, TGameObj*> targets;
static std::tr1::unordered_map<TGameObj*, TGameObj*> sources;
TGameObj* __stdcall sf_check_critters_in_lof(TGameObj* object, DWORD checkTile, DWORD team) {
if (object && object->pid >> 24 == OBJ_TYPE_CRITTER && object->teamNum != team) { // not friendly fire
if (object->tile == checkTile) return nullptr;
TGameObj* obj = nullptr; // continue checking the line of fire from object to checkTile
MakeStraightPathFunc(object, object->tile, checkTile, 0, (DWORD*)&obj, 32, (void*)obj_shoot_blocking_at_);
if (!sf_check_critters_in_lof(obj, checkTile, team)) return nullptr;
}
return object;
}
// Returns the friendly critter that is in the line of fire
TGameObj* __stdcall CheckFriendlyFire(TGameObj* target, TGameObj* attacker) {
TGameObj* object = nullptr;
MakeStraightPathFunc(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 32, (void*)obj_shoot_blocking_at_);
return sf_check_critters_in_lof(object, target->tile, attacker->teamNum); // 0 if there are no friendly critters
}
static void __declspec(naked) ai_try_attack_hook_FleeFix() {
__asm {
or byte ptr [esi + 0x3C], 8; // set new 'ReTarget' flag
@@ -272,6 +289,14 @@ static void __declspec(naked) cai_perform_distance_prefs_hack() {
lea edx, [edx + ecx - 1];
cmp edx, 5; // minimum threshold distance
jge skipMove; // distance >= 5?
// check combat rating
mov eax, esi;
call combatai_rating_;
mov edx, eax; // source rating
mov eax, edi;
call combatai_rating_;
cmp eax, edx; // target vs source rating
jl skipMove; // target rating is low
moveAway:
mov ebx, 10; // move away max distance
retn;
@@ -283,6 +308,32 @@ skipMove:
////////////////////////////////////////////////////////////////////////////////
static long __fastcall RollFriendlyFire(TGameObj* target, TGameObj* attacker) {
if (CheckFriendlyFire(target, attacker)) {
long dice = RollRandom(1, 10);
return (StatLevel(attacker, STAT_iq) >= dice); // 1 - is friendly
}
return 0;
}
static void __declspec(naked) combat_safety_invalidate_weapon_func_hook_check() {
static DWORD safety_invalidate_weapon_burst_friendly = 0x4216C9;
__asm {
pushadc;
mov ecx, esi; // target
call RollFriendlyFire;
test eax, eax;
jnz friendly;
popadc;
jmp combat_ctd_init_;
friendly:
lea esp, [esp + 8 + 3 * 4];
jmp safety_invalidate_weapon_burst_friendly; // "Friendly was in the way!"
}
}
////////////////////////////////////////////////////////////////////////////////
static void __fastcall CombatAttackHook(TGameObj* source, TGameObj* target) {
sources[target] = source; // who attacked the 'target' from the last time
targets[source] = target; // who was attacked by the 'source' from the last time
@@ -328,6 +379,10 @@ void AIInit() {
/////////////////////// Combat AI behavior fixes ///////////////////////
// Fix to reduce friendly fire in burst attacks
// Adds a check/roll for friendly critters in the line of fire when AI uses burst attacks
HookCall(0x421666, combat_safety_invalidate_weapon_func_hook_check);
// 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);
+4
View File
@@ -21,6 +21,10 @@
#include "FalloutEngine.h"
void AIInit();
TGameObj* __stdcall sf_check_critters_in_lof(TGameObj* object, DWORD checkTile, DWORD team);
TGameObj* __stdcall CheckFriendlyFire(TGameObj* target, TGameObj* attacker);
void __stdcall AICombatStart();
void __stdcall AICombatEnd();
+5
View File
@@ -303,6 +303,7 @@ const DWORD combat_input_ = 0x4227F4;
const DWORD combat_should_end_ = 0x422C60;
const DWORD combat_turn_ = 0x42299C;
const DWORD combat_turn_run_ = 0x4227DC;
const DWORD combatai_rating_ = 0x42B90C;
const DWORD compute_damage_ = 0x4247B8;
const DWORD compute_spray_ = 0x423488;
const DWORD config_get_string_ = 0x42BF48;
@@ -994,6 +995,10 @@ TGameObj* __stdcall ScrFindObjFromProgram(TProgram* program) {
WRAP_WATCOM_CALL1(scr_find_obj_from_program_, program)
}
long __stdcall RollRandom(long minValue, long maxValue) {
WRAP_WATCOM_CALL2(roll_random_, minValue, maxValue)
}
// Saves pointer to script object into scriptPtr using scriptID.
// Returns 0 on success, -1 on failure.
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr) {
+3
View File
@@ -564,6 +564,7 @@ extern const DWORD combat_input_;
extern const DWORD combat_should_end_;
extern const DWORD combat_turn_;
extern const DWORD combat_turn_run_;
extern const DWORD combatai_rating_;
extern const DWORD compute_damage_;
extern const DWORD compute_spray_;
extern const DWORD config_get_string_;
@@ -1144,6 +1145,8 @@ long __stdcall XFSeek(DbFile* file, long fOffset, long origin);
TGameObj* __stdcall ScrFindObjFromProgram(TProgram* program);
long __stdcall RollRandom(long minValue, long maxValue);
// Saves pointer to script object into scriptPtr using scriptID.
// Returns 0 on success, -1 on failure.
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr);
+8 -3
View File
@@ -76,9 +76,14 @@ struct TGameObj {
char gap_38[4];
long itemCharges;
long critterAP_weaponAmmoPid;
char gap_44[16];
TGameObj* whoHitMe;
char gap_58[12];
long damageFlags; // critter
long damageLastTurn; // critter
long aiPacket; // critter
long teamNum; // critter
TGameObj* whoHitMe; // critter
long health; // critter
long rads; // critter
long poison; // critter
DWORD pid;
long cid;
long lightDistance;
+1 -1
View File
@@ -737,7 +737,7 @@ static void sf_unwield_slot() {
if (update) IntfaceUpdateItems(0, -1, -1);
}
void sf_get_window_attribute() {
static void sf_get_window_attribute() {
long attr = 0;
if (opHandler.numArgs() > 1) attr = opHandler.arg(1).rawValue();