summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c553
1 files changed, 405 insertions, 148 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 347ef3d2a..0fd8bda2a 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -848,79 +848,134 @@ static const char *parse_callfunc(const char *p, int require_paren, int is_custo
nullpo_retr(NULL, p);
// is need add check for arg null pointer below?
- func = script->add_word(p);
- if (script->str_data[func].type == C_FUNC) {
- script->syntax.nested_call++;
- if (script->syntax.last_func != -1) {
- if (script->str_data[func].val == script->buildin_lang_macro_offset) {
- script->syntax.lang_macro_active = true;
- macro = true;
- } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
- script->syntax.lang_macro_fmtstring_active = true;
- macro = true;
- }
+
+ if (*p == '"') {
+ p2 = ++p; // jump to the start of the word
+
+ // find the closing quote
+ while (*p2 != '"') {
+ ++p2;
}
- if( !macro ) {
- // buildin function
+ if (p2[1] == ':' && p2[2] == ':') {
+ func = script->add_str("callfunctionofnpc");
+ arg = "*"; // we already take care of the "vs" part of "vs*"
+
+ script->syntax.nested_call++;
script->syntax.last_func = script->str_data[func].val;
script->addl(func);
script->addc(C_ARG);
- }
- arg = script->buildin[script->str_data[func].val];
- if (script->str_data[func].deprecated)
- DeprecationWarning(p);
- if( !arg ) arg = &null_arg; // Use a dummy, null string
- } else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ) {
- // script defined function
- script->addl(script->buildin_callsub_ref);
- script->addc(C_ARG);
- script->addl(func);
- arg = script->buildin[script->str_data[script->buildin_callsub_ref].val];
- if( *arg == 0 )
- disp_error_message("parse_callfunc: callsub has no arguments, please review its definition",p);
- if( *arg != '*' )
- ++arg; // count func as argument
+ script->addc(C_STR);
+ do {
+ script->addb(*p++); // npc name
+ } while (p < p2);
+ script->addb(0);
+
+ p = p2 + 3; // skip to start of func name
+ p2 = script->skip_word(p);
+
+ script->addc(C_STR);
+ do {
+ script->addb(*p++); // func name
+ } while (p < p2);
+ script->addb(0);
+
+ p = p2; // skip to just before the ()
+ } else {
+ disp_error_message("script:parse_callfunc: invalid public function call syntax!", p2 + 1);
+ }
} else {
+ func = script->add_word(p);
+ if (script->str_data[func].type == C_FUNC) {
+ script->syntax.nested_call++;
+
+ if (script->syntax.last_func != -1) {
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
+ script->syntax.lang_macro_active = true;
+ macro = true;
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
+ script->syntax.lang_macro_fmtstring_active = true;
+ macro = true;
+ }
+ }
+
+ if (!macro) {
+ // buildin function
+ script->syntax.last_func = script->str_data[func].val;
+ script->addl(func);
+ script->addc(C_ARG);
+ }
+
+ arg = script->buildin[script->str_data[func].val];
+
+ if (script->str_data[func].deprecated == 1) {
+ DeprecationWarning(p);
+ }
+
+ if (arg == NULL) {
+ arg = &null_arg; // Use a dummy, null string
+ }
+ } else if (script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS) {
+ // script defined function
+ script->addl(script->buildin_callsub_ref);
+ script->addc(C_ARG);
+ script->addl(func);
+ arg = script->buildin[script->str_data[script->buildin_callsub_ref].val];
+
+ if (*arg == 0) {
+ disp_error_message("script:parse_callfunc: callsub has no arguments, please review its definition", p);
+ }
+
+ if (*arg != '*') {
+ ++arg; // count func as argument
+ }
+ } else {
#ifdef SCRIPT_CALLFUNC_CHECK
- const char* name = script->get_str(func);
- if( !is_custom && strdb_get(script->userfunc_db, name) == NULL ) {
+ const char *name = script->get_str(func);
+ if (is_custom == 0 && strdb_get(script->userfunc_db, name) == NULL) {
#endif
- disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p);
+ disp_error_message("script:parse_callfunc: expect command, missing function name or calling undeclared function", p);
#ifdef SCRIPT_CALLFUNC_CHECK
- } else {;
- script->addl(script->buildin_callfunc_ref);
- script->addc(C_ARG);
- script->addc(C_STR);
- while( *name ) script->addb(*name ++);
- script->addb(0);
- arg = script->buildin[script->str_data[script->buildin_callfunc_ref].val];
- if( *arg != '*' ) ++ arg;
- }
+ } else {
+ script->addl(script->buildin_callfunc_ref);
+ script->addc(C_ARG);
+ script->addc(C_STR);
+
+ while (*name != '\0') {
+ script->addb(*name++);
+ }
+
+ script->addb(0);
+ arg = script->buildin[script->str_data[script->buildin_callfunc_ref].val];
+
+ if (*arg != '*') {
+ ++ arg;
+ }
+ }
#endif
+ }
}
p = script->skip_word(p);
p = script->skip_space(p);
script->syntax.curly[script->syntax.curly_count].type = TYPE_ARGLIST;
script->syntax.curly[script->syntax.curly_count].count = 0;
- if( *p == ';' )
- {// <func name> ';'
+
+ if (*p == ';') {
+ // <func name> ';'
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
- } else if( *p == '(' && *(p2=script->skip_space(p+1)) == ')' )
- {// <func name> '(' ')'
+ } else if (*p == '(' && *(p2 = script->skip_space(p + 1)) == ')') {
+ // <func name> '(' ')'
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
p = p2;
- /*
- } else if( 0 && require_paren && *p != '(' )
- {// <func name>
- script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
- */
- } else {// <func name> <arg list>
- if( require_paren ) {
- if( *p != '(' )
- disp_error_message("need '('",p);
+ } else {
+ // <func name> <arg list>
+ if (require_paren == 1) {
+ if (*p != '(') {
+ disp_error_message("script:parse_callfunc: need '('", p);
+ }
+
++p; // skip '('
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
} else if( *p == '(' ) {
@@ -928,41 +983,65 @@ static const char *parse_callfunc(const char *p, int require_paren, int is_custo
} else {
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
}
+
++script->syntax.curly_count;
- while( *arg ) {
- p2=script->parse_subexpr(p,-1);
- if( p == p2 )
- break; // not an argument
- if( *arg != '*' )
- ++arg; // next argument
- p=script->skip_space(p2);
- if( *arg == 0 || *p != ',' )
- break; // no more arguments
+ while (*arg != '\0') {
+ p2 = script->parse_subexpr(p, -1);
+
+ if (p == p2) {
+ // not an argument
+ break;
+ }
+
+ if (*arg != '*') {
+ // next argument
+ ++arg;
+ }
+
+ p = script->skip_space(p2);
+
+ if (*arg == 0 || *p != ',') {
+ // no more arguments
+ break;
+ }
+
++p; // skip comma
}
+
--script->syntax.curly_count;
}
- if( arg && *arg && *arg != '?' && *arg != '*' )
- disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script->config.warn_func_mismatch_paramnum);
- if( script->syntax.curly[script->syntax.curly_count].type != TYPE_ARGLIST )
- disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p);
- if( script->syntax.curly[script->syntax.curly_count].flag == ARGLIST_PAREN ) {
- if( *p != ')' )
- disp_error_message("parse_callfunc: expected ')' to close argument list",p);
+
+ if (arg != NULL && *arg != '\0' && *arg != '?' && *arg != '*') {
+ disp_error_message2("script:parse_callfunc: not enough arguments, expected ','", p, script->config.warn_func_mismatch_paramnum);
+ }
+
+ if (script->syntax.curly[script->syntax.curly_count].type != TYPE_ARGLIST) {
+ disp_error_message("parse_callfunc: DEBUG last curly is not an argument list", p);
+ }
+
+ if (script->syntax.curly[script->syntax.curly_count].flag == ARGLIST_PAREN) {
+ if (*p != ')') {
+ disp_error_message("script:parse_callfunc: expected ')' to close argument list", p);
+ }
+
++p;
- if (script->str_data[func].val == script->buildin_lang_macro_offset)
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
script->syntax.lang_macro_active = false;
- else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset)
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
script->syntax.lang_macro_fmtstring_active = false;
+ }
}
if (!macro) {
- if (0 == --script->syntax.nested_call)
+ if (0 == --script->syntax.nested_call) {
script->syntax.last_func = -1;
+ }
+
script->addc(C_FUNC);
}
+
return p;
}
@@ -1230,16 +1309,29 @@ static int script_string_dup(char *str)
*------------------------------------------*/
static const char *parse_simpleexpr(const char *p)
{
- p=script->skip_space(p);
+ p = script->skip_space(p);
nullpo_retr(NULL, p);
- if (*p == ';' || *p == ',')
- disp_error_message("parse_simpleexpr: unexpected end of expression",p);
+
+ if (*p == ';' || *p == ',') {
+ disp_error_message("script:parse_simpleexpr: unexpected end of expression", p);
+ }
+
if (*p == '(') {
return script->parse_simpleexpr_paren(p);
} else if (is_number(p)) {
return script->parse_simpleexpr_number(p);
} else if(*p == '"') {
+ const char *p2 = p + 1;
+
+ while (*p2 != '"') {
+ ++p2;
+ }
+
+ if (p2[1] == ':' && p2[2] == ':') {
+ return script->parse_callfunc(p, 1, 0); // XXX: why does callfunc use int for booleans?
+ }
+
return script->parse_simpleexpr_string(p);
} else {
return script->parse_simpleexpr_name(p);
@@ -1577,6 +1669,85 @@ static const char *parse_line(const char *p)
return p;
}
+/**
+ * parses a local function expression
+ *
+ * expects these formats:
+ * function <name>;
+ * function <name> { <script> }
+ *
+ * this is invoked by script->parse_syntax() after checking whether the function
+ * is public or not
+ *
+ * @param p - a pointer to the start of the function expression
+ * @param is_public - whether this function should be accessible from outside the NPC scope
+ */
+static const char *parse_syntax_function (const char *p, bool is_public)
+{
+ const char *func_name = script->skip_space(p); // the name of the local function
+ p = script->skip_word(func_name);
+
+ if (p == func_name) {
+ disp_error_message("script:parse_syntax_function: function name is missing or invalid", p);
+ }
+
+ const char *p2 = script->skip_space(p);
+
+ if (*p2 == ';') {
+ // function <name> ;
+ // function declaration - just register the name
+ int l = script->add_word(func_name);
+
+ if (script->str_data[l].type == C_NOP) {
+ // register only, if the name was not used by something else
+ script->str_data[l].type = C_USERFUNC;
+ } else if (script->str_data[l].type != C_USERFUNC) {
+ disp_error_message("script:parse_syntax_function: function name is already in use", func_name);
+ }
+
+ // Close condition of if, for, while
+ p = script->parse_syntax_close(p2 + 1);
+ return p;
+ } else if (*p2 == '{') {
+ // function <name> <line/block of code>
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_USERFUNC;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ ++script->syntax.curly_count;
+
+ // Jump over the function code
+ char label[256];
+ sprintf(label, "goto __FN%x_FIN;", (unsigned int)script->syntax.curly[script->syntax.curly_count - 1].index);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
+ ++script->syntax.curly_count;
+ script->parse_line(label);
+ --script->syntax.curly_count;
+
+ // Set the position of the function (label)
+ int l = script->add_word(func_name);
+
+ if (script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC) {
+ // register only, if the name was not used by something else
+ script->str_data[l].type = C_USERFUNC;
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
+
+ if ((script->parse_options & SCRIPT_USE_LABEL_DB) != 0) {
+ script->label_add(l, VECTOR_LENGTH(script->buf),
+ LABEL_IS_USERFUNC | (is_public ? LABEL_IS_EXTERN : 0));
+ }
+ } else {
+ disp_error_message("script:parse_syntax_function: function name is already in use", func_name);
+ }
+
+ return script->skip_space(p);
+ } else {
+ disp_error_message("script:parse_syntax_function: expected ';' or '{' at function syntax", p);
+ }
+
+ return p;
+}
+
// { ... } Closing process
static const char *parse_curly_close(const char *p)
{
@@ -1920,65 +2091,11 @@ static const char *parse_syntax(const char *p)
script->set_label(l, VECTOR_LENGTH(script->buf), p);
return p;
} else if( p2 - p == 8 && strncmp(p, "function", 8) == 0 ) {
- // internal script function
- const char *func_name;
-
- func_name = script->skip_space(p2);
- p = script->skip_word(func_name);
- if( p == func_name )
- disp_error_message("parse_syntax:function: function name is missing or invalid", p);
- p2 = script->skip_space(p);
- if( *p2 == ';' )
- {// function <name> ;
- // function declaration - just register the name
- int l;
- l = script->add_word(func_name);
- if( script->str_data[l].type == C_NOP )// register only, if the name was not used by something else
- script->str_data[l].type = C_USERFUNC;
- else if( script->str_data[l].type == C_USERFUNC )
- ; // already registered
- else
- disp_error_message("parse_syntax:function: function name is invalid", func_name);
-
- // Close condition of if, for, while
- p = script->parse_syntax_close(p2 + 1);
- return p;
- }
- else if(*p2 == '{')
- {// function <name> <line/block of code>
- char label[256];
- int l;
-
- script->syntax.curly[script->syntax.curly_count].type = TYPE_USERFUNC;
- script->syntax.curly[script->syntax.curly_count].count = 1;
- script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
- script->syntax.curly[script->syntax.curly_count].flag = 0;
- ++script->syntax.curly_count;
-
- // Jump over the function code
- sprintf(label, "goto __FN%x_FIN;", (unsigned int)script->syntax.curly[script->syntax.curly_count-1].index);
- script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
- ++script->syntax.curly_count;
- script->parse_line(label);
- --script->syntax.curly_count;
-
- // Set the position of the function (label)
- l=script->add_word(func_name);
- if( script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
- {
- script->str_data[l].type = C_USERFUNC;
- script->set_label(l, VECTOR_LENGTH(script->buf), p);
- if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(l, VECTOR_LENGTH(script->buf));
- }
- else
- disp_error_message("parse_syntax:function: function name is invalid", func_name);
-
- return script->skip_space(p);
- }
- else
- {
- disp_error_message("expect ';' or '{' at function syntax",p);
+ // local function not marked as public or private
+ if (script->config.functions_private_by_default) {
+ return script->parse_syntax_function(p2, false);
+ } else {
+ return script->parse_syntax_function(p2, true);
}
}
break;
@@ -2006,6 +2123,26 @@ static const char *parse_syntax(const char *p)
return p;
}
break;
+ case 'p':
+ case 'P':
+ if (p2 - p == 6 && strncmp(p, "public", 6) == 0) {
+ p2 = script->skip_space(p2);
+ const char *p3 = script->skip_word(p2);
+
+ if (p3 - p2 == 8 && strncmp(p2, "function", 8) == 0) {
+ // local function explicitly marked as public
+ return script->parse_syntax_function(p3, true);
+ }
+ } else if (p2 - p == 7 && strncmp(p, "private", 7) == 0) {
+ p2 = script->skip_space(p2);
+ const char *p3 = script->skip_word(p2);
+
+ if (p3 - p2 == 8 && strncmp(p2, "function", 8) == 0) {
+ // local function explicitly marked as private
+ return script->parse_syntax_function(p3, false);
+ }
+ }
+ break;
case 's':
case 'S':
if( p2 - p == 6 && strncmp(p, "switch", 6) == 0 ) {
@@ -2668,25 +2805,32 @@ static struct script_code *parse_script(const char *src, const char *file, int l
}
}
- while( script->syntax.curly_count != 0 || *p != end )
- {
- if( *p == '\0' )
- disp_error_message("unexpected end of script",p);
+ while (script->syntax.curly_count != 0 || *p != end) {
+ if (*p == '\0') {
+ disp_error_message("script:parse_script: unexpected end of script", p);
+ }
+
// Special handling only label
- tmpp=script->skip_space(script->skip_word(p));
- if(*tmpp==':' && !(strncmp(p,"default:",8) == 0 && p + 7 == tmpp)) {
- i=script->add_word(p);
+ tmpp = script->skip_space(script->skip_word(p));
+
+ if (*tmpp == ':' && !(strncmp(p, "default:", 8) == 0 && p + 7 == tmpp)
+ && !(strncmp(p, "function", 8) == 0 && script->skip_space(p + 8) == tmpp)) {
+ i = script->add_word(p);
script->set_label(i, VECTOR_LENGTH(script->buf), p);
- if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(i, VECTOR_LENGTH(script->buf));
- p=tmpp+1;
- p=script->skip_space(p);
+
+ if ((script->parse_options & SCRIPT_USE_LABEL_DB) != 0) {
+ bool is_extern = ((p[0] == 'O' || p[0] == 'o') && (p[1] == 'N' || p[1] == 'n'));
+ script->label_add(i, VECTOR_LENGTH(script->buf), is_extern ? LABEL_IS_EXTERN : 0);
+ }
+
+ p = tmpp + 1;
+ p = script->skip_space(p);
continue;
}
// All other lumped
- p=script->parse_line(p);
- p=script->skip_space(p);
+ p = script->parse_line(p);
+ p = script->skip_space(p);
script->parse_nextline(false, p);
}
@@ -4866,6 +5010,8 @@ static bool script_config_read(const char *filename, bool imported)
libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_paramnum", &script->config.warn_func_mismatch_paramnum);
libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_argtypes", &script->config.warn_func_mismatch_argtypes);
+ libconfig->setting_lookup_bool_real(setting, "functions_private_by_default", &script->config.functions_private_by_default);
+ libconfig->setting_lookup_bool_real(setting, "functions_as_events", &script->config.functions_as_events);
libconfig->setting_lookup_int(setting, "check_cmdcount", &script->config.check_cmdcount);
libconfig->setting_lookup_int(setting, "check_gotocount", &script->config.check_gotocount);
libconfig->setting_lookup_int(setting, "input_min_value", &script->config.input_min_value);
@@ -6435,6 +6581,111 @@ static BUILDIN(callfunc)
return true;
}
+
+/**
+ * Calls a local function within a NPC as if it was part of the current scope.
+ * Resumes execution in the previous scope once the NPC function returns. This
+ * is essentially a clone of buildin_callsub that can run in arbitrary NPCs.
+ *
+ * Usage:
+ * callfunctionofnpc("<npc name>", "<function name>"{, <arg>...})
+ * callfunctionofnpc(<npc id>, "<function name>"{, <arg>...})
+ *
+ * This buildin is also used internally by this syntax:
+ * "<npc name>"::<function name>({<arg>...})
+ */
+static BUILDIN(callfunctionofnpc) {
+ struct npc_data *nd = NULL;
+
+ if (script_isstring(st, 2)) {
+ nd = npc->name2id(script_getstr(st, 2));
+ } else {
+ nd = map->id2nd(script_getnum(st, 2));
+ }
+
+ if (nd == NULL) {
+ ShowError("script:callfunctionofnpc: NPC not found.\n");
+ st->state = END;
+ return false;
+ }
+
+ const char *function_name = script_getstr(st, 3);
+ int pos = -1;
+
+ // find the function label within the label list of the NPC
+ for (int i = 0; i < nd->u.scr.label_list_num; ++i) {
+ if (strcmp(nd->u.scr.label_list[i].name, function_name) == 0) {
+ if ((nd->u.scr.label_list[i].flags & LABEL_IS_EXTERN) != 0
+ && (nd->u.scr.label_list[i].flags & LABEL_IS_USERFUNC) != 0) {
+ // function label found: set the start location
+ pos = nd->u.scr.label_list[i].pos;
+ } else if ((nd->u.scr.label_list[i].flags & LABEL_IS_USERFUNC) != 0) {
+ ShowError("script:callfunctionofnpc: function '%s' is not marked as public in NPC '%s'.\n", function_name, nd->name);
+ st->state = END;
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (pos < 0) {
+ ShowError("script:callfunctionofnpc: function '%s' not found in NPC '%s'!\n", function_name, nd->name);
+ st->state = END;
+ return false;
+ }
+
+ // alloc a reg_db reference of the current scope for the new scope
+ struct reg_db *ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 2);
+ // scope variables (.@var)
+ ref[0].vars = st->stack->scope.vars;
+ ref[0].arrays = st->stack->scope.arrays;
+ // npc variables (.var)
+ ref[1].vars = st->script->local.vars;
+ ref[1].arrays = st->script->local.arrays;
+
+ int i = 0;
+
+ // make sure the arguments we push retain their current reg_db references:
+ // this allows to do things like set(getarg(0), ...)
+ for (i = st->start + 4; i < st->end; i++) {
+ struct script_data *data = script->push_copy(st->stack, i);
+
+ if (data_isreference(data) && data->ref == NULL) {
+ const char *name = reference_getname(data);
+
+ if (name[0] == '.') {
+ data->ref = (name[1] == '@' ? &ref[0] : &ref[1]);
+ }
+ }
+ }
+
+ // save the previous scope
+ struct script_retinfo *ri = NULL;
+ CREATE(ri, struct script_retinfo, 1);
+ ri->script = st->script; // script code
+ ri->scope.vars = st->stack->scope.vars; // scope variables
+ ri->scope.arrays = st->stack->scope.arrays; // scope arrays
+ ri->pos = st->pos; // script location
+ ri->nargs = i - st->start - 4; // argument count
+ ri->defsp = st->stack->defsp; // default stack pointer
+ script->push_retinfo(st->stack, ri, ref);
+
+ // change the current scope to the scope of the function
+ st->pos = pos;
+ st->script = nd->u.scr.script;
+ st->stack->defsp = st->stack->sp;
+ st->state = GOTO;
+ st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
+
+ // make sure local reg_db of the other NPC is initialized
+ if (st->script->local.vars == NULL) {
+ st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ }
+
+ return true;
+}
+
/*==========================================
* subroutine call
*------------------------------------------*/
@@ -27428,6 +27679,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(identify, "i"),
BUILDIN_DEF(identifyidx, "i"),
BUILDIN_DEF(openlapineddukddakboxui, "i"),
+
+ BUILDIN_DEF(callfunctionofnpc, "vs*"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
@@ -27439,7 +27692,7 @@ static void script_parse_builtin(void)
#undef BUILDIN_DEF
#undef BUILDIN_DEF2
-static void script_label_add(int key, int pos)
+static void script_label_add(int key, int pos, enum script_label_flags flags)
{
int idx = script->label_count;
@@ -27450,6 +27703,7 @@ static void script_label_add(int key, int pos)
script->labels[idx].key = key;
script->labels[idx].pos = pos;
+ script->labels[idx].flags = flags;
script->label_count++;
}
@@ -28261,6 +28515,7 @@ void script_defaults(void)
script->parse_syntax_close = parse_syntax_close;
script->parse_syntax_close_sub = parse_syntax_close_sub;
script->parse_syntax = parse_syntax;
+ script->parse_syntax_function = parse_syntax_function;
script->get_com = get_com;
script->get_num = get_num;
script->op2name = script_op2name;
@@ -28365,6 +28620,8 @@ void script_defaults(void)
script->config.ontouch_name = "OnTouch_"; //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
script->config.ontouch2_name = "OnTouch"; //ontouch2_name (run whenever a char walks into the OnTouch area)
script->config.onuntouch_name = "OnUnTouch"; //onuntouch_name (run whenever a char walks from the OnTouch area)
+ script->config.functions_private_by_default = true;
+ script->config.functions_as_events = false;
// for ENABLE_CASE_CHECK
script->calc_hash_ci = calc_hash_ci;