mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Adjusted how the fix for create_object_sid works
Added CreateObjectSidFix option.
This commit is contained in:
@@ -609,6 +609,10 @@ StartGDialogFix=0
|
|||||||
;num_attacks - the number of free action points on the first turn only
|
;num_attacks - the number of free action points on the first turn only
|
||||||
AttackComplexFix=0
|
AttackComplexFix=0
|
||||||
|
|
||||||
|
;Set to 1 to enable the create_object_sid script function to run the 'start' script procedure when creating an object
|
||||||
|
;It is recommended to enable this option only if you are developing a new project (TC), otherwise it may affect some existing game scripts
|
||||||
|
CreateObjectSidFix=0
|
||||||
|
|
||||||
;Set to 1 to fix the issue with the division operator treating negative integers as unsigned
|
;Set to 1 to fix the issue with the division operator treating negative integers as unsigned
|
||||||
;Note: To perform the unsigned integer division, use the new 'div' operator
|
;Note: To perform the unsigned integer division, use the new 'div' operator
|
||||||
DivisionOperatorFix=1
|
DivisionOperatorFix=1
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ WRAP_WATCOM_FUNC3(long, register_object_turn_towards, fo::GameObject*, object, l
|
|||||||
WRAP_WATCOM_FUNC2(long, roll_random, long, minValue, long, maxValue)
|
WRAP_WATCOM_FUNC2(long, roll_random, long, minValue, long, maxValue)
|
||||||
WRAP_WATCOM_FUNC1(long*, runProgram, fo::Program*, progPtr)
|
WRAP_WATCOM_FUNC1(long*, runProgram, fo::Program*, progPtr)
|
||||||
WRAP_WATCOM_FUNC1(long, selectWindowID, long, sWinID)
|
WRAP_WATCOM_FUNC1(long, selectWindowID, long, sWinID)
|
||||||
|
WRAP_WATCOM_FUNC1(void, scr_build_lookup_table, fo::ScriptInstance*, script)
|
||||||
WRAP_WATCOM_FUNC1(fo::ScriptInstance*, scr_find_first_at, long, elevation)
|
WRAP_WATCOM_FUNC1(fo::ScriptInstance*, scr_find_first_at, long, elevation)
|
||||||
WRAP_WATCOM_FUNC0(fo::ScriptInstance*, scr_find_next_at)
|
WRAP_WATCOM_FUNC0(fo::ScriptInstance*, scr_find_next_at)
|
||||||
WRAP_WATCOM_FUNC1(fo::GameObject*, scr_find_obj_from_program, fo::Program*, program)
|
WRAP_WATCOM_FUNC1(fo::GameObject*, scr_find_obj_from_program, fo::Program*, program)
|
||||||
|
|||||||
@@ -1824,10 +1824,12 @@ static void __declspec(naked) op_obj_can_hear_obj_hack() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// correct signed division by 4
|
||||||
static void __declspec(naked) ai_best_weapon_hack() {
|
static void __declspec(naked) ai_best_weapon_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
sar edx, 31;
|
add edx, 3;
|
||||||
sub eax, edx
|
test eax, eax;
|
||||||
|
cmovs eax, edx;
|
||||||
sar eax, 1;
|
sar eax, 1;
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
@@ -2994,6 +2996,8 @@ skip:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool createObjectSidStartFix = false;
|
||||||
|
|
||||||
static void __declspec(naked) op_create_object_sid_hack() {
|
static void __declspec(naked) op_create_object_sid_hack() {
|
||||||
static const char* proDbgMsg = "\nError: attempt to create object with PID of %d: %s!";
|
static const char* proDbgMsg = "\nError: attempt to create object with PID of %d: %s!";
|
||||||
using fo::Scripts::start;
|
using fo::Scripts::start;
|
||||||
@@ -3001,8 +3005,22 @@ static void __declspec(naked) op_create_object_sid_hack() {
|
|||||||
mov ebx, [esp + 0x50 - 0x20 + 4]; // createObj
|
mov ebx, [esp + 0x50 - 0x20 + 4]; // createObj
|
||||||
test ebx, ebx;
|
test ebx, ebx;
|
||||||
jz noObject;
|
jz noObject;
|
||||||
|
mov ecx, [ebx + scriptId];
|
||||||
|
cmp ecx, -1;
|
||||||
|
jne init;
|
||||||
|
mov edx, ebx;
|
||||||
|
mov eax, esi;
|
||||||
|
retn;
|
||||||
|
init:
|
||||||
|
cmp createObjectSidStartFix, 0;
|
||||||
|
jne runStart;
|
||||||
|
call ScriptExtender::InitScript;
|
||||||
|
mov edx, ebx;
|
||||||
|
mov eax, esi;
|
||||||
|
retn;
|
||||||
|
runStart:
|
||||||
mov edx, start; // procedure
|
mov edx, start; // procedure
|
||||||
mov eax, [ebx + scriptId];
|
mov eax, ecx;
|
||||||
call fo::funcoffs::exec_script_proc_;
|
call fo::funcoffs::exec_script_proc_;
|
||||||
end:
|
end:
|
||||||
mov edx, ebx;
|
mov edx, ebx;
|
||||||
@@ -3795,6 +3813,7 @@ void BugFixes::init()
|
|||||||
HookCall(0x4B6C13, checkAllRegions_hook);
|
HookCall(0x4B6C13, checkAllRegions_hook);
|
||||||
|
|
||||||
// Fix for the script attached to an object not being initialized properly upon object creation
|
// Fix for the script attached to an object not being initialized properly upon object creation
|
||||||
|
createObjectSidStartFix = (IniReader::GetConfigInt("Misc", "CreateObjectSidFix", 0) != 0);
|
||||||
MakeCall(0x4551C0, op_create_object_sid_hack, 1);
|
MakeCall(0x4551C0, op_create_object_sid_hack, 1);
|
||||||
// Fix the error handling in create_object_sid function to prevent a crash when the proto is missing
|
// Fix the error handling in create_object_sid function to prevent a crash when the proto is missing
|
||||||
SafeWrite8(0x45507B, 0x51); // jz 0x4550CD
|
SafeWrite8(0x45507B, 0x51); // jz 0x4550CD
|
||||||
|
|||||||
+12
-13
@@ -39,6 +39,15 @@ static bool cutsPatch = false;
|
|||||||
static std::vector<std::string> patchFiles;
|
static std::vector<std::string> patchFiles;
|
||||||
static std::vector<int> savPrototypes;
|
static std::vector<int> savPrototypes;
|
||||||
|
|
||||||
|
static void PlayerGenderCutsRestore() {
|
||||||
|
if (cutsPatch) { // restore
|
||||||
|
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
||||||
|
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
||||||
|
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
||||||
|
cutsPatch = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void CheckPlayerGender() {
|
static void CheckPlayerGender() {
|
||||||
isFemale = fo::HeroIsFemale();
|
isFemale = fo::HeroIsFemale();
|
||||||
|
|
||||||
@@ -49,11 +58,8 @@ static void CheckPlayerGender() {
|
|||||||
SafeWrite32(0x43FA9F, (DWORD)cutsEndGameFemale);
|
SafeWrite32(0x43FA9F, (DWORD)cutsEndGameFemale);
|
||||||
SafeWrite32(0x44EB5B, (DWORD)cutsSubFemale);
|
SafeWrite32(0x44EB5B, (DWORD)cutsSubFemale);
|
||||||
SafeWrite32(0x48152E, (DWORD)cutsDeathFemale);
|
SafeWrite32(0x48152E, (DWORD)cutsDeathFemale);
|
||||||
} else if (cutsPatch) {
|
} else {
|
||||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
PlayerGenderCutsRestore();
|
||||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
|
||||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
|
||||||
cutsPatch = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,14 +503,7 @@ void LoadOrder::init() {
|
|||||||
LoadGameHook::OnAfterGameStarted() += CheckPlayerGender;
|
LoadGameHook::OnAfterGameStarted() += CheckPlayerGender;
|
||||||
if (femaleMsgs > 1) {
|
if (femaleMsgs > 1) {
|
||||||
MakeCall(0x480A95, gnw_main_hack); // before new game start from main menu. TODO: need moved to address 0x480A9A (it busy in movies.cpp)
|
MakeCall(0x480A95, gnw_main_hack); // before new game start from main menu. TODO: need moved to address 0x480A9A (it busy in movies.cpp)
|
||||||
LoadGameHook::OnGameExit() += []() {
|
LoadGameHook::OnGameExit() += PlayerGenderCutsRestore;
|
||||||
if (cutsPatch) { // restore
|
|
||||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
|
||||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
|
||||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
|
||||||
cutsPatch = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,14 +428,14 @@ void __fastcall SetSelfObject(fo::Program* script, fo::GameObject* obj) {
|
|||||||
|
|
||||||
// loads script from .int file into a sScriptProgram struct, filling script pointer and proc lookup table
|
// loads script from .int file into a sScriptProgram struct, filling script pointer and proc lookup table
|
||||||
void InitScriptProgram(ScriptProgram &prog, const char* fileName, bool fullPath) {
|
void InitScriptProgram(ScriptProgram &prog, const char* fileName, bool fullPath) {
|
||||||
fo::Program* scriptPtr = fullPath
|
fo::Program* scriptPtr = (fullPath)
|
||||||
? fo::func::allocateProgram(fileName)
|
? fo::func::allocateProgram(fileName)
|
||||||
: fo::func::loadProgram(fileName);
|
: fo::func::loadProgram(fileName);
|
||||||
|
|
||||||
if (scriptPtr) {
|
if (scriptPtr) {
|
||||||
const char** procTable = fo::var::procTableStrs;
|
|
||||||
prog.ptr = scriptPtr;
|
prog.ptr = scriptPtr;
|
||||||
// fill lookup table
|
// fill lookup table
|
||||||
|
const char** procTable = fo::var::procTableStrs;
|
||||||
for (int i = 0; i < fo::Scripts::ScriptProc::count; ++i) {
|
for (int i = 0; i < fo::Scripts::ScriptProc::count; ++i) {
|
||||||
prog.procLookup[i] = fo::func::interpretFindProcedure(prog.ptr, procTable[i]);
|
prog.procLookup[i] = fo::func::interpretFindProcedure(prog.ptr, procTable[i]);
|
||||||
}
|
}
|
||||||
@@ -481,6 +481,26 @@ bool IsGameScript(const char* filename) {
|
|||||||
return false; // script name was not found in scripts.lst
|
return false; // script name was not found in scripts.lst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loads and initializes script file (for normal game scripts)
|
||||||
|
long __fastcall ScriptExtender::InitScript(long sid) {
|
||||||
|
fo::ScriptInstance* scriptPtr;
|
||||||
|
if (fo::func::scr_ptr(sid, &scriptPtr) == -1) return -1;
|
||||||
|
|
||||||
|
scriptPtr->program = fo::func::loadProgram(fo::var::scriptListInfo[scriptPtr->scriptIdx & 0xFFFFFF].fileName);
|
||||||
|
if (!scriptPtr->program) return -1;
|
||||||
|
if (scriptPtr->program->flags & 0x124) return 0;
|
||||||
|
|
||||||
|
// fill lookup table
|
||||||
|
fo::func::scr_build_lookup_table(scriptPtr);
|
||||||
|
|
||||||
|
scriptPtr->flags |= 4 | 1; // init | loaded
|
||||||
|
scriptPtr->action = fo::Scripts::ScriptProc::no_p_proc;
|
||||||
|
scriptPtr->scriptOverrides = 0;
|
||||||
|
|
||||||
|
fo::func::runProgram(scriptPtr->program);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void LoadGlobalScriptsList() {
|
static void LoadGlobalScriptsList() {
|
||||||
dlogr("Running global scripts...", DL_SCRIPT);
|
dlogr("Running global scripts...", DL_SCRIPT);
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ public:
|
|||||||
|
|
||||||
static int __stdcall ScriptHasLoaded(fo::Program* script);
|
static int __stdcall ScriptHasLoaded(fo::Program* script);
|
||||||
|
|
||||||
|
// loads and initializes script file (for normal game scripts)
|
||||||
|
static long __fastcall InitScript(long sid);
|
||||||
|
|
||||||
// Called before map exit (before map_exit_p_proc handlers in normal scripts)
|
// Called before map exit (before map_exit_p_proc handlers in normal scripts)
|
||||||
static Delegate<>& OnMapExit();
|
static Delegate<>& OnMapExit();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user