diff options
Diffstat (limited to 'src/map/script.cpp')
-rw-r--r-- | src/map/script.cpp | 2736 |
1 files changed, 1230 insertions, 1506 deletions
diff --git a/src/map/script.cpp b/src/map/script.cpp index 6d65fd2..7281784 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -12,6 +12,7 @@ #include "../common/cxxstdio.hpp" #include "../common/db.hpp" #include "../common/extract.hpp" +#include "../common/intern-pool.hpp" #include "../common/lock.hpp" #include "../common/random.hpp" #include "../common/socket.hpp" @@ -35,49 +36,33 @@ #include "../poison.hpp" -//#define DEBUG_FUNCIN -//#define DEBUG_DISP -//#define DEBUG_RUN +constexpr bool DEBUG_DISP = false; +constexpr bool DEBUG_RUN = false; -constexpr int SCRIPT_BLOCK_SIZE = 256; -enum -{ LABEL_NEXTLINE = 1, LABEL_START }; -static -ScriptCode *script_buf; -static -int script_pos, script_size; - -static -char *str_buf; -static -int str_pos, str_size; -static struct str_data_t { - ScriptCode type; - int str; + ByteCode type; + std::string strs; int backpatch; - int label; - void(*func)(ScriptState *); + int label_; int val; - int next; -} *str_data; +}; static -int str_num = LABEL_START, str_data_size; +Map<std::string, str_data_t> str_datam; static -int str_hash[16]; +str_data_t LABEL_NEXTLINE_; static DMap<int, int> mapreg_db; static -DMap<int, char *> mapregstr_db; +Map<int, std::string> mapregstr_db; static int mapreg_dirty = -1; char mapreg_txt[256] = "save/mapreg.txt"; constexpr std::chrono::milliseconds MAPREG_AUTOSAVE_INTERVAL = std::chrono::seconds(10); Map<std::string, int> scriptlabel_db; -DMap<std::string, const ScriptCode *> userfunc_db; +UPMap<std::string, const ScriptBuffer> userfunc_db; static const char *pos[11] = @@ -108,14 +93,7 @@ struct Script_Config static int parse_cmd_if = 0; static -int parse_cmd; - -/*========================================== - * ローカルプロトタイプ宣言 (必要な物のみ) - *------------------------------------------ - */ -static -const char *parse_subexpr(const char *, int); +str_data_t *parse_cmdp; static void run_func(ScriptState *st); @@ -127,172 +105,84 @@ void mapreg_setregstr(int num, const char *str); struct BuiltinFunction { - void(*func)(ScriptState *); + void (*func)(ScriptState *); const char *name; const char *arg; }; // defined later extern BuiltinFunction builtin_functions[]; +static +InternPool variable_names; -enum class ScriptCode : uint8_t +enum class ByteCode : uint8_t { // types and specials - NOP, POS, INT, PARAM, FUNC, STR, CONSTSTR, ARG, - NAME, EOL, RETINFO, + NOP, POS, INT, PARAM_, FUNC_, STR, CONSTSTR, ARG, + VARIABLE, EOL, RETINFO, // unary and binary operators LOR, LAND, LE, LT, GE, GT, EQ, NE, - XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, NEG, LNOT, - NOT, R_SHIFT, L_SHIFT -}; + XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, + NEG, LNOT, NOT, R_SHIFT, L_SHIFT, -/*========================================== - * 文字列のハッシュを計算 - *------------------------------------------ - */ -static -int calc_hash(const char *s) -{ - const unsigned char *p = (const unsigned char *)s; - int h = 0; - while (*p) - { - h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8); - h += *p++; - } - return h & 15; -} + // additions + // needed because FUNC is used for the actual call + FUNC_REF, +}; -/*========================================== - * str_dataの中に名前があるか検索する - *------------------------------------------ - */ -// 既存のであれば番号、無ければ-1 static -int search_str(const char *p) +str_data_t *search_strp(const std::string& p) { - int i; - i = str_hash[calc_hash(p)]; - while (i) - { - if (strcmp(str_buf + str_data[i].str, p) == 0) - { - return i; - } - i = str_data[i].next; - } - return -1; + return str_datam.search(p); } -/*========================================== - * str_dataに名前を登録 - *------------------------------------------ - */ -// 既存のであれば番号、無ければ登録して新規番号 static -int add_str(const char *p) +str_data_t *add_strp(const std::string& p) { - int i; - char *lowcase; - // TODO remove lowcase - lowcase = strdup(p); - for (i = 0; lowcase[i]; i++) - lowcase[i] = tolower(lowcase[i]); - if ((i = search_str(lowcase)) >= 0) - { - free(lowcase); - return i; - } - free(lowcase); + std::string lowcase = p; + for (char& c : lowcase) + c = tolower(c); - i = calc_hash(p); - if (str_hash[i] == 0) - { - str_hash[i] = str_num; - } - else - { - i = str_hash[i]; - for (;;) - { - if (strcmp(str_buf + str_data[i].str, p) == 0) - { - return i; - } - if (str_data[i].next == 0) - break; - i = str_data[i].next; - } - str_data[i].next = str_num; - } - if (str_num >= str_data_size) - { - str_data_size += 128; - RECREATE(str_data, struct str_data_t, str_data_size); - memset(str_data + (str_data_size - 128), '\0', 128); - } - while (str_pos + strlen(p) + 1 >= str_size) - { - str_size += 256; - str_buf = (char *) realloc(str_buf, str_size); - memset(str_buf + (str_size - 256), '\0', 256); - } - strcpy(str_buf + str_pos, p); - str_data[str_num].type = ScriptCode::NOP; - str_data[str_num].str = str_pos; - str_data[str_num].next = 0; - str_data[str_num].func = NULL; - str_data[str_num].backpatch = -1; - str_data[str_num].label = -1; - str_pos += strlen(p) + 1; - return str_num++; -} + if (str_data_t *rv = search_strp(lowcase)) + return rv; -/*========================================== - * スクリプトバッファサイズの確認と拡張 - *------------------------------------------ - */ -static -void check_script_buf(int size) -{ - if (script_pos + size >= script_size) - { - script_size += SCRIPT_BLOCK_SIZE; - script_buf = (ScriptCode *) realloc(script_buf, script_size); - memset(script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0', - SCRIPT_BLOCK_SIZE); - } + // ? + if (str_data_t *rv = search_strp(p)) + return rv; + + str_data_t *datum = str_datam.init(p); + datum->type = ByteCode::NOP; + datum->strs = p; + datum->backpatch = -1; + datum->label_ = -1; + return datum; } /*========================================== * スクリプトバッファに1バイト書き込む *------------------------------------------ */ -static -void add_scriptc(ScriptCode a) +void ScriptBuffer::add_scriptc(ByteCode a) { - check_script_buf(1); - script_buf[script_pos++] = a; + script_buf.push_back(a); } /*========================================== * スクリプトバッファにデータタイプを書き込む *------------------------------------------ */ -static -void add_scriptb(uint8_t a) +void ScriptBuffer::add_scriptb(uint8_t a) { - add_scriptc(static_cast<ScriptCode>(a)); + add_scriptc(static_cast<ByteCode>(a)); } /*========================================== * スクリプトバッファに整数を書き込む *------------------------------------------ */ -static -void add_scripti(unsigned int a) +void ScriptBuffer::add_scripti(uint32_t a) { while (a >= 0x40) { @@ -307,37 +197,43 @@ void add_scripti(unsigned int a) *------------------------------------------ */ // 最大16Mまで -static -void add_scriptl(int l) +void ScriptBuffer::add_scriptl(str_data_t *ld) { - int backpatch = str_data[l].backpatch; + int backpatch = ld->backpatch; - switch (str_data[l].type) + switch (ld->type) { - case ScriptCode::POS: - add_scriptc(ScriptCode::POS); - add_scriptb({uint8_t(str_data[l].label)}); - add_scriptb({uint8_t(str_data[l].label >> 8)}); - add_scriptb({uint8_t(str_data[l].label >> 16)}); + case ByteCode::POS: + add_scriptc(ByteCode::POS); + add_scriptb(static_cast<uint8_t>(ld->label_)); + add_scriptb(static_cast<uint8_t>(ld->label_ >> 8)); + add_scriptb(static_cast<uint8_t>(ld->label_ >> 16)); break; - case ScriptCode::NOP: - // ラベルの可能性があるのでbackpatch用データ埋め込み - add_scriptc(ScriptCode::NAME); - str_data[l].backpatch = script_pos; - add_scriptb({uint8_t(backpatch)}); - add_scriptb({uint8_t(backpatch >> 8)}); - add_scriptb({uint8_t(backpatch >> 16)}); + case ByteCode::NOP: + // need to set backpatch, because it might become a label later + add_scriptc(ByteCode::VARIABLE); + ld->backpatch = script_buf.size(); + add_scriptb(static_cast<uint8_t>(backpatch)); + add_scriptb(static_cast<uint8_t>(backpatch >> 8)); + add_scriptb(static_cast<uint8_t>(backpatch >> 16)); break; - case ScriptCode::INT: - add_scripti(str_data[l].val); + case ByteCode::INT: + add_scripti(ld->val); break; - default: - // もう他の用途と確定してるので数字をそのまま - add_scriptc(ScriptCode::NAME); - add_scriptb({uint8_t(l)}); - add_scriptb({uint8_t(l >> 8)}); - add_scriptb({uint8_t(l >> 16)}); + case ByteCode::FUNC_: + add_scriptc(ByteCode::FUNC_REF); + add_scriptb(static_cast<uint8_t>(ld->val)); + add_scriptb(static_cast<uint8_t>(ld->val >> 8)); + add_scriptb(static_cast<uint8_t>(ld->val >> 16)); + break; + case ByteCode::PARAM_: + add_scriptc(ByteCode::PARAM_); + add_scriptb(static_cast<uint8_t>(ld->val)); + add_scriptb(static_cast<uint8_t>(ld->val >> 8)); + add_scriptb(static_cast<uint8_t>(ld->val >> 16)); break; + default: + abort(); } } @@ -345,21 +241,23 @@ void add_scriptl(int l) * ラベルを解決する *------------------------------------------ */ -static -void set_label(int l, int pos_) +void ScriptBuffer::set_label(str_data_t *ld, int pos_) { - int i, next; + int next; - str_data[l].type = ScriptCode::POS; - str_data[l].label = pos_; - for (i = str_data[l].backpatch; i >= 0 && i != 0x00ffffff;) + ld->type = ByteCode::POS; + ld->label_ = pos_; + for (int i = ld->backpatch; i >= 0 && i != 0x00ffffff; i = next) { - next = (*(int *)(script_buf + i)) & 0x00ffffff; - script_buf[i - 1] = ScriptCode::POS; - script_buf[i] = static_cast<ScriptCode>(pos_); - script_buf[i + 1] = static_cast<ScriptCode>(pos_ >> 8); - script_buf[i + 2] = static_cast<ScriptCode>(pos_ >> 16); - i = next; + next = 0; + // woot! no longer endian-dependent! + next |= static_cast<uint8_t>(script_buf[i + 0]) << 0; + next |= static_cast<uint8_t>(script_buf[i + 1]) << 8; + next |= static_cast<uint8_t>(script_buf[i + 2]) << 16; + script_buf[i - 1] = ByteCode::POS; + script_buf[i] = static_cast<ByteCode>(pos_); + script_buf[i + 1] = static_cast<ByteCode>(pos_ >> 8); + script_buf[i + 2] = static_cast<ByteCode>(pos_ >> 16); } } @@ -474,16 +372,11 @@ void disp_error_message(const char *mes, const char *pos_) * 項の解析 *------------------------------------------ */ -static -const char *parse_simpleexpr(const char *p) +const char *ScriptBuffer::parse_simpleexpr(const char *p) { int i; p = skip_space(p); -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_simpleexpr %s\n", p); -#endif if (*p == ';' || *p == ',') { disp_error_message("unexpected expr end", p); @@ -509,7 +402,7 @@ const char *parse_simpleexpr(const char *p) } else if (*p == '"') { - add_scriptc(ScriptCode::STR); + add_scriptc(ByteCode::STR); p++; while (*p && *p != '"') { @@ -532,57 +425,42 @@ const char *parse_simpleexpr(const char *p) } else { - int l; // label , register , function etc - if (skip_word(p) == p) + const char *p2 = skip_word(p); + if (p2 == p) { disp_error_message("unexpected character", p); exit(1); } - char *p2 = const_cast<char *>(skip_word(p)); - char c = *p2; - *p2 = 0; // 名前をadd_strする - l = add_str(p); + str_data_t *ld = add_strp(std::string(p, p2)); - parse_cmd = l; // warn_*_mismatch_paramnumのために必要 - if (l == search_str("if")) // warn_cmd_no_commaのために必要 + parse_cmdp = ld; // warn_*_mismatch_paramnumのために必要 + // why not just check l->str == "if" or std::string(p, p2) == "if"? + if (ld == search_strp("if")) // warn_cmd_no_commaのために必要 parse_cmd_if++; -/* - // 廃止予定のl14/l15,およびプレフィックスlの警告 - if ( strcmp(str_buf+str_data[l].str,"l14")==0 || - strcmp(str_buf+str_data[l].str,"l15")==0 ){ - disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p); - }else if (str_buf[str_data[l].str]=='l'){ - disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2); - } -*/ - *p2 = c; p = p2; - if (str_data[l].type != ScriptCode::FUNC && c == '[') + if (ld->type != ByteCode::FUNC_ && *p == '[') { // array(name[i] => getelementofarray(name,i) ) - add_scriptl(search_str("getelementofarray")); - add_scriptc(ScriptCode::ARG); - add_scriptl(l); + add_scriptl(search_strp("getelementofarray")); + add_scriptc(ByteCode::ARG); + add_scriptl(ld); p = parse_subexpr(p + 1, -1); p = skip_space(p); - if ((*p++) != ']') + if (*p != ']') { disp_error_message("unmatch ']'", p); exit(1); } - add_scriptc(ScriptCode::FUNC); + p++; + add_scriptc(ByteCode::FUNC_); } else - add_scriptl(l); + add_scriptl(ld); } -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_simpleexpr end %s\n", p); -#endif return p; } @@ -590,15 +468,11 @@ const char *parse_simpleexpr(const char *p) * 式の解析 *------------------------------------------ */ -const char *parse_subexpr(const char *p, int limit) +const char *ScriptBuffer::parse_subexpr(const char *p, int limit) { - ScriptCode op; + ByteCode op; int opl, len; -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_subexpr %s\n", p); -#endif p = skip_space(p); if (*p == '-') @@ -606,14 +480,14 @@ const char *parse_subexpr(const char *p, int limit) const char *tmpp = skip_space(p + 1); if (*tmpp == ';' || *tmpp == ',') { - add_scriptl(LABEL_NEXTLINE); + add_scriptl(&LABEL_NEXTLINE_); p++; return p; } } const char *tmpp = p; - if ((op = ScriptCode::NEG, *p == '-') || (op = ScriptCode::LNOT, *p == '!') - || (op = ScriptCode::NOT, *p == '~')) + if ((op = ByteCode::NEG, *p == '-') || (op = ByteCode::LNOT, *p == '!') + || (op = ByteCode::NOT, *p == '~')) { p = parse_subexpr(p + 1, 100); add_scriptc(op); @@ -621,39 +495,40 @@ const char *parse_subexpr(const char *p, int limit) else p = parse_simpleexpr(p); p = skip_space(p); - while (((op = ScriptCode::ADD, opl = 6, len = 1, *p == '+') || - (op = ScriptCode::SUB, opl = 6, len = 1, *p == '-') || - (op = ScriptCode::MUL, opl = 7, len = 1, *p == '*') || - (op = ScriptCode::DIV, opl = 7, len = 1, *p == '/') || - (op = ScriptCode::MOD, opl = 7, len = 1, *p == '%') || - (op = ScriptCode::FUNC, opl = 8, len = 1, *p == '(') || - (op = ScriptCode::LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') || - (op = ScriptCode::AND, opl = 5, len = 1, *p == '&') || - (op = ScriptCode::LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') || - (op = ScriptCode::OR, opl = 4, len = 1, *p == '|') || - (op = ScriptCode::XOR, opl = 3, len = 1, *p == '^') || - (op = ScriptCode::EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') || - (op = ScriptCode::NE, opl = 2, len = 2, *p == '!' && p[1] == '=') || - (op = ScriptCode::R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') || - (op = ScriptCode::GE, opl = 2, len = 2, *p == '>' && p[1] == '=') || - (op = ScriptCode::GT, opl = 2, len = 1, *p == '>') || - (op = ScriptCode::L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') || - (op = ScriptCode::LE, opl = 2, len = 2, *p == '<' && p[1] == '=') || - (op = ScriptCode::LT, opl = 2, len = 1, *p == '<')) && opl > limit) + while (((op = ByteCode::ADD, opl = 6, len = 1, *p == '+') || + (op = ByteCode::SUB, opl = 6, len = 1, *p == '-') || + (op = ByteCode::MUL, opl = 7, len = 1, *p == '*') || + (op = ByteCode::DIV, opl = 7, len = 1, *p == '/') || + (op = ByteCode::MOD, opl = 7, len = 1, *p == '%') || + (op = ByteCode::FUNC_, opl = 8, len = 1, *p == '(') || + (op = ByteCode::LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') || + (op = ByteCode::AND, opl = 5, len = 1, *p == '&') || + (op = ByteCode::LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') || + (op = ByteCode::OR, opl = 4, len = 1, *p == '|') || + (op = ByteCode::XOR, opl = 3, len = 1, *p == '^') || + (op = ByteCode::EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') || + (op = ByteCode::NE, opl = 2, len = 2, *p == '!' && p[1] == '=') || + (op = ByteCode::R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') || + (op = ByteCode::GE, opl = 2, len = 2, *p == '>' && p[1] == '=') || + (op = ByteCode::GT, opl = 2, len = 1, *p == '>') || + (op = ByteCode::L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') || + (op = ByteCode::LE, opl = 2, len = 2, *p == '<' && p[1] == '=') || + (op = ByteCode::LT, opl = 2, len = 1, *p == '<')) && opl > limit) { p += len; - if (op == ScriptCode::FUNC) + if (op == ByteCode::FUNC_) { - int i = 0, func = parse_cmd; + int i = 0; + str_data_t *funcp = parse_cmdp; const char *plist[128]; - if (str_data[func].type != ScriptCode::FUNC) + if (funcp->type != ByteCode::FUNC_) { disp_error_message("expect function", tmpp); exit(0); } - add_scriptc(ScriptCode::ARG); + add_scriptc(ByteCode::ARG); while (*p && *p != ')' && i < 128) { plist[i] = p; @@ -670,16 +545,17 @@ const char *parse_subexpr(const char *p, int limit) i++; } plist[i] = p; - if (*(p++) != ')') + if (*p != ')') { disp_error_message("func request '(' ')'", p); exit(1); } + p++; - if (str_data[func].type == ScriptCode::FUNC + if (funcp->type == ByteCode::FUNC_ && script_config.warn_func_mismatch_paramnum) { - const char *arg = builtin_functions[str_data[func].val].arg; + const char *arg = builtin_functions[funcp->val].arg; int j = 0; for (j = 0; arg[j]; j++) if (arg[j] == '*') @@ -691,17 +567,13 @@ const char *parse_subexpr(const char *p, int limit) } } } - else // not op == ScriptCode::FUNC + else // not op == ByteCode::FUNC { p = parse_subexpr(p, opl); } add_scriptc(op); p = skip_space(p); } -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_subexpr end %s\n", p); -#endif return p; /* return first untreated operator */ } @@ -709,13 +581,8 @@ const char *parse_subexpr(const char *p, int limit) * 式の評価 *------------------------------------------ */ -static -const char *parse_expr(const char *p) +const char *ScriptBuffer::parse_expr(const char *p) { -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_expr %s\n", p); -#endif switch (*p) { case ')': @@ -728,10 +595,6 @@ const char *parse_expr(const char *p) exit(1); } p = parse_subexpr(p, -1); -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_expr end %s\n", p); -#endif return p; } @@ -739,10 +602,9 @@ const char *parse_expr(const char *p) * 行の解析 *------------------------------------------ */ -static -const char *parse_line(const char *p) +const char *ScriptBuffer::parse_line(const char *p) { - int i = 0, cmd; + int i = 0; const char *plist[128]; p = skip_space(p); @@ -756,14 +618,14 @@ const char *parse_line(const char *p) p = parse_simpleexpr(p); p = skip_space(p); - cmd = parse_cmd; - if (str_data[cmd].type != ScriptCode::FUNC) + str_data_t *cmd = parse_cmdp; + if (cmd->type != ByteCode::FUNC_) { disp_error_message("expect command", p2); // exit(0); } - add_scriptc(ScriptCode::ARG); + add_scriptc(ByteCode::ARG); while (p && *p && *p != ';' && i < 128) { plist[i] = p; @@ -787,12 +649,12 @@ const char *parse_line(const char *p) disp_error_message("need ';'", p); exit(1); } - add_scriptc(ScriptCode::FUNC); + add_scriptc(ByteCode::FUNC_); - if (str_data[cmd].type == ScriptCode::FUNC + if (cmd->type == ByteCode::FUNC_ && script_config.warn_cmd_mismatch_paramnum) { - const char *arg = builtin_functions[str_data[cmd].val].arg; + const char *arg = builtin_functions[cmd->val].arg; int j = 0; for (j = 0; arg[j]; j++) if (arg[j] == '*') @@ -814,13 +676,11 @@ const char *parse_line(const char *p) static void add_builtin_functions(void) { - int i, n; - for (i = 0; builtin_functions[i].func; i++) + for (int i = 0; builtin_functions[i].func; i++) { - n = add_str(builtin_functions[i].name); - str_data[n].type = ScriptCode::FUNC; - str_data[n].val = i; - str_data[n].func = builtin_functions[i].func; + str_data_t *n = add_strp(builtin_functions[i].name); + n->type = ByteCode::FUNC_; + n->val = i; } } @@ -844,34 +704,33 @@ void read_constdb(void) if (line[0] == '/' && line[1] == '/') continue; - char *name = nullptr; + std::string name; int val; int type = 0; // if not provided -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" - if (sscanf(line.c_str(), "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2) - { - free(name); - continue; - } -#pragma GCC diagnostic pop - for (char *p = name; *p; ++p) - *p = tolower(*p); - int n = add_str(name); - free(name); - str_data[n].type = type ? ScriptCode::PARAM : ScriptCode::INT; - str_data[n].val = val; + if (SSCANF(line, "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2) + continue; + for (char& c : name) + c = tolower(c); + str_data_t *n = add_strp(name); + n->type = type ? ByteCode::PARAM_ : ByteCode::INT; + n->val = val; } } +std::unique_ptr<const ScriptBuffer> parse_script(const char *src, int line) +{ + auto script_buf = make_unique<ScriptBuffer>(); + script_buf->parse_script(src, line); + return std::move(script_buf); +} + /*========================================== * スクリプトの解析 *------------------------------------------ */ -const ScriptCode *parse_script(const char *src, int line) +void ScriptBuffer::parse_script(const char *src, int line) { const char *p; - int i; static int first = 1; if (first) @@ -880,19 +739,17 @@ const ScriptCode *parse_script(const char *src, int line) read_constdb(); } first = 0; - script_buf = (ScriptCode *) calloc(SCRIPT_BLOCK_SIZE, 1); - script_pos = 0; - script_size = SCRIPT_BLOCK_SIZE; - str_data[LABEL_NEXTLINE].type = ScriptCode::NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; - for (i = LABEL_START; i < str_num; i++) - { - if (str_data[i].type == ScriptCode::POS || str_data[i].type == ScriptCode::NAME) + LABEL_NEXTLINE_.type = ByteCode::NOP; + LABEL_NEXTLINE_.backpatch = -1; + LABEL_NEXTLINE_.label_ = -1; + for (auto& pair : str_datam) + { + str_data_t& dit = pair.second; + if (dit.type == ByteCode::POS || dit.type == ByteCode::VARIABLE) { - str_data[i].type = ScriptCode::NOP; - str_data[i].backpatch = -1; - str_data[i].label = -1; + dit.type = ByteCode::NOP; + dit.backpatch = -1; + dit.label_ = -1; } } @@ -908,7 +765,7 @@ const ScriptCode *parse_script(const char *src, int line) if (*p != '{') { disp_error_message("not found '{'", p); - return NULL; + abort(); } for (p++; p && *p && *p != '}';) { @@ -916,20 +773,20 @@ const ScriptCode *parse_script(const char *src, int line) // labelだけ特殊処理 if (*skip_space(skip_word(p)) == ':') { - char *tmpp = const_cast<char *>(skip_word(p)); - char c = *tmpp; - *tmpp = '\0'; - int l = add_str(p); - if (str_data[l].label != -1) + const char *tmpp = skip_word(p); + std::string str(p, tmpp); + str_data_t *ld = add_strp(str); + bool e1 = ld->type != ByteCode::NOP; + bool e2 = ld->type == ByteCode::POS; + bool e3 = ld->label_ != -1; + assert (e1 == e2 && e2 == e3); + if (e3) { - *tmpp = c; disp_error_message("dup label ", p); exit(1); } - set_label(l, script_pos); - std::string str(p, skip_word(p)); - scriptlabel_db.insert(str, script_pos); - *tmpp = c; + set_label(ld, script_buf.size()); + scriptlabel_db.insert(str, script_buf.size()); p = tmpp + 1; continue; } @@ -937,58 +794,63 @@ const ScriptCode *parse_script(const char *src, int line) // 他は全部一緒くた p = parse_line(p); p = skip_space(p); - add_scriptc(ScriptCode::EOL); + add_scriptc(ByteCode::EOL); - set_label(LABEL_NEXTLINE, script_pos); - str_data[LABEL_NEXTLINE].type = ScriptCode::NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; + set_label(&LABEL_NEXTLINE_, script_buf.size()); + LABEL_NEXTLINE_.type = ByteCode::NOP; + LABEL_NEXTLINE_.backpatch = -1; + LABEL_NEXTLINE_.label_ = -1; } - add_scriptc(ScriptCode::NOP); + add_scriptc(ByteCode::NOP); - script_size = script_pos; - script_buf = (ScriptCode *) realloc(script_buf, script_pos + 1); - - // 未解決のラベルを解決 - for (i = LABEL_START; i < str_num; i++) + // resolve the unknown labels + for (auto& pair : str_datam) { - if (str_data[i].type == ScriptCode::NOP) + str_data_t& sit = pair.second; + if (sit.type == ByteCode::NOP) { - int j, next; - str_data[i].type = ScriptCode::NAME; - str_data[i].label = i; - for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff;) + sit.type = ByteCode::VARIABLE; + sit.label_ = 0; // anything but -1. Shouldn't matter, but helps asserts. + size_t pool_index = variable_names.intern(sit.strs); + for (int next, j = sit.backpatch; j >= 0 && j != 0x00ffffff; j = next) { - next = (*(int *)(script_buf + j)) & 0x00ffffff; - script_buf[j] = static_cast<ScriptCode>(i); - script_buf[j + 1] = static_cast<ScriptCode>(i >> 8); - script_buf[j + 2] = static_cast<ScriptCode>(i >> 16); - j = next; + next = 0; + next |= static_cast<uint8_t>(script_buf[j + 0]) << 0; + next |= static_cast<uint8_t>(script_buf[j + 1]) << 8; + next |= static_cast<uint8_t>(script_buf[j + 2]) << 16; + script_buf[j] = static_cast<ByteCode>(pool_index); + script_buf[j + 1] = static_cast<ByteCode>(pool_index >> 8); + script_buf[j + 2] = static_cast<ByteCode>(pool_index >> 16); } } } -#ifdef DEBUG_DISP - for (i = 0; i < script_pos; i++) + if (!DEBUG_DISP) + return; + for (size_t i = 0; i < script_buf.size(); i++) { if ((i & 15) == 0) - PRINTF("%04x : ", i); + PRINTF("%04zx : ", i); PRINTF("%02x ", script_buf[i]); if ((i & 15) == 15) PRINTF("\n"); } PRINTF("\n"); -#endif - - return script_buf; } // // 実行系 // -enum -{ STOP = 1, END, RERUNLINE, GOTO, RETFUNC }; +enum class ScriptEndState +{ + ZERO, + STOP, + END, + RERUNLINE, + GOTO, + RETFUNC, +}; /*========================================== * ridからsdへの解決 @@ -1013,11 +875,20 @@ static void get_val(ScriptState *st, struct script_data *data) { dumb_ptr<map_session_data> sd = NULL; - if (data->type == ScriptCode::NAME) + + if (data->type == ByteCode::PARAM_) { - char *name = str_buf + str_data[data->u.num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; + if ((sd = script_rid2sd(st)) == NULL) + PRINTF("get_val error param SP::%d\n", data->u.num); + data->type = ByteCode::INT; + if (sd) + data->u.num = pc_readparam(sd, static_cast<SP>(data->u.num)); + } + else if (data->type == ByteCode::VARIABLE) + { + const std::string& name = variable_names.outtern(data->u.num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$') { @@ -1026,43 +897,29 @@ void get_val(ScriptState *st, struct script_data *data) } if (postfix == '$') { - - data->type = ScriptCode::CONSTSTR; + data->type = ByteCode::CONSTSTR; if (prefix == '@' || prefix == 'l') { if (sd) - data->u.str = pc_readregstr(sd, data->u.num); + data->u.str = dumb_string::fake(pc_readregstr(sd, data->u.num)); } else if (prefix == '$') { - data->u.str = mapregstr_db.get(data->u.num); + std::string *s = mapregstr_db.search(data->u.num); + data->u.str = s ? dumb_string::fake(s->c_str()) : dumb_string(); } else { PRINTF("script: get_val: illegal scope string variable.\n"); - data->u.str = "!!ERROR!!"; + data->u.str = dumb_string::fake("!!ERROR!!"); } - if (data->u.str == NULL) - data->u.str = ""; - + if (!data->u.str) + data->u.str = dumb_string::fake(""); } else { - - data->type = ScriptCode::INT; - if (str_data[data->u.num & 0x00ffffff].type == ScriptCode::INT) - { - // unreachable - data->u.num = str_data[data->u.num & 0x00ffffff].val; - } - else if (str_data[data->u.num & 0x00ffffff].type == ScriptCode::PARAM) - { - if (sd) - data->u.num = - pc_readparam(sd, - SP(str_data[data->u.num & 0x00ffffff].val)); - } - else if (prefix == '@' || prefix == 'l') + data->type = ByteCode::INT; + if (prefix == '@' || prefix == 'l') { if (sd) data->u.num = pc_readreg(sd, data->u.num); @@ -1076,18 +933,18 @@ void get_val(ScriptState *st, struct script_data *data) if (name[1] == '#') { if (sd) - data->u.num = pc_readaccountreg2(sd, name); + data->u.num = pc_readaccountreg2(sd, name.c_str()); } else { if (sd) - data->u.num = pc_readaccountreg(sd, name); + data->u.num = pc_readaccountreg(sd, name.c_str()); } } else { if (sd) - data->u.num = pc_readglobalreg(sd, name); + data->u.num = pc_readglobalreg(sd, name.c_str()); } } } @@ -1101,7 +958,7 @@ static struct script_data get_val2(ScriptState *st, int num) { struct script_data dat; - dat.type = ScriptCode::NAME; + dat.type = ByteCode::VARIABLE; dat.u.num = num; get_val(st, &dat); return dat; @@ -1112,21 +969,30 @@ struct script_data get_val2(ScriptState *st, int num) *------------------------------------------ */ static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct script_data vd) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, struct script_data vd) { - char prefix = *name; - char postfix = name[strlen(name) - 1]; + if (type == ByteCode::PARAM_) + { + int val = vd.u.num; + pc_setparam(sd, static_cast<SP>(num), val); + return; + } + assert (type == ByteCode::VARIABLE); + + const std::string& name = variable_names.outtern(num); + char prefix = name.front(); + char postfix = name.back(); if (postfix == '$') { - const char *str = vd.u.str; + dumb_string str = vd.u.str; if (prefix == '@' || prefix == 'l') { - pc_setregstr(sd, num, str); + pc_setregstr(sd, num, str.c_str()); } else if (prefix == '$') { - mapreg_setregstr(num, str); + mapreg_setregstr(num, str.c_str()); } else { @@ -1137,11 +1003,7 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct sc { // 数値 int val = vd.u.num; - if (str_data[num & 0x00ffffff].type == ScriptCode::PARAM) - { - pc_setparam(sd, SP(str_data[num & 0x00ffffff].val), val); - } - else if (prefix == '@' || prefix == 'l') + if (prefix == '@' || prefix == 'l') { pc_setreg(sd, num, val); } @@ -1152,31 +1014,31 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct sc else if (prefix == '#') { if (name[1] == '#') - pc_setaccountreg2(sd, name, val); + pc_setaccountreg2(sd, name.c_str(), val); else - pc_setaccountreg(sd, name, val); + pc_setaccountreg(sd, name.c_str(), val); } else { - pc_setglobalreg(sd, name, val); + pc_setglobalreg(sd, name.c_str(), val); } } } static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, int id) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, int id) { struct script_data vd; vd.u.num = id; - set_reg(sd, num, name, vd); + set_reg(sd, type, num, vd); } static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, const char *zd) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, dumb_string zd) { struct script_data vd; vd.u.str = zd; - set_reg(sd, num, name, vd); + set_reg(sd, type, num, vd); } /*========================================== @@ -1184,26 +1046,16 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, const cha *------------------------------------------ */ static -const char *conv_str(ScriptState *st, struct script_data *data) +dumb_string conv_str(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type != ScriptCode::RETINFO); - if (data->type == ScriptCode::INT) - { - char *buf; - buf = (char *) calloc(16, 1); - sprintf(buf, "%d", data->u.num); - data->type = ScriptCode::STR; - data->u.str = buf; - } -#if 1 - else if (data->type == ScriptCode::NAME) + assert (data->type != ByteCode::RETINFO); + if (data->type == ByteCode::INT) { - // テンポラリ。本来無いはず - data->type = ScriptCode::CONSTSTR; - data->u.str = str_buf + str_data[data->u.num].str; + std::string buf = STRPRINTF("%d", data->u.num); + data->type = ByteCode::STR; + data->u.str = dumb_string::copys(buf); } -#endif return data->u.str; } @@ -1215,23 +1067,23 @@ static int conv_num(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type != ScriptCode::RETINFO); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + assert (data->type != ByteCode::RETINFO); + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *p = data->u.str; - data->u.num = atoi(p); - if (data->type == ScriptCode::STR) - free(const_cast<char *>(p)); - data->type = ScriptCode::INT; + dumb_string p = data->u.str; + data->u.num = atoi(p.c_str()); + if (data->type == ByteCode::STR) + p.delete_(); + data->type = ByteCode::INT; } return data->u.num; } static -const ScriptCode *conv_script(ScriptState *st, struct script_data *data) +const ScriptBuffer *conv_script(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type == ScriptCode::RETINFO); + assert (data->type == ByteCode::RETINFO); return data->u.script; } @@ -1240,45 +1092,27 @@ const ScriptCode *conv_script(ScriptState *st, struct script_data *data) *------------------------------------------ */ static -void push_val(struct script_stack *stack, ScriptCode type, int val) +void push_val(struct script_stack *stack, ByteCode type, int val) { - assert (type != ScriptCode::RETINFO); - assert (type != ScriptCode::STR); - assert (type != ScriptCode::CONSTSTR); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), 0, - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%d)-> %d\n",type,val,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.num = val; - stack->sp++; + assert (type != ByteCode::RETINFO); + assert (type != ByteCode::STR); + assert (type != ByteCode::CONSTSTR); + + script_data nsd {}; + nsd.type = type; + nsd.u.num = val; + stack->stack_datav.push_back(nsd); } static -void push_script(struct script_stack *stack, ScriptCode type, const ScriptCode *code) +void push_script(struct script_stack *stack, ByteCode type, const ScriptBuffer *code) { - assert (type == ScriptCode::RETINFO); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), 0, - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%d)-> %d\n",type,val,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.script = code; - stack->sp++; + assert (type == ByteCode::RETINFO); + + script_data nsd {}; + nsd.type = type; + nsd.u.script = code; + stack->stack_datav.push_back(nsd); } /*========================================== @@ -1286,23 +1120,14 @@ void push_script(struct script_stack *stack, ScriptCode type, const ScriptCode * *------------------------------------------ */ static -void push_str(struct script_stack *stack, ScriptCode type, const char *str) +void push_str(struct script_stack *stack, ByteCode type, dumb_string str) { - assert (type == ScriptCode::STR || type == ScriptCode::CONSTSTR); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), '\0', - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%x)-> %d\n",type,str,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.str = str; - stack->sp++; + assert (type == ByteCode::STR || type == ByteCode::CONSTSTR); + + script_data nsd {}; + nsd.type = type; + nsd.u.str = str; + stack->stack_datav.push_back(nsd); } /*========================================== @@ -1312,19 +1137,10 @@ void push_str(struct script_stack *stack, ScriptCode type, const char *str) static void push_copy(struct script_stack *stack, int pos_) { - switch (stack->stack_data[pos_].type) - { - case ScriptCode::CONSTSTR: - push_str(stack, ScriptCode::CONSTSTR, stack->stack_data[pos_].u.str); - break; - case ScriptCode::STR: - push_str(stack, ScriptCode::STR, strdup(stack->stack_data[pos_].u.str)); - break; - default: - push_val(stack, stack->stack_data[pos_].type, - stack->stack_data[pos_].u.num); - break; - } + script_data csd = stack->stack_datav[pos_]; + if (csd.type == ByteCode::STR) + csd.u.str = csd.u.str.dup(); + stack->stack_datav.push_back(csd); } /*========================================== @@ -1334,22 +1150,18 @@ void push_copy(struct script_stack *stack, int pos_) static void pop_stack(struct script_stack *stack, int start, int end) { - int i; - for (i = start; i < end; i++) + for (int i = start; i < end; i++) { - if (stack->stack_data[i].type == ScriptCode::STR) - { - free(const_cast<char *>(stack->stack_data[i].u.str)); - } - } - if (stack->sp > end) - { - memmove(&stack->stack_data[start], &stack->stack_data[end], - sizeof(stack->stack_data[0]) * (stack->sp - end)); + if (stack->stack_datav[i].type == ByteCode::STR) + stack->stack_datav[i].u.str.delete_(); } - stack->sp -= end - start; + auto it = stack->stack_datav.begin(); + stack->stack_datav.erase(it + start, it + end); } +#define AARGO2(n) (st->stack->stack_datav[st->start + (n)]) +#define HARGO2(n) (st->end > st->start + (n)) + // // 埋め込み関数 // @@ -1360,9 +1172,8 @@ void pop_stack(struct script_stack *stack, int start, int end) static void builtin_mes(ScriptState *st) { - conv_str(st, &(st->stack->stack_data[st->start + 2])); - clif_scriptmes(script_rid2sd(st), st->oid, - st->stack->stack_data[st->start + 2].u.str); + dumb_string mes = conv_str(st, &AARGO2(2)); + clif_scriptmes(script_rid2sd(st), st->oid, mes.c_str()); } /*========================================== @@ -1372,15 +1183,15 @@ void builtin_mes(ScriptState *st) static void builtin_goto(ScriptState *st) { - if (st->stack->stack_data[st->start + 2].type != ScriptCode::POS) + if (AARGO2(2).type != ByteCode::POS) { PRINTF("script: goto: not label !\n"); - st->state = END; + st->state = ScriptEndState::END; return; } - st->pos = conv_num(st, &(st->stack->stack_data[st->start + 2])); - st->state = GOTO; + st->scriptp.pos = conv_num(st, &AARGO2(2)); + st->state = ScriptEndState::GOTO; } /*========================================== @@ -1390,10 +1201,10 @@ void builtin_goto(ScriptState *st) static void builtin_callfunc(ScriptState *st) { - const ScriptCode *scr; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string str = conv_str(st, &AARGO2(2)); + const ScriptBuffer *scr = userfunc_db.get(str.str()); - if ((scr = userfunc_db.get(str))) + if (scr) { int j = 0; assert (st->start + 3 == st->end); @@ -1402,20 +1213,19 @@ void builtin_callfunc(ScriptState *st) push_copy(st->stack, i); #endif - push_val(st->stack, ScriptCode::INT, j); // 引数の数をプッシュ - push_val(st->stack, ScriptCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ - push_val(st->stack, ScriptCode::INT, st->pos); // 現在のスクリプト位置をプッシュ - push_script(st->stack, ScriptCode::RETINFO, st->script); // 現在のスクリプトをプッシュ + push_val(st->stack, ByteCode::INT, j); // 引数の数をプッシュ + push_val(st->stack, ByteCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ + push_val(st->stack, ByteCode::INT, st->scriptp.pos); // 現在のスクリプト位置をプッシュ + push_script(st->stack, ByteCode::RETINFO, st->scriptp.code); // 現在のスクリプトをプッシュ - st->pos = 0; - st->script = scr; + st->scriptp = ScriptPointer(scr, 0); st->defsp = st->start + 4 + j; - st->state = GOTO; + st->state = ScriptEndState::GOTO; } else { PRINTF("script:callfunc: function not found! [%s]\n", str); - st->state = END; + st->state = ScriptEndState::END; } } @@ -1426,7 +1236,7 @@ void builtin_callfunc(ScriptState *st) static void builtin_callsub(ScriptState *st) { - int pos_ = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int pos_ = conv_num(st, &AARGO2(2)); int j = 0; assert (st->start + 3 == st->end); #if 0 @@ -1434,14 +1244,14 @@ void builtin_callsub(ScriptState *st) push_copy(st->stack, i); #endif - push_val(st->stack, ScriptCode::INT, j); // 引数の数をプッシュ - push_val(st->stack, ScriptCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ - push_val(st->stack, ScriptCode::INT, st->pos); // 現在のスクリプト位置をプッシュ - push_script(st->stack, ScriptCode::RETINFO, st->script); // 現在のスクリプトをプッシュ + push_val(st->stack, ByteCode::INT, j); // 引数の数をプッシュ + push_val(st->stack, ByteCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ + push_val(st->stack, ByteCode::INT, st->scriptp.pos); // 現在のスクリプト位置をプッシュ + push_script(st->stack, ByteCode::RETINFO, st->scriptp.code); // 現在のスクリプトをプッシュ - st->pos = pos_; + st->scriptp.pos = pos_; st->defsp = st->start + 4 + j; - st->state = GOTO; + st->state = ScriptEndState::GOTO; } /*========================================== @@ -1452,12 +1262,12 @@ static void builtin_return(ScriptState *st) { #if 0 - if (st->end > st->start + 2) + if (HARGO2(2)) { // 戻り値有り push_copy(st->stack, st->start + 2); } #endif - st->state = RETFUNC; + st->state = ScriptEndState::RETFUNC; } /*========================================== @@ -1467,7 +1277,7 @@ void builtin_return(ScriptState *st) static void builtin_next(ScriptState *st) { - st->state = STOP; + st->state = ScriptEndState::STOP; clif_scriptnext(script_rid2sd(st), st->oid); } @@ -1478,14 +1288,14 @@ void builtin_next(ScriptState *st) static void builtin_close(ScriptState *st) { - st->state = END; + st->state = ScriptEndState::END; clif_scriptclose(script_rid2sd(st), st->oid); } static void builtin_close2(ScriptState *st) { - st->state = STOP; + st->state = ScriptEndState::STOP; clif_scriptclose(script_rid2sd(st), st->oid); } @@ -1496,69 +1306,54 @@ void builtin_close2(ScriptState *st) static void builtin_menu(ScriptState *st) { - char *buf; - int i, len = 0; // [fate] len is the total # of bytes we need to transmit the string choices - int menu_choices = 0; - int finished_menu_items = 0; // [fate] set to 1 after we hit the first empty string - - dumb_ptr<map_session_data> sd; - - sd = script_rid2sd(st); - - // We don't need to do this iteration if the player cancels, strictly speaking. - for (i = st->start + 2; i < st->end; i += 2) - { - int choice_len; - conv_str(st, &(st->stack->stack_data[i])); - choice_len = strlen(st->stack->stack_data[i].u.str); - len += choice_len + 1; // count # of bytes we'll need for packet. Only used if menu_or_input = 0. - - if (choice_len && !finished_menu_items) - ++menu_choices; - else - finished_menu_items = 1; - } + dumb_ptr<map_session_data> sd = script_rid2sd(st); if (sd->state.menu_or_input == 0) { - st->state = RERUNLINE; + // First half: show menu. + st->state = ScriptEndState::RERUNLINE; sd->state.menu_or_input = 1; - buf = (char *) calloc(len + 1, 1); - buf[0] = 0; - for (i = st->start + 2; menu_choices > 0; i += 2, --menu_choices) + std::string buf; + for (int i = st->start + 2; i < st->end; i += 2) { - strcat(buf, st->stack->stack_data[i].u.str); - strcat(buf, ":"); + dumb_string choice_str = conv_str(st, &AARGO2(i - st->start)); + if (!choice_str[0]) + break; + buf += choice_str.c_str(); + buf += ':'; } - clif_scriptmenu(script_rid2sd(st), st->oid, buf); - free(buf); - } - else if (sd->npc_menu == 0xff) - { // cansel - sd->state.menu_or_input = 0; - st->state = END; + + clif_scriptmenu(script_rid2sd(st), st->oid, buf.c_str()); } else - { // goto動作 - // ragemu互換のため - pc_setreg(sd, add_str("l15"), sd->npc_menu); - pc_setreg(sd, add_str("@menu"), sd->npc_menu); + { + // Rerun: item is chosen from menu. + if (sd->npc_menu == 0xff) + { + // cancel + sd->state.menu_or_input = 0; + st->state = ScriptEndState::END; + return; + } + + // Actually jump to the label. + // Logic change: menu_choices is the *total* number of labels, + // not just the displayed number that ends with the "". + // (Would it be better to pop the stack before rerunning?) + int menu_choices = (st->end - (st->start + 2)) / 2; + pc_setreg(sd, variable_names.intern("@menu"), sd->npc_menu); sd->state.menu_or_input = 0; if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices) { - if (st->stack-> - stack_data[st->start + sd->npc_menu * 2 + 1].type != ScriptCode::POS) + int arg_index = (sd->npc_menu - 1) * 2 + 1; + if (AARGO2(arg_index + 2).type != ByteCode::POS) { - st->state = END; + st->state = ScriptEndState::END; return; } - st->pos = - conv_num(st, - &(st-> - stack->stack_data[st->start + sd->npc_menu * 2 + - 1])); - st->state = GOTO; + st->scriptp.pos = conv_num(st, &AARGO2(arg_index + 2)); + st->state = ScriptEndState::GOTO; } } } @@ -1570,18 +1365,18 @@ void builtin_menu(ScriptState *st) static void builtin_rand(ScriptState *st) { - if (st->end > st->start + 3) + if (HARGO2(3)) { - int min = conv_num(st, &(st->stack->stack_data[st->start + 2])); - int max = conv_num(st, &(st->stack->stack_data[st->start + 3])); + int min = conv_num(st, &AARGO2(2)); + int max = conv_num(st, &AARGO2(3)); if (min > max) std::swap(max, min); - push_val(st->stack, ScriptCode::INT, random_::in(min, max)); + push_val(st->stack, ByteCode::INT, random_::in(min, max)); } else { - int range = conv_num(st, &(st->stack->stack_data[st->start + 2])); - push_val(st->stack, ScriptCode::INT, range <= 0 ? 0 : random_::to(range)); + int range = conv_num(st, &AARGO2(2)); + push_val(st->stack, ByteCode::INT, range <= 0 ? 0 : random_::to(range)); } } @@ -1594,10 +1389,11 @@ void builtin_pow(ScriptState *st) { int a, b; - a = conv_num(st, &(st->stack->stack_data[st->start + 2])); - b = conv_num(st, &(st->stack->stack_data[st->start + 3])); + a = conv_num(st, &AARGO2(2)); + b = conv_num(st, &AARGO2(3)); - push_val(st->stack, ScriptCode::INT, (int) pow(a * 0.001, b)); +#warning "This is silly" + push_val(st->stack, ByteCode::INT, static_cast<int>(pow(a * 0.001, b))); } @@ -1611,17 +1407,17 @@ void builtin_isat(ScriptState *st) int x, y; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); if (!sd) return; - push_val(st->stack, ScriptCode::INT, - (x == sd->bl_x) - && (y == sd->bl_y) && (!strcmp(str, map[sd->bl_m].name))); - + using namespace operators; + push_val(st->stack, ByteCode::INT, + (x == sd->bl_x) && (y == sd->bl_y) + && (str == sd->bl_m->name)); } /*========================================== @@ -1634,29 +1430,30 @@ void builtin_warp(ScriptState *st) int x, y; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - if (strcmp(str, "Random") == 0) + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + using namespace operators; + if (str == "Random") pc_randomwarp(sd, BeingRemoveWhy::WARPED); - else if (strcmp(str, "SavePoint") == 0) + else if (str == "SavePoint") { - if (map[sd->bl_m].flag.noreturn) // 蝶禁止 + if (sd->bl_m->flag.noreturn) // 蝶禁止 return; pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED); } - else if (strcmp(str, "Save") == 0) + else if (str == "Save") { - if (map[sd->bl_m].flag.noreturn) // 蝶禁止 + if (sd->bl_m->flag.noreturn) // 蝶禁止 return; pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED); } else - pc_setpos(sd, str, x, y, BeingRemoveWhy::GONE); + pc_setpos(sd, str.c_str(), x, y, BeingRemoveWhy::GONE); } /*========================================== @@ -1664,35 +1461,40 @@ void builtin_warp(ScriptState *st) *------------------------------------------ */ static -void builtin_areawarp_sub(dumb_ptr<block_list> bl, const char *mapname, int x, int y) +void builtin_areawarp_sub(dumb_ptr<block_list> bl, dumb_string mapname, int x, int y) { dumb_ptr<map_session_data> sd = bl->as_player(); - if (strcmp(mapname, "Random") == 0) + using namespace operators; + if (mapname == "Random") pc_randomwarp(sd, BeingRemoveWhy::WARPED); else - pc_setpos(sd, mapname, x, y, BeingRemoveWhy::GONE); + pc_setpos(sd, mapname.c_str(), x, y, BeingRemoveWhy::GONE); } static void builtin_areawarp(ScriptState *st) { - int x, y, m; + int x, y; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 7])); - x = conv_num(st, &(st->stack->stack_data[st->start + 8])); - y = conv_num(st, &(st->stack->stack_data[st->start + 9])); - - if ((m = map_mapname2mapid(mapname)) < 0) + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + dumb_string str = conv_str(st, &AARGO2(7)); + x = conv_num(st, &AARGO2(8)); + y = conv_num(st, &AARGO2(9)); + + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } /*========================================== @@ -1704,8 +1506,8 @@ void builtin_heal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_heal(script_rid2sd(st), hp, sp); } @@ -1718,8 +1520,8 @@ void builtin_itemheal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_itemheal(script_rid2sd(st), hp, sp); } @@ -1732,8 +1534,8 @@ void builtin_percentheal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_percentheal(script_rid2sd(st), hp, sp); } @@ -1745,57 +1547,42 @@ static void builtin_input(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = - (st->end > - st->start + 2) ? st->stack->stack_data[st->start + 2].u.num : 0; - const char *name = - (st->end > - st->start + 2) ? str_buf + str_data[num & 0x00ffffff].str : ""; -// char prefix=*name; - char postfix = name[strlen(name) - 1]; + script_data& scrd = AARGO2(2); + ByteCode type = scrd.type; + assert (type == ByteCode::VARIABLE); + + int num = scrd.u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); +// char prefix = name.front(); + char postfix = name.back(); sd = script_rid2sd(st); if (sd->state.menu_or_input) { + // Second time (rerun) sd->state.menu_or_input = 0; if (postfix == '$') { - // 文字列 - if (st->end > st->start + 2) - { // 引数1個 - set_reg(sd, num, name, sd->npc_str); - } - else - { - PRINTF("builtin_input: string discarded !!\n"); - } + set_reg(sd, type, num, dumb_string::fake(sd->npc_str)); } else { - //commented by Lupus (check Value Number Input fix in clif.c) //** Fix by fritz :X keeps people from abusing old input bugs + // wtf? if (sd->npc_amount < 0) //** If input amount is less then 0 { clif_tradecancelled(sd); // added "Deal has been cancelled" message by Valaris builtin_close(st); //** close } - // 数値 - if (st->end > st->start + 2) - { // 引数1個 - set_reg(sd, num, name, sd->npc_amount); - } - else - { - // ragemu互換のため - pc_setreg(sd, add_str("l14"), sd->npc_amount); - } + set_reg(sd, type, num, sd->npc_amount); } } else { - st->state = RERUNLINE; + // First time - send prompt to client, then wait + st->state = ScriptEndState::RERUNLINE; if (postfix == '$') clif_scriptinputstr(sd, st->oid); else @@ -1813,14 +1600,14 @@ void builtin_if (ScriptState *st) { int sel, i; - sel = conv_num(st, &(st->stack->stack_data[st->start + 2])); + sel = conv_num(st, &AARGO2(2)); if (!sel) return; // 関数名をコピー push_copy(st->stack, st->start + 3); // 間に引数マーカを入れて - push_val(st->stack, ScriptCode::ARG, 0); + push_val(st->stack, ByteCode::ARG, 0); // 残りの引数をコピー for (i = st->start + 4; i < st->end; i++) { @@ -1838,16 +1625,20 @@ static void builtin_set(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - - if (st->stack->stack_data[st->start + 2].type != ScriptCode::NAME) + int num = AARGO2(2).u.num; + if (AARGO2(2).type == ByteCode::PARAM_) { - PRINTF("script: builtin_set: not name\n"); + sd = script_rid2sd(st); + + int val = conv_num(st, &AARGO2(3)); + set_reg(sd, ByteCode::PARAM_, num, val); return; } + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); + + assert (AARGO2(2).type == ByteCode::VARIABLE); if (prefix != '$') sd = script_rid2sd(st); @@ -1855,14 +1646,14 @@ void builtin_set(ScriptState *st) if (postfix == '$') { // 文字列 - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - set_reg(sd, num, name, str); + dumb_string str = conv_str(st, &AARGO2(3)); + set_reg(sd, ByteCode::VARIABLE, num, str); } else { // 数値 - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); - set_reg(sd, num, name, val); + int val = conv_num(st, &AARGO2(3)); + set_reg(sd, ByteCode::VARIABLE, num, val); } } @@ -1875,11 +1666,11 @@ static void builtin_setarray(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - int i, j; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$' && prefix != '@') { @@ -1889,12 +1680,12 @@ void builtin_setarray(ScriptState *st) if (prefix != '$') sd = script_rid2sd(st); - for (j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++) + for (int j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++) { if (postfix == '$') - set_reg(sd, num + (j << 24), name, conv_str(st, &(st->stack->stack_data[i]))); + set_reg(sd, ByteCode::VARIABLE, num + (j << 24), conv_str(st, &AARGO2(i - st->start))); else - set_reg(sd, num + (j << 24), name, conv_num(st, &(st->stack->stack_data[i]))); + set_reg(sd, ByteCode::VARIABLE, num + (j << 24), conv_num(st, &AARGO2(i - st->start))); } } @@ -1906,12 +1697,12 @@ static void builtin_cleararray(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - int sz = conv_num(st, &(st->stack->stack_data[st->start + 4])); - int i; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); + int sz = conv_num(st, &AARGO2(4)); if (prefix != '$' && prefix != '@') { @@ -1922,11 +1713,11 @@ void builtin_cleararray(ScriptState *st) sd = script_rid2sd(st); if (postfix == '$') - for (i = 0; i < sz; i++) - set_reg(sd, num + (i << 24), name, conv_str(st, &(st->stack->stack_data[st->start + 3]))); + for (int i = 0; i < sz; i++) + set_reg(sd, ByteCode::VARIABLE, num + (i << 24), conv_str(st, &AARGO2(3))); else - for (i = 0; i < sz; i++) - set_reg(sd, num + (i << 24), name, conv_num(st, &(st->stack->stack_data[st->start + 3]))); + for (int i = 0; i < sz; i++) + set_reg(sd, ByteCode::VARIABLE, num + (i << 24), conv_num(st, &AARGO2(3))); } @@ -1941,7 +1732,7 @@ int getarraysize(ScriptState *st, int num, int postfix) for (; i < 128; i++) { struct script_data vd = get_val2(st, num + (i << 24)); - if (postfix == '$' ? bool(*vd.u.str) : bool(vd.u.num)) + if (postfix == '$' ? bool(vd.u.str[0]) : bool(vd.u.num)) c = i; } return c + 1; @@ -1950,10 +1741,11 @@ int getarraysize(ScriptState *st, int num, int postfix) static void builtin_getarraysize(ScriptState *st) { - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$' && prefix != '@') { @@ -1961,7 +1753,7 @@ void builtin_getarraysize(ScriptState *st) return; } - push_val(st->stack, ScriptCode::INT, getarraysize(st, num, postfix)); + push_val(st->stack, ByteCode::INT, getarraysize(st, num, postfix)); } /*========================================== @@ -1971,25 +1763,25 @@ void builtin_getarraysize(ScriptState *st) static void builtin_getelementofarray(ScriptState *st) { - if (st->stack->stack_data[st->start + 2].type == ScriptCode::NAME) + if (AARGO2(2).type == ByteCode::VARIABLE) { - int i = conv_num(st, &(st->stack->stack_data[st->start + 3])); + int i = conv_num(st, &AARGO2(3)); if (i > 127 || i < 0) { PRINTF("script: getelementofarray (operator[]): param2 illegal number %d\n", i); - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::NAME, - (i << 24) | st->stack->stack_data[st->start + 2].u.num); + push_val(st->stack, ByteCode::VARIABLE, + (i << 24) | AARGO2(2).u.num); } } else { PRINTF("script: getelementofarray (operator[]): param1 not name !\n"); - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } } @@ -2000,8 +1792,8 @@ void builtin_getelementofarray(ScriptState *st) static void builtin_setlook(ScriptState *st) { - LOOK type = LOOK(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + LOOK type = LOOK(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); pc_changelook(script_rid2sd(st), type, val); @@ -2021,13 +1813,13 @@ void builtin_countitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data; - if ((item_data = itemdb_searchname(name)) != NULL) + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); + if (item_data != NULL) nameid = item_data->nameid; } else @@ -2044,7 +1836,7 @@ void builtin_countitem(ScriptState *st) if (battle_config.error_log) PRINTF("wrong item ID : countitem (%i)\n", nameid); } - push_val(st->stack, ScriptCode::INT, count); + push_val(st->stack, ByteCode::INT, count); } @@ -2061,33 +1853,33 @@ void builtin_checkweight(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); if (item_data) nameid = item_data->nameid; } else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); + amount = conv_num(st, &AARGO2(3)); if (amount <= 0 || nameid < 500) { //if get wrong item ID or amount<=0, don't count weight of non existing items - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } if (itemdb_weight(nameid) * amount + sd->weight > sd->max_weight) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } } @@ -2106,12 +1898,12 @@ void builtin_getitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); nameid = 727; //Default to iten if (item_data != NULL) nameid = item_data->nameid; @@ -2120,7 +1912,7 @@ void builtin_getitem(ScriptState *st) nameid = conv_num(st, data); if ((amount = - conv_num(st, &(st->stack->stack_data[st->start + 3]))) <= 0) + conv_num(st, &AARGO2(3))) <= 0) { return; //return if amount <=0, skip the useles iteration } @@ -2130,8 +1922,8 @@ void builtin_getitem(ScriptState *st) memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; - if (st->end > st->start + 5) //アイテムを指定したIDに渡す - sd = map_id2sd(conv_num(st, &(st->stack->stack_data[st->start + 5]))); + if (HARGO2(5)) //アイテムを指定したIDに渡す + sd = map_id2sd(conv_num(st, &AARGO2(5))); if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り return; PickupFail flag; @@ -2154,19 +1946,19 @@ static void builtin_makeitem(ScriptState *st) { int nameid, amount, flag = 0; - int x, y, m; + int x, y; struct item item_tmp; dumb_ptr<map_session_data> sd; struct script_data *data; sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); nameid = 512; //Apple Item ID if (item_data) nameid = item_data->nameid; @@ -2174,15 +1966,17 @@ void builtin_makeitem(ScriptState *st) else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 4])); - x = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y = conv_num(st, &(st->stack->stack_data[st->start + 6])); + amount = conv_num(st, &AARGO2(3)); + dumb_string mapname = conv_str(st, &AARGO2(4)); + x = conv_num(st, &AARGO2(5)); + y = conv_num(st, &AARGO2(6)); - if (sd && strcmp(mapname, "this") == 0) + map_local *m; + using namespace operators; + if (sd && mapname == "this") m = sd->bl_m; else - m = map_mapname2mapid(mapname); + m = map_mapname2mapid(mapname.c_str()); if (nameid > 0) { @@ -2211,12 +2005,12 @@ void builtin_delitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); //nameid=512; if (item_data) nameid = item_data->nameid; @@ -2224,7 +2018,7 @@ void builtin_delitem(ScriptState *st) else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); + amount = conv_num(st, &AARGO2(3)); if (nameid < 500 || amount <= 0) { @@ -2272,19 +2066,19 @@ void builtin_readparam(ScriptState *st) { dumb_ptr<map_session_data> sd; - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - if (st->end > st->start + 3) - sd = map_nick2sd(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + SP type = SP(conv_num(st, &AARGO2(2))); + if (HARGO2(3)) + sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str()); else sd = script_rid2sd(st); if (sd == NULL) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } - push_val(st->stack, ScriptCode::INT, pc_readparam(sd, type)); + push_val(st->stack, ByteCode::INT, pc_readparam(sd, type)); } @@ -2298,24 +2092,24 @@ void builtin_getcharid(ScriptState *st) int num; dumb_ptr<map_session_data> sd; - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); - if (st->end > st->start + 3) - sd = map_nick2sd(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + num = conv_num(st, &AARGO2(2)); + if (HARGO2(3)) + sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str()); else sd = script_rid2sd(st); if (sd == NULL) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } if (num == 0) - push_val(st->stack, ScriptCode::INT, sd->status.char_id); + push_val(st->stack, ByteCode::INT, sd->status.char_id); if (num == 1) - push_val(st->stack, ScriptCode::INT, sd->status.party_id); + push_val(st->stack, ByteCode::INT, sd->status.party_id); if (num == 2) - push_val(st->stack, ScriptCode::INT, 0/*guild_id*/); + push_val(st->stack, ByteCode::INT, 0/*guild_id*/); if (num == 3) - push_val(st->stack, ScriptCode::INT, sd->status.account_id); + push_val(st->stack, ByteCode::INT, sd->status.account_id); } /*========================================== @@ -2323,22 +2117,14 @@ void builtin_getcharid(ScriptState *st) *------------------------------------------ */ static -char *builtin_getpartyname_sub(int party_id) +dumb_string builtin_getpartyname_sub(int party_id) { - struct party *p; - - p = NULL; - p = party_search(party_id); + struct party *p = party_search(party_id); - if (p != NULL) - { - char *buf; - buf = (char *) calloc(24, 1); - strcpy(buf, p->name); - return buf; - } + if (p) + return dumb_string::copy(p->name); - return 0; + return dumb_string(); } /*========================================== @@ -2352,27 +2138,24 @@ void builtin_strcharinfo(ScriptState *st) int num; sd = script_rid2sd(st); - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); if (num == 0) { - char *buf; - buf = (char *) calloc(24, 1); - strncpy(buf, sd->status.name, 23); - push_str(st->stack, ScriptCode::STR, buf); + dumb_string buf = dumb_string::copy(sd->status.name); + push_str(st->stack, ByteCode::STR, buf); } if (num == 1) { - char *buf; - buf = builtin_getpartyname_sub(sd->status.party_id); - if (buf != 0) - push_str(st->stack, ScriptCode::STR, buf); + dumb_string buf = builtin_getpartyname_sub(sd->status.party_id); + if (buf) + push_str(st->stack, ByteCode::STR, buf); else - push_str(st->stack, ScriptCode::CONSTSTR, ""); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); } if (num == 2) { // was: guild name - push_str(st->stack, ScriptCode::CONSTSTR, ""); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); } } @@ -2411,19 +2194,19 @@ void builtin_getequipid(ScriptState *st) PRINTF("getequipid: sd == NULL\n"); return; } - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); i = pc_checkequip(sd, equip[num - 1]); if (i >= 0) { item = sd->inventory_data[i]; if (item) - push_val(st->stack, ScriptCode::INT, item->nameid); + push_val(st->stack, ByteCode::INT, item->nameid); else - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); } } @@ -2437,25 +2220,25 @@ void builtin_getequipname(ScriptState *st) int i, num; dumb_ptr<map_session_data> sd; struct item_data *item; - char *buf; - buf = (char *) calloc(64, 1); + std::string buf; + sd = script_rid2sd(st); - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); i = pc_checkequip(sd, equip[num - 1]); if (i >= 0) { item = sd->inventory_data[i]; if (item) - sprintf(buf, "%s-[%s]", pos[num - 1], item->jname); + buf = STRPRINTF("%s-[%s]", pos[num - 1], item->jname); else - sprintf(buf, "%s-[%s]", pos[num - 1], pos[10]); + buf = STRPRINTF("%s-[%s]", pos[num - 1], pos[10]); } else { - sprintf(buf, "%s-[%s]", pos[num - 1], pos[10]); + buf = STRPRINTF("%s-[%s]", pos[num - 1], pos[10]); } - push_str(st->stack, ScriptCode::STR, buf); + push_str(st->stack, ByteCode::STR, dumb_string::copys(buf)); } @@ -2466,8 +2249,8 @@ void builtin_getequipname(ScriptState *st) static void builtin_statusup2(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SP type = SP(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_statusup2(sd, type, val); @@ -2480,8 +2263,8 @@ void builtin_statusup2(ScriptState *st) static void builtin_bonus(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SP type = SP(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_bonus(sd, type, val); @@ -2494,9 +2277,9 @@ void builtin_bonus(ScriptState *st) static void builtin_bonus2(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int type2 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - int val = conv_num(st, &(st->stack->stack_data[st->start + 4])); + SP type = SP(conv_num(st, &AARGO2(2))); + int type2 = conv_num(st, &AARGO2(3)); + int val = conv_num(st, &AARGO2(4)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_bonus2(sd, type, type2, val); @@ -2512,10 +2295,10 @@ void builtin_skill(ScriptState *st) int level, flag = 1; dumb_ptr<map_session_data> sd; - SkillID id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - level = conv_num(st, &(st->stack->stack_data[st->start + 3])); - if (st->end > st->start + 4) - flag = conv_num(st, &(st->stack->stack_data[st->start + 4])); + SkillID id = SkillID(conv_num(st, &AARGO2(2))); + level = conv_num(st, &AARGO2(3)); + if (HARGO2(4)) + flag = conv_num(st, &AARGO2(4)); sd = script_rid2sd(st); pc_skill(sd, id, level, flag); clif_skillinfoblock(sd); @@ -2532,8 +2315,8 @@ void builtin_setskill(ScriptState *st) int level; dumb_ptr<map_session_data> sd; - SkillID id = static_cast<SkillID>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - level = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SkillID id = static_cast<SkillID>(conv_num(st, &AARGO2(2))); + level = conv_num(st, &AARGO2(3)); sd = script_rid2sd(st); sd->status.skill[id].lv = level; @@ -2547,8 +2330,8 @@ void builtin_setskill(ScriptState *st) static void builtin_getskilllv(ScriptState *st) { - SkillID id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - push_val(st->stack, ScriptCode::INT, pc_checkskill(script_rid2sd(st), id)); + SkillID id = SkillID(conv_num(st, &AARGO2(2))); + push_val(st->stack, ByteCode::INT, pc_checkskill(script_rid2sd(st), id)); } /*========================================== @@ -2558,7 +2341,7 @@ void builtin_getskilllv(ScriptState *st) static void builtin_getgmlevel(ScriptState *st) { - push_val(st->stack, ScriptCode::INT, pc_isGM(script_rid2sd(st))); + push_val(st->stack, ByteCode::INT, pc_isGM(script_rid2sd(st))); } /*========================================== @@ -2568,7 +2351,7 @@ void builtin_getgmlevel(ScriptState *st) static void builtin_end(ScriptState *st) { - st->state = END; + st->state = ScriptEndState::END; } /*========================================== @@ -2583,7 +2366,7 @@ void builtin_getopt2(ScriptState *st) sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, uint16_t(sd->opt2)); + push_val(st->stack, ByteCode::INT, uint16_t(sd->opt2)); } @@ -2597,7 +2380,7 @@ void builtin_setopt2(ScriptState *st) { dumb_ptr<map_session_data> sd; - Opt2 new_opt2 = Opt2(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + Opt2 new_opt2 = Opt2(conv_num(st, &AARGO2(2))); sd = script_rid2sd(st); if (new_opt2 == sd->opt2) return; @@ -2616,10 +2399,10 @@ void builtin_savepoint(ScriptState *st) { int x, y; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - pc_setsavepoint(script_rid2sd(st), str, x, y); + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + pc_setsavepoint(script_rid2sd(st), str.c_str(), x, y); } /*========================================== @@ -2636,7 +2419,7 @@ static void builtin_gettimetick(ScriptState *st) /* Asgard Version */ { int type; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); switch (type) { @@ -2644,18 +2427,18 @@ void builtin_gettimetick(ScriptState *st) /* Asgard Version */ case 1: { struct tm t = TimeT::now(); - push_val(st->stack, ScriptCode::INT, + push_val(st->stack, ByteCode::INT, t.tm_hour * 3600 + t.tm_min * 60 + t.tm_sec); break; } /* Seconds since Unix epoch. */ case 2: - push_val(st->stack, ScriptCode::INT, static_cast<time_t>(TimeT::now())); + push_val(st->stack, ByteCode::INT, static_cast<time_t>(TimeT::now())); break; /* System tick(unsigned int, and yes, it will wrap). */ case 0: default: - push_val(st->stack, ScriptCode::INT, gettick().time_since_epoch().count()); + push_val(st->stack, ByteCode::INT, gettick().time_since_epoch().count()); break; } } @@ -2670,58 +2453,40 @@ void builtin_gettimetick(ScriptState *st) /* Asgard Version */ static void builtin_gettime(ScriptState *st) /* Asgard Version */ { - int type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int type = conv_num(st, &AARGO2(2)); struct tm t = TimeT::now(); switch (type) { case 1: //Sec(0~59) - push_val(st->stack, ScriptCode::INT, t.tm_sec); + push_val(st->stack, ByteCode::INT, t.tm_sec); break; case 2: //Min(0~59) - push_val(st->stack, ScriptCode::INT, t.tm_min); + push_val(st->stack, ByteCode::INT, t.tm_min); break; case 3: //Hour(0~23) - push_val(st->stack, ScriptCode::INT, t.tm_hour); + push_val(st->stack, ByteCode::INT, t.tm_hour); break; case 4: //WeekDay(0~6) - push_val(st->stack, ScriptCode::INT, t.tm_wday); + push_val(st->stack, ByteCode::INT, t.tm_wday); break; case 5: //MonthDay(01~31) - push_val(st->stack, ScriptCode::INT, t.tm_mday); + push_val(st->stack, ByteCode::INT, t.tm_mday); break; case 6: //Month(01~12) - push_val(st->stack, ScriptCode::INT, t.tm_mon + 1); + push_val(st->stack, ByteCode::INT, t.tm_mon + 1); break; case 7: //Year(20xx) - push_val(st->stack, ScriptCode::INT, t.tm_year + 1900); + push_val(st->stack, ByteCode::INT, t.tm_year + 1900); break; default: //(format error) - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); break; } } /*========================================== - * GetTimeStr("TimeFMT", Length); - *------------------------------------------ - */ -static -void builtin_gettimestr(ScriptState *st) -{ - struct tm now = TimeT::now(); - - const char *fmtstr = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int maxlen = conv_num(st, &(st->stack->stack_data[st->start + 3])); - - char *tmpstr = (char *) calloc(maxlen + 1, 1); - strftime(tmpstr, maxlen, fmtstr, &now); - - push_str(st->stack, ScriptCode::STR, tmpstr); -} - -/*========================================== * カプラ倉庫を開く *------------------------------------------ */ @@ -2733,9 +2498,9 @@ void builtin_openstorage(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); // if (sync) { - st->state = STOP; + st->state = ScriptEndState::STOP; sd->npc_flags.storage = 1; -// } else st->state = END; +// } else st->state = ScriptEndState::END; storage_storageopen(sd); } @@ -2750,8 +2515,8 @@ void builtin_getexp(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); int base = 0, job = 0; - base = conv_num(st, &(st->stack->stack_data[st->start + 2])); - job = conv_num(st, &(st->stack->stack_data[st->start + 3])); + base = conv_num(st, &AARGO2(2)); + job = conv_num(st, &AARGO2(3)); if (base < 0 || job < 0) return; if (sd) @@ -2769,16 +2534,16 @@ void builtin_monster(ScriptState *st) int mob_class, amount, x, y; const char *event = ""; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 5])); - mob_class = conv_num(st, &(st->stack->stack_data[st->start + 6])); - amount = conv_num(st, &(st->stack->stack_data[st->start + 7])); - if (st->end > st->start + 8) - event = conv_str(st, &(st->stack->stack_data[st->start + 8])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + dumb_string str = conv_str(st, &AARGO2(5)); + mob_class = conv_num(st, &AARGO2(6)); + amount = conv_num(st, &AARGO2(7)); + if (HARGO2(8)) + event = conv_str(st, &AARGO2(8)).c_str(); - mob_once_spawn(map_id2sd(st->rid), mapname, x, y, str, mob_class, amount, + mob_once_spawn(map_id2sd(st->rid), mapname.c_str(), x, y, str.c_str(), mob_class, amount, event); } @@ -2792,18 +2557,18 @@ void builtin_areamonster(ScriptState *st) int mob_class, amount, x0, y0, x1, y1; const char *event = ""; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 7])); - mob_class = conv_num(st, &(st->stack->stack_data[st->start + 8])); - amount = conv_num(st, &(st->stack->stack_data[st->start + 9])); - if (st->end > st->start + 10) - event = conv_str(st, &(st->stack->stack_data[st->start + 10])); - - mob_once_spawn_area(map_id2sd(st->rid), mapname, x0, y0, x1, y1, str, mob_class, + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + dumb_string str = conv_str(st, &AARGO2(7)); + mob_class = conv_num(st, &AARGO2(8)); + amount = conv_num(st, &AARGO2(9)); + if (HARGO2(10)) + event = conv_str(st, &AARGO2(10)).c_str(); + + mob_once_spawn_area(map_id2sd(st->rid), mapname.c_str(), x0, y0, x1, y1, str.c_str(), mob_class, amount, event); } @@ -2812,19 +2577,20 @@ void builtin_areamonster(ScriptState *st) *------------------------------------------ */ static -void builtin_killmonster_sub(dumb_ptr<block_list> bl, const char *event, int allflag) +void builtin_killmonster_sub(dumb_ptr<block_list> bl, dumb_string event, int allflag) { dumb_ptr<mob_data> md = bl->as_mob(); if (!allflag) { - if (strcmp(event, md->npc_event) == 0) + using namespace operators; + if (event == md->npc_event) mob_delete(md); return; } else if (allflag) { - if (md->spawndelay1 == static_cast<interval_t>(-1) - && md->spawndelay2 == static_cast<interval_t>(-1)) + if (md->spawn.delay1 == static_cast<interval_t>(-1) + && md->spawn.delay2 == static_cast<interval_t>(-1)) mob_delete(md); return; } @@ -2833,16 +2599,21 @@ void builtin_killmonster_sub(dumb_ptr<block_list> bl, const char *event, int all static void builtin_killmonster(ScriptState *st) { - int m, allflag = 0; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); - if (strcmp(event, "All") == 0) + int allflag = 0; + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string event = conv_str(st, &AARGO2(3)); + using namespace operators; + if (event == "All") allflag = 1; - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_killmonster_sub, ph::_1, event, allflag), - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); } static @@ -2854,13 +2625,16 @@ void builtin_killmonsterall_sub(dumb_ptr<block_list> bl) static void builtin_killmonsterall(ScriptState *st) { - int m; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string mapname = conv_str(st, &AARGO2(2)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(builtin_killmonsterall_sub, - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); } /*========================================== @@ -2870,8 +2644,8 @@ void builtin_killmonsterall(ScriptState *st) static void builtin_donpcevent(ScriptState *st) { - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_event_do(event); + dumb_string event = conv_str(st, &AARGO2(2)); + npc_event_do(event.c_str()); } /*========================================== @@ -2881,9 +2655,9 @@ void builtin_donpcevent(ScriptState *st) static void builtin_addtimer(ScriptState *st) { - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); - pc_addeventtimer(script_rid2sd(st), tick, event); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2))); + dumb_string event = conv_str(st, &AARGO2(3)); + pc_addeventtimer(script_rid2sd(st), tick, event.c_str()); } /*========================================== @@ -2894,8 +2668,8 @@ static void builtin_initnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2913,8 +2687,8 @@ static void builtin_startnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2931,8 +2705,8 @@ static void builtin_stopnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2949,10 +2723,10 @@ static void builtin_getnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - int type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int type = conv_num(st, &AARGO2(2)); int val = 0; - if (st->end > st->start + 3) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + if (HARGO2(3)) + nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2961,16 +2735,16 @@ void builtin_getnpctimer(ScriptState *st) switch (type) { case 0: - val = (int) npc_gettimerevent_tick(nd).count(); + val = npc_gettimerevent_tick(nd).count(); break; case 1: - val = (nd->scr.nexttimer >= 0); + val = nd->scr.nexttimer != nd->scr.timer_eventv.end(); break; case 2: - val = nd->scr.timeramount; + val = nd->scr.timer_eventv.size(); break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -2981,9 +2755,9 @@ static void builtin_setnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - if (st->end > st->start + 3) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2))); + if (HARGO2(3)) + nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -3000,13 +2774,16 @@ static void builtin_announce(ScriptState *st) { int flag; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - flag = conv_num(st, &(st->stack->stack_data[st->start + 3])); + dumb_string str = conv_str(st, &AARGO2(2)); + flag = conv_num(st, &AARGO2(3)); if (flag & 0x0f) { - dumb_ptr<block_list> bl = (flag & 0x08) ? map_id2bl(st->oid) : - (dumb_ptr<block_list>) script_rid2sd(st); + dumb_ptr<block_list> bl; + if (flag & 0x08) + bl = map_id2bl(st->oid); + else + bl = script_rid2sd(st); clif_GMmessage(bl, str, flag); } else @@ -3018,24 +2795,28 @@ void builtin_announce(ScriptState *st) *------------------------------------------ */ static -void builtin_mapannounce_sub(dumb_ptr<block_list> bl, const char *str, int flag) +void builtin_mapannounce_sub(dumb_ptr<block_list> bl, dumb_string str, int flag) { - clif_GMmessage(bl, str, flag | 3); + clif_GMmessage(bl, str.c_str(), flag | 3); } static void builtin_mapannounce(ScriptState *st) { - int flag, m; + int flag; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - flag = conv_num(st, &(st->stack->stack_data[st->start + 4])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string str = conv_str(st, &AARGO2(3)); + flag = conv_num(st, &AARGO2(4)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_mapannounce_sub, ph::_1, str, flag & 0x10), - m, 0, 0, map[m].xs, map[m].ys, BL::PC); + m, + 0, 0, + m->xs, m->ys, + BL::PC); } /*========================================== @@ -3045,19 +2826,19 @@ void builtin_mapannounce(ScriptState *st) static void builtin_getusers(ScriptState *st) { - int flag = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int flag = conv_num(st, &AARGO2(2)); dumb_ptr<block_list> bl = map_id2bl((flag & 0x08) ? st->oid : st->rid); int val = 0; switch (flag & 0x07) { case 0: - val = map[bl->bl_m].users; + val = bl->bl_m->users; break; case 1: val = map_getusers(); break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -3067,14 +2848,14 @@ void builtin_getusers(ScriptState *st) static void builtin_getmapusers(ScriptState *st) { - int m; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - if ((m = map_mapname2mapid(str)) < 0) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } - push_val(st->stack, ScriptCode::INT, map[m].users); + push_val(st->stack, ByteCode::INT, m->users); } /*========================================== @@ -3097,26 +2878,30 @@ void builtin_getareausers_living_sub(dumb_ptr<block_list> bl, int *users) static void builtin_getareausers(ScriptState *st) { - int m, x0, y0, x1, y1, users = 0; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + int x0, y0, x1, y1, users = 0; + dumb_string str = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); int living = 0; - if (st->end > st->start + 7) + if (HARGO2(7)) { - living = conv_num(st, &(st->stack->stack_data[st->start + 7])); + living = conv_num(st, &AARGO2(7)); } - if ((m = map_mapname2mapid(str)) < 0) + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } map_foreachinarea(std::bind(living ? builtin_getareausers_living_sub: builtin_getareausers_sub, ph::_1, &users), - m, x0, y0, x1, y1, BL::PC); - push_val(st->stack, ScriptCode::INT, users); + m, + x0, y0, + x1, y1, + BL::PC); + push_val(st->stack, ByteCode::INT, users); } /*========================================== @@ -3149,21 +2934,21 @@ void builtin_getareadropitem_sub_anddelete(dumb_ptr<block_list> bl, int item, in static void builtin_getareadropitem(ScriptState *st) { - int m, x0, y0, x1, y1, item, amount = 0, delitems = 0; + int x0, y0, x1, y1, item, amount = 0, delitems = 0; struct script_data *data; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + dumb_string str = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); - data = &(st->stack->stack_data[st->start + 7]); + data = &AARGO2(7); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); item = 512; if (item_data) item = item_data->nameid; @@ -3171,22 +2956,29 @@ void builtin_getareadropitem(ScriptState *st) else item = conv_num(st, data); - if (st->end > st->start + 8) - delitems = conv_num(st, &(st->stack->stack_data[st->start + 8])); + if (HARGO2(8)) + delitems = conv_num(st, &AARGO2(8)); - if ((m = map_mapname2mapid(str)) < 0) + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } if (delitems) map_foreachinarea(std::bind(builtin_getareadropitem_sub_anddelete, ph::_1, item, &amount), - m, x0, y0, x1, y1, BL::ITEM); + m, + x0, y0, + x1, y1, + BL::ITEM); else map_foreachinarea(std::bind(builtin_getareadropitem_sub, ph::_1, item, &amount), - m, x0, y0, x1, y1, BL::ITEM); + m, + x0, y0, + x1, y1, + BL::ITEM); - push_val(st->stack, ScriptCode::INT, amount); + push_val(st->stack, ByteCode::INT, amount); } /*========================================== @@ -3196,8 +2988,8 @@ void builtin_getareadropitem(ScriptState *st) static void builtin_enablenpc(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_enable(str, 1); + dumb_string str = conv_str(st, &AARGO2(2)); + npc_enable(str.c_str(), 1); } /*========================================== @@ -3207,8 +2999,8 @@ void builtin_enablenpc(ScriptState *st) static void builtin_disablenpc(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_enable(str, 0); + dumb_string str = conv_str(st, &AARGO2(2)); + npc_enable(str.c_str(), 0); } /*========================================== @@ -3220,8 +3012,8 @@ void builtin_sc_start(ScriptState *st) { dumb_ptr<block_list> bl; int val1; - StatusChange type = static_cast<StatusChange>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 3]))); + StatusChange type = static_cast<StatusChange>(conv_num(st, &AARGO2(2))); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(3))); if (tick < std::chrono::seconds(1)) // work around old behaviour of: // speed potion @@ -3231,9 +3023,9 @@ void builtin_sc_start(ScriptState *st) // which used to use seconds // all others used milliseconds tick *= 1000; - val1 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - if (st->end > st->start + 5) //指定したキャラを状態異常にする - bl = map_id2bl(conv_num(st, &(st->stack->stack_data[st->start + 5]))); + val1 = conv_num(st, &AARGO2(4)); + if (HARGO2(5)) //指定したキャラを状態異常にする + bl = map_id2bl(conv_num(st, &AARGO2(5))); else bl = map_id2bl(st->rid); skill_status_change_start(bl, type, val1, tick); @@ -3247,7 +3039,7 @@ static void builtin_sc_end(ScriptState *st) { dumb_ptr<block_list> bl; - StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + StatusChange type = StatusChange(conv_num(st, &AARGO2(2))); bl = map_id2bl(st->rid); skill_status_change_end(bl, type, nullptr); } @@ -3256,10 +3048,10 @@ static void builtin_sc_check(ScriptState *st) { dumb_ptr<block_list> bl; - StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + StatusChange type = StatusChange(conv_num(st, &AARGO2(2))); bl = map_id2bl(st->rid); - push_val(st->stack, ScriptCode::INT, skill_status_change_active(bl, type)); + push_val(st->stack, ByteCode::INT, skill_status_change_active(bl, type)); } @@ -3270,9 +3062,9 @@ void builtin_sc_check(ScriptState *st) static void builtin_debugmes(ScriptState *st) { - conv_str(st, &(st->stack->stack_data[st->start + 2])); - PRINTF("script debug : %d %d : %s\n", st->rid, st->oid, - st->stack->stack_data[st->start + 2].u.str); + dumb_string mes = conv_str(st, &AARGO2(2)); + PRINTF("script debug : %d %d : %s\n", + st->rid, st->oid, mes); } /*========================================== @@ -3318,8 +3110,8 @@ void builtin_changesex(ScriptState *st) static void builtin_attachrid(ScriptState *st) { - st->rid = conv_num(st, &(st->stack->stack_data[st->start + 2])); - push_val(st->stack, ScriptCode::INT, (map_id2sd(st->rid) != NULL)); + st->rid = conv_num(st, &AARGO2(2)); + push_val(st->stack, ByteCode::INT, (map_id2sd(st->rid) != NULL)); } /*========================================== @@ -3339,9 +3131,9 @@ void builtin_detachrid(ScriptState *st) static void builtin_isloggedin(ScriptState *st) { - push_val(st->stack, ScriptCode::INT, + push_val(st->stack, ByteCode::INT, map_id2sd(conv_num(st, - &(st->stack->stack_data[st->start + 2]))) != NULL); + &AARGO2(2))) != NULL); } /*========================================== @@ -3376,59 +3168,57 @@ enum static void builtin_setmapflag(ScriptState *st) { - int m, i; - - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - map[m].flag.nomemo = 1; + m->flag.nomemo = 1; break; case MF_NOTELEPORT: - map[m].flag.noteleport = 1; + m->flag.noteleport = 1; break; case MF_NOBRANCH: - map[m].flag.nobranch = 1; + m->flag.nobranch = 1; break; case MF_NOPENALTY: - map[m].flag.nopenalty = 1; + m->flag.nopenalty = 1; break; case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 1; + m->flag.pvp_noparty = 1; break; case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 1; + m->flag.nozenypenalty = 1; break; case MF_NOTRADE: - map[m].flag.notrade = 1; + m->flag.notrade = 1; break; case MF_NOWARP: - map[m].flag.nowarp = 1; + m->flag.nowarp = 1; break; case MF_NOPVP: - map[m].flag.nopvp = 1; + m->flag.nopvp = 1; break; case MF_NOICEWALL: // [Valaris] - map[m].flag.noicewall = 1; + m->flag.noicewall = 1; break; case MF_SNOW: // [Valaris] - map[m].flag.snow = 1; + m->flag.snow = 1; break; case MF_FOG: // [Valaris] - map[m].flag.fog = 1; + m->flag.fog = 1; break; case MF_SAKURA: // [Valaris] - map[m].flag.sakura = 1; + m->flag.sakura = 1; break; case MF_LEAVES: // [Valaris] - map[m].flag.leaves = 1; + m->flag.leaves = 1; break; case MF_RAIN: // [Valaris] - map[m].flag.rain = 1; + m->flag.rain = 1; break; } } @@ -3438,137 +3228,133 @@ void builtin_setmapflag(ScriptState *st) static void builtin_removemapflag(ScriptState *st) { - int m, i; - - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - map[m].flag.nomemo = 0; + m->flag.nomemo = 0; break; case MF_NOTELEPORT: - map[m].flag.noteleport = 0; + m->flag.noteleport = 0; break; case MF_NOSAVE: - map[m].flag.nosave = 0; + m->flag.nosave = 0; break; case MF_NOBRANCH: - map[m].flag.nobranch = 0; + m->flag.nobranch = 0; break; case MF_NOPENALTY: - map[m].flag.nopenalty = 0; + m->flag.nopenalty = 0; break; case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 0; + m->flag.pvp_noparty = 0; break; case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 0; + m->flag.nozenypenalty = 0; break; case MF_NOWARP: - map[m].flag.nowarp = 0; + m->flag.nowarp = 0; break; case MF_NOPVP: - map[m].flag.nopvp = 0; + m->flag.nopvp = 0; break; case MF_NOICEWALL: // [Valaris] - map[m].flag.noicewall = 0; + m->flag.noicewall = 0; break; case MF_SNOW: // [Valaris] - map[m].flag.snow = 0; + m->flag.snow = 0; break; case MF_FOG: // [Valaris] - map[m].flag.fog = 0; + m->flag.fog = 0; break; case MF_SAKURA: // [Valaris] - map[m].flag.sakura = 0; + m->flag.sakura = 0; break; case MF_LEAVES: // [Valaris] - map[m].flag.leaves = 0; + m->flag.leaves = 0; break; case MF_RAIN: // [Valaris] - map[m].flag.rain = 0; + m->flag.rain = 0; break; - } } - } static void builtin_getmapflag(ScriptState *st) { - int m, i, r = -1; + int r = -1; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - r = map[m].flag.nomemo; + r = m->flag.nomemo; break; case MF_NOTELEPORT: - r = map[m].flag.noteleport; + r = m->flag.noteleport; break; case MF_NOSAVE: - r = map[m].flag.nosave; + r = m->flag.nosave; break; case MF_NOBRANCH: - r = map[m].flag.nobranch; + r = m->flag.nobranch; break; case MF_NOPENALTY: - r = map[m].flag.nopenalty; + r = m->flag.nopenalty; break; case MF_PVP_NOPARTY: - r = map[m].flag.pvp_noparty; + r = m->flag.pvp_noparty; break; case MF_NOZENYPENALTY: - r = map[m].flag.nozenypenalty; + r = m->flag.nozenypenalty; break; case MF_NOWARP: - r = map[m].flag.nowarp; + r = m->flag.nowarp; break; case MF_NOPVP: - r = map[m].flag.nopvp; + r = m->flag.nopvp; break; case MF_NOICEWALL: // [Valaris] - r = map[m].flag.noicewall; + r = m->flag.noicewall; break; case MF_SNOW: // [Valaris] - r = map[m].flag.snow; + r = m->flag.snow; break; case MF_FOG: // [Valaris] - r = map[m].flag.fog; + r = m->flag.fog; break; case MF_SAKURA: // [Valaris] - r = map[m].flag.sakura; + r = m->flag.sakura; break; case MF_LEAVES: // [Valaris] - r = map[m].flag.leaves; + r = m->flag.leaves; break; case MF_RAIN: // [Valaris] - r = map[m].flag.rain; + r = m->flag.rain; break; } } - push_val(st->stack, ScriptCode::INT, r); + push_val(st->stack, ByteCode::INT, r); } static void builtin_pvpon(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int m = map_mapname2mapid(str); - if (m >= 0 && !map[m].flag.pvp && !map[m].flag.nopvp) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr && !m->flag.pvp && !m->flag.nopvp) { - map[m].flag.pvp = 1; + m->flag.pvp = 1; if (battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] return; @@ -3598,11 +3384,11 @@ void builtin_pvpon(ScriptState *st) static void builtin_pvpoff(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int m = map_mapname2mapid(str); - if (m >= 0 && map[m].flag.pvp && map[m].flag.nopvp) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr && m->flag.pvp && m->flag.nopvp) { - map[m].flag.pvp = 0; + m->flag.pvp = 0; if (battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] return; @@ -3633,7 +3419,7 @@ static void builtin_emotion(ScriptState *st) { int type; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); if (type < 0 || type > 100) return; clif_emotion(map_id2bl(st->oid), type); @@ -3642,73 +3428,82 @@ void builtin_emotion(ScriptState *st) static void builtin_mapwarp(ScriptState *st) // Added by RoVeRT { - int x, y, m; + int x, y; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string mapname = conv_str(st, &AARGO2(2)); x0 = 0; y0 = 0; - x1 = map[map_mapname2mapid(mapname)].xs; - y1 = map[map_mapname2mapid(mapname)].ys; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - x = conv_num(st, &(st->stack->stack_data[st->start + 4])); - y = conv_num(st, &(st->stack->stack_data[st->start + 5])); - - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + x1 = m->xs; + y1 = m->ys; + dumb_string str = conv_str(st, &AARGO2(3)); + x = conv_num(st, &AARGO2(4)); + y = conv_num(st, &AARGO2(5)); + + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } static void builtin_cmdothernpc(ScriptState *st) // Added by RoVeRT { - const char *npc = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *command = conv_str(st, &(st->stack->stack_data[st->start + 3])); + dumb_string npc = conv_str(st, &AARGO2(2)); + dumb_string command = conv_str(st, &AARGO2(3)); - npc_command(map_id2sd(st->rid), npc, command); + npc_command(map_id2sd(st->rid), npc.c_str(), command.c_str()); } static -void builtin_mobcount_sub(dumb_ptr<block_list> bl, const char *event, int *c) +void builtin_mobcount_sub(dumb_ptr<block_list> bl, dumb_string event, int *c) { - if (strcmp(event, bl->as_mob()->npc_event) == 0) + using namespace operators; + if (event == bl->as_mob()->npc_event) (*c)++; } static void builtin_mobcount(ScriptState *st) // Added by RoVeRT { - int m, c = 0; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); + int c = 0; + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string event = conv_str(st, &AARGO2(3)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } map_foreachinarea(std::bind(builtin_mobcount_sub, ph::_1, event, &c), - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); - push_val(st->stack, ScriptCode::INT, (c - 1)); + push_val(st->stack, ByteCode::INT, (c - 1)); } static void builtin_marriage(ScriptState *st) { - const char *partner = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string partner = conv_str(st, &AARGO2(2)); dumb_ptr<map_session_data> sd = script_rid2sd(st); - dumb_ptr<map_session_data> p_sd = map_nick2sd(partner); + dumb_ptr<map_session_data> p_sd = map_nick2sd(partner.c_str()); if (sd == NULL || p_sd == NULL || pc_marriage(sd, p_sd) < 0) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } static @@ -3716,17 +3511,17 @@ void builtin_divorce(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - st->state = STOP; // rely on pc_divorce to restart + st->state = ScriptEndState::STOP; // rely on pc_divorce to restart sd->npc_flags.divorce = 1; if (sd == NULL || pc_divorce(sd) < 0) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } /*========================================== @@ -3737,15 +3532,14 @@ static void builtin_getitemname(ScriptState *st) { struct item_data *i_data; - char *item_name; struct script_data *data; - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - i_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + i_data = itemdb_searchname(name.c_str()); } else { @@ -3753,26 +3547,25 @@ void builtin_getitemname(ScriptState *st) i_data = itemdb_search(item_id); } - item_name = (char *) calloc(24, 1); + dumb_string item_name; if (i_data) - strncpy(item_name, i_data->jname, 23); + item_name = dumb_string::copy(i_data->jname); else - strncpy(item_name, "Unknown Item", 23); - - push_str(st->stack, ScriptCode::STR, item_name); + item_name = dumb_string::copy("Unknown Item"); + push_str(st->stack, ByteCode::STR, item_name); } static void builtin_getspellinvocation(ScriptState *st) { - const char *name = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string name = conv_str(st, &AARGO2(2)); - const char *invocation = magic_find_invocation(name); + const char *invocation = magic_find_invocation(name.str()); if (!invocation) invocation = "..."; - push_str(st->stack, ScriptCode::STR, strdup(invocation)); + push_str(st->stack, ByteCode::STR, dumb_string::copy(invocation)); } static @@ -3780,7 +3573,7 @@ void builtin_getpartnerid2(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->status.partner_id); + push_val(st->stack, ByteCode::INT, sd->status.partner_id); } /*========================================== @@ -3799,30 +3592,30 @@ void builtin_getinventorylist(ScriptState *st) if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) { - pc_setreg(sd, add_str("@inventorylist_id") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_id") + (j << 24), sd->status.inventory[i].nameid); - pc_setreg(sd, add_str("@inventorylist_amount") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_amount") + (j << 24), sd->status.inventory[i].amount); - pc_setreg(sd, add_str("@inventorylist_equip") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_equip") + (j << 24), uint16_t(sd->status.inventory[i].equip)); - pc_setreg(sd, add_str("@inventorylist_refine") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_refine") + (j << 24), sd->status.inventory[i].refine); - pc_setreg(sd, add_str("@inventorylist_identify") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_identify") + (j << 24), sd->status.inventory[i].identify); - pc_setreg(sd, add_str("@inventorylist_attribute") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_attribute") + (j << 24), sd->status.inventory[i].attribute); - pc_setreg(sd, add_str("@inventorylist_card1") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card1") + (j << 24), sd->status.inventory[i].card[0]); - pc_setreg(sd, add_str("@inventorylist_card2") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card2") + (j << 24), sd->status.inventory[i].card[1]); - pc_setreg(sd, add_str("@inventorylist_card3") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card3") + (j << 24), sd->status.inventory[i].card[2]); - pc_setreg(sd, add_str("@inventorylist_card4") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card4") + (j << 24), sd->status.inventory[i].card[3]); j++; } } - pc_setreg(sd, add_str("@inventorylist_count"), j); + pc_setreg(sd, variable_names.intern("@inventorylist_count"), j); } static @@ -3842,18 +3635,18 @@ void builtin_getactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv) { - pc_setreg(sd, add_str("@skilllist_id") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_id") + (count << 24), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, add_str("@skilllist_lv") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_lv") + (count << 24), sd->status.skill[skill_id].lv); - pc_setreg(sd, add_str("@skilllist_flag") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_flag") + (count << 24), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, add_str("@skilllist_name$") + (count << 24), - skill_name(skill_id)); + pc_setregstr(sd, variable_names.intern("@skilllist_name$") + (count << 24), + skill_name(skill_id).c_str()); ++count; } } - pc_setreg(sd, add_str("@skilllist_count"), count); + pc_setreg(sd, variable_names.intern("@skilllist_count"), count); } @@ -3873,25 +3666,25 @@ void builtin_getunactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv && !bool(sd->status.skill[skill_id].flags & SkillFlags::POOL_ACTIVATED)) { - pc_setreg(sd, add_str("@skilllist_id") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_id") + (count << 24), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, add_str("@skilllist_lv") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_lv") + (count << 24), sd->status.skill[skill_id].lv); - pc_setreg(sd, add_str("@skilllist_flag") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_flag") + (count << 24), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, add_str("@skilllist_name$") + (count << 24), - skill_name(skill_id)); + pc_setregstr(sd, variable_names.intern("@skilllist_name$") + (count << 24), + skill_name(skill_id).c_str()); ++count; } } - pc_setreg(sd, add_str("@skilllist_count"), count); + pc_setreg(sd, variable_names.intern("@skilllist_count"), count); } static void builtin_poolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - SkillID skill_id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + SkillID skill_id = SkillID(conv_num(st, &AARGO2(2))); skill_pool_activate(sd, skill_id); clif_skillinfoblock(sd); @@ -3902,7 +3695,7 @@ static void builtin_unpoolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - SkillID skill_id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + SkillID skill_id = SkillID(conv_num(st, &AARGO2(2))); skill_pool_deactivate(sd, skill_id); clif_skillinfoblock(sd); @@ -3925,18 +3718,18 @@ void builtin_misceffect(ScriptState *st) { int type; int id = 0; - const char *name = NULL; + dumb_string name; dumb_ptr<block_list> bl = NULL; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); - if (st->end > st->start + 3) + if (HARGO2(3)) { - struct script_data *sdata = &(st->stack->stack_data[st->start + 3]); + struct script_data *sdata = &AARGO2(3); get_val(st, sdata); - if (sdata->type == ScriptCode::STR || sdata->type == ScriptCode::CONSTSTR) + if (sdata->type == ByteCode::STR || sdata->type == ByteCode::CONSTSTR) name = conv_str(st, sdata); else id = conv_num(st, sdata); @@ -3944,7 +3737,7 @@ void builtin_misceffect(ScriptState *st) if (name) { - dumb_ptr<map_session_data> sd = map_nick2sd(name); + dumb_ptr<map_session_data> sd = map_nick2sd(name.c_str()); if (sd) bl = sd; } @@ -3978,7 +3771,7 @@ void builtin_specialeffect(ScriptState *st) clif_specialeffect(bl, conv_num(st, - &(st->stack->stack_data[st->start + 2])), + &AARGO2(2)), 0); } @@ -3993,7 +3786,7 @@ void builtin_specialeffect2(ScriptState *st) clif_specialeffect(sd, conv_num(st, - &(st->stack->stack_data[st->start + 2])), + &AARGO2(2)), 0); } @@ -4030,7 +3823,7 @@ void builtin_unequipbyid(ScriptState *st) if (sd == NULL) return; - EQUIP slot_id = EQUIP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + EQUIP slot_id = EQUIP(conv_num(st, &AARGO2(2))); if (slot_id >= EQUIP() && slot_id < EQUIP::COUNT && sd->equip_index[slot_id] >= 0) @@ -4053,9 +3846,9 @@ void builtin_gmcommand(ScriptState *st) dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - const char *cmd = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string cmd = conv_str(st, &AARGO2(2)); - is_atcommand(sd->fd, sd, cmd, 99); + is_atcommand(sd->fd, sd, cmd.c_str(), 99); } @@ -4070,28 +3863,28 @@ void builtin_npcwarp(ScriptState *st) int x, y; dumb_ptr<npc_data> nd = NULL; - x = conv_num(st, &(st->stack->stack_data[st->start + 2])); - y = conv_num(st, &(st->stack->stack_data[st->start + 3])); - const char *npc = conv_str(st, &(st->stack->stack_data[st->start + 4])); - nd = npc_name2id(npc); + x = conv_num(st, &AARGO2(2)); + y = conv_num(st, &AARGO2(3)); + dumb_string npc = conv_str(st, &AARGO2(4)); + nd = npc_name2id(npc.c_str()); if (!nd) return; - short m = nd->bl_m; + map_local *m = nd->bl_m; /* Crude sanity checks. */ - if (m < 0 || !nd->bl_prev - || x < 0 || x > map[m].xs -1 - || y < 0 || y > map[m].ys - 1) + if (m == nullptr || !nd->bl_prev + || x < 0 || x > m->xs -1 + || y < 0 || y > m->ys - 1) return; - npc_enable(npc, 0); + npc_enable(npc.c_str(), 0); map_delblock(nd); /* [Freeyorp] */ nd->bl_x = x; nd->bl_y = y; map_addblock(nd); - npc_enable(npc, 1); + npc_enable(npc.c_str(), 1); } @@ -4103,12 +3896,11 @@ void builtin_npcwarp(ScriptState *st) static void builtin_message(ScriptState *st) { - dumb_ptr<map_session_data> pl_sd = NULL; + dumb_string player = conv_str(st, &AARGO2(2)); + dumb_string msg = conv_str(st, &AARGO2(3)); - const char *player = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *msg = conv_str(st, &(st->stack->stack_data[st->start + 3])); - - if ((pl_sd = map_nick2sd(player)) == NULL) + dumb_ptr<map_session_data> pl_sd = map_nick2sd(player.c_str()); + if (pl_sd == NULL) return; clif_displaymessage(pl_sd->fd, msg); @@ -4123,19 +3915,14 @@ void builtin_message(ScriptState *st) static void builtin_npctalk(ScriptState *st) { - char message[255]; - dumb_ptr<npc_data> nd = map_id_as_npc(st->oid); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string str = conv_str(st, &AARGO2(2)); if (nd) { - memcpy(message, nd->name, 24); - strcat(message, " : "); - strcat(message, str); - clif_message(nd, message); + std::string message = std::string(nd->name) + " : " + str.c_str(); + clif_message(nd, message.c_str()); } - } /*========================================== @@ -4147,7 +3934,7 @@ void builtin_getlook(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - LOOK type = LOOK(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + LOOK type = LOOK(conv_num(st, &AARGO2(2))); int val = -1; switch (type) { @@ -4179,7 +3966,7 @@ void builtin_getlook(ScriptState *st) break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -4190,27 +3977,27 @@ static void builtin_getsavepoint(ScriptState *st) { int x, y, type; - char *mapname; dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); x = sd->status.save_point.x; y = sd->status.save_point.y; switch (type) { case 0: - mapname = (char*)calloc(24, 1); - strncpy(mapname, sd->status.save_point.map, 23); - push_str(st->stack, ScriptCode::STR, mapname); + { + dumb_string mapname = dumb_string::copy(sd->status.save_point.map); + push_str(st->stack, ByteCode::STR, mapname); + } break; case 1: - push_val(st->stack, ScriptCode::INT, x); + push_val(st->stack, ByteCode::INT, x); break; case 2: - push_val(st->stack, ScriptCode::INT, y); + push_val(st->stack, ByteCode::INT, y); break; } } @@ -4220,30 +4007,33 @@ void builtin_getsavepoint(ScriptState *st) *------------------------------------------ */ static -void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, const char *event) +void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, dumb_string event) { - pc_addeventtimer(bl->as_player(), tick, event); + pc_addeventtimer(bl->as_player(), tick, event.c_str()); } static void builtin_areatimer(ScriptState *st) { - int m; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 7]))); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 8])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(7))); + dumb_string event = conv_str(st, &AARGO2(8)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areatimer_sub, ph::_1, tick, event), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } /*========================================== @@ -4256,20 +4046,20 @@ void builtin_isin(ScriptState *st) int x1, y1, x2, y2; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x2 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y2 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + dumb_string str = conv_str(st, &AARGO2(2)); + x1 = conv_num(st, &AARGO2(3)); + y1 = conv_num(st, &AARGO2(4)); + x2 = conv_num(st, &AARGO2(5)); + y2 = conv_num(st, &AARGO2(6)); if (!sd) return; - push_val(st->stack, ScriptCode::INT, + using namespace operators; + push_val(st->stack, ByteCode::INT, (sd->bl_x >= x1 && sd->bl_x <= x2) && (sd->bl_y >= y1 && sd->bl_y <= y2) - && (!strcmp(str, map[sd->bl_m].name))); - + && (str == sd->bl_m->name)); } // Trigger the shop on a (hopefully) nearby shop NPC @@ -4282,7 +4072,7 @@ void builtin_shop(ScriptState *st) if (!sd) return; - nd = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + nd = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); if (!nd) return; @@ -4299,7 +4089,7 @@ void builtin_isdead(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, pc_isdead(sd)); + push_val(st->stack, ByteCode::INT, pc_isdead(sd)); } /*======================================== @@ -4309,18 +4099,18 @@ void builtin_isdead(ScriptState *st) static void builtin_fakenpcname(ScriptState *st) { - const char *name = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *newname = conv_str(st, &(st->stack->stack_data[st->start + 3])); - int newsprite = conv_num(st, &(st->stack->stack_data[st->start + 4])); - dumb_ptr<npc_data> nd = npc_name2id(name); + dumb_string name = conv_str(st, &AARGO2(2)); + dumb_string newname = conv_str(st, &AARGO2(3)); + int newsprite = conv_num(st, &AARGO2(4)); + dumb_ptr<npc_data> nd = npc_name2id(name.c_str()); if (!nd) return; - strzcpy(nd->name, newname, sizeof(nd->name)); + strzcpy(nd->name, newname.c_str(), sizeof(nd->name)); nd->npc_class = newsprite; // Refresh this npc - npc_enable(name, 0); - npc_enable(name, 1); + npc_enable(name.c_str(), 0); + npc_enable(name.c_str(), 1); } @@ -4333,7 +4123,7 @@ void builtin_getx(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->bl_x); + push_val(st->stack, ByteCode::INT, sd->bl_x); } /*============================ @@ -4345,7 +4135,7 @@ void builtin_gety(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->bl_y); + push_val(st->stack, ByteCode::INT, sd->bl_y); } /* @@ -4357,7 +4147,7 @@ void builtin_getmap(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); // A map_data lives essentially forever. - push_str(st->stack, ScriptCode::CONSTSTR, map[sd->bl_m].name); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake(sd->bl_m->name)); } // @@ -4368,13 +4158,14 @@ void builtin_getmap(ScriptState *st) *------------------------------------------ */ static -ScriptCode get_com(const ScriptCode *script, int *pos_) +ByteCode get_com(ScriptPointer *script) { - if (static_cast<uint8_t>(script[*pos_]) >= 0x80) + if (static_cast<uint8_t>(script->peek()) >= 0x80) { - return ScriptCode::INT; + // synthetic! Does not advance pos yet. + return ByteCode::INT; } - return script[(*pos_)++]; + return script->pop(); } /*========================================== @@ -4382,18 +4173,19 @@ ScriptCode get_com(const ScriptCode *script, int *pos_) *------------------------------------------ */ static -int get_num(const ScriptCode *scr, int *pos_) +int get_num(ScriptPointer *scr) { - const uint8_t *script = reinterpret_cast<const uint8_t *>(scr); - int i, j; - i = 0; - j = 0; - while (script[*pos_] >= 0xc0) + int i = 0; + int j = 0; + uint8_t val; + do { - i += (script[(*pos_)++] & 0x7f) << j; + val = static_cast<uint8_t>(scr->pop()); + i += (val & 0x7f) << j; j += 6; } - return i + ((script[(*pos_)++] & 0x7f) << j); + while (val >= 0xc0); + return i; } /*========================================== @@ -4403,20 +4195,22 @@ int get_num(const ScriptCode *scr, int *pos_) static int pop_val(ScriptState *st) { - if (st->stack->sp <= 0) + if (st->stack->stack_datav.empty()) return 0; - st->stack->sp--; - get_val(st, &(st->stack->stack_data[st->stack->sp])); - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::INT) - return st->stack->stack_data[st->stack->sp].u.num; - return 0; + script_data& back = st->stack->stack_datav.back(); + get_val(st, &back); + int rv = 0; + if (back.type == ByteCode::INT) + rv = back.u.num; + st->stack->stack_datav.pop_back(); + return rv; } static bool isstr(struct script_data& c) { - return c.type == ScriptCode::STR - || c.type == ScriptCode::CONSTSTR; + return c.type == ByteCode::STR + || c.type == ByteCode::CONSTSTR; } /*========================================== @@ -4426,36 +4220,29 @@ bool isstr(struct script_data& c) static void op_add(ScriptState *st) { - st->stack->sp--; - get_val(st, &(st->stack->stack_data[st->stack->sp])); - get_val(st, &(st->stack->stack_data[st->stack->sp - 1])); + get_val(st, &st->stack->stack_datav.back()); + script_data back = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &st->stack->stack_datav.back()); + script_data& back1 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); - if (isstr(st->stack->stack_data[st->stack->sp]) - || isstr(st->stack->stack_data[st->stack->sp - 1])) + if (!(isstr(back) || isstr(back1))) { - conv_str(st, &(st->stack->stack_data[st->stack->sp])); - conv_str(st, &(st->stack->stack_data[st->stack->sp - 1])); - } - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::INT) - { // ii - st->stack->stack_data[st->stack->sp - 1].u.num += - st->stack->stack_data[st->stack->sp].u.num; + back1.u.num += back.u.num; } else - { // ssの予定 - char *buf; - buf = (char *) - calloc(strlen(st->stack->stack_data[st->stack->sp - 1].u.str) + - strlen(st->stack->stack_data[st->stack->sp].u.str) + 1, - 1); - strcpy(buf, st->stack->stack_data[st->stack->sp - 1].u.str); - strcat(buf, st->stack->stack_data[st->stack->sp].u.str); - if (st->stack->stack_data[st->stack->sp - 1].type == ScriptCode::STR) - free(const_cast<char *>(st->stack->stack_data[st->stack->sp - 1].u.str)); - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::STR) - free(const_cast<char *>(st->stack->stack_data[st->stack->sp].u.str)); - st->stack->stack_data[st->stack->sp - 1].type = ScriptCode::STR; - st->stack->stack_data[st->stack->sp - 1].u.str = buf; + { + dumb_string sb = conv_str(st, &back); + dumb_string sb1 = conv_str(st, &back1); + // ssの予定 + std::string buf = sb1.str() + sb.str(); + if (back1.type == ByteCode::STR) + back1.u.str.delete_(); + if (back.type == ByteCode::STR) + back.u.str.delete_(); + back1.type = ByteCode::STR; + back1.u.str = dumb_string::copys(buf); } } @@ -4464,43 +4251,37 @@ void op_add(ScriptState *st) *------------------------------------------ */ static -void op_2str(ScriptState *st, ScriptCode op, int sp1, int sp2) +void op_2str(ScriptState *st, ByteCode op, dumb_string s1, dumb_string s2) { - const char *s1 = st->stack->stack_data[sp1].u.str; - const char *s2 = st->stack->stack_data[sp2].u.str; int a = 0; + using namespace operators; switch (op) { - case ScriptCode::EQ: - a = (strcmp(s1, s2) == 0); + case ByteCode::EQ: + a = s1 == s2; break; - case ScriptCode::NE: - a = (strcmp(s1, s2) != 0); + case ByteCode::NE: + a = s1 != s2; break; - case ScriptCode::GT: - a = (strcmp(s1, s2) > 0); + case ByteCode::GT: + a = s1 > s2; break; - case ScriptCode::GE: - a = (strcmp(s1, s2) >= 0); + case ByteCode::GE: + a = s1 >= s2; break; - case ScriptCode::LT: - a = (strcmp(s1, s2) < 0); + case ByteCode::LT: + a = s1 < s2; break; - case ScriptCode::LE: - a = (strcmp(s1, s2) <= 0); + case ByteCode::LE: + a = s1 <= s2; break; default: PRINTF("illegal string operater\n"); break; } - push_val(st->stack, ScriptCode::INT, a); - - if (st->stack->stack_data[sp1].type == ScriptCode::STR) - free(const_cast<char *>(s1)); - if (st->stack->stack_data[sp2].type == ScriptCode::STR) - free(const_cast<char *>(s2)); + push_val(st->stack, ByteCode::INT, a); } /*========================================== @@ -4508,63 +4289,63 @@ void op_2str(ScriptState *st, ScriptCode op, int sp1, int sp2) *------------------------------------------ */ static -void op_2num(ScriptState *st, ScriptCode op, int i1, int i2) +void op_2num(ScriptState *st, ByteCode op, int i1, int i2) { switch (op) { - case ScriptCode::SUB: + case ByteCode::SUB: i1 -= i2; break; - case ScriptCode::MUL: + case ByteCode::MUL: i1 *= i2; break; - case ScriptCode::DIV: + case ByteCode::DIV: i1 /= i2; break; - case ScriptCode::MOD: + case ByteCode::MOD: i1 %= i2; break; - case ScriptCode::AND: + case ByteCode::AND: i1 &= i2; break; - case ScriptCode::OR: + case ByteCode::OR: i1 |= i2; break; - case ScriptCode::XOR: + case ByteCode::XOR: i1 ^= i2; break; - case ScriptCode::LAND: + case ByteCode::LAND: i1 = i1 && i2; break; - case ScriptCode::LOR: + case ByteCode::LOR: i1 = i1 || i2; break; - case ScriptCode::EQ: + case ByteCode::EQ: i1 = i1 == i2; break; - case ScriptCode::NE: + case ByteCode::NE: i1 = i1 != i2; break; - case ScriptCode::GT: + case ByteCode::GT: i1 = i1 > i2; break; - case ScriptCode::GE: + case ByteCode::GE: i1 = i1 >= i2; break; - case ScriptCode::LT: + case ByteCode::LT: i1 = i1 < i2; break; - case ScriptCode::LE: + case ByteCode::LE: i1 = i1 <= i2; break; - case ScriptCode::R_SHIFT: + case ByteCode::R_SHIFT: i1 = i1 >> i2; break; - case ScriptCode::L_SHIFT: + case ByteCode::L_SHIFT: i1 = i1 << i2; break; } - push_val(st->stack, ScriptCode::INT, i1); + push_val(st->stack, ByteCode::INT, i1); } /*========================================== @@ -4572,34 +4353,35 @@ void op_2num(ScriptState *st, ScriptCode op, int i1, int i2) *------------------------------------------ */ static -void op_2(ScriptState *st, ScriptCode op) +void op_2(ScriptState *st, ByteCode op) { - int i1, i2; - const char *s1 = NULL, *s2 = NULL; + // pop_val has unfortunate implications here + script_data d2 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &d2); + script_data d1 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &d1); - i2 = pop_val(st); - if (isstr(st->stack->stack_data[st->stack->sp])) - s2 = st->stack->stack_data[st->stack->sp].u.str; - - i1 = pop_val(st); - if (isstr(st->stack->stack_data[st->stack->sp])) - s1 = st->stack->stack_data[st->stack->sp].u.str; - - if (s1 != NULL && s2 != NULL) + if (isstr(d1) && isstr(d2)) { // ss => op_2str - op_2str(st, op, st->stack->sp, st->stack->sp + 1); + op_2str(st, op, d1.u.str, d2.u.str); + if (d1.type == ByteCode::STR) + d1.u.str.delete_(); + if (d2.type == ByteCode::STR) + d2.u.str.delete_(); } - else if (s1 == NULL && s2 == NULL) + else if (!(isstr(d1) || isstr(d2))) { // ii => op_2num - op_2num(st, op, i1, i2); + op_2num(st, op, d1.u.num, d2.u.num); } else { // si,is => error - PRINTF("script: op_2: int&str, str&int not allow."); - push_val(st->stack, ScriptCode::INT, 0); + PRINTF("script: op_2: int&str, str&int not allow.\n"); + push_val(st->stack, ByteCode::INT, 0); } } @@ -4608,23 +4390,23 @@ void op_2(ScriptState *st, ScriptCode op) *------------------------------------------ */ static -void op_1num(ScriptState *st, ScriptCode op) +void op_1num(ScriptState *st, ByteCode op) { int i1; i1 = pop_val(st); switch (op) { - case ScriptCode::NEG: + case ByteCode::NEG: i1 = -i1; break; - case ScriptCode::NOT: + case ByteCode::NOT: i1 = ~i1; break; - case ScriptCode::LNOT: + case ByteCode::LNOT: i1 = !i1; break; } - push_val(st->stack, ScriptCode::INT, i1); + push_val(st->stack, ByteCode::INT, i1); } /*========================================== @@ -4633,102 +4415,94 @@ void op_1num(ScriptState *st, ScriptCode op) */ void run_func(ScriptState *st) { - int i, start_sp, end_sp, func; - - end_sp = st->stack->sp; - for (i = end_sp - 1; i >= 0 && st->stack->stack_data[i].type != ScriptCode::ARG; - i--); - if (i == 0) + size_t end_sp = st->stack->stack_datav.size(); + size_t start_sp = end_sp - 1; + while (st->stack->stack_datav[start_sp].type != ByteCode::ARG) { - if (battle_config.error_log) - PRINTF("function not found\n"); -// st->stack->sp=0; - st->state = END; - return; + start_sp--; + if (start_sp == 0) + { + if (battle_config.error_log) + PRINTF("function not found\n"); + st->state = ScriptEndState::END; + return; + } } - start_sp = i - 1; - st->start = i - 1; + // the func is before the arg + start_sp--; + st->start = start_sp; st->end = end_sp; - func = st->stack->stack_data[st->start].u.num; - if (st->stack->stack_data[st->start].type != ScriptCode::NAME - || str_data[func].type != ScriptCode::FUNC) + size_t func = st->stack->stack_datav[st->start].u.num; + if (st->stack->stack_datav[st->start].type != ByteCode::FUNC_REF) { PRINTF("run_func: not function and command! \n"); -// st->stack->sp=0; - st->state = END; + st->state = ScriptEndState::END; return; } -#ifdef DEBUG_RUN - if (battle_config.etc_log) + + if (DEBUG_RUN && battle_config.etc_log) { - PRINTF("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str, - func, str_data[func].type); + PRINTF("run_func : %s\n", + builtin_functions[func].name); PRINTF("stack dump :"); - for (i = 0; i < end_sp; i++) + for (script_data& d : st->stack->stack_datav) { - switch (st->stack->stack_data[i].type) + // this is not *nearly* complete enough to be useful ... + switch (d.type) { - case ScriptCode::INT: - PRINTF(" int(%d)", st->stack->stack_data[i].u.num); + case ByteCode::INT: + PRINTF(" int(%d)", d.u.num); + break; + case ByteCode::RETINFO: + PRINTF(" retinfo(%p)", static_cast<const void *>(d.u.script)); + break; + case ByteCode::PARAM_: + PRINTF(" param(%d)", d.u.num); break; - case ScriptCode::NAME: - PRINTF(" name(%s)", - str_buf + - str_data[st->stack->stack_data[i].u.num].str); + case ByteCode::VARIABLE: + PRINTF(" name(%s)", variable_names.outtern(d.u.num)); break; - case ScriptCode::ARG: + case ByteCode::ARG: PRINTF(" arg"); break; - case ScriptCode::POS: - PRINTF(" pos(%d)", st->stack->stack_data[i].u.num); + case ByteCode::POS: + PRINTF(" pos(%d)", d.u.num); break; default: - PRINTF(" %d,%d", st->stack->stack_data[i].type, - st->stack->stack_data[i].u.num); + PRINTF(" %d,%d", d.type, d.u.num); } } PRINTF("\n"); } -#endif - if (str_data[func].func) - { - str_data[func].func(st); - } - else - { - if (battle_config.error_log) - PRINTF("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str, - func, str_data[func].type); - push_val(st->stack, ScriptCode::INT, 0); - } + builtin_functions[func].func(st); pop_stack(st->stack, start_sp, end_sp); - if (st->state == RETFUNC) + if (st->state == ScriptEndState::RETFUNC) { // ユーザー定義関数からの復帰 int olddefsp = st->defsp; pop_stack(st->stack, st->defsp, start_sp); // 復帰に邪魔なスタック削除 if (st->defsp < 4 - || st->stack->stack_data[st->defsp - 1].type != ScriptCode::RETINFO) + || st->stack->stack_datav[st->defsp - 1].type != ByteCode::RETINFO) { PRINTF("script:run_func (return) return without callfunc or callsub!\n"); - st->state = END; + st->state = ScriptEndState::END; return; } assert (olddefsp == st->defsp); // pretty sure it hasn't changed yet - st->script = conv_script(st, &(st->stack->stack_data[olddefsp - 1])); // スクリプトを復元 - st->pos = conv_num(st, &(st->stack->stack_data[olddefsp - 2])); // スクリプト位置の復元 - st->defsp = conv_num(st, &(st->stack->stack_data[olddefsp - 3])); // 基準スタックポインタを復元 + st->scriptp.code = conv_script(st, &st->stack->stack_datav[olddefsp - 1]); // スクリプトを復元 + st->scriptp.pos = conv_num(st, &st->stack->stack_datav[olddefsp - 2]); // スクリプト位置の復元 + st->defsp = conv_num(st, &st->stack->stack_datav[olddefsp - 3]); // 基準スタックポインタを復元 // Number of arguments. - i = conv_num(st, &(st->stack->stack_data[olddefsp - 4])); // 引数の数所得 + int i = conv_num(st, &st->stack->stack_datav[olddefsp - 4]); // 引数の数所得 assert (i == 0); pop_stack(st->stack, olddefsp - 4 - i, olddefsp); // 要らなくなったスタック(引数と復帰用データ)削除 - st->state = GOTO; + st->state = ScriptEndState::GOTO; } } @@ -4737,205 +4511,190 @@ void run_func(ScriptState *st) *------------------------------------------ */ static -void run_script_main(const ScriptCode *script, int pos_, int, int, - ScriptState *st, const ScriptCode *rootscript) +void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) { - int rerun_pos; int cmdcount = script_config.check_cmdcount; int gotocount = script_config.check_gotocount; struct script_stack *stack = st->stack; - st->defsp = stack->sp; - st->script = script; + st->defsp = stack->stack_datav.size(); - rerun_pos = st->pos; - for (st->state = 0; st->state == 0;) + int rerun_pos = st->scriptp.pos; + st->state = ScriptEndState::ZERO; + while (st->state == ScriptEndState::ZERO) { - switch (ScriptCode c = get_com(script, &st->pos)) + switch (ByteCode c = get_com(&st->scriptp)) { - case ScriptCode::EOL: - if (stack->sp != st->defsp) + case ByteCode::EOL: + if (stack->stack_datav.size() != st->defsp) { if (battle_config.error_log) - PRINTF("stack.sp (%d) != default (%d)\n", stack->sp, + PRINTF("stack.sp (%zu) != default (%d)\n", + stack->stack_datav.size(), st->defsp); - stack->sp = st->defsp; + stack->stack_datav.resize(st->defsp); } - rerun_pos = st->pos; + rerun_pos = st->scriptp.pos; break; - case ScriptCode::INT: - push_val(stack, ScriptCode::INT, get_num(script, &st->pos)); + case ByteCode::INT: + // synthesized! + push_val(stack, ByteCode::INT, get_num(&st->scriptp)); break; - case ScriptCode::POS: - case ScriptCode::NAME: - push_val(stack, c, (*(const int *)(script + st->pos)) & 0xffffff); - st->pos += 3; + + case ByteCode::POS: + case ByteCode::VARIABLE: + case ByteCode::FUNC_REF: + // Note that these 3 have *very* different meanings, + // despite being encoded similarly. + { + int arg = 0; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 0; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 8; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 16; + push_val(stack, c, arg); + } break; - case ScriptCode::ARG: + case ByteCode::ARG: push_val(stack, c, 0); break; - case ScriptCode::STR: - push_str(stack, ScriptCode::CONSTSTR, reinterpret_cast<const char *>(script + st->pos)); - while (script[st->pos++] != ScriptCode::NOP); + case ByteCode::STR: + // ScriptPointer.pops() leaves it .pos pointing to the \0. + push_str(stack, ByteCode::CONSTSTR, dumb_string::fake(st->scriptp.pops())); break; - case ScriptCode::FUNC: + case ByteCode::FUNC_: run_func(st); - if (st->state == GOTO) + if (st->state == ScriptEndState::GOTO) { - rerun_pos = st->pos; - script = st->script; - st->state = 0; + rerun_pos = st->scriptp.pos; + st->state = ScriptEndState::ZERO; if (gotocount > 0 && (--gotocount) <= 0) { PRINTF("run_script: infinity loop !\n"); - st->state = END; + st->state = ScriptEndState::END; } } break; - case ScriptCode::ADD: + case ByteCode::ADD: op_add(st); break; - case ScriptCode::SUB: - case ScriptCode::MUL: - case ScriptCode::DIV: - case ScriptCode::MOD: - case ScriptCode::EQ: - case ScriptCode::NE: - case ScriptCode::GT: - case ScriptCode::GE: - case ScriptCode::LT: - case ScriptCode::LE: - case ScriptCode::AND: - case ScriptCode::OR: - case ScriptCode::XOR: - case ScriptCode::LAND: - case ScriptCode::LOR: - case ScriptCode::R_SHIFT: - case ScriptCode::L_SHIFT: + case ByteCode::SUB: + case ByteCode::MUL: + case ByteCode::DIV: + case ByteCode::MOD: + case ByteCode::EQ: + case ByteCode::NE: + case ByteCode::GT: + case ByteCode::GE: + case ByteCode::LT: + case ByteCode::LE: + case ByteCode::AND: + case ByteCode::OR: + case ByteCode::XOR: + case ByteCode::LAND: + case ByteCode::LOR: + case ByteCode::R_SHIFT: + case ByteCode::L_SHIFT: op_2(st, c); break; - case ScriptCode::NEG: - case ScriptCode::NOT: - case ScriptCode::LNOT: + case ByteCode::NEG: + case ByteCode::NOT: + case ByteCode::LNOT: op_1num(st, c); break; - case ScriptCode::NOP: - st->state = END; + case ByteCode::NOP: + st->state = ScriptEndState::END; break; default: if (battle_config.error_log) - PRINTF("unknown command : %d @ %d\n", c, pos_); - st->state = END; + PRINTF("unknown command : %d @ %zu\n", + c, st->scriptp.pos); + st->state = ScriptEndState::END; break; } if (cmdcount > 0 && (--cmdcount) <= 0) { PRINTF("run_script: infinity loop !\n"); - st->state = END; + st->state = ScriptEndState::END; } } switch (st->state) { - case STOP: + case ScriptEndState::STOP: break; - case END: + case ScriptEndState::END: { dumb_ptr<map_session_data> sd = map_id2sd(st->rid); - st->pos = -1; + st->scriptp.code = nullptr; + st->scriptp.pos = -1; if (sd && sd->npc_id == st->oid) npc_event_dequeue(sd); } break; - case RERUNLINE: - { - st->pos = rerun_pos; - } + case ScriptEndState::RERUNLINE: + st->scriptp.pos = rerun_pos; break; } - if (st->state != END) + if (st->state != ScriptEndState::END) { // 再開するためにスタック情報を保存 dumb_ptr<map_session_data> sd = map_id2sd(st->rid); - if (sd /* && sd->npc_stackbuf==NULL */ ) + if (sd) { - if (sd->npc_stackbuf) - free(sd->npc_stackbuf); - sd->npc_stackbuf = (struct script_data *) - calloc(sizeof(stack->stack_data[0]) * stack->sp_max, 1); - memcpy(sd->npc_stackbuf, stack->stack_data, - sizeof(stack->stack_data[0]) * stack->sp_max); - sd->npc_stack = stack->sp; - sd->npc_stackmax = stack->sp_max; - sd->npc_script = script; + sd->npc_stackbuf = stack->stack_datav; + sd->npc_script = st->scriptp.code; + // sd->npc_pos is set later ... ??? sd->npc_scriptroot = rootscript; } } - } /*========================================== * スクリプトの実行 *------------------------------------------ */ -int run_script(const ScriptCode *script, int pos_, int rid, int oid) +int run_script(ScriptPointer sp, int rid, int oid) { - return run_script_l(script, pos_, rid, oid, 0, NULL); + return run_script_l(sp, rid, oid, 0, NULL); } -int run_script_l(const ScriptCode *script, int pos_, int rid, int oid, +int run_script_l(ScriptPointer sp, int rid, int oid, int args_nr, argrec_t *args) { struct script_stack stack; ScriptState st; dumb_ptr<map_session_data> sd = map_id2sd(rid); - const ScriptCode *rootscript = script; + const ScriptBuffer *rootscript = sp.code; int i; - if (script == NULL || pos_ < 0) + if (sp.code == NULL || sp.pos >> 24) return -1; - if (sd && sd->npc_stackbuf && sd->npc_scriptroot == rootscript) + if (sd && !sd->npc_stackbuf.empty() && sd->npc_scriptroot == rootscript) { // 前回のスタックを復帰 - script = sd->npc_script; - stack.sp = sd->npc_stack; - stack.sp_max = sd->npc_stackmax; - stack.stack_data = (struct script_data *) - calloc(stack.sp_max, sizeof(stack.stack_data[0])); - memcpy(stack.stack_data, sd->npc_stackbuf, - sizeof(stack.stack_data[0]) * stack.sp_max); - free(sd->npc_stackbuf); - sd->npc_stackbuf = NULL; - } - else - { - // スタック初期化 - stack.sp = 0; - stack.sp_max = 64; - stack.stack_data = (struct script_data *) - calloc(stack.sp_max, sizeof(stack.stack_data[0])); + sp.code = sd->npc_script; + stack.stack_datav = std::move(sd->npc_stackbuf); } st.stack = &stack; - st.pos = pos_; + st.scriptp = sp; st.rid = rid; st.oid = oid; for (i = 0; i < args_nr; i++) { if (args[i].name[strlen(args[i].name) - 1] == '$') - pc_setregstr(sd, add_str(args[i].name), args[i].v.s); + pc_setregstr(sd, variable_names.intern(args[i].name), args[i].v.s); else - pc_setreg(sd, add_str(args[i].name), args[i].v.i); + pc_setreg(sd, variable_names.intern(args[i].name), args[i].v.i); } - run_script_main(script, pos_, rid, oid, &st, rootscript); + run_script_main(&st, rootscript); - free(stack.stack_data); - stack.stack_data = NULL; - return st.pos; + stack.stack_datav.clear(); + return st.scriptp.pos; } /*========================================== @@ -4955,16 +4714,11 @@ void mapreg_setreg(int num, int val) */ void mapreg_setregstr(int num, const char *str) { - char *p = mapregstr_db.get(num); - if (p) - free(p); - if (!str || !*str) - p = NULL; + mapregstr_db.erase(num); else - p = strdup(str); + mapregstr_db.insert(num, str); - mapregstr_db.put(num, p); mapreg_dirty = 1; } @@ -4994,12 +4748,11 @@ void script_load_mapreg(void) record<','>(&buf1), &buf2))) { - int s = add_str(buf1.c_str()); + int s = variable_names.intern(buf1); int key = (index << 24) | s; if (buf1.back() == '$') { - char *p = strdup(buf2.c_str()); - mapregstr_db.put(key, p); + mapregstr_db.insert(key, buf2); } else { @@ -5027,7 +4780,7 @@ static void script_save_mapreg_intsub(int key, int data, FILE *fp) { int num = key & 0x00ffffff, i = key >> 24; - char *name = str_buf + str_data[num].str; + const std::string& name = variable_names.outtern(num); if (name[1] != '@') { if (i == 0) @@ -5038,10 +4791,10 @@ void script_save_mapreg_intsub(int key, int data, FILE *fp) } static -void script_save_mapreg_strsub(int key, char *data, FILE *fp) +void script_save_mapreg_strsub(int key, const std::string& data, FILE *fp) { int num = key & 0x00ffffff, i = key >> 24; - char *name = str_buf + str_data[num].str; + const std::string& name = variable_names.outtern(num); if (name[1] != '@') { if (i == 0) @@ -5084,49 +4837,21 @@ void script_config_read() script_config.check_gotocount = 512; } -/*========================================== - * 終了 - *------------------------------------------ - */ - -static -void mapregstr_db_final(char *data) -{ - free(data); -} - -static -void userfunc_db_final(const ScriptCode *data) -{ - free(const_cast<ScriptCode *>(data)); -} - void do_final_script(void) { if (mapreg_dirty >= 0) script_save_mapreg(); -#if 0 - // labels are allocated just out of this - // (so it's a leak ...) - // this is disabled because it leads to a crash - // due to double-free - if (script_buf) - free(script_buf); -#endif mapreg_db.clear(); for (auto& pair : mapregstr_db) - mapregstr_db_final(pair.second); + pair.second.clear(); mapregstr_db.clear(); scriptlabel_db.clear(); for (auto& pair : userfunc_db) - userfunc_db_final(pair.second); + pair.second.reset(); userfunc_db.clear(); - if (str_data) - free(str_data); - if (str_buf) - free(str_buf); + str_datam.clear(); } /*========================================== @@ -5196,7 +4921,6 @@ BuiltinFunction builtin_functions[] = BUILTIN(savepoint, "Mxy"), BUILTIN(gettimetick, "i"), BUILTIN(gettime, "i"), - BUILTIN(gettimestr, "si"), BUILTIN(openstorage, "*"), BUILTIN(monster, "Mxysmi*"), BUILTIN(areamonster, "Mxyxysmi*"), |