mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Refactored the code for "substr" script function
* fixed the crashing bug and added a new behavior. Changed the error message due to missing critter frame (again): * replaced the interruption with printing the error message to in-game message window.
This commit is contained in:
@@ -262,7 +262,10 @@ Some utility/math functions are available:
|
|||||||
- you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0))
|
- you can use this to search for a substring in a string like this: strlen(get_array(string_split(haystack, needle), 0))
|
||||||
|
|
||||||
> string substr(string, start, length)
|
> string substr(string, start, length)
|
||||||
- cuts a substring from a string starting at "start" up to "length" characters. If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st"). If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te")
|
- cuts a substring from a string starting at "start" up to "length" characters. The first character position starts with 0 (zero).
|
||||||
|
- If start is negative - it indicates starting position from the end of the string (for example substr("test", -2, 2) will return last 2 charactes: "st").
|
||||||
|
- If length is negative - it means so many characters will be omitted from the end of string (example: substr("test", 0, -2) will return string without last 2 characters: "te").
|
||||||
|
- If length is zero - it will return a string from the starting position to the end of the string **New behavior** for sfall 4.2.2/3.8.22
|
||||||
|
|
||||||
> int strlen(string string)
|
> int strlen(string string)
|
||||||
- returns string length
|
- returns string length
|
||||||
@@ -452,6 +455,7 @@ Some utility/math functions are available:
|
|||||||
|
|
||||||
> array sfall_func2("get_ini_section", string fileName, string section)
|
> array sfall_func2("get_ini_section", string fileName, string section)
|
||||||
- returns an associative array of keys and values for a given INI file and section
|
- returns an associative array of keys and values for a given INI file and section
|
||||||
|
- NOTE: all keys and their values will be of String type
|
||||||
|
|
||||||
> int sfall_func0("car_gas_amount")
|
> int sfall_func0("car_gas_amount")
|
||||||
- returns current amount of fuel in player's car (between 0 and 80000)
|
- returns current amount of fuel in player's car (between 0 and 80000)
|
||||||
|
|||||||
@@ -321,12 +321,15 @@ artNotExist:
|
|||||||
push eax;
|
push eax;
|
||||||
push artDbgMsg;
|
push artDbgMsg;
|
||||||
call fo::funcoffs::debug_printf_;
|
call fo::funcoffs::debug_printf_;
|
||||||
add esp, 8;
|
mov eax, [esp + 0x124 - 0x1C + 12]; // filename
|
||||||
cmp isDebug, 0;
|
push eax;
|
||||||
jz skip;
|
push artDbgMsg;
|
||||||
int 3; // break program
|
lea eax, [esp + 0x124 - 0x124 + 20]; // buf
|
||||||
skip:
|
push eax;
|
||||||
retn;
|
call fo::funcoffs::sprintf_;
|
||||||
|
add esp, 20;
|
||||||
|
lea eax, [esp + 4];
|
||||||
|
jmp fo::funcoffs::display_print_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +368,7 @@ static void DebugModePatch() {
|
|||||||
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
|
if (iniGetInt("Debugging", "HideObjIsNullMsg", 0, ::sfall::ddrawIni)) {
|
||||||
MakeJump(0x453FD2, dbg_error_hack);
|
MakeJump(0x453FD2, dbg_error_hack);
|
||||||
}
|
}
|
||||||
// prints a debug message about missing art file for critters and interrupts game execution
|
// prints a debug message about missing art file for critters to debug.log and the message window
|
||||||
HookCall(0x419B65, art_data_size_hook);
|
HookCall(0x419B65, art_data_size_hook);
|
||||||
|
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
|
|||||||
@@ -523,9 +523,9 @@ end:
|
|||||||
|
|
||||||
static void __declspec(naked) DialogHook() {
|
static void __declspec(naked) DialogHook() {
|
||||||
__asm {
|
__asm {
|
||||||
cmp dword ptr [esp + 0x14], 0x45A5C9; // call from op_gsay_end_
|
test inLoop, DIALOG; // check bit flag
|
||||||
je changeMode;
|
jz changeMode;
|
||||||
jmp fo::funcoffs::gdProcess_;
|
jmp fo::funcoffs::gdProcess_;
|
||||||
changeMode:
|
changeMode:
|
||||||
_InLoop(1, DIALOG);
|
_InLoop(1, DIALOG);
|
||||||
call fo::funcoffs::gdProcess_;
|
call fo::funcoffs::gdProcess_;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace script
|
|||||||
|
|
||||||
void sf_create_array(OpcodeContext& ctx) {
|
void sf_create_array(OpcodeContext& ctx) {
|
||||||
auto arrayId = CreateArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
auto arrayId = CreateArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
||||||
ctx.setReturn(arrayId, DataType::INT);
|
ctx.setReturn(arrayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_set_array(OpcodeContext& ctx) {
|
void sf_set_array(OpcodeContext& ctx) {
|
||||||
@@ -55,7 +55,7 @@ void sf_get_array(OpcodeContext& ctx) {
|
|||||||
);
|
);
|
||||||
} else if (ctx.arg(0).isString()) {
|
} else if (ctx.arg(0).isString()) {
|
||||||
if (ctx.arg(1).isInt()) {
|
if (ctx.arg(1).isInt()) {
|
||||||
auto str = Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), 1);
|
const char* str = Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), 1);
|
||||||
ctx.setReturn(str); // returns char of string
|
ctx.setReturn(str); // returns char of string
|
||||||
} else {
|
} else {
|
||||||
ctx.printOpcodeError("%s() - index must be numeric when used on a string.", ctx.getOpcodeName());
|
ctx.printOpcodeError("%s() - index must be numeric when used on a string.", ctx.getOpcodeName());
|
||||||
@@ -83,7 +83,7 @@ void sf_resize_array(OpcodeContext& ctx) {
|
|||||||
|
|
||||||
void sf_temp_array(OpcodeContext& ctx) {
|
void sf_temp_array(OpcodeContext& ctx) {
|
||||||
auto arrayId = TempArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
auto arrayId = TempArray(ctx.arg(0).rawValue(), ctx.arg(1).rawValue());
|
||||||
ctx.setReturn(arrayId, DataType::INT);
|
ctx.setReturn(arrayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_fix_array(OpcodeContext& ctx) {
|
void sf_fix_array(OpcodeContext& ctx) {
|
||||||
@@ -200,7 +200,7 @@ static DWORD ListAsArray(DWORD type) {
|
|||||||
|
|
||||||
void sf_list_as_array(OpcodeContext& ctx) {
|
void sf_list_as_array(OpcodeContext& ctx) {
|
||||||
auto arrayId = ListAsArray(ctx.arg(0).rawValue());
|
auto arrayId = ListAsArray(ctx.arg(0).rawValue());
|
||||||
ctx.setReturn(arrayId, DataType::INT);
|
ctx.setReturn(arrayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD ListBegin(DWORD type) {
|
static DWORD ListBegin(DWORD type) {
|
||||||
@@ -212,7 +212,7 @@ static DWORD ListBegin(DWORD type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sf_list_begin(OpcodeContext& ctx) {
|
void sf_list_begin(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(ListBegin(ctx.arg(0).rawValue()), DataType::INT);
|
ctx.setReturn(ListBegin(ctx.arg(0).rawValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static fo::GameObject* ListNext(sList* list) {
|
static fo::GameObject* ListNext(sList* list) {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ void __declspec(naked) op_game_loaded() {
|
|||||||
movzx edx, al;
|
movzx edx, al;
|
||||||
mov eax, ebx;
|
mov eax, ebx;
|
||||||
_RET_VAL_INT;
|
_RET_VAL_INT;
|
||||||
pop ecx;
|
pop ecx;
|
||||||
retn;
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,29 +190,40 @@ void sf_string_split(OpcodeContext& ctx) {
|
|||||||
ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue()));
|
ctx.setReturn(StringSplit(ctx.arg(0).strValue(), ctx.arg(1).strValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Substring(const char* str, int pos, int length) {
|
static char* tempTextBuf = nullptr;
|
||||||
char* newstr;
|
|
||||||
int srclen;
|
char* Substring(const char* str, int startPos, int length) {
|
||||||
srclen = strlen(str);
|
int len = strlen(str);
|
||||||
if (pos < 0)
|
|
||||||
pos = srclen + pos;
|
if (startPos < 0) {
|
||||||
if (length < 0)
|
startPos += len; // start from end
|
||||||
length = srclen - pos + length;
|
if (startPos < 0) startPos = 0;
|
||||||
if (pos >= srclen)
|
}
|
||||||
length = 0;
|
if (length < 0) {
|
||||||
else if (length + pos > srclen)
|
length += len - startPos; // cutoff at end
|
||||||
length = srclen - pos;
|
if (length == 0) {
|
||||||
newstr = new char[length + 1]; // memory leak!!!
|
return "";
|
||||||
if (length > 0)
|
} else if (length < 0) {
|
||||||
memcpy(newstr, &str[pos], length);
|
length = -length; // length can't be negative
|
||||||
newstr[length] = '\0';
|
}
|
||||||
return newstr;
|
}
|
||||||
|
// check position
|
||||||
|
if (startPos >= len) return ""; // start position is out of string length, return empty string
|
||||||
|
if (length == 0 || length + startPos > len) {
|
||||||
|
length = len - startPos; // set the correct length, the length of characters goes beyond the end of the string
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempTextBuf) delete[] tempTextBuf;
|
||||||
|
tempTextBuf = new char[length + 1];
|
||||||
|
memcpy(tempTextBuf, &str[startPos], length);
|
||||||
|
tempTextBuf[length] = '\0';
|
||||||
|
return tempTextBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_substr(OpcodeContext& ctx) {
|
void sf_substr(OpcodeContext& ctx) {
|
||||||
ctx.setReturn(
|
const char* str = ctx.arg(0).strValue();
|
||||||
Substring(ctx.arg(0).strValue(), ctx.arg(1).rawValue(), ctx.arg(2).rawValue())
|
if (*str != '\0') str = Substring(str, ctx.arg(1).rawValue(), ctx.arg(2).rawValue());
|
||||||
);
|
ctx.setReturn(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_string_compare(OpcodeContext& ctx) {
|
void sf_string_compare(OpcodeContext& ctx) {
|
||||||
@@ -225,7 +236,6 @@ void sf_string_compare(OpcodeContext& ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* sprintfbuf = nullptr;
|
|
||||||
// A safer version of sprintf for using in user scripts.
|
// A safer version of sprintf for using in user scripts.
|
||||||
static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
||||||
int fmtlen = strlen(format);
|
int fmtlen = strlen(format);
|
||||||
@@ -290,18 +300,18 @@ static char* _stdcall sprintf_lite(const char* format, ScriptValue value) {
|
|||||||
} else {
|
} else {
|
||||||
buflen = j + 30; // numbers
|
buflen = j + 30; // numbers
|
||||||
}
|
}
|
||||||
if (sprintfbuf) {
|
if (tempTextBuf) {
|
||||||
delete[] sprintfbuf;
|
delete[] tempTextBuf;
|
||||||
}
|
}
|
||||||
sprintfbuf = new char[buflen + 1];
|
tempTextBuf = new char[buflen + 1];
|
||||||
if (value.isFloat()) {
|
if (value.isFloat()) {
|
||||||
_snprintf(sprintfbuf, buflen, newfmt, value.floatValue());
|
_snprintf(tempTextBuf, buflen, newfmt, value.floatValue());
|
||||||
} else {
|
} else {
|
||||||
_snprintf(sprintfbuf, buflen, newfmt, value.rawValue());
|
_snprintf(tempTextBuf, buflen, newfmt, value.rawValue());
|
||||||
}
|
}
|
||||||
sprintfbuf[buflen] = '\0'; // just in case
|
tempTextBuf[buflen] = '\0'; // just in case
|
||||||
delete[] newfmt;
|
delete[] newfmt;
|
||||||
return sprintfbuf;
|
return tempTextBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sf_sprintf(OpcodeContext& ctx) {
|
void sf_sprintf(OpcodeContext& ctx) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace sfall
|
|||||||
namespace script
|
namespace script
|
||||||
{
|
{
|
||||||
|
|
||||||
char* Substring(const char* str, int pos, int length);
|
char* Substring(const char* str, int startPos, int length);
|
||||||
|
|
||||||
class OpcodeContext;
|
class OpcodeContext;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user