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:
@@ -604,6 +604,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
|
||||
|
||||
+23
-4
@@ -1804,10 +1804,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;
|
||||
}
|
||||
@@ -2974,6 +2976,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 Scripts::start;
|
||||
@@ -2981,8 +2985,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 InitScript;
|
||||
mov edx, ebx;
|
||||
mov eax, esi;
|
||||
retn;
|
||||
runStart:
|
||||
mov edx, start; // procedure
|
||||
mov eax, [ebx + scriptId];
|
||||
mov eax, ecx;
|
||||
call exec_script_proc_;
|
||||
end:
|
||||
mov edx, ebx;
|
||||
@@ -2990,7 +3008,7 @@ end:
|
||||
retn;
|
||||
noObject:
|
||||
push [esi];
|
||||
push [esp + 0x50 - 0x34 + 2*4]; // object pid
|
||||
push [esp + 0x50 - 0x34 + 8]; // object pid
|
||||
push proDbgMsg;
|
||||
call debug_printf_;
|
||||
add esp, 3*4;
|
||||
@@ -3789,6 +3807,7 @@ void BugFixes_Init()
|
||||
HookCall(0x4B6C13, checkAllRegions_hook);
|
||||
|
||||
// Fix for the script attached to an object not being initialized properly upon object creation
|
||||
createObjectSidStartFix = (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
|
||||
|
||||
@@ -155,9 +155,9 @@ void __declspec(naked) fo_interpretError(const char* fmt, ...) {
|
||||
__asm jmp interpretError_;
|
||||
}
|
||||
|
||||
long __fastcall fo_tile_num(long x, long y) {
|
||||
long __stdcall fo_tile_num(long x, long y) {
|
||||
__asm push ebx; // don't delete (bug in tile_num_)
|
||||
WRAP_WATCOM_FCALL2(tile_num_, x, y)
|
||||
WRAP_WATCOM_CALL2(tile_num_, x, y)
|
||||
__asm pop ebx;
|
||||
}
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ void __stdcall fo_interpretReturnValue(TProgram* scriptPtr, DWORD val, DWORD val
|
||||
// USE WITH CAUTION
|
||||
void __declspec() fo_interpretError(const char* fmt, ...);
|
||||
|
||||
long __fastcall fo_tile_num(long x, long y);
|
||||
long __stdcall fo_tile_num(long x, long y);
|
||||
|
||||
TGameObj* __fastcall obj_blocking_at_wrapper(TGameObj* obj, DWORD tile, DWORD elevation, void* func);
|
||||
|
||||
|
||||
@@ -500,6 +500,8 @@ FUNC(report_explosion_, 0x413144)
|
||||
FUNC(reset_box_bar_win_, 0x4614A0)
|
||||
FUNC(roll_random_, 0x4A30C0)
|
||||
FUNC(runProgram_, 0x46E154) // eax - programPtr, called once for each program after first loaded - hooks program to game and UI events
|
||||
FUNC(scr_build_lookup_table_, 0x4A49D0)
|
||||
FUNC(scr_exec_map_enter_scripts_, 0x4A67DC)
|
||||
FUNC(scr_exec_map_exit_scripts_, 0x4A69A0)
|
||||
FUNC(scr_exec_map_update_scripts_, 0x4A67E4)
|
||||
FUNC(scr_find_first_at_, 0x4A6524) // eax - elevation, returns spatial scriptID
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
/*
|
||||
For functions that have 3 or more arguments, it is preferable to use the fastcall calling convention
|
||||
because the compiler builds the better/optimized code when calling the engine functions
|
||||
|
||||
NOTES: be careful when using fastcall for engine functions inside C++ loops, as VS2010 might generate unexpected glithes
|
||||
*/
|
||||
WRAP_WATCOM_FFUNC4(long, _word_wrap, const char*, text, int, maxWidth, DWORD*, buf, BYTE*, count)
|
||||
WRAP_WATCOM_FFUNC3(long, ai_have_ammo, TGameObj*, critter, TGameObj*, item, TGameObj**, outAmmo)
|
||||
@@ -179,6 +181,7 @@ WRAP_WATCOM_FUNC3(long, register_object_turn_towards, TGameObj*, object, long, t
|
||||
WRAP_WATCOM_FUNC2(long, roll_random, long, minValue, long, maxValue)
|
||||
WRAP_WATCOM_FUNC1(long*, runProgram, TProgram*, progPtr)
|
||||
WRAP_WATCOM_FUNC1(long, selectWindowID, long, sWinID)
|
||||
WRAP_WATCOM_FUNC1(void, scr_build_lookup_table, TScript*, script)
|
||||
WRAP_WATCOM_FUNC1(TScript*, scr_find_first_at, long, elevation)
|
||||
WRAP_WATCOM_FUNC0(TScript*, scr_find_next_at)
|
||||
WRAP_WATCOM_FUNC1(TGameObj*, scr_find_obj_from_program, TProgram*, program)
|
||||
|
||||
@@ -372,7 +372,7 @@ static void __stdcall GameInitialized(int initResult) { // OnAfterGameInit
|
||||
}
|
||||
|
||||
static void __stdcall GameExit() { // OnGameExit
|
||||
if (femaleMsgs > 1) RestoreCutsState();
|
||||
if (femaleMsgs > 1) PlayerGenderCutsRestore();
|
||||
}
|
||||
|
||||
static void __stdcall GameClose() { // OnBeforeGameClose
|
||||
|
||||
+11
-14
@@ -33,6 +33,15 @@ static bool cutsPatch = false;
|
||||
|
||||
static std::vector<int> savPrototypes;
|
||||
|
||||
void PlayerGenderCutsRestore() {
|
||||
if (cutsPatch) { // restore
|
||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
||||
cutsPatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckPlayerGender() {
|
||||
isFemale = HeroIsFemale();
|
||||
|
||||
@@ -43,24 +52,12 @@ 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreCutsState() {
|
||||
if (cutsPatch) { // restore
|
||||
SafeWrite32(0x43FA9F, FO_VAR_aTextSCuts);
|
||||
SafeWrite32(0x44EB5B, FO_VAR_aTextSCutsS);
|
||||
SafeWrite32(0x48152E, FO_VAR_aTextSCutsSS);
|
||||
cutsPatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
static const DWORD scr_get_dialog_msg_file_Back = 0x4A6BD2;
|
||||
|
||||
static void __declspec(naked) scr_get_dialog_msg_file_hack1() {
|
||||
|
||||
+1
-1
@@ -27,4 +27,4 @@ void LoadOrder_art_get_name_hack();
|
||||
extern long femaleMsgs;
|
||||
|
||||
void CheckPlayerGender();
|
||||
void RestoreCutsState();
|
||||
void PlayerGenderCutsRestore();
|
||||
|
||||
@@ -995,9 +995,9 @@ void InitScriptProgram(sScriptProgram &prog, const char* fileName) {
|
||||
TProgram* scriptPtr = fo_loadProgram(fileName);
|
||||
|
||||
if (scriptPtr) {
|
||||
const char** procTable = ptr_procTableStrs;
|
||||
prog.ptr = scriptPtr;
|
||||
// fill lookup table
|
||||
const char** procTable = ptr_procTableStrs;
|
||||
for (int i = 0; i < Scripts::count; ++i) {
|
||||
prog.procLookup[i] = fo_interpretFindProcedure(prog.ptr, procTable[i]);
|
||||
}
|
||||
@@ -1043,6 +1043,26 @@ bool __stdcall 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 InitScript(long sid) {
|
||||
TScript* scriptPtr;
|
||||
if (fo_scr_ptr(sid, &scriptPtr) == -1) return -1;
|
||||
|
||||
scriptPtr->program = fo_loadProgram((*ptr_scriptListInfo)[scriptPtr->scriptIdx & 0xFFFFFF].fileName);
|
||||
if (!scriptPtr->program) return -1;
|
||||
if (scriptPtr->program->flags & 0x124) return 0;
|
||||
|
||||
// fill lookup table
|
||||
fo_scr_build_lookup_table(scriptPtr);
|
||||
|
||||
scriptPtr->flags |= 4 | 1; // init | loaded
|
||||
scriptPtr->action = Scripts::no_p_proc;
|
||||
scriptPtr->scriptOverrides = 0;
|
||||
|
||||
fo_runProgram(scriptPtr->program);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void LoadGlobalScriptsList() {
|
||||
dlogr("Running global scripts...", DL_SCRIPT);
|
||||
|
||||
|
||||
@@ -65,8 +65,6 @@ long __stdcall SetGlobalVar(const char* var, int val);
|
||||
|
||||
long __stdcall GetGlobalVar(const char* var);
|
||||
|
||||
int __stdcall ScriptHasLoaded(TProgram* script);
|
||||
|
||||
// loads script from .int file into a sScriptProgram struct, filling script pointer and proc lookup table
|
||||
// prog - reference to program structure
|
||||
// fileName - the script file name without extension
|
||||
@@ -93,6 +91,11 @@ void __stdcall AddTimerEventScripts(TProgram* script, long time, long param);
|
||||
void __stdcall RemoveTimerEventScripts(TProgram* script, long param);
|
||||
void __stdcall RemoveTimerEventScripts(TProgram* script);
|
||||
|
||||
int __stdcall ScriptHasLoaded(TProgram* script);
|
||||
|
||||
// loads and initializes script file (for normal game scripts)
|
||||
long __fastcall InitScript(long sid);
|
||||
|
||||
// variables
|
||||
extern DWORD availableGlobalScriptTypes;
|
||||
extern bool alwaysFindScripts;
|
||||
|
||||
Reference in New Issue
Block a user