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
|
||||
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
|
||||
;Note: To perform the unsigned integer division, use the new 'div' operator
|
||||
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_FUNC1(long*, runProgram, fo::Program*, progPtr)
|
||||
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_FUNC0(fo::ScriptInstance*, scr_find_next_at)
|
||||
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() {
|
||||
__asm {
|
||||
sar edx, 31;
|
||||
sub eax, edx
|
||||
add edx, 3;
|
||||
test eax, eax;
|
||||
cmovs eax, edx;
|
||||
sar eax, 1;
|
||||
retn;
|
||||
}
|
||||
@@ -2994,6 +2996,8 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
static bool createObjectSidStartFix = false;
|
||||
|
||||
static void __declspec(naked) op_create_object_sid_hack() {
|
||||
static const char* proDbgMsg = "\nError: attempt to create object with PID of %d: %s!";
|
||||
using fo::Scripts::start;
|
||||
@@ -3001,8 +3005,22 @@ static void __declspec(naked) op_create_object_sid_hack() {
|
||||
mov ebx, [esp + 0x50 - 0x20 + 4]; // createObj
|
||||
test ebx, ebx;
|
||||
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 eax, [ebx + scriptId];
|
||||
mov eax, ecx;
|
||||
call fo::funcoffs::exec_script_proc_;
|
||||
end:
|
||||
mov edx, ebx;
|
||||
@@ -3795,6 +3813,7 @@ void BugFixes::init()
|
||||
HookCall(0x4B6C13, checkAllRegions_hook);
|
||||
|
||||
// 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);
|
||||
// Fix the error handling in create_object_sid function to prevent a crash when the proto is missing
|
||||
SafeWrite8(0x45507B, 0x51); // jz 0x4550CD
|
||||
|
||||
+12
-13
@@ -39,6 +39,15 @@ static bool cutsPatch = false;
|
||||
static std::vector<std::string> patchFiles;
|
||||
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() {
|
||||
isFemale = fo::HeroIsFemale();
|
||||
|
||||
@@ -49,11 +58,8 @@ static void CheckPlayerGender() {
|
||||
SafeWrite32(0x43FA9F, (DWORD)cutsEndGameFemale);
|
||||
SafeWrite32(0x44EB5B, (DWORD)cutsSubFemale);
|
||||
SafeWrite32(0x48152E, (DWORD)cutsDeathFemale);
|
||||
} else if (cutsPatch) {
|
||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
||||
cutsPatch = false;
|
||||
} else {
|
||||
PlayerGenderCutsRestore();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,14 +503,7 @@ void LoadOrder::init() {
|
||||
LoadGameHook::OnAfterGameStarted() += CheckPlayerGender;
|
||||
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)
|
||||
LoadGameHook::OnGameExit() += []() {
|
||||
if (cutsPatch) { // restore
|
||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
||||
cutsPatch = false;
|
||||
}
|
||||
};
|
||||
LoadGameHook::OnGameExit() += PlayerGenderCutsRestore;
|
||||
}
|
||||
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
|
||||
void InitScriptProgram(ScriptProgram &prog, const char* fileName, bool fullPath) {
|
||||
fo::Program* scriptPtr = fullPath
|
||||
fo::Program* scriptPtr = (fullPath)
|
||||
? fo::func::allocateProgram(fileName)
|
||||
: fo::func::loadProgram(fileName);
|
||||
|
||||
if (scriptPtr) {
|
||||
const char** procTable = fo::var::procTableStrs;
|
||||
prog.ptr = scriptPtr;
|
||||
// fill lookup table
|
||||
const char** procTable = fo::var::procTableStrs;
|
||||
for (int i = 0; i < fo::Scripts::ScriptProc::count; ++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
|
||||
}
|
||||
|
||||
// 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() {
|
||||
dlogr("Running global scripts...", DL_SCRIPT);
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ public:
|
||||
|
||||
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)
|
||||
static Delegate<>& OnMapExit();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user