////////////////////////////////////////////////////////////////////////// // high level scripting interface ////////////////////////////////////////////////////////////////////////// bool BaseKeyboardState::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { ////////////////////////////////////////////////////////////////////////// // IsKeyDown ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "IsKeyDown") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); int vKey; if (val->_type == VAL_STRING && strlen(val->getString()) > 0) { const char *str = val->getString(); char temp = str[0]; if (temp >= 'A' && temp <= 'Z') { temp += ('a' - 'A'); } vKey = (int)temp; } else { vKey = val->getInt(); } bool isDown = _keyStates[vKeyToKeyCode(vKey)]; stack->pushBool(isDown); return STATUS_OK; } else { return BaseScriptable::scCallMethod(script, stack, thisStack, name); } }
SXDate::SXDate(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { stack->correctParams(6); memset(&_tm, 0, sizeof(_tm)); ScValue *valYear = stack->pop(); _tm.tm_year = valYear->getInt() - 1900; _tm.tm_mon = stack->pop()->getInt() - 1; _tm.tm_mday = stack->pop()->getInt(); _tm.tm_hour = stack->pop()->getInt(); _tm.tm_min = stack->pop()->getInt(); _tm.tm_sec = stack->pop()->getInt(); if (valYear->isNULL()) { g_system->getTimeAndDate(_tm); } }
SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { _string = nullptr; _capacity = 0; stack->correctParams(1); ScValue *val = stack->pop(); if (val->isInt()) { _capacity = MAX(0, val->getInt()); if (_capacity > 0) { _string = new char[_capacity]; memset(_string, 0, _capacity); } } else { setStringVal(val->getString()); } if (_capacity == 0) { setStringVal(""); } }
////////////////////////////////////////////////////////////////////////// // high level scripting interface ////////////////////////////////////////////////////////////////////////// bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { ////////////////////////////////////////////////////////////////////////// // GoTo / GoToAsync ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "GoTo") == 0 || strcmp(name, "GoToAsync") == 0) { stack->correctParams(2); int x = stack->pop()->getInt(); int y = stack->pop()->getInt(); goTo(x, y); if (strcmp(name, "GoToAsync") != 0) { script->waitForExclusive(this); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // GoToObject / GoToObjectAsync ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GoToObject") == 0 || strcmp(name, "GoToObjectAsync") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); if (!val->isNative()) { script->runtimeError("actor.%s method accepts an entity refrence only", name); stack->pushNULL(); return STATUS_OK; } AdObject *obj = (AdObject *)val->getNative(); if (!obj || obj->getType() != OBJECT_ENTITY) { script->runtimeError("actor.%s method accepts an entity refrence only", name); stack->pushNULL(); return STATUS_OK; } AdEntity *ent = (AdEntity *)obj; if (ent->getWalkToX() == 0 && ent->getWalkToY() == 0) { goTo(ent->_posX, ent->_posY); } else { goTo(ent->getWalkToX(), ent->getWalkToY(), ent->getWalkToDir()); } if (strcmp(name, "GoToObjectAsync") != 0) { script->waitForExclusive(this); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // TurnTo / TurnToAsync ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "TurnTo") == 0 || strcmp(name, "TurnToAsync") == 0) { stack->correctParams(1); int dir; ScValue *val = stack->pop(); // turn to object? if (val->isNative() && _gameRef->validObject((BaseObject *)val->getNative())) { BaseObject *obj = (BaseObject *)val->getNative(); int angle = (int)(atan2((double)(obj->_posY - _posY), (double)(obj->_posX - _posX)) * (180 / 3.14)); dir = (int)angleToDirection(angle); } // otherwise turn to direction else { dir = val->getInt(); } if (dir >= 0 && dir < NUM_DIRECTIONS) { turnTo((TDirection)dir); if (strcmp(name, "TurnToAsync") != 0) { script->waitForExclusive(this); } } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // IsWalking ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "IsWalking") == 0) { stack->correctParams(0); stack->pushBool(_state == STATE_FOLLOWING_PATH); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // MergeAnims ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "MergeAnims") == 0) { stack->correctParams(1); stack->pushBool(DID_SUCCEED(mergeAnims(stack->pop()->getString()))); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // UnloadAnim ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "UnloadAnim") == 0) { stack->correctParams(1); const char *animName = stack->pop()->getString(); bool found = false; for (uint32 i = 0; i < _anims.size(); i++) { if (scumm_stricmp(_anims[i]->getName(), animName) == 0) { // invalidate sprites in use if (_anims[i]->containsSprite(_tempSprite2)) { _tempSprite2 = nullptr; } if (_anims[i]->containsSprite(_currentSprite)) { _currentSprite = nullptr; } if (_anims[i]->containsSprite(_animSprite2)) { _animSprite2 = nullptr; } delete _anims[i]; _anims[i] = nullptr; _anims.remove_at(i); i--; found = true; } } stack->pushBool(found); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // HasAnim ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "HasAnim") == 0) { stack->correctParams(1); const char *animName = stack->pop()->getString(); stack->pushBool(getAnimByName(animName) != nullptr); return STATUS_OK; } else { return AdTalkHolder::scCallMethod(script, stack, thisStack, name); } }
bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { ////////////////////////////////////////////////////////////////////////// // Substring ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "Substring") == 0) { stack->correctParams(2); int start = stack->pop()->getInt(); int end = stack->pop()->getInt(); if (end < start) { BaseUtils::swap(&start, &end); } //try { WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } //WideString subStr = str.substr(start, end - start + 1); WideString subStr(str.c_str() + start, end - start + 1); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); } // } catch (std::exception &) { // stack->pushNULL(); // } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Substr ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Substr") == 0) { stack->correctParams(2); int start = stack->pop()->getInt(); ScValue *val = stack->pop(); int len = val->getInt(); if (!val->isNULL() && len <= 0) { stack->pushString(""); return STATUS_OK; } if (val->isNULL()) { len = strlen(_string) - start; } // try { WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } // WideString subStr = str.substr(start, len); WideString subStr(str.c_str() + start, len); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); } // } catch (std::exception &) { // stack->pushNULL(); // } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // ToUpperCase ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ToUpperCase") == 0) { stack->correctParams(0); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } str.toUppercase(); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(str).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(str).c_str()); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // ToLowerCase ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ToLowerCase") == 0) { stack->correctParams(0); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } str.toLowercase(); if (_gameRef->_textEncoding == TEXT_UTF8) { stack->pushString(StringUtil::wideToUtf8(str).c_str()); } else { stack->pushString(StringUtil::wideToAnsi(str).c_str()); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // IndexOf ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "IndexOf") == 0) { stack->correctParams(2); const char *strToFind = stack->pop()->getString(); int index = stack->pop()->getInt(); WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } WideString toFind; if (_gameRef->_textEncoding == TEXT_UTF8) { toFind = StringUtil::utf8ToWide(strToFind); } else { toFind = StringUtil::ansiToWide(strToFind); } int indexOf = StringUtil::indexOf(str, toFind, index); stack->pushInt(indexOf); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Split ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Split") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); char separators[MAX_PATH_LENGTH] = ","; if (!val->isNULL()) { strcpy(separators, val->getString()); } SXArray *array = new SXArray(_gameRef); if (!array) { stack->pushNULL(); return STATUS_OK; } WideString str; if (_gameRef->_textEncoding == TEXT_UTF8) { str = StringUtil::utf8ToWide(_string); } else { str = StringUtil::ansiToWide(_string); } WideString delims; if (_gameRef->_textEncoding == TEXT_UTF8) { delims = StringUtil::utf8ToWide(separators); } else { delims = StringUtil::ansiToWide(separators); } Common::Array<WideString> parts; uint32 start = 0; for(uint32 i = 0; i < str.size() + 1; i++) { char ch = str.c_str()[i]; if(ch=='\0' || delims.contains(ch)) { char *part = new char[i - start + 1]; if(i != start) { Common::strlcpy(part, str.c_str() + start, i - start + 1); part[i - start] = '\0'; } else { part[0] = '\0'; } val = new ScValue(_gameRef, part); array->push(val); delete[] part; delete val; val = nullptr; start = i + 1; } } for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) { WideString &part = (*it); if (_gameRef->_textEncoding == TEXT_UTF8) { val = new ScValue(_gameRef, StringUtil::wideToUtf8(part).c_str()); } else { val = new ScValue(_gameRef, StringUtil::wideToAnsi(part).c_str()); } array->push(val); delete val; val = nullptr; } stack->pushNative(array, false); return STATUS_OK; } else { return STATUS_FAILED; } }
////////////////////////////////////////////////////////////////////////// // high level scripting interface ////////////////////////////////////////////////////////////////////////// bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { ////////////////////////////////////////////////////////////////////////// // PlayAnim / PlayAnimAsync ////////////////////////////////////////////////////////////////////////// if (strcmp(name, "PlayAnim") == 0 || strcmp(name, "PlayAnimAsync") == 0) { stack->correctParams(1); if (DID_FAIL(playAnim(stack->pop()->getString()))) { stack->pushBool(false); } else { if (strcmp(name, "PlayAnimAsync") != 0) { script->waitFor(this); } stack->pushBool(true); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Reset ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Reset") == 0) { stack->correctParams(0); reset(); stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // IsTalking ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "IsTalking") == 0) { stack->correctParams(0); stack->pushBool(_state == STATE_TALKING); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // StopTalk / StopTalking ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "StopTalk") == 0 || strcmp(name, "StopTalking") == 0) { stack->correctParams(0); if (_sentence) { _sentence->finish(); } if (_state == STATE_TALKING) { _state = _nextState; _nextState = STATE_READY; stack->pushBool(true); } else { stack->pushBool(false); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // ForceTalkAnim ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "ForceTalkAnim") == 0) { stack->correctParams(1); const char *animName = stack->pop()->getString(); delete[] _forcedTalkAnimName; _forcedTalkAnimName = new char[strlen(animName) + 1]; strcpy(_forcedTalkAnimName, animName); _forcedTalkAnimUsed = false; stack->pushBool(true); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // Talk / TalkAsync ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "Talk") == 0 || strcmp(name, "TalkAsync") == 0) { stack->correctParams(5); const char *text = stack->pop()->getString(); ScValue *soundVal = stack->pop(); int duration = stack->pop()->getInt(); ScValue *valStances = stack->pop(); const char *stances = valStances->isNULL() ? nullptr : valStances->getString(); int align = 0; ScValue *val = stack->pop(); if (val->isNULL()) { align = TAL_CENTER; } else { align = val->getInt(); } align = MIN(MAX(0, align), NUM_TEXT_ALIGN - 1); const char *sound = soundVal->isNULL() ? nullptr : soundVal->getString(); talk(text, sound, duration, stances, (TTextAlign)align); if (strcmp(name, "TalkAsync") != 0) { script->waitForExclusive(this); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // StickToRegion ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "StickToRegion") == 0) { stack->correctParams(1); AdLayer *main = ((AdGame *)_gameRef)->_scene->_mainLayer; bool regFound = false; uint32 i; ScValue *val = stack->pop(); if (val->isNULL() || !main) { _stickRegion = nullptr; regFound = true; } else if (val->isString()) { const char *regionName = val->getString(); for (i = 0; i < main->_nodes.size(); i++) { if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region->getName() && scumm_stricmp(main->_nodes[i]->_region->getName(), regionName) == 0) { _stickRegion = main->_nodes[i]->_region; regFound = true; break; } } } else if (val->isNative()) { BaseScriptable *obj = val->getNative(); for (i = 0; i < main->_nodes.size(); i++) { if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region == obj) { _stickRegion = main->_nodes[i]->_region; regFound = true; break; } } } if (!regFound) { _stickRegion = nullptr; } stack->pushBool(regFound); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // SetFont ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "SetFont") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); if (val->isNULL()) { setFont(nullptr); } else { setFont(val->getString()); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // GetFont ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GetFont") == 0) { stack->correctParams(0); if (_font && _font->getFilename()) { stack->pushString(_font->getFilename()); } else { stack->pushNULL(); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // TakeItem ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "TakeItem") == 0) { stack->correctParams(2); if (!_inventory) { _inventory = new AdInventory(_gameRef); ((AdGame *)_gameRef)->registerInventory(_inventory); } ScValue *val = stack->pop(); if (!val->isNULL()) { const char *itemName = val->getString(); val = stack->pop(); const char *insertAfter = val->isNULL() ? nullptr : val->getString(); if (DID_FAIL(_inventory->insertItem(itemName, insertAfter))) { script->runtimeError("Cannot add item '%s' to inventory", itemName); } else { // hide associated entities ((AdGame *)_gameRef)->_scene->handleItemAssociations(itemName, false); } } else { script->runtimeError("TakeItem: item name expected"); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // DropItem ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "DropItem") == 0) { stack->correctParams(1); if (!_inventory) { _inventory = new AdInventory(_gameRef); ((AdGame *)_gameRef)->registerInventory(_inventory); } ScValue *val = stack->pop(); if (!val->isNULL()) { if (DID_FAIL(_inventory->removeItem(val->getString()))) { script->runtimeError("Cannot remove item '%s' from inventory", val->getString()); } else { // show associated entities ((AdGame *)_gameRef)->_scene->handleItemAssociations(val->getString(), true); } } else { script->runtimeError("DropItem: item name expected"); } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // GetItem ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GetItem") == 0) { stack->correctParams(1); if (!_inventory) { _inventory = new AdInventory(_gameRef); ((AdGame *)_gameRef)->registerInventory(_inventory); } ScValue *val = stack->pop(); if (val->_type == VAL_STRING) { AdItem *item = ((AdGame *)_gameRef)->getItemByName(val->getString()); if (item) { stack->pushNative(item, true); } else { stack->pushNULL(); } } else if (val->isNULL() || val->getInt() < 0 || val->getInt() >= (int32)_inventory->_takenItems.size()) { stack->pushNULL(); } else { stack->pushNative(_inventory->_takenItems[val->getInt()], true); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // HasItem ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "HasItem") == 0) { stack->correctParams(1); if (!_inventory) { _inventory = new AdInventory(_gameRef); ((AdGame *)_gameRef)->registerInventory(_inventory); } ScValue *val = stack->pop(); if (!val->isNULL()) { for (uint32 i = 0; i < _inventory->_takenItems.size(); i++) { if (val->getNative() == _inventory->_takenItems[i]) { stack->pushBool(true); return STATUS_OK; } else if (scumm_stricmp(val->getString(), _inventory->_takenItems[i]->getName()) == 0) { stack->pushBool(true); return STATUS_OK; } } } else { script->runtimeError("HasItem: item name expected"); } stack->pushBool(false); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // CreateParticleEmitter ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "CreateParticleEmitter") == 0) { stack->correctParams(3); bool followParent = stack->pop()->getBool(); int offsetX = stack->pop()->getInt(); int offsetY = stack->pop()->getInt(); PartEmitter *emitter = createParticleEmitter(followParent, offsetX, offsetY); if (emitter) { stack->pushNative(_partEmitter, true); } else { stack->pushNULL(); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // DeleteParticleEmitter ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "DeleteParticleEmitter") == 0) { stack->correctParams(0); if (_partEmitter) { _gameRef->unregisterObject(_partEmitter); _partEmitter = nullptr; } stack->pushNULL(); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // AddAttachment ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "AddAttachment") == 0) { stack->correctParams(4); const char *filename = stack->pop()->getString(); bool preDisplay = stack->pop()->getBool(true); int offsetX = stack->pop()->getInt(); int offsetY = stack->pop()->getInt(); bool res; AdEntity *ent = new AdEntity(_gameRef); if (DID_FAIL(res = ent->loadFile(filename))) { delete ent; ent = nullptr; script->runtimeError("AddAttachment() failed loading entity '%s'", filename); stack->pushBool(false); } else { _gameRef->registerObject(ent); ent->_posX = offsetX; ent->_posY = offsetY; ent->_active = true; if (preDisplay) { _attachmentsPre.add(ent); } else { _attachmentsPost.add(ent); } stack->pushBool(true); } return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // RemoveAttachment ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "RemoveAttachment") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); bool found = false; if (val->isNative()) { BaseScriptable *obj = val->getNative(); for (uint32 i = 0; i < _attachmentsPre.size(); i++) { if (_attachmentsPre[i] == obj) { found = true; _gameRef->unregisterObject(_attachmentsPre[i]); _attachmentsPre.remove_at(i); i--; } } for (uint32 i = 0; i < _attachmentsPost.size(); i++) { if (_attachmentsPost[i] == obj) { found = true; _gameRef->unregisterObject(_attachmentsPost[i]); _attachmentsPost.remove_at(i); i--; } } } else { const char *attachmentName = val->getString(); for (uint32 i = 0; i < _attachmentsPre.size(); i++) { if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { found = true; _gameRef->unregisterObject(_attachmentsPre[i]); _attachmentsPre.remove_at(i); i--; } } for (uint32 i = 0; i < _attachmentsPost.size(); i++) { if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { found = true; _gameRef->unregisterObject(_attachmentsPost[i]); _attachmentsPost.remove_at(i); i--; } } } stack->pushBool(found); return STATUS_OK; } ////////////////////////////////////////////////////////////////////////// // GetAttachment ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "GetAttachment") == 0) { stack->correctParams(1); ScValue *val = stack->pop(); AdObject *ret = nullptr; if (val->isInt()) { int index = val->getInt(); int currIndex = 0; for (uint32 i = 0; i < _attachmentsPre.size(); i++) { if (currIndex == index) { ret = _attachmentsPre[i]; } currIndex++; } for (uint32 i = 0; i < _attachmentsPost.size(); i++) { if (currIndex == index) { ret = _attachmentsPost[i]; } currIndex++; } } else { const char *attachmentName = val->getString(); for (uint32 i = 0; i < _attachmentsPre.size(); i++) { if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { ret = _attachmentsPre[i]; break; } } if (!ret) { for (uint32 i = 0; i < _attachmentsPost.size(); i++) { if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { ret = _attachmentsPre[i]; break; } } } } if (ret != nullptr) { stack->pushNative(ret, true); } else { stack->pushNULL(); } return STATUS_OK; } else { return BaseObject::scCallMethod(script, stack, thisStack, name); } }