/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "got/game/script.h" #include "common/textconsole.h" #include "got/events.h" #include "got/game/back.h" #include "got/game/main.h" #include "got/game/object.h" #include "got/game/status.h" #include "got/gfx/image.h" #include "got/utils/file.h" #include "got/vars.h" #include "got/views/dialogs/ask.h" #include "got/views/dialogs/say.h" namespace Got { #define ERROR_MAX 10 #define SCR_BUFF_SIZE 5000 static const char *SCR_COMMAND[] = { "!@#$%", "END", "GOTO", "GOSUB", "RETURN", "FOR", "NEXT", "IF", "ELSE", "RUN", "ADDJEWELS", "ADDHEALTH", "ADDMAGIC", "ADDKEYS", "ADDSCORE", "SAY", "ASK", "SOUND", "PLACETILE", "ITEMGIVE", "ITEMTAKE", "ITEMSAY", "SETFLAG", "LTOA", "PAUSE", "TEXT", "EXEC", "VISIBLE", "RANDOM", nullptr}; static const char *INTERNAL_VARIABLE[] = { "@JEWELS", "@HEALTH", "@MAGIC", "@SCORE", "@SCREEN", "@KEYS", "@OW", "@GULP", "@SWISH", "@YAH", "@ELECTRIC", "@THUNDER", "@DOOR", "@FALL", "@ANGEL", "@WOOP", "@DEAD", "@BRAAPP", "@WIND", "@PUNCH", "@CLANG", "@EXPLODE", "@FLAG", "@ITEM", "@THORTILE", "@THORPOS", nullptr}; static const char *SCR_ERROR[] = { "!@#$%", "Out of Memory", "Can't Read Script", "Too Many Labels", "No END", "Syntax", "Out of Range", "Undefined Label", "RETURN Without GOSUB", "Nesting", "NEXT Without FOR", nullptr}; static const char *OFFENSE[] = { "Cussing", "Rebellion", "Kissing Your Mother Goodbye", "Being a Thunder God", "Door-to-Door Sales", "Carrying a Concealed Hammer"}; static const char *REASON[] = { "We heard you say 'Booger'.", "You look kind of rebellious.", "Your mother turned you in.", "We don't want you here.", "Nobody wants your sweepers.", "That's a dangerous weapon."}; Scripts::ScrFunction Scripts::scr_func[5] = { &Scripts::scr_func1, &Scripts::scr_func2, &Scripts::scr_func3, &Scripts::scr_func4, &Scripts::scr_func5 }; Scripts *g_scripts; void executeScript(long index, const Gfx::Pics &speakerIcon, ScriptEndFn endFn) { g_scripts->executeScript(index, speakerIcon, endFn); } Scripts::Scripts() { g_scripts = this; } Scripts::~Scripts() { g_scripts = nullptr; } void Scripts::executeScript(long index, const Gfx::Pics &speakerIcon, ScriptEndFn endFn) { // Firstly disable any on-screen actors for (int i = 0; i < MAX_ACTORS; i++) _G(actor[i])._show = 0; _endFn = endFn; _scrIndex = index; _scrPic = speakerIcon; Common::fill(_numVar, _numVar + 26, 0); Common::fill((char *)_strVar, (char *)_strVar + 81 * 26, 0); runScript(); } void Scripts::runScript(bool firstTime) { // Clear line label buffer, line ptrs, and the gosub stack Common::fill((char *)_lineLabel, (char *)_lineLabel + 32 * 9, 0); Common::fill(_linePtr, _linePtr + 32, (char *)nullptr); Common::fill(_gosubStack, _gosubStack + 32, (char *)nullptr); _gosubPtr = 0; Common::fill(_forVar, _forVar + 11, 0); Common::fill(_forVal, _forVal + 11, 0); Common::fill(_forStack, _forStack + 11, (char *)nullptr); _forPtr = 0; int i = readScriptFile(); if (i != 0) { scriptError(i); scriptExit(); return; } if (firstTime) scriptEntry(); _buffPtr = _buffer; scriptLoop(); } void Scripts::scriptLoop() { while (_paused == SCRIPT_READY) { if (_G(cheat) && _G(keyFlag[GOT_B])) break; int ret = getCommand(); if (ret == -1) break; // Ignore NO END error if (ret == -2) { scriptError(5); // Syntax error break; } if (ret > 0) { ret = execCommand(ret); if (ret == -100) { // RUN command if (_buffer) free(_buffer); runScript(false); return; } if (!ret) break; } } if (_paused == SCRIPT_READY) scriptExit(); } void Scripts::scriptExit() { if (_buffer) { free(_buffer); _buffer = nullptr; } if (_endFn) _endFn(); } int Scripts::skipColon() { while (*_buffPtr == 0 || *_buffPtr == ':') { _buffPtr++; if (_buffPtr > _buffEnd) return 0; } return 1; } int Scripts::getCommand() { if (!skipColon()) return -1; int i = 0; while (true) { if (!SCR_COMMAND[i]) break; // Lookup command int len = strlen(SCR_COMMAND[i]); if (!strncmp(_buffPtr, SCR_COMMAND[i], len)) { _buffPtr += len; return i; } i++; } if (Common::isAlpha(*_buffPtr)) { int ret; if (*(_buffPtr + 1) == '=') { // Num var assignment i = (*_buffPtr) - 65; _buffPtr += 2; ret = calcValue(); if (!ret) return -2; _numVar[i] = _lValue; return 0; } if (*(_buffPtr + 1) == '$' && *(_buffPtr + 2) == '=') { i = (*_buffPtr) - 65; _buffPtr += 3; ret = calcString(0); // String var assignment if (ret == 0) return -2; if (ret == -1) return -3; if (strlen(_tempS) > 80) return -3; Common::strcpy_s(_strVar[i], _tempS); return 0; } } return -2; } int Scripts::calcString(int mode) { // if mode==1 stop at comma char varString[255]; uint varNumber; Common::strcpy_s(varString, ""); if (!skipColon()) return 0; strloop: if (*_buffPtr == '"') { getStr(); if (strlen(varString) + strlen(_tempS) < 255) Common::strcat_s(varString, _tempS); goto nextstr; } if (Common::isAlpha(*_buffPtr)) { if (*(_buffPtr + 1) == '$') { varNumber = (*_buffPtr) - 65; if (strlen(varString) + strlen(_strVar[varNumber]) < 255) Common::strcat_s(varString, _strVar[varNumber]); _buffPtr += 2; goto nextstr; } } return 0; nextstr: if (*_buffPtr == 0 || *_buffPtr == 58) { _buffPtr++; goto strdone; } if (*_buffPtr == ',' && mode == 1) goto strdone; if (*_buffPtr == '+') { _buffPtr++; goto strloop; } return 0; strdone: Common::strcpy_s(_tempS, (char *)varString); return 1; } void Scripts::getStr() { _buffPtr++; int t = 0; while (true) { if (*_buffPtr == '"' || *_buffPtr == 0) { _tempS[t] = 0; if (*_buffPtr == '"') _buffPtr++; return; } _tempS[t++] = *_buffPtr; _buffPtr++; } } int Scripts::calcValue() { long tmpVal2 = 0; char expType = 1; while (true) { if (!getNextValue()) return 0; switch (expType) { case 0: tmpVal2 = tmpVal2 * _lTemp; break; case 1: tmpVal2 = tmpVal2 + _lTemp; break; case 2: tmpVal2 = tmpVal2 - _lTemp; break; case 3: if (_lTemp != 0) tmpVal2 = tmpVal2 / _lTemp; break; default: break; } const char ch = *_buffPtr; switch (ch) { case 42: expType = 0; /* multiply */ break; case 43: expType = 1; /* add */ break; case 45: expType = 2; /* minus */ break; case 47: expType = 3; /* divide */ break; default: _lValue = tmpVal2; return 1; } _buffPtr++; } } int Scripts::getNextValue() { const char ch = *_buffPtr; if (ch == 0 || ch == ':') return 0; if (ch == 64) return getInternalVariable(); if (Common::isAlpha(ch)) { _buffPtr++; _lTemp = _numVar[ch - 65]; return 1; } if (strchr("0123456789-", ch)) { char tmpString[25]; int tmpIndex = 0; tmpString[tmpIndex] = ch; _buffPtr++; tmpIndex++; while (strchr("0123456789", *_buffPtr) && *_buffPtr != 0) { tmpString[tmpIndex] = *_buffPtr; _buffPtr++; tmpIndex++; } tmpString[tmpIndex] = 0; if (tmpIndex > 10) return 0; _lTemp = atol(tmpString); return 1; } return 0; } int Scripts::getInternalVariable() { int i = 0; while (true) { if (!INTERNAL_VARIABLE[i]) return 0; // Lookup internal variable const int len = strlen(INTERNAL_VARIABLE[i]); if (!strncmp(_buffPtr, INTERNAL_VARIABLE[i], len)) { _buffPtr += len; break; } i++; } switch (i) { case 0: _lTemp = _G(thorInfo)._jewels; break; case 1: _lTemp = _G(thor)->_health; break; case 2: _lTemp = _G(thorInfo)._magic; break; case 3: _lTemp = _G(thorInfo)._score; break; case 4: _lTemp = _G(currentLevel); break; case 5: _lTemp = _G(thorInfo)._keys; break; case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: _lTemp = (long)(i - 5l); break; case 22: if (!calcValue()) return 0; i = (int)_lValue; if (i < 1 || i > 64) return 0; _lTemp = _G(setup)._flags[i - 1] ? 1 : 0; break; case 23: if (_G(thorInfo)._inventory & 64) _lTemp = _G(thorInfo)._object; else _lTemp = 0; break; case 24: _lTemp = _G(scrn)._iconGrid[(_G(thor)->_y + 8) / 16][(_G(thor)->_x + 7) / 16]; break; case 25: _lTemp = (((_G(thor)->_y + 8) / 16) * 20) + ((_G(thor)->_x + 7) / 16); break; default: return 0; } return 1; } int Scripts::getLine(char *src, char *dst) { int cnt = 0; if (!src) return cnt; while (*src != 13) { if (*src != 10) { *dst = *src; dst++; } cnt++; src++; } *dst = 0; cnt++; return cnt; } int Scripts::readScriptFile() { char tmpBuffer[255]; char quoteFlag; int len, p, ret, cnt; Common::String str; char tmps[255]; char *sbuff = nullptr; char *sb; _buffer = (char *)malloc(SCR_BUFF_SIZE); if (!_buffer) { ret = 1; goto done; }; _buffPtr = _buffer; Common::fill(_buffer, _buffer + SCR_BUFF_SIZE, 0); sbuff = (char *)malloc(25000l); sb = sbuff; if (!sb) { ret = 1; goto done; }; str = Common::String::format("SPEAK%d", _G(area)); if (resourceRead(str.c_str(), sb) < 0) { ret = 6; goto done; } str = Common::String::format("|%ld", _scrIndex); Common::strcpy_s(tmpBuffer, str.c_str()); while (true) { cnt = getLine(sb, (char *)tmps); sb += cnt; if (!strcmp(tmps, "|EOF")) { ret = 2; goto done; } if (!strcmp(tmps, tmpBuffer)) break; } _numLabels = 0; while (true) { cnt = getLine(sb, (char *)tmps); if (!strcmp(tmps, "|STOP")) { if (_buffPtr != _buffer) { _buffEnd = _buffPtr; ret = 0; goto done; } ret = 2; goto done; } sb += cnt; len = strlen(tmps); if (len < 2) { *_buffPtr = 0; _buffPtr++; continue; } quoteFlag = 0; p = 0; for (int i = 0; i < len; i++) { char ch = tmps[i]; if (ch == 34) quoteFlag ^= 1; else if (ch == 13 || ch == 10) { // Check for CR tmpBuffer[p] = 0; break; } if ((ch == 39 || ch == 96) && !quoteFlag) { tmpBuffer[p] = 0; break; } if (!quoteFlag) ch = toupper(ch); if (quoteFlag || ch > 32) { tmpBuffer[p++] = ch; } } tmpBuffer[p] = 0; len = strlen(tmpBuffer); if (len > 0 && len < 10 && tmpBuffer[len - 1] == ':') { //line label tmpBuffer[len - 1] = 0; _linePtr[_numLabels] = _buffPtr; Common::strcpy_s(_lineLabel[_numLabels++], (char *)tmpBuffer); if (_numLabels > 31) { ret = 3; goto done; } *_buffPtr = 0; _buffPtr++; continue; } Common::strcpy_s(_buffPtr, SCR_BUFF_SIZE, tmpBuffer); _buffPtr += strlen(tmpBuffer); *_buffPtr = 0; _buffPtr++; } done: if (sbuff) free(sbuff); return ret; } void Scripts::scriptError(int err_num) { int lineNum = 1; char *tb = _buffer; while (1) { if (*tb == 0) lineNum++; if (tb >= _buffPtr) break; tb++; } if (err_num > ERROR_MAX) err_num = 5; // Unknown=syntax warning("%s in Line #%d", SCR_ERROR[err_num], lineNum); } int Scripts::cmd_goto() { char s[255]; Common::strcpy_s(s, _buffPtr); char *p = strchr(s, ':'); if (p) *p = 0; for (int i = 0; i < _numLabels; i++) { int len = strlen(s); if (len == 0) break; if (!strcmp(s, _lineLabel[i])) { _newPtr = _linePtr[i]; _buffPtr += len; return 0; } } return 8; } int Scripts::cmd_if() { if (!calcValue()) return 5; const long tmpVal1 = _lValue; char expType = *_buffPtr; _buffPtr++; const char ch = *_buffPtr; if (ch == 60 || ch == 61 || ch == 62) { if (expType == *_buffPtr) return 5; expType += *_buffPtr; _buffPtr++; } if (!calcValue()) return 5; const long tmpVal2 = _lValue; _buffPtr += 4; switch (expType) { case 60: /* less than */ if (tmpVal1 < tmpVal2) goto iftrue; goto iffalse; case 61: /* equal */ if (tmpVal1 == tmpVal2) goto iftrue; goto iffalse; case 62: /* greater than */ if (tmpVal1 > tmpVal2) goto iftrue; goto iffalse; case 121: /* less than or equal */ if (tmpVal1 <= tmpVal2) goto iftrue; goto iffalse; case 122: /* less or greater (not equal) */ if (tmpVal1 != tmpVal2) goto iftrue; goto iffalse; case 123: /* greater than or equal */ if (tmpVal1 >= tmpVal2) goto iftrue; goto iffalse; default: return 5; } iffalse: while (*_buffPtr != 0) _buffPtr++; while (*_buffPtr == 0) _buffPtr++; if (!strncmp(_buffPtr, "ELSE", 4)) _buffPtr += 4; iftrue: return 0; } int Scripts::cmd_run() { if (!calcValue()) return 5; _buffPtr++; _scrIndex = _lValue; return -100; } int Scripts::cmd_addJewels() { if (!calcValue()) return 5; _buffPtr++; addJewels(_lValue); return 0; } int Scripts::cmd_addHealth() { if (!calcValue()) return 5; _buffPtr++; addHealth((int)_lValue); return 0; } int Scripts::cmd_addMagic() { if (!calcValue()) return 5; _buffPtr++; addMagic((int)_lValue); return 0; } int Scripts::cmd_addKeys() { if (!calcValue()) return 5; _buffPtr++; addKeys((int)_lValue); return 0; } int Scripts::cmd_addScore() { if (!calcValue()) return 5; _buffPtr++; addScore((int)_lValue); return 0; } int Scripts::cmd_say(int mode, int type) { int obj = 0; if (mode) { if (!calcValue()) return 5; _buffPtr++; obj = (int)_lValue; if (obj < 0 || obj > 32) return 6; if (obj) obj += 10; } Common::fill(_G(tmpBuff), _G(tmpBuff) + TMP_SIZE, 0); char *p = (char *)_G(tmpBuff); while (calcString(0)) { Common::strcpy_s(p, TMP_SIZE, _tempS); p += strlen(_tempS); *(p) = 10; p++; } *(p - 1) = 0; pause(); Views::Dialogs::Say::show(obj, _scrPic, type); return 0; } int Scripts::cmd_ask() { int v = 0; char title[41], opt[41]; Common::StringArray opts; memset(_G(tmpBuff), 0, TMP_SIZE); if (!skipColon()) return 5; if (Common::isAlpha(*_buffPtr)) { v = *_buffPtr - 65; _buffPtr++; if (*_buffPtr != ',') return 5; _buffPtr++; } else { return 5; } if (!calcString(1)) return 5; strncpy(title, _tempS, 41); title[40] = 0; if (*_buffPtr == ',') { _buffPtr++; if (!calcValue()) return 5; _buffPtr++; } else { return 5; } _askVar = v; while (calcString(0)) { Common::strcpy_s(opt, _tempS); opts.push_back(opt); if (opts.size() > 9) return 3; } // Pause the script execution, and open up an ask window. // Execution of the script will resume after a selection. pause(); Views::Dialogs::Ask::show(title, opts); return 0; } void Scripts::pause() { _paused = SCRIPT_PAUSED; } void Scripts::resume() { _paused = SCRIPT_RESUMING; } void Scripts::setAskResponse(int option) { _numVar[_askVar] = option; resume(); } void Scripts::runIfResuming() { if (_paused == SCRIPT_RESUMING) { _paused = SCRIPT_READY; scriptLoop(); } } int Scripts::cmd_sound() { if (!calcValue()) return 5; _buffPtr++; if (_lValue < 1 || _lValue > 16) return 6; playSound((int)_lValue - 1, true); return 0; } int Scripts::cmd_setTile() { if (!calcValue()) return 5; _buffPtr++; const int screen = (int)_lValue; if (!calcValue()) return 5; _buffPtr++; const int pos = (int)_lValue; if (!calcValue()) return 5; const int tile = (int)_lValue; if (screen < 0 || screen > 119) return 6; if (pos < 0 || pos > 239) return 6; if (tile < 0 || tile > 230) return 6; if (screen == _G(currentLevel)) { placeTile(pos % 20, pos / 20, tile); } else { Level tmp; tmp.load(screen); tmp._iconGrid[pos / 20][pos % 20] = tile; tmp.save(screen); } return 0; } int Scripts::cmd_itemGive() { if (!calcValue()) return 5; _buffPtr++; int i = (int)_lValue; if (i < 1 || i > 15) return 6; _G(thorInfo)._inventory |= 64; _G(thorInfo)._selectedItem = 7; _G(thorInfo)._object = i; _G(thorInfo)._objectName = OBJECT_NAMES[_G(thorInfo)._object - 1]; return 0; } int Scripts::cmd_itemTake() { deleteObject(); return 0; } int Scripts::cmd_setFlag() { if (!calcValue()) return 5; int i = (int)_lValue; if (i < 1 || i > 64) return 6; _G(setup)._flags[i - 1] = true; return 0; } int Scripts::cmd_ltoa() { int sv; if (!calcValue()) return 5; _buffPtr++; if (Common::isAlpha(*_buffPtr)) { if (*(_buffPtr + 1) == '$') { sv = (*_buffPtr) - 65; _buffPtr += 2; } else { return 5; } } else { return 5; } Common::String str = Common::String::format("%ld", _lValue); Common::strcpy_s(_strVar[sv], str.c_str()); return 0; } int Scripts::cmd_pause() { if (!calcValue()) return 5; _buffPtr++; if (_lValue < 1 || _lValue > 65535l) return 6; Got::pause((int)_lValue); return 0; } int Scripts::cmd_visible() { if (!calcValue()) return 5; _buffPtr++; if (_lValue < 1 || _lValue > 16) return 6; actorVisible((int)_lValue); return 0; } int Scripts::cmd_random() { int v; if (Common::isAlpha(*_buffPtr)) { v = *_buffPtr - 65; _buffPtr++; if (*_buffPtr != ',') return 5; _buffPtr++; } else { return 5; } if (!calcValue()) return 5; _buffPtr++; int r = (int)_lValue; if (r < 1 || r > 1000) return 6; _numVar[v] = g_events->getRandomNumber(r - 1); return 0; } void Scripts::scr_func1() { playSound(FALL, true); _G(newLevel) = 109; _G(newLevelTile) = 215; _G(thor)->_x = (_G(newLevelTile) % 20) * 16; _G(thor)->_y = ((_G(newLevelTile) / 20) * 16) - 2; _G(thor)->_lastX[0] = _G(thor)->_x; _G(thor)->_lastX[1] = _G(thor)->_x; _G(thor)->_lastY[0] = _G(thor)->_y; _G(thor)->_lastY[1] = _G(thor)->_y; _G(thor)->_show = 2; } void Scripts::scr_func2() { int r = g_events->getRandomNumber(5); Common::strcpy_s(_strVar[0], 81, OFFENSE[r]); Common::strcpy_s(_strVar[1], 81, REASON[r]); } void Scripts::scr_func3() { int p = (((_G(thor)->_y + 8) / 16) * 20) + ((_G(thor)->_x + 7) / 16); int y = p / 20; int x = p % 20; if (y < 0 || x < 0 || y > 11) { playSound(BRAAPP, true); _G(keyFlag[key_magic]) = false; return; } if (_G(scrn)._iconGrid[y][x] < 174 || _G(scrn)._iconGrid[y][x] > 178) { playSound(BRAAPP, true); _G(keyFlag[key_magic]) = false; return; } _numVar[0] = 1; playSound(WOOP, true); if (_G(currentLevel) == 106 && p == 69) { placeTile(x, y, 220); _G(keyFlag[key_magic]) = false; return; } _G(keyFlag[key_magic]) = false; placeTile(x, y, 191); if ((g_events->getRandomNumber(99)) < 25 || (_G(currentLevel) == 13 && p == 150 && !_G(setup).f26 && _G(setup).f28)) { if (!_G(objectMap[p]) && _G(scrn)._iconGrid[y][x] >= 140) { // nothing there and solid int o = g_events->getRandomNumber(1, 5); if (_G(currentLevel) == 13 && p == 150 && !_G(setup).f26 && _G(setup).f28) o = 20; _G(objectMap[p]) = o; _G(objectIndex[p]) = 31; // actor is 3-15 } } } void Scripts::scr_func4() { _G(thunderSnakeCounter) = 60; } void Scripts::scr_func5() { _G(scrn)._actorLoc[0] -= 2; _G(scrn)._actorLoc[1] -= 2; _G(scrn)._actorLoc[2] -= 2; _G(scrn)._actorLoc[3] -= 2; _G(actor[3])._i1 = 16; } int Scripts::cmd_exec() { if (!calcValue()) return 5; _buffPtr++; if (_lValue < 1 || _lValue > 10) return 6; if (_lValue > 5) { error("cmd_exec - unhandled lValue %ld", _lValue); } (this->*scr_func[_lValue - 1])(); return 0; } int Scripts::execCommand(int num) { char ch; int ret = 0; switch (num) { case 1: // end return 0; case 2: // goto ret = cmd_goto(); if (!ret) _buffPtr = _newPtr; break; case 3: // gosub ret = cmd_goto(); if (!ret) { _gosubPtr++; if (_gosubPtr > 31) { ret = 10; break; } _gosubStack[_gosubPtr] = _buffPtr; _buffPtr = _newPtr; } break; case 4: // return if (!_gosubPtr) { ret = 9; break; } _buffPtr = _gosubStack[_gosubPtr--]; break; case 5: // for _forPtr++; if (_forPtr > 10) { ret = 10; break; } ch = *_buffPtr; if (!Common::isAlpha(ch)) { ret = 5; break; } ch -= 65; _forVar[_forPtr] = ch; _buffPtr += 2; if (!calcValue()) { ret = 5; break; } _numVar[_forVar[_forPtr]] = _lValue; _buffPtr += 2; if (!calcValue()) { ret = 5; break; } _forVal[_forPtr] = _lValue; _forStack[_forPtr] = _buffPtr; break; case 6: // next if (!_forPtr) { ret = 11; break; } _numVar[_forVar[_forPtr]] = _numVar[_forVar[_forPtr]] + 1; if (_numVar[_forVar[_forPtr]] <= _forVal[_forPtr]) _buffPtr = _forStack[_forPtr]; else _forPtr--; break; case 7: // if ret = cmd_if(); break; case 8: // else while (*_buffPtr != 0) _buffPtr++; break; case 9: // run ret = cmd_run(); if (ret < 0) return -100; break; case 10: // addjewels ret = cmd_addJewels(); break; case 11: // addhealth ret = cmd_addHealth(); break; case 12: // addmagic ret = cmd_addMagic(); break; case 13: // addkeys ret = cmd_addKeys(); break; case 14: // addscore ret = cmd_addScore(); break; case 15: // say ret = cmd_say(0, 1); break; case 16: // ask ret = cmd_ask(); break; case 17: // sound ret = cmd_sound(); break; case 18: // settile ret = cmd_setTile(); break; case 19: // itemgive ret = cmd_itemGive(); break; case 20: // itemtake ret = cmd_itemTake(); break; case 21: // itemsay ret = cmd_say(1, 1); break; case 22: // setflag ret = cmd_setFlag(); break; case 23: // ltoa ret = cmd_ltoa(); break; case 24: // pause ret = cmd_pause(); break; case 25: // text ret = cmd_say(0, 0); break; case 26: // exec ret = cmd_exec(); break; case 27: // visible ret = cmd_visible(); break; case 28: // random ret = cmd_random(); break; default: ret = 5; } if (ret > 0) { scriptError(ret); return 0; } return 1; } } // namespace Got