From e3595393c85cbffa4fd604527e747bc701a2d5f4 Mon Sep 17 00:00:00 2001 From: lolbot-iichan Date: Mon, 27 Aug 2018 01:03:43 +0300 Subject: WINTERMUTE: Add FoxTail arrays methods Game.Split(str,sep) is added to split string into array of substrings with separator array.Delete(index) is added to delete an array item by index --- engines/wintermute/base/base_game.cpp | 39 ++++++++++++++++++++++ .../base/scriptables/script_ext_array.cpp | 34 +++++++++++++++++-- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index a0659cac86..16ad1f51a2 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -48,6 +48,7 @@ #include "engines/wintermute/base/base_surface_storage.h" #include "engines/wintermute/base/saveload.h" #include "engines/wintermute/base/save_thumb_helper.h" +#include "engines/wintermute/base/scriptables/script_ext_array.h" #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script_engine.h" #include "engines/wintermute/base/scriptables/script_stack.h" @@ -3114,6 +3115,44 @@ bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack stack->pushBool(val); } +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] Split + // Returns array of words of a string, using another as a delimeter + // Used to split strings by 1 character delimeter in various scripts + // All the delimeters ever used in FoxTail are: " ", "@", "#", "$", "&" + // So, this implementation takes 1st char of delimeter string only + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Split") == 0) { + stack->correctParams(2); + const char *str = stack->pop()->getString(); + const char sep = stack->pop()->getString()[0]; + size_t size = strlen(str) + 1; + + // There is no way to makeSXArray() with exactly 1 given element + // That's why we are creating empty Array and SXArray::push() later + stack->pushInt(0); + BaseScriptable *arr = makeSXArray(_gameRef, stack); + + // Iterating string copy, replacing delimeter with '\0' and pushing matches + char *copy = new char[size]; + strcpy(copy, str); + char *begin = copy; + for (char *it = copy; it < copy + size; it++) { + if (*it == sep || *it == '\0') { + *it = '\0'; + stack->pushString(begin); + ((SXArray *)arr)->push(stack->pop()); + begin = it + 1; + } + } + + stack->pushNative(arr, false); + + delete[] copy; + } +#endif + ////////////////////////////////////////////////////////////////////////// // failure else { diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp index 7431029cbf..05effd991e 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -118,8 +118,7 @@ bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, ////////////////////////////////////////////////////////////////////////// // Pop ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Pop") == 0) { - + else if (strcmp(name, "Pop") == 0) { stack->correctParams(0); if (_length > 0) { @@ -133,7 +132,36 @@ bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, } return STATUS_OK; - } else { + } + +#ifdef ENABLE_FOXTAIL + ////////////////////////////////////////////////////////////////////////// + // [FoxTail] Delete + // Removes item from array by index, shifting other elements + // Used to shuffle arrays and delete found items in various scripts + // Return value is never used + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Delete") == 0) { + stack->correctParams(1); + + int shiftPoint = stack->pop()->getInt(0); + char paramNameFrom[20]; + char paramNameTo[20]; + + for (int i = shiftPoint; i < _length - 1 ; i++) { + sprintf(paramNameFrom, "%d", i + 1); + sprintf(paramNameTo, "%d", i); + _values->setProp(paramNameTo, _values->getProp(paramNameFrom), false); + } + _values->deleteProp(paramNameFrom); + _length--; + stack->pushNULL(); + + return STATUS_OK; + } +#endif + + else { return STATUS_FAILED; } } -- cgit v1.2.3