diff --git a/artifacts/scripting/compiler/sslc_readme.md b/artifacts/scripting/compiler/sslc_readme.md index 4be48e78..56b071c0 100644 --- a/artifacts/scripting/compiler/sslc_readme.md +++ b/artifacts/scripting/compiler/sslc_readme.md @@ -323,6 +323,8 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by __NOTE:__ Just like `for` loop, `continue` statement will respect increments of a hidden counter variable, so you can safely use it inside `foreach`. +- `#pragma sce` directive. If present anywhere in the script source, it will enable short-circuit evaluation for all the logical `AND` and `OR` operators, even if the command line option `-s` is not used. + --- ### Fixes @@ -348,6 +350,10 @@ There are several changes in this version of sslc which may result in problems f ### Changelog +**sfall 4.4.10:** +- added `#pragma sce` directive +- added support for nested array expressions + **sfall 4.4.7:** - fixed leftover stack data caused by the `break` statement - added Linux & WebAssembly builds diff --git a/docs/sslc.md b/docs/sslc.md index a6335913..19c0798a 100644 --- a/docs/sslc.md +++ b/docs/sslc.md @@ -330,6 +330,8 @@ Syntax which requires sfall for compiled scripts to be interpreted is marked by __NOTE:__ Just like `for` loop, `continue` statement will respect increments of a hidden counter variable, so you can safely use it inside `foreach`. +- `#pragma sce` directive. If present anywhere in the script source, it will enable short-circuit evaluation for all the logical `AND` and `OR` operators, even if the command line option `-s` is not used. + ## Fixes - `playmoviealpharect` was using the token for `playmoviealpha`, breaking both functions in the process. diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index c4133cc7..83a8e404 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -3619,6 +3619,33 @@ skip: } } +static __declspec(naked) void wmRndEncounterPick_hack() { + static const DWORD wmRndEncounterPick_Ret = 0x4C0F86; + __asm { + cmp dword ptr [esp + 0xD0 - 0x20 + 4], 0; // candidatesLength + jle skip; + mov edx, STAT_lu; // overwritten engine code + retn; +skip: + mov eax, -1; // error (no candidate) + add esp, 4; + jmp wmRndEncounterPick_Ret; // exit from func + } +} + +static __declspec(naked) void wmRndEncounterOccurred_hook_pick() { + static const DWORD wmRndEncounterOccurred_Ret = 0x4C0BD4; + __asm { + call fo::funcoffs::wmRndEncounterPick_; + test eax, eax; + js skip; // -1 - no encounter candidate + retn; +skip: + add esp, 4; + jmp wmRndEncounterOccurred_Ret; // continue movement + } +} + void BugFixes::init() { #ifndef NDEBUG LoadGameHook::OnBeforeGameClose() += PrintAddrList; @@ -4495,6 +4522,10 @@ void BugFixes::init() { // Fix incorrect upper limit in mouse_set_sensitivity_ engine function SafeWrite8(0x4CAC54, 0x77); // jae > ja SafeWrite8(0x50FA0A, 0x04); // 2.5 (was 2.0) + + // Fix for getting stuck on an empty map when the encounter table has no available entries + MakeCall(0x4C0DF3, wmRndEncounterPick_hack); + HookCall(0x4C080A, wmRndEncounterOccurred_hook_pick); } } diff --git a/sfall/Modules/Scripting/Arrays.cpp b/sfall/Modules/Scripting/Arrays.cpp index 96e4b90c..e2714da2 100644 --- a/sfall/Modules/Scripting/Arrays.cpp +++ b/sfall/Modules/Scripting/Arrays.cpp @@ -773,8 +773,8 @@ void SaveArray(const ScriptValue& key, DWORD id) { */ void SetArrayFromExpression(const ScriptValue& key, const ScriptValue& val) { DWORD arrayId = !arrayExpressionStack.empty() - ? arrayExpressionStack.back() - : expressionArrayId; + ? arrayExpressionStack.back() + : expressionArrayId; if (arrayId == 0 || !ArrayExists(arrayId)) return; diff --git a/sfall/version.h b/sfall/version.h index efdc79c1..ffd41b5a 100644 --- a/sfall/version.h +++ b/sfall/version.h @@ -25,6 +25,6 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 4 #define VERSION_BUILD 9 -#define VERSION_REV 1 +#define VERSION_REV 2 -#define VERSION_STRING "4.4.9.1" +#define VERSION_STRING "4.4.9.2"