mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Removed NPCStage6Fix from ddraw.ini (always enabled)
Moved the code of NPCStage6Fix to BugFixes module. (to its original relative location, right above MultiHexPathingFix) Reorganized some code in BugFixes.cpp.
This commit is contained in:
@@ -509,9 +509,6 @@ AnimationsAtOnceLimit=120
|
|||||||
;Set to 1 to remove the limits that stop the player rolling critical successes/misses in the first few days of game time
|
;Set to 1 to remove the limits that stop the player rolling critical successes/misses in the first few days of game time
|
||||||
RemoveCriticalTimelimits=0
|
RemoveCriticalTimelimits=0
|
||||||
|
|
||||||
;Set to 1 to enable party members with level 6 protos to reach level 6
|
|
||||||
NPCStage6Fix=0
|
|
||||||
|
|
||||||
;Change the colour of the font used on the main menu for the Fallout/sfall version number and copyright text
|
;Change the colour of the font used on the main menu for the Fallout/sfall version number and copyright text
|
||||||
;It's the last byte ('3C' by default) that picks the colour used. The first byte supplies additional flags for this option
|
;It's the last byte ('3C' by default) that picks the colour used. The first byte supplies additional flags for this option
|
||||||
;MainMenuFontColour=0x00003C
|
;MainMenuFontColour=0x00003C
|
||||||
|
|||||||
+73
-47
@@ -817,6 +817,25 @@ static void __declspec(naked) op_wield_obj_critter_adjust_ac_hook() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const DWORD NPCStage6Fix1End = 0x493D16;
|
||||||
|
static void __declspec(naked) NPCStage6Fix1() {
|
||||||
|
__asm {
|
||||||
|
imul eax, edx, 204; // necessary memory = number of NPC records in party.txt * record size
|
||||||
|
mov ebx, eax; // copy total record size for later memset
|
||||||
|
call fo::funcoffs::mem_malloc_; // malloc the necessary memory
|
||||||
|
jmp NPCStage6Fix1End; // call memset to set all malloc'ed memory to 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const DWORD NPCStage6Fix2End = 0x49423A;
|
||||||
|
static void __declspec(naked) NPCStage6Fix2() {
|
||||||
|
__asm {
|
||||||
|
imul edx, edx, 204; // NPC number as listed in party.txt * record size
|
||||||
|
mov eax, ds:[FO_VAR_partyMemberAIOptions]; // get starting offset of internal NPC table
|
||||||
|
jmp NPCStage6Fix2End; // eax+edx = offset of specific NPC record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Haenlomal: Check path to critter for attack
|
// Haenlomal: Check path to critter for attack
|
||||||
static void __declspec(naked) MultiHexFix() {
|
static void __declspec(naked) MultiHexFix() {
|
||||||
__asm {
|
__asm {
|
||||||
@@ -830,24 +849,6 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const DWORD ai_move_steps_closer_run_object_ret = 0x42A169;
|
|
||||||
static void __declspec(naked) MultiHexCombatRunFix() {
|
|
||||||
__asm {
|
|
||||||
test [edi + flags + 1], 0x08; // is target multihex?
|
|
||||||
jnz multiHex;
|
|
||||||
test [esi + flags + 1], 0x08; // is source multihex?
|
|
||||||
jz runTile;
|
|
||||||
multiHex:
|
|
||||||
mov edx, [esp + 4]; // source's destination tilenum
|
|
||||||
cmp [edi + tile], edx; // target's tilenum
|
|
||||||
jnz runTile;
|
|
||||||
add esp, 4;
|
|
||||||
jmp ai_move_steps_closer_run_object_ret;
|
|
||||||
runTile:
|
|
||||||
retn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const DWORD ai_move_steps_closer_move_object_ret = 0x42A192;
|
static const DWORD ai_move_steps_closer_move_object_ret = 0x42A192;
|
||||||
static void __declspec(naked) MultiHexCombatMoveFix() {
|
static void __declspec(naked) MultiHexCombatMoveFix() {
|
||||||
__asm {
|
__asm {
|
||||||
@@ -866,6 +867,24 @@ moveTile:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const DWORD ai_move_steps_closer_run_object_ret = 0x42A169;
|
||||||
|
static void __declspec(naked) MultiHexCombatRunFix() {
|
||||||
|
__asm {
|
||||||
|
test [edi + flags + 1], 0x08; // is target multihex?
|
||||||
|
jnz multiHex;
|
||||||
|
test [esi + flags + 1], 0x08; // is source multihex?
|
||||||
|
jz runTile;
|
||||||
|
multiHex:
|
||||||
|
mov edx, [esp + 4]; // source's destination tilenum
|
||||||
|
cmp [edi + tile], edx; // target's tilenum
|
||||||
|
jnz runTile;
|
||||||
|
add esp, 4;
|
||||||
|
jmp ai_move_steps_closer_run_object_ret;
|
||||||
|
runTile:
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//checks if an attacked object is a critter before attempting dodge animation
|
//checks if an attacked object is a critter before attempting dodge animation
|
||||||
static void __declspec(naked) action_melee_hack() {
|
static void __declspec(naked) action_melee_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
@@ -1288,30 +1307,28 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __stdcall ItemCountFixStdcall(fo::GameObject* who, fo::GameObject* item) {
|
static int __stdcall ItemCountFix(fo::GameObject* who, fo::GameObject* item) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < who->invenSize; i++) {
|
for (int i = 0; i < who->invenSize; i++) {
|
||||||
auto tableItem = &who->invenTable[i];
|
auto tableItem = &who->invenTable[i];
|
||||||
if (tableItem->object == item) {
|
if (tableItem->object == item) {
|
||||||
count += tableItem->count;
|
count += tableItem->count;
|
||||||
} else if (fo::func::item_get_type(tableItem->object) == fo::item_type_container) {
|
} else if (fo::func::item_get_type(tableItem->object) == fo::item_type_container) {
|
||||||
count += ItemCountFixStdcall(tableItem->object, item);
|
count += ItemCountFix(tableItem->object, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) ItemCountFix() {
|
static void __declspec(naked) item_count_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
push ebx;
|
|
||||||
push ecx;
|
push ecx;
|
||||||
push edx; // save state
|
push edx; // save state
|
||||||
push edx; // item
|
push edx; // item
|
||||||
push eax; // container-object
|
push eax; // container-object
|
||||||
call ItemCountFixStdcall;
|
call ItemCountFix;
|
||||||
pop edx;
|
pop edx;
|
||||||
pop ecx;
|
pop ecx; // restore
|
||||||
pop ebx; // restore
|
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1870,6 +1887,14 @@ skip:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) op_attack_hook() {
|
||||||
|
__asm {
|
||||||
|
mov esi, dword ptr [esp + 0x3C + 4]; // free_move
|
||||||
|
mov ebx, dword ptr [esp + 0x40 + 4]; // add amount damage to target
|
||||||
|
jmp fo::funcoffs::gdialogActive_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __declspec(naked) combat_attack_hack() {
|
static void __declspec(naked) combat_attack_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
mov ebx, ds:[FO_VAR_main_ctd + 0x2C]; // amountTarget
|
mov ebx, ds:[FO_VAR_main_ctd + 0x2C]; // amountTarget
|
||||||
@@ -1883,14 +1908,6 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) op_attack_hook() {
|
|
||||||
__asm {
|
|
||||||
mov esi, dword ptr [esp + 0x3C + 4]; // free_move
|
|
||||||
mov ebx, dword ptr [esp + 0x40 + 4]; // add amount damage to target
|
|
||||||
jmp fo::funcoffs::gdialogActive_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __declspec(naked) op_use_obj_on_obj_hack() {
|
static void __declspec(naked) op_use_obj_on_obj_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
test eax, eax; // source
|
test eax, eax; // source
|
||||||
@@ -2268,14 +2285,14 @@ skip:
|
|||||||
|
|
||||||
static long __fastcall GetFreeTilePlacement(long elev, long tile) {
|
static long __fastcall GetFreeTilePlacement(long elev, long tile) {
|
||||||
long count = 0, dist = 1;
|
long count = 0, dist = 1;
|
||||||
long freeTile = tile;
|
long checkTile = tile;
|
||||||
long rotation = fo::var::rotation;
|
long rotation = fo::var::rotation;
|
||||||
while (fo::func::obj_blocking_at(0, freeTile, elev)) {
|
while (fo::func::obj_blocking_at(0, checkTile, elev)) {
|
||||||
freeTile = fo::func::tile_num_in_direction(freeTile, rotation, dist);
|
checkTile = fo::func::tile_num_in_direction(checkTile, rotation, dist);
|
||||||
if (++count > 5 && ++dist > 5) return tile;
|
if (++count > 5 && ++dist > 5) return tile;
|
||||||
if (++rotation > 5) rotation = 0;
|
if (++rotation > 5) rotation = 0;
|
||||||
}
|
}
|
||||||
return freeTile;
|
return checkTile; // free tile
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) map_check_state_hook() {
|
static void __declspec(naked) map_check_state_hook() {
|
||||||
@@ -2497,6 +2514,15 @@ void BugFixes::init()
|
|||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
//if (GetConfigInt("Misc", "NPCStage6Fix", 1)) {
|
||||||
|
dlog("Applying NPC Stage 6 Fix.", DL_INIT);
|
||||||
|
MakeJump(0x493CE9, NPCStage6Fix1);
|
||||||
|
SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage
|
||||||
|
SafeWrite8(0x4940BB, 204); // move pointer by 204 bytes instead of 200
|
||||||
|
MakeJump(0x494224, NPCStage6Fix2);
|
||||||
|
dlogr(" Done", DL_INIT);
|
||||||
|
//}
|
||||||
|
|
||||||
//if (GetConfigInt("Misc", "MultiHexPathingFix", 1)) {
|
//if (GetConfigInt("Misc", "MultiHexPathingFix", 1)) {
|
||||||
dlog("Applying MultiHex Pathing Fix.", DL_INIT);
|
dlog("Applying MultiHex Pathing Fix.", DL_INIT);
|
||||||
MakeCalls(MultiHexFix, {0x42901F, 0x429170});
|
MakeCalls(MultiHexFix, {0x42901F, 0x429170});
|
||||||
@@ -2602,7 +2628,7 @@ void BugFixes::init()
|
|||||||
MakeCall(0x471A94, use_inventory_on_hack);
|
MakeCall(0x471A94, use_inventory_on_hack);
|
||||||
|
|
||||||
// Fix item_count function returning incorrect value when there is a container-item inside
|
// Fix item_count function returning incorrect value when there is a container-item inside
|
||||||
MakeJump(0x47808C, ItemCountFix); // replacing item_count_ function
|
MakeJump(0x47808C, item_count_hack); // replacing item_count_ function
|
||||||
|
|
||||||
// Fix for Sequence stat value not being printed correctly when using "print to file" option
|
// Fix for Sequence stat value not being printed correctly when using "print to file" option
|
||||||
MakeCall(0x4396F5, Save_as_ASCII_hack, 2);
|
MakeCall(0x4396F5, Save_as_ASCII_hack, 2);
|
||||||
@@ -2766,14 +2792,6 @@ void BugFixes::init()
|
|||||||
// Fix returned result value when the file is missing
|
// Fix returned result value when the file is missing
|
||||||
HookCall(0x4C6162, db_freadInt_hook);
|
HookCall(0x4C6162, db_freadInt_hook);
|
||||||
|
|
||||||
// Fix for attack_complex still causing minimum damage to the target when the attacker misses
|
|
||||||
MakeCall(0x422FE5, combat_attack_hack, 1);
|
|
||||||
|
|
||||||
// Fix for critter_mod_skill taking a negative amount value as a positive
|
|
||||||
dlog("Applying critter_mod_skill fix.", DL_INIT);
|
|
||||||
SafeWrite8(0x45B910, 0x7E); // jbe > jle
|
|
||||||
dlogr(" Done", DL_INIT);
|
|
||||||
|
|
||||||
// Fix and repurpose the unused called_shot/num_attack arguments of attack_complex function
|
// Fix and repurpose the unused called_shot/num_attack arguments of attack_complex function
|
||||||
// also change the behavior of the result flags arguments
|
// also change the behavior of the result flags arguments
|
||||||
// called_shot - additional damage, when the damage received by the target is above the specified minimum
|
// called_shot - additional damage, when the damage received by the target is above the specified minimum
|
||||||
@@ -2788,6 +2806,14 @@ void BugFixes::init()
|
|||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix for attack_complex still causing minimum damage to the target when the attacker misses
|
||||||
|
MakeCall(0x422FE5, combat_attack_hack, 1);
|
||||||
|
|
||||||
|
// Fix for critter_mod_skill taking a negative amount value as a positive
|
||||||
|
dlog("Applying critter_mod_skill fix.", DL_INIT);
|
||||||
|
SafeWrite8(0x45B910, 0x7E); // jbe > jle
|
||||||
|
dlogr(" Done", DL_INIT);
|
||||||
|
|
||||||
// Fix crash when calling use_obj/use_obj_on_obj without using set_self in global scripts
|
// Fix crash when calling use_obj/use_obj_on_obj without using set_self in global scripts
|
||||||
// also change the behavior of use_obj_on_obj function
|
// also change the behavior of use_obj_on_obj function
|
||||||
// if the object uses the item on itself, then another function is called (not a bug fix)
|
// if the object uses the item on itself, then another function is called (not a bug fix)
|
||||||
|
|||||||
@@ -207,27 +207,6 @@ really_end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const DWORD NPCStage6Fix1End = 0x493D16;
|
|
||||||
static void __declspec(naked) NPCStage6Fix1() {
|
|
||||||
__asm {
|
|
||||||
mov eax, 204; // set record size to 204 bytes
|
|
||||||
imul eax, edx; // multiply by number of NPC records in party.txt
|
|
||||||
mov ebx, eax; // copy total record size for later memset
|
|
||||||
call fo::funcoffs::mem_malloc_; // malloc the necessary memory
|
|
||||||
jmp NPCStage6Fix1End; // call memset to set all malloc'ed memory to 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const DWORD NPCStage6Fix2End = 0x49423A;
|
|
||||||
static void __declspec(naked) NPCStage6Fix2() {
|
|
||||||
__asm {
|
|
||||||
mov eax, 204; // record size is 204 bytes
|
|
||||||
imul edx, eax; // multiply by NPC number as listed in party.txt
|
|
||||||
mov eax, dword ptr ds:[FO_VAR_partyMemberAIOptions]; // get starting offset of internal NPC table
|
|
||||||
jmp NPCStage6Fix2End; // eax+edx = offset of specific NPC record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const DWORD ScannerHookRet = 0x41BC1D;
|
static const DWORD ScannerHookRet = 0x41BC1D;
|
||||||
static const DWORD ScannerHookFail = 0x41BC65;
|
static const DWORD ScannerHookFail = 0x41BC65;
|
||||||
static void __declspec(naked) ScannerAutomapHook() {
|
static void __declspec(naked) ScannerAutomapHook() {
|
||||||
@@ -512,17 +491,6 @@ void CorpseLineOfFireFix() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcStage6Fix() {
|
|
||||||
if (GetConfigInt("Misc", "NPCStage6Fix", 1)) {
|
|
||||||
dlog("Applying NPC Stage 6 Fix.", DL_INIT);
|
|
||||||
MakeJump(0x493CE9, NPCStage6Fix1);
|
|
||||||
SafeWrite8(0x494063, 6); // loop should look for a potential 6th stage
|
|
||||||
SafeWrite8(0x4940BB, 204); // move pointer by 204 bytes instead of 200
|
|
||||||
MakeJump(0x494224, NPCStage6Fix2);
|
|
||||||
dlogr(" Done", DL_INIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MotionScannerFlagsPatch() {
|
void MotionScannerFlagsPatch() {
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
if (flags = GetConfigInt("Misc", "MotionScannerFlags", 1)) {
|
if (flags = GetConfigInt("Misc", "MotionScannerFlags", 1)) {
|
||||||
@@ -810,7 +778,6 @@ void MiscPatches::init() {
|
|||||||
BlockCall(0x4425E6);
|
BlockCall(0x4425E6);
|
||||||
|
|
||||||
OverrideMusicDirPatch();
|
OverrideMusicDirPatch();
|
||||||
NpcStage6Fix();
|
|
||||||
BoostScriptDialogLimitPatch();
|
BoostScriptDialogLimitPatch();
|
||||||
MotionScannerFlagsPatch();
|
MotionScannerFlagsPatch();
|
||||||
EncounterTableSizePatch();
|
EncounterTableSizePatch();
|
||||||
|
|||||||
@@ -712,7 +712,7 @@ void SaveArray(const ScriptValue& key, DWORD id) {
|
|||||||
it->second.key.unset();
|
it->second.key.unset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// make "saved" array
|
// make array "saved"
|
||||||
itArray->second.key.setByType(key.rawValue(), key.type());
|
itArray->second.key.setByType(key.rawValue(), key.type());
|
||||||
savedArrays.emplace(itArray->second.key, id); // savedArrays[itArray->second.key] = id;
|
savedArrays.emplace(itArray->second.key, id); // savedArrays[itArray->second.key] = id;
|
||||||
} else { // key of int(0) is used to "unsave" array without destroying it
|
} else { // key of int(0) is used to "unsave" array without destroying it
|
||||||
|
|||||||
@@ -694,7 +694,7 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* valueOutRange = "%s() - argument values out of range.";
|
static const char* valueOutRange = "%s() - argument values out of range.";
|
||||||
|
|
||||||
void sf_set_critical_table(OpcodeContext& ctx) {
|
void sf_set_critical_table(OpcodeContext& ctx) {
|
||||||
DWORD critter = ctx.arg(0).asInt(),
|
DWORD critter = ctx.arg(0).asInt(),
|
||||||
|
|||||||
Reference in New Issue
Block a user