mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Rewrote the fix to allow fleeing NPC to use drugs.
Code edits to Perks.cpp/PerksOp.hpp.
This commit is contained in:
+30
-15
@@ -40,22 +40,9 @@ static void __declspec(naked) ai_try_attack_hook_FleeFix() {
|
||||
static const DWORD combat_ai_hook_flee_Ret = 0x42B22F;
|
||||
static void __declspec(naked) combat_ai_hook_FleeFix() {
|
||||
__asm {
|
||||
test byte ptr [ebp], 8; // 'ReTarget' flag
|
||||
test byte ptr [ebp], 8; // 'ReTarget' flag (critter.combat_state)
|
||||
jnz reTarget;
|
||||
test byte ptr [ebp], 4; // flee flag? (critter.combat_state)
|
||||
jz tryHeal;
|
||||
flee:
|
||||
jmp critter_name_;
|
||||
tryHeal:
|
||||
call ai_check_drugs_; // try to heal
|
||||
mov eax, esi;
|
||||
mov edx, STAT_current_hp;
|
||||
call stat_level_;
|
||||
cmp eax, [ebx + 0x10]; // minimum hp, below which NPC will run away
|
||||
mov eax, esi;
|
||||
jl flee;
|
||||
add esp, 4;
|
||||
jmp combat_ai_hook_flee_Ret;
|
||||
reTarget:
|
||||
and byte ptr [ebp], ~(4 | 8); // unset Flee/ReTarget flags
|
||||
xor edi, edi;
|
||||
@@ -65,6 +52,31 @@ reTarget:
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD combat_ai_hack_Ret = 0x42B204;
|
||||
static void __declspec(naked) combat_ai_hack() {
|
||||
__asm {
|
||||
mov edx, [ebx + 0x10]; // cap.min_hp
|
||||
cmp eax, edx;
|
||||
jl tryHeal; // curr_hp < min_hp
|
||||
end:
|
||||
add esp, 4;
|
||||
jmp combat_ai_hack_Ret;
|
||||
tryHeal:
|
||||
mov eax, esi;
|
||||
call ai_check_drugs_;
|
||||
push edx;
|
||||
mov eax, esi;
|
||||
mov edx, STAT_current_hp;
|
||||
call stat_level_;
|
||||
pop edx;
|
||||
cmp eax, edx; // edx - minimum hp, below which NPC will run away
|
||||
jge end;
|
||||
retn; // flee
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static DWORD RetryCombatLastAP;
|
||||
static DWORD RetryCombatMinAP;
|
||||
static void __declspec(naked) RetryCombatHook() {
|
||||
@@ -92,6 +104,8 @@ end:
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void __fastcall CombatAttackHook(DWORD source, DWORD target) {
|
||||
sources[target] = source;
|
||||
targets[source] = target;
|
||||
@@ -178,8 +192,9 @@ void AIInit() {
|
||||
/////////////////////// Combat AI behavior fixes ///////////////////////
|
||||
|
||||
// Fix to allow fleeing NPC to use drugs
|
||||
HookCall(0x42B1E3, combat_ai_hook_FleeFix);
|
||||
MakeCall(0x42B1DC, combat_ai_hack);
|
||||
// Fix for NPC stuck in fleeing mode when the hit chance of a target was too low
|
||||
HookCall(0x42B1E3, combat_ai_hook_FleeFix);
|
||||
HookCall(0x42ABA8, ai_try_attack_hook_FleeFix);
|
||||
HookCall(0x42ACE5, ai_try_attack_hook_FleeFix);
|
||||
// Disable fleeing when NPC cannot move closer to target
|
||||
|
||||
@@ -125,9 +125,6 @@ static void TakeControlOfNPC(TGameObj* npc) {
|
||||
(*ptr_perkLevelDataList)[i] = 0;
|
||||
}
|
||||
|
||||
// change character name
|
||||
CritterPcSetName(CritterName(npc));
|
||||
|
||||
// change level
|
||||
int level = IsPartyMember(npc)
|
||||
? PartyMemberGetCurrentLevel(npc)
|
||||
@@ -136,6 +133,9 @@ static void TakeControlOfNPC(TGameObj* npc) {
|
||||
*ptr_Level_ = level;
|
||||
*ptr_last_level = level;
|
||||
|
||||
// change character name
|
||||
CritterPcSetName(CritterName(npc));
|
||||
|
||||
// reset other stats
|
||||
*ptr_Experience_ = 0;
|
||||
*ptr_free_perk = 0;
|
||||
@@ -472,8 +472,8 @@ void PartyControlInit() {
|
||||
|
||||
// Gets dude perks and traits from script while controlling another NPC
|
||||
// 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_hook_
|
||||
HookCall(0x458326, GetRealDudeTrait); //op_has_trait_hook_
|
||||
HookCall(0x458242, GetRealDudePerk); // op_has_trait_
|
||||
HookCall(0x458326, GetRealDudeTrait); // op_has_trait_
|
||||
} else
|
||||
dlogr(" Disabled.", DL_INIT);
|
||||
|
||||
|
||||
+14
-9
@@ -205,7 +205,11 @@ void _stdcall SetSelectablePerk(char* name, int active, int image, char* desc) {
|
||||
}
|
||||
|
||||
void _stdcall SetFakePerk(char* name, int level, int image, char* desc) {
|
||||
if (level < 0 || level > 100) return;
|
||||
if (level > 100) {
|
||||
level = 100;
|
||||
} else if (level < 0 ) {
|
||||
return;
|
||||
}
|
||||
size_t size = fakePerks.size();
|
||||
if (level == 0) { // remove perk from fakePerks
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
@@ -235,7 +239,11 @@ void _stdcall SetFakePerk(char* name, int level, int image, char* desc) {
|
||||
}
|
||||
|
||||
void _stdcall SetFakeTrait(char* name, int active, int image, char* desc) {
|
||||
if (active < 0 || active > 1) return;
|
||||
if (active > 1) {
|
||||
active = 1;
|
||||
} else if (active < 0) {
|
||||
return;
|
||||
}
|
||||
size_t size = fakeTraits.size();
|
||||
if (active == 0) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
@@ -474,12 +482,11 @@ cLoop:
|
||||
}
|
||||
}
|
||||
|
||||
// Build a table of perks ID numbers available for selection
|
||||
// data buffer has limited size for 119 perks
|
||||
// Build a table of perks ID numbers available for selection, data buffer has limited size for 119 perks
|
||||
static DWORD _stdcall HandleExtraSelectablePerks(DWORD available, DWORD* data) {
|
||||
for (DWORD i = 0; i < fakeSelectablePerks.size(); i++) {
|
||||
if (available >= 119) break; // exit if the buffer is overfull
|
||||
data[available++] = PERK_count + i; //*(WORD*)(_name_sort_list + (offset+i)*8)=(WORD)(PERK_count+i);
|
||||
data[available++] = PERK_count + i;
|
||||
}
|
||||
return available; // total number of perks available for selection
|
||||
}
|
||||
@@ -488,8 +495,7 @@ static void __declspec(naked) GetAvailablePerksHook() {
|
||||
__asm {
|
||||
push ecx;
|
||||
push edx; // arg data
|
||||
mov ecx, IgnoringDefaultPerks;
|
||||
test ecx, ecx;
|
||||
cmp IgnoringDefaultPerks, 0;
|
||||
jnz skipDefaults;
|
||||
call perk_make_list_; // return available count
|
||||
jmp next;
|
||||
@@ -590,8 +596,7 @@ static void _stdcall AddFakePerk(DWORD perkID) {
|
||||
}
|
||||
}
|
||||
if (addPerkMode & 4) { // delete from selectable perks
|
||||
RemoveSelectableID.push_back(perkID);
|
||||
//fakeSelectablePerks.remove_at(perkID);
|
||||
RemoveSelectableID.push_back(perkID); //fakeSelectablePerks.remove_at(perkID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1196,16 +1196,16 @@ static void __declspec(naked) CombatOverHook() {
|
||||
}
|
||||
}
|
||||
|
||||
static int maxCountProto = 512;
|
||||
static int maxCountLoadProto = 512;
|
||||
static void __declspec(naked) proto_ptr_hack() {
|
||||
__asm {
|
||||
mov ecx, maxCountProto;
|
||||
mov ecx, maxCountLoadProto;
|
||||
cmp ecx, 4096;
|
||||
jae skip;
|
||||
cmp eax, ecx;
|
||||
jb end;
|
||||
add ecx, 256;
|
||||
mov maxCountProto, ecx;
|
||||
mov maxCountLoadProto, ecx;
|
||||
skip:
|
||||
cmp eax, ecx;
|
||||
end:
|
||||
|
||||
@@ -49,7 +49,6 @@ typedef struct {
|
||||
} sScriptProgram;
|
||||
|
||||
void ScriptExtenderSetup();
|
||||
void LoadProtoAutoMaxLimit();
|
||||
bool _stdcall isGameScript(const char* filename);
|
||||
void LoadGlobalScripts();
|
||||
void ClearGlobalScripts();
|
||||
@@ -96,6 +95,8 @@ static char reg_anim_combat_check = 1;
|
||||
extern DWORD isGlobalScriptLoading;
|
||||
extern DWORD AvailableGlobalScriptTypes;
|
||||
|
||||
void LoadProtoAutoMaxLimit();
|
||||
|
||||
// object's unique id
|
||||
extern long objUniqueID;
|
||||
long SetObjectUniqueID(TGameObj* obj);
|
||||
@@ -138,6 +139,5 @@ enum ScriptProc : long
|
||||
push_p_proc = 24,
|
||||
is_dropping_p_proc = 25,
|
||||
combat_is_starting_p_proc = 26,
|
||||
combat_is_over_p_proc = 27,
|
||||
count = 28
|
||||
combat_is_over_p_proc = 27
|
||||
};
|
||||
|
||||
+17
-21
@@ -547,28 +547,24 @@ end:
|
||||
|
||||
static void __declspec(naked) remove_trait() {
|
||||
__asm {
|
||||
pushad;
|
||||
mov ebp, eax;
|
||||
call interpretPopShort_;
|
||||
mov edi, eax;
|
||||
mov eax, ebp;
|
||||
call interpretPopLong_;
|
||||
cmp di, VAR_TYPE_INT;
|
||||
jnz end;
|
||||
xor ebx, ebx;
|
||||
dec ebx;
|
||||
mov ecx, ds:[_pc_trait2];
|
||||
cmp eax, ds:[_pc_trait];
|
||||
jne next;
|
||||
mov ds:[_pc_trait], ecx;
|
||||
mov ds:[_pc_trait2], ebx;
|
||||
jmp end;
|
||||
next:
|
||||
cmp eax, ds:[_pc_trait2];
|
||||
jne end;
|
||||
mov ds:[_pc_trait2], ebx;
|
||||
push ecx;
|
||||
_GET_ARG_INT(end);
|
||||
test eax, eax;
|
||||
jl end;
|
||||
mov edx, -1;
|
||||
cmp eax, ds:[_pc_trait];
|
||||
jne next;
|
||||
mov ecx, ds:[_pc_trait2];
|
||||
mov ds:[_pc_trait], ecx;
|
||||
mov ds:[_pc_trait2], edx;
|
||||
end:
|
||||
popad;
|
||||
pop ecx;
|
||||
retn;
|
||||
next:
|
||||
cmp eax, ds:[_pc_trait2];
|
||||
jne end;
|
||||
mov ds:[_pc_trait2], edx;
|
||||
pop ecx;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user