diff options
Diffstat (limited to 'src/map/script.c')
-rw-r--r-- | src/map/script.c | 1322 |
1 files changed, 857 insertions, 465 deletions
diff --git a/src/map/script.c b/src/map/script.c index d85f064b7..0d04ea31b 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; } @@ -1324,16 +1403,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); @@ -1659,6 +1751,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) { @@ -2002,65 +2173,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; @@ -2088,6 +2205,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 ) { @@ -2750,25 +2887,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); } @@ -3477,6 +3621,32 @@ static void set_reg_instance_num(struct script_state *st, int64 num, const char } /** + * Validates if a variable is permanent (stored in database) by passed variable name. + * + * @param name The variable name to validate. + * @return True if variable is permanent, otherwise false. + * + **/ +static bool script_is_permanent_variable(const char *name) +{ + nullpo_retr(false, name); + + if (strlen(name) == 0) + return false; + + if (ISALNUM(name[0]) != 0) + return true; // Permanent characater variable. + + if (name[0] == '#') + return true; // Permanent (global) account variable. + + if (strlen(name) > 1 && name[0] == '$' && ISALNUM(name[1]) != 0) + return true; // Permanent server variable. + + return false; +} + +/** * Stores the value of a script variable * * @param st current script state. @@ -3521,6 +3691,18 @@ static int set_reg(struct script_state *st, struct map_session_data *sd, int64 n if (is_string_variable(name)) {// string variable const char *str = (const char*)value; + if (script->is_permanent_variable(name) && strlen(str) > SCRIPT_STRING_VAR_LENGTH) { + ShowError("script:set_reg: Value of variable %s is too long: %lu! Maximum is %d. Skipping...\n", + name, strlen(str), SCRIPT_STRING_VAR_LENGTH); + + if (st != NULL) { + script->reportsrc(st); + st->state = END; + } + + return 0; + } + switch (prefix) { case '@': if (ref) { @@ -4910,6 +5092,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); @@ -6479,6 +6663,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 *------------------------------------------*/ @@ -11080,36 +11369,33 @@ static BUILDIN(itemskill) { struct map_session_data *sd = script->rid2sd(st); - if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER) + if (sd == NULL) return true; - pc->itemskill_clear(sd); - sd->skillitem = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2); - sd->skillitemlv = script_getnum(st, 3); - sd->state.itemskill_conditions_checked = 0; // Skill casting items will check the conditions prior to the target selection in AEGIS. Thus we need a flag to prevent checking them twice. + sd->auto_cast_current.type = AUTOCAST_ITEM; + sd->auto_cast_current.skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2); + sd->auto_cast_current.skill_lv = script_getnum(st, 3); int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE; - sd->state.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS) ? 1 : 0; // Unset in pc_itemskill_clear(). + sd->auto_cast_current.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS); - if (sd->state.itemskill_check_conditions == 1) { - if (skill->check_condition_castbegin(sd, sd->skillitem, sd->skillitemlv) == 0 - || skill->check_condition_castend(sd, sd->skillitem, sd->skillitemlv) == 0) { - pc->itemskill_clear(sd); + if (sd->auto_cast_current.itemskill_check_conditions) { + if (skill->check_condition_castbegin(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv) == 0 + || skill->check_condition_castend(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv) == 0) { return true; } - sd->state.itemskill_conditions_checked = 1; // Unset in pc_itemskill_clear(). + sd->auto_cast_current.itemskill_conditions_checked = true; } - sd->state.itemskill_no_casttime = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST) ? 1 : 0; // Unset in pc_itemskill_clear(). - sd->state.itemskill_castonself = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF) ? 1 : 0; // Unset in pc_itemskill_clear(). + sd->auto_cast_current.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST); + sd->auto_cast_current.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF); - // itemskill_conditions_checked/itemskill_no_conditions/itemskill_no_casttime/itemskill_castonself abuse prevention. Unset in pc_itemskill_clear(). - sd->itemskill_id = sd->skillitem; - sd->itemskill_lv = sd->skillitemlv; + VECTOR_ENSURE(sd->auto_cast, 1, 1); + VECTOR_PUSH(sd->auto_cast, sd->auto_cast_current); - clif->item_skill(sd, sd->skillitem, sd->skillitemlv); + clif->item_skill(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv); return true; } @@ -15034,10 +15320,10 @@ static BUILDIN(getiteminfo) script_pushint(st, it->nameid); break; case ITEMINFO_AEGISNAME: - script_pushstr(st, it->name); + script_pushstrcopy(st, it->name); break; case ITEMINFO_NAME: - script_pushstr(st, it->jname); + script_pushstrcopy(st, it->jname); break; default: ShowError("buildin_getiteminfo: Invalid item info type %d.\n", type); @@ -16197,7 +16483,6 @@ static BUILDIN(atcommand) struct map_session_data *sd, *dummy_sd = NULL; int fd; const char* cmd; - bool ret = true; cmd = script_getstr(st,2); @@ -16220,11 +16505,12 @@ static BUILDIN(atcommand) if (!atcommand->exec(fd, sd, cmd, false)) { ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); - script->reportsrc(st); - ret = false; + if (dummy_sd != NULL) + aFree(dummy_sd); + return false; } if (dummy_sd) aFree(dummy_sd); - return ret; + return true; } /** @@ -18948,7 +19234,14 @@ static BUILDIN(npcshopdelitem) size--; } - RECREATE(nd->u.shop.shop_item, struct npc_item_list, size); + int alloc_size = size; + if (size < 0) { + size = 0; + alloc_size = 1; + } else if (size < 1) { + alloc_size = 1; + } + RECREATE(nd->u.shop.shop_item, struct npc_item_list, alloc_size); nd->u.shop.count = size; script_pushint(st,1); @@ -19349,12 +19642,14 @@ static BUILDIN(pcblockmove) static BUILDIN(setpcblock) { - struct map_session_data *sd = script->rid2sd(st); + struct map_session_data *sd = script_hasdata(st, 4) ? script->id2sd(st, script_getnum(st, 4)) : script->rid2sd(st); enum pcblock_action_flag type = script_getnum(st, 2); int state = (script_getnum(st, 3) > 0) ? 1 : 0; - if (sd == NULL) + if (sd == NULL) { + script_pushint(st, 0); return true; + } if ((type & PCBLOCK_MOVE) != 0) sd->block_action.move = state; @@ -19383,12 +19678,13 @@ static BUILDIN(setpcblock) if ((type & PCBLOCK_NPC) != 0) sd->block_action.npc = state; + script_pushint(st, 1); return true; } static BUILDIN(checkpcblock) { - struct map_session_data *sd = script->rid2sd(st); + struct map_session_data *sd = script_hasdata(st, 2) ? script->id2sd(st, script_getnum(st, 2)) : script->rid2sd(st); int retval = PCBLOCK_NONE; if (sd == NULL) { @@ -19497,26 +19793,25 @@ static BUILDIN(getunittype) /** * Sets real-time unit data for a game object. - * Setunitdata <GUID>,<DataType>,<Val1>{,<Val2>,<Val3>} + * + * @code{.herc} + * setunitdata <GUID>, <DataType>, <Val1>{, <Val2>, <Val3>} + * @endcode + * * @param1 GUID GID of the unit. * @param2 DataType Type of Data to be set for the unit. * @param3 Value#1 Value to be passed as change in data. * @param4 Value#2 Optional int value to be passed for certain data types. * @param5 Value#3 Optional int value to be passed for certain data types. * @return 1 on success, 0 on failure. - - Note: Please make this script command only modify ONE INTEGER value. - If need to modify string type data, or having multiple arguments, please - introduce a new script command. - */ + * + * Note: Please make this script command only modify ONE INTEGER value. + * If need to modify string type data, or having multiple arguments, please introduce a new script command. + * + **/ static BUILDIN(setunitdata) { - struct block_list *bl = NULL; - const char *mapname = NULL, *udtype = NULL; - int type = 0, val = 0, val2 = 0, val3 = 0; - struct map_session_data *tsd = NULL; - - bl = map->id2bl(script_getnum(st, 2)); + struct block_list *bl = map->id2bl(script_getnum(st, 2)); if (bl == NULL) { ShowWarning("buildin_setunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2)); @@ -19524,22 +19819,26 @@ static BUILDIN(setunitdata) return false; } - type = script_getnum(st, 3); + int type = script_getnum(st, 3); - /* type bounds */ + // Type bounds. if (type < UDT_SIZE || type >= UDT_MAX) { // Note: UDT_TYPE is not valid here ShowError("buildin_setunitdata: Invalid unit data type %d provided.\n", type); script_pushint(st, 0); return false; } - /* Mandatory Argument 3. Subject to deprecate. */ + const char *mapname = NULL; + int val = 0; + + // Mandatory argument #3. Subject to deprecate. if (type == UDT_MAPIDXY) { if (!script_isstringtype(st, 4)) { ShowError("buildin_setunitdata: Invalid data type for argument #3.\n"); script_pushint(st, 0); return false; } + mapname = script_getstr(st, 4); } else { if (script_isstringtype(st, 4)) { @@ -19547,68 +19846,87 @@ static BUILDIN(setunitdata) script_pushint(st, 0); return false; } + val = script_getnum(st, 4); } -/* checks if value is out of bounds. */ + +/**************************************************************************************************** + * Define temporary macros. [BEGIN] + ****************************************************************************************************/ + +// Checks if value is out of bounds. #define setunitdata_check_bounds(arg, min, max) \ do { \ if (script_getnum(st, (arg)) < (min) || script_getnum(st, (arg)) > (max)) { \ - ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", script_getnum(st, (arg)), (arg)-1, (min), (max)); \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", \ + script_getnum(st, (arg)), (arg) - 1, (min), (max)); \ script_pushint(st, 0); \ return false; \ } \ } while(0); -/* checks if value is out of bounds. */ + +// Checks if value is too low. #define setunitdata_check_min(arg, min) \ do { \ if (script_getnum(st, (arg)) < (min)) { \ - ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", script_getnum(st, (arg)), (arg)-1, (min)); \ + ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", \ + script_getnum(st, (arg)), (arg) - 1, (min)); \ script_pushint(st, 0); \ return false; \ } \ } while(0); -/* checks if the argument doesn't exist, if required. - * also checks if the argument exists, if not required. */ + +// Checks if the argument doesn't exist, if required. Also checks if the argument exists, if not required. #define setunitdata_assert_arg(arg, required) \ do { \ if (required && !script_hasdata(st, (arg))) { \ - ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg)-1); \ + ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg) - 1); \ script_pushint(st, 0); \ return false; \ } else if (!required && script_hasdata(st, arg)) { \ - ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg)-1, type); \ + ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg) - 1, type); \ script_pushint(st, 0); \ return false; \ } \ } while (0); -/* checks if the data is an integer. */ + +// Checks if the data is an integer. #define setunitdata_check_int(arg) \ do { \ setunitdata_assert_arg((arg), true); \ if (script_isstringtype(st, (arg))) { \ - ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg)-1); \ + ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg) - 1); \ script_pushint(st, 0); \ return false; \ } \ } while(0); -/* checks if the data is a string. */ + +// Checks if the data is a string. #define setunitdata_check_string(arg) \ do { \ setunitdata_assert_arg((arg), true); \ if (script_isinttype(st, (arg))) { \ - ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg)-1); \ + ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg) - 1); \ script_pushint(st, 0); \ return false; \ } \ } while(0); +/**************************************************************************************************** + * Define temporary macros. [END] + ****************************************************************************************************/ + if (type != UDT_MAPIDXY && type != UDT_WALKTOXY) { setunitdata_assert_arg(5, false); setunitdata_assert_arg(6, false); } - switch (type) - { + int val2 = 0; + int val3 = 0; + + struct map_session_data *tsd = NULL; + + switch (type) { case UDT_SIZE: setunitdata_check_bounds(4, SZ_SMALL, SZ_BIG); break; @@ -19634,30 +19952,36 @@ static BUILDIN(setunitdata) case UDT_MASTERAID: setunitdata_check_min(4, 0); tsd = map->id2sd(val); + if (tsd == NULL) { - ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n",val); + ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n", val); script_pushint(st, 0); return false; } + break; case UDT_MASTERCID: setunitdata_check_min(4, 0); tsd = map->charid2sd(val); + if (tsd == NULL) { - ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n",val); + ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n", val); script_pushint(st, 0); return false; } + break; case UDT_MAPIDXY: - if ((val = map->mapname2mapid(mapname)) == -1) { + if ((val = map->mapname2mapid(mapname)) == INDEX_NOT_FOUND) { ShowError("buildin_setunitdata: Non-existent map %s provided.\n", mapname); + script_pushint(st, 0); return false; } + setunitdata_check_int(5); setunitdata_check_int(6); - setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); - setunitdata_check_bounds(6, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2); + setunitdata_check_bounds(6, 0, MAX_MAP_SIZE / 2); val2 = script_getnum(st, 5); val3 = script_getnum(st, 6); break; @@ -19665,8 +19989,8 @@ static BUILDIN(setunitdata) setunitdata_assert_arg(6, false); setunitdata_check_int(5); val2 = script_getnum(st, 5); - setunitdata_check_bounds(4, 0, MAX_MAP_SIZE/2); - setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2); + setunitdata_check_bounds(4, 0, MAX_MAP_SIZE / 2); + setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2); break; case UDT_SPEED: setunitdata_check_bounds(4, 0, MAX_WALK_SPEED); @@ -19721,7 +20045,7 @@ static BUILDIN(setunitdata) setunitdata_check_bounds(4, 0, SHRT_MAX); break; case UDT_HUNGER: - setunitdata_check_bounds(4, 0, 99); + setunitdata_check_bounds(4, PET_HUNGER_STARVING, PET_HUNGER_STUFFED); // Pets and Homunculi have the same hunger value bounds. break; case UDT_RACE: case UDT_ELETYPE: @@ -19729,19 +20053,20 @@ static BUILDIN(setunitdata) setunitdata_check_bounds(4, 0, CHAR_MAX); break; case UDT_GROUP: - { setunitdata_check_bounds(4, 0, INT_MAX); + struct unit_data *ud = unit->bl2ud2(bl); + if (ud == NULL) { ShowError("buildin_setunitdata: ud is NULL!\n"); script_pushint(st, 0); return false; } + ud->groupId = script_getnum(st, 4); clif->blname_ack(0, bl); // Send update to client. script_pushint(st, 1); return true; - } case UDT_DAMAGE_TAKEN_RATE: setunitdata_check_bounds(4, 1, INT_MAX); break; @@ -19749,67 +20074,81 @@ static BUILDIN(setunitdata) break; } +/**************************************************************************************************** + * Undefine temporary macros. [BEGIN] + ****************************************************************************************************/ + #undef setunitdata_check_bounds +#undef setunitdata_check_min #undef setunitdata_assert_arg #undef setunitdata_check_int #undef setunitdata_check_string - /* Set the values */ +/**************************************************************************************************** + * Undefine temporary macros. [END] + ****************************************************************************************************/ + + // Set the values. switch (bl->type) { - case BL_MOB: - { + case BL_MOB: { struct mob_data *md = BL_UCAST(BL_MOB, bl); - nullpo_retr(false, md); - switch (type) - { + if (md == NULL) { + ShowError("buildin_setunitdata: Can't find monster for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } + + switch (type) { case UDT_SIZE: - md->status.size = (unsigned char) val; + md->status.size = (unsigned char)val; break; case UDT_LEVEL: md->level = val; - if (battle_config.show_mob_info & 4) + + if ((battle_config.show_mob_info & 4) != 0) clif->blname_ack(0, &md->bl); + break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); clif->blname_ack(0, &md->bl); break; case UDT_MAXHP: - md->status.max_hp = (unsigned int) val; + md->status.max_hp = (unsigned int)val; clif->blname_ack(0, &md->bl); break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: - md->status.max_sp = (unsigned int) val; + md->status.max_sp = (unsigned int)val; break; case UDT_MASTERAID: md->master_id = val; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_SPEED: - md->status.speed = (unsigned short) val; + md->status.speed = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_MODE: - md->status.mode = (enum e_mode) val; + md->status.mode = (enum e_mode)val; break; case UDT_AI: - md->special_state.ai = (enum ai) val; + md->special_state.ai = (enum ai)val; break; case UDT_SCOPTION: - md->sc.option = (unsigned int) val; + md->sc.option = (unsigned int)val; break; case UDT_SEX: - md->vd->sex = (char) val; + md->vd->sex = (char)val; break; case UDT_CLASS: mob->class_change(md, val); @@ -19845,112 +20184,115 @@ static BUILDIN(setunitdata) md->ud.canmove_tick = val; break; case UDT_STR: - md->status.str = (unsigned short) val; + md->status.str = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_AGI: - md->status.agi = (unsigned short) val; + md->status.agi = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_VIT: - md->status.vit = (unsigned short) val; + md->status.vit = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_INT: - md->status.int_ = (unsigned short) val; + md->status.int_ = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_DEX: - md->status.dex = (unsigned short) val; + md->status.dex = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_LUK: - md->status.luk = (unsigned short) val; + md->status.luk = (unsigned short)val; status->calc_misc(bl, &md->status, md->level); break; case UDT_ATKRANGE: - md->status.rhw.range = (unsigned short) val; + md->status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - md->status.rhw.atk = (unsigned short) val; + md->status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - md->status.rhw.atk2 = (unsigned short) val; + md->status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - md->status.matk_min = (unsigned short) val; + md->status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - md->status.matk_max = (unsigned short) val; + md->status.matk_max = (unsigned short)val; break; case UDT_DEF: - md->status.def = (defType) val; + md->status.def = (defType)val; break; case UDT_MDEF: - md->status.mdef = (defType) val; + md->status.mdef = (defType)val; break; case UDT_HIT: - md->status.hit = (short) val; + md->status.hit = (short)val; break; case UDT_FLEE: - md->status.flee = (short) val; + md->status.flee = (short)val; break; case UDT_PDODGE: - md->status.flee2 = (short) val; + md->status.flee2 = (short)val; break; case UDT_CRIT: - md->status.cri = (short) val; + md->status.cri = (short)val; break; case UDT_RACE: - md->status.race = (unsigned char) val; + md->status.race = (unsigned char)val; break; case UDT_ELETYPE: - md->status.def_ele = (unsigned char) val; + md->status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - md->status.ele_lv = (unsigned char) val; + md->status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - md->status.amotion = (unsigned short) val; + md->status.amotion = (unsigned short)val; break; case UDT_ADELAY: - md->status.adelay = (unsigned short) val; + md->status.adelay = (unsigned short)val; break; case UDT_DMOTION: - md->status.dmotion = (unsigned short) val; + md->status.dmotion = (unsigned short)val; break; case UDT_DAMAGE_TAKEN_RATE: - md->dmg_taken_rate = (int) val; + md->dmg_taken_rate = (int)val; break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for mob unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for mob unit.\n", type); script_pushint(st, 0); return false; } - } + break; - case BL_HOM: - { + } + case BL_HOM: { struct homun_data *hd = BL_UCAST(BL_HOM, bl); - nullpo_retr(false, hd); + if (hd == NULL) { + ShowError("buildin_setunitdata: Can't find Homunculus for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } - switch (type) - { + switch (type) { case UDT_SIZE: - hd->base_status.size = (unsigned char) val; + hd->base_status.size = (unsigned char)val; break; case UDT_LEVEL: - hd->homunculus.level = (short) val; + hd->homunculus.level = (short)val; break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXHP: hd->homunculus.max_hp = val; break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: hd->homunculus.max_sp = val; @@ -19960,14 +20302,14 @@ static BUILDIN(setunitdata) hd->master = tsd; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_SPEED: - hd->base_status.speed = (unsigned short) val; + hd->base_status.speed = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_LOOKDIR: @@ -19977,136 +20319,138 @@ static BUILDIN(setunitdata) hd->ud.canmove_tick = val; break; case UDT_STR: - hd->base_status.str = (unsigned short) val; + hd->base_status.str = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_AGI: - hd->base_status.agi = (unsigned short) val; + hd->base_status.agi = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_VIT: - hd->base_status.vit = (unsigned short) val; + hd->base_status.vit = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_INT: - hd->base_status.int_ = (unsigned short) val; + hd->base_status.int_ = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_DEX: - hd->base_status.dex = (unsigned short) val; + hd->base_status.dex = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_LUK: - hd->base_status.luk = (unsigned short) val; + hd->base_status.luk = (unsigned short)val; status->calc_misc(bl, &hd->base_status, hd->homunculus.level); break; case UDT_ATKRANGE: - hd->base_status.rhw.range = (unsigned short) val; + hd->base_status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - hd->base_status.rhw.atk = (unsigned short) val; + hd->base_status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - hd->base_status.rhw.atk2 = (unsigned short) val; + hd->base_status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - hd->base_status.matk_min = (unsigned short) val; + hd->base_status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - hd->base_status.matk_max = (unsigned short) val; + hd->base_status.matk_max = (unsigned short)val; break; case UDT_DEF: - hd->base_status.def = (defType) val; + hd->base_status.def = (defType)val; break; case UDT_MDEF: - hd->base_status.mdef = (defType) val; + hd->base_status.mdef = (defType)val; break; case UDT_HIT: - hd->base_status.hit = (short) val; + hd->base_status.hit = (short)val; break; case UDT_FLEE: - hd->base_status.flee = (short) val; + hd->base_status.flee = (short)val; break; case UDT_PDODGE: - hd->base_status.flee2 = (short) val; + hd->base_status.flee2 = (short)val; break; case UDT_CRIT: - hd->base_status.cri = (short) val; + hd->base_status.cri = (short)val; break; case UDT_RACE: - hd->base_status.race = (unsigned char) val; + hd->base_status.race = (unsigned char)val; break; case UDT_ELETYPE: - hd->base_status.def_ele = (unsigned char) val; + hd->base_status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - hd->base_status.ele_lv = (unsigned char) val; + hd->base_status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - hd->base_status.amotion = (unsigned short) val; + hd->base_status.amotion = (unsigned short)val; break; case UDT_ADELAY: - hd->base_status.adelay = (unsigned short) val; + hd->base_status.adelay = (unsigned short)val; break; case UDT_DMOTION: - hd->base_status.dmotion = (unsigned short) val; + hd->base_status.dmotion = (unsigned short)val; break; case UDT_HUNGER: - hd->homunculus.hunger = (short) val; + hd->homunculus.hunger = (short)val; clif->send_homdata(hd->master, SP_HUNGRY, hd->homunculus.hunger); break; case UDT_INTIMACY: - homun->add_intimacy(hd, (unsigned int) val); + homun->add_intimacy(hd, (unsigned int)val); clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100); break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for homunculus unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for homunculus unit.\n", type); script_pushint(st, 0); return false; } - clif->send_homdata(hd->master, SP_ACK, 0); // send homun data - } + clif->send_homdata(hd->master, SP_ACK, 0); // Send Homunculus data. break; - case BL_PET: - { + } + case BL_PET: { struct pet_data *pd = BL_UCAST(BL_PET, bl); - nullpo_retr(false, pd); + if (pd == NULL) { + ShowError("buildin_setunitdata: Can't find pet for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } - switch (type) - { + switch (type) { case UDT_SIZE: - pd->status.size = (unsigned char) val; + pd->status.size = (unsigned char)val; break; case UDT_LEVEL: - pd->pet.level = (short) val; + pd->pet.level = (short)val; break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXHP: - pd->status.max_hp = (unsigned int) val; + pd->status.max_hp = (unsigned int)val; break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: - pd->status.max_sp = (unsigned int) val; + pd->status.max_sp = (unsigned int)val; break; case UDT_MASTERAID: pd->pet.account_id = val; pd->msd = tsd; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_SPEED: - pd->status.speed = (unsigned short) val; + pd->status.speed = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_LOOKDIR: @@ -20116,130 +20460,133 @@ static BUILDIN(setunitdata) pd->ud.canmove_tick = val; break; case UDT_STR: - pd->status.str = (unsigned short) val; + pd->status.str = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_AGI: - pd->status.agi = (unsigned short) val; + pd->status.agi = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_VIT: - pd->status.vit = (unsigned short) val; + pd->status.vit = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_INT: - pd->status.int_ = (unsigned short) val; + pd->status.int_ = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_DEX: - pd->status.dex = (unsigned short) val; + pd->status.dex = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_LUK: - pd->status.luk = (unsigned short) val; + pd->status.luk = (unsigned short)val; status->calc_misc(bl, &pd->status, pd->pet.level); break; case UDT_ATKRANGE: - pd->status.rhw.range = (unsigned short) val; + pd->status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - pd->status.rhw.atk = (unsigned short) val; + pd->status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - pd->status.rhw.atk2 = (unsigned short) val; + pd->status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - pd->status.matk_min = (unsigned short) val; + pd->status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - pd->status.matk_max = (unsigned short) val; + pd->status.matk_max = (unsigned short)val; break; case UDT_DEF: - pd->status.def = (defType) val; + pd->status.def = (defType)val; break; case UDT_MDEF: - pd->status.mdef = (defType) val; + pd->status.mdef = (defType)val; break; case UDT_HIT: - pd->status.hit = (short) val; + pd->status.hit = (short)val; break; case UDT_FLEE: - pd->status.flee = (short) val; + pd->status.flee = (short)val; break; case UDT_PDODGE: - pd->status.flee2 = (short) val; + pd->status.flee2 = (short)val; break; case UDT_CRIT: - pd->status.cri = (short) val; + pd->status.cri = (short)val; break; case UDT_RACE: - pd->status.race = (unsigned char) val; + pd->status.race = (unsigned char)val; break; case UDT_ELETYPE: - pd->status.def_ele = (unsigned char) val; + pd->status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - pd->status.ele_lv = (unsigned char) val; + pd->status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - pd->status.amotion = (unsigned short) val; + pd->status.amotion = (unsigned short)val; break; case UDT_ADELAY: - pd->status.adelay = (unsigned short) val; + pd->status.adelay = (unsigned short)val; break; case UDT_DMOTION: - pd->status.dmotion = (unsigned short) val; + pd->status.dmotion = (unsigned short)val; break; case UDT_INTIMACY: pet->set_intimate(pd, val); clif->send_petdata(pd->msd, pd, 1, pd->pet.intimate); break; case UDT_HUNGER: - pd->pet.hungry = (short) val; + pet->set_hunger(pd, val); break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for pet unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for pet unit.\n", type); script_pushint(st, 0); return false; } - clif->send_petstatus(pd->msd); // send pet data - } + + clif->send_petstatus(pd->msd); // Send pet data. break; - case BL_MER: - { + } + case BL_MER: { struct mercenary_data *mc = BL_UCAST(BL_MER, bl); - nullpo_retr(false, mc); + if (mc == NULL) { + ShowError("buildin_setunitdata: Can't find mercenary for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } - switch (type) - { + switch (type) { case UDT_SIZE: - mc->base_status.size = (unsigned char) val; + mc->base_status.size = (unsigned char)val; break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXHP: - mc->base_status.max_hp = (unsigned int) val; + mc->base_status.max_hp = (unsigned int)val; break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: - mc->base_status.max_sp = (unsigned int) val; + mc->base_status.max_sp = (unsigned int)val; break; case UDT_MASTERCID: mc->mercenary.char_id = val; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_SPEED: - mc->base_status.size = (unsigned char) val; + mc->base_status.size = (unsigned char)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_LOOKDIR: @@ -20249,131 +20596,134 @@ static BUILDIN(setunitdata) mc->ud.canmove_tick = val; break; case UDT_STR: - mc->base_status.str = (unsigned short) val; + mc->base_status.str = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_AGI: - mc->base_status.agi = (unsigned short) val; + mc->base_status.agi = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_VIT: - mc->base_status.vit = (unsigned short) val; + mc->base_status.vit = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_INT: - mc->base_status.int_ = (unsigned short) val; + mc->base_status.int_ = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_DEX: - mc->base_status.dex = (unsigned short) val; + mc->base_status.dex = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_LUK: - mc->base_status.luk = (unsigned short) val; + mc->base_status.luk = (unsigned short)val; status->calc_misc(bl, &mc->base_status, mc->db->lv); break; case UDT_ATKRANGE: - mc->base_status.rhw.range = (unsigned short) val; + mc->base_status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - mc->base_status.rhw.atk = (unsigned short) val; + mc->base_status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - mc->base_status.rhw.atk2 = (unsigned short) val; + mc->base_status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - mc->base_status.matk_min = (unsigned short) val; + mc->base_status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - mc->base_status.matk_max = (unsigned short) val; + mc->base_status.matk_max = (unsigned short)val; break; case UDT_DEF: - mc->base_status.def = (defType) val; + mc->base_status.def = (defType)val; break; case UDT_MDEF: - mc->base_status.mdef = (defType) val; + mc->base_status.mdef = (defType)val; break; case UDT_HIT: - mc->base_status.hit = (short) val; + mc->base_status.hit = (short)val; break; case UDT_FLEE: - mc->base_status.flee = (short) val; + mc->base_status.flee = (short)val; break; case UDT_PDODGE: - mc->base_status.flee2 = (short) val; + mc->base_status.flee2 = (short)val; break; case UDT_CRIT: - mc->base_status.cri = (short) val; + mc->base_status.cri = (short)val; break; case UDT_RACE: - mc->base_status.race = (unsigned char) val; + mc->base_status.race = (unsigned char)val; break; case UDT_ELETYPE: - mc->base_status.def_ele = (unsigned char) val; + mc->base_status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - mc->base_status.ele_lv = (unsigned char) val; + mc->base_status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - mc->base_status.amotion = (unsigned short) val; + mc->base_status.amotion = (unsigned short)val; break; case UDT_ADELAY: - mc->base_status.adelay = (unsigned short) val; + mc->base_status.adelay = (unsigned short)val; break; case UDT_DMOTION: - mc->base_status.dmotion = (unsigned short) val; + mc->base_status.dmotion = (unsigned short)val; break; case UDT_MERC_KILLCOUNT: - mc->mercenary.kill_count = (unsigned int) val; + mc->mercenary.kill_count = (unsigned int)val; break; case UDT_LIFETIME: - mc->mercenary.life_time = (unsigned int) val; + mc->mercenary.life_time = (unsigned int)val; break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for mercenary unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for mercenary unit.\n", type); script_pushint(st, 0); return false; } + // Send mercenary data. clif->mercenary_info(map->charid2sd(mc->mercenary.char_id)); clif->mercenary_skillblock(map->charid2sd(mc->mercenary.char_id)); - } break; - case BL_ELEM: - { + } + case BL_ELEM: { struct elemental_data *ed = BL_UCAST(BL_ELEM, bl); - nullpo_retr(false, ed); + if (ed == NULL) { + ShowError("buildin_setunitdata: Can't find Elemental for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } - switch (type) - { + switch (type) { case UDT_SIZE: - ed->base_status.size = (unsigned char) val; + ed->base_status.size = (unsigned char)val; break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXHP: - ed->base_status.max_hp = (unsigned int) val; + ed->base_status.max_hp = (unsigned int)val; break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: - ed->base_status.max_sp = (unsigned int) val; + ed->base_status.max_sp = (unsigned int)val; break; case UDT_MASTERCID: ed->elemental.char_id = val; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_SPEED: - ed->base_status.speed = (unsigned short) val; + ed->base_status.speed = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_LOOKDIR: @@ -20383,211 +20733,214 @@ static BUILDIN(setunitdata) ed->ud.canmove_tick = val; break; case UDT_STR: - ed->base_status.str = (unsigned short) val; + ed->base_status.str = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_AGI: - ed->base_status.agi = (unsigned short) val; + ed->base_status.agi = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_VIT: - ed->base_status.vit = (unsigned short) val; + ed->base_status.vit = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_INT: - ed->base_status.int_ = (unsigned short) val; + ed->base_status.int_ = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_DEX: - ed->base_status.dex = (unsigned short) val; + ed->base_status.dex = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_LUK: - ed->base_status.luk = (unsigned short) val; + ed->base_status.luk = (unsigned short)val; status->calc_misc(bl, &ed->base_status, ed->db->lv); break; case UDT_ATKRANGE: - ed->base_status.rhw.range = (unsigned short) val; + ed->base_status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - ed->base_status.rhw.atk = (unsigned short) val; + ed->base_status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - ed->base_status.rhw.atk2 = (unsigned short) val; + ed->base_status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - ed->base_status.matk_min = (unsigned short) val; + ed->base_status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - ed->base_status.matk_max = (unsigned short) val; + ed->base_status.matk_max = (unsigned short)val; break; case UDT_DEF: - ed->base_status.def = (defType) val; + ed->base_status.def = (defType)val; break; case UDT_MDEF: - ed->base_status.mdef = (defType) val; + ed->base_status.mdef = (defType)val; break; case UDT_HIT: - ed->base_status.hit = (short) val; + ed->base_status.hit = (short)val; break; case UDT_FLEE: - ed->base_status.flee = (short) val; + ed->base_status.flee = (short)val; break; case UDT_PDODGE: - ed->base_status.flee2 = (short) val; + ed->base_status.flee2 = (short)val; break; case UDT_CRIT: - ed->base_status.cri = (short) val; + ed->base_status.cri = (short)val; break; case UDT_RACE: - ed->base_status.race = (unsigned char) val; + ed->base_status.race = (unsigned char)val; break; case UDT_ELETYPE: - ed->base_status.def_ele = (unsigned char) val; + ed->base_status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - ed->base_status.ele_lv = (unsigned char) val; + ed->base_status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - ed->base_status.amotion = (unsigned short) val; + ed->base_status.amotion = (unsigned short)val; break; case UDT_ADELAY: - ed->base_status.adelay = (unsigned short) val; + ed->base_status.adelay = (unsigned short)val; break; case UDT_DMOTION: - ed->base_status.dmotion = (unsigned short) val; + ed->base_status.dmotion = (unsigned short)val; break; case UDT_LIFETIME: ed->elemental.life_time = val; break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for elemental unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for elemental unit.\n", type); script_pushint(st, 0); return false; } - clif->elemental_info(ed->master); - } + + clif->elemental_info(ed->master); // Send Elemental data. break; - case BL_NPC: - { + } + case BL_NPC: { struct npc_data *nd = BL_UCAST(BL_NPC, bl); - nullpo_retr(false, nd); + if (nd == NULL) { + ShowError("buildin_setunitdata: Can't find NPC for GID %d!\n", script_getnum(st, 2)); + script_pushint(st, 0); + return false; + } - switch (type) - { + switch (type) { case UDT_SIZE: - nd->status.size = (unsigned char) val; + nd->status.size = (unsigned char)val; break; case UDT_LEVEL: - nd->level = (unsigned short) val; + nd->level = (unsigned short)val; break; case UDT_HP: - status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXHP: - nd->status.max_hp = (unsigned int) val; + nd->status.max_hp = (unsigned int)val; break; case UDT_SP: - status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT); + status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT); break; case UDT_MAXSP: - nd->status.max_sp = (unsigned int) val; + nd->status.max_sp = (unsigned int)val; break; case UDT_MAPIDXY: - unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT); + unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT); break; case UDT_WALKTOXY: if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0) - unit->movepos(bl, (short) val, (short) val2, 0, 0); + unit->movepos(bl, (short)val, (short)val2, 0, 0); break; case UDT_CLASS: - npc->setclass(nd, (short) val); + npc->setclass(nd, (short)val); break; case UDT_SPEED: - nd->speed = (short) val; + nd->speed = (short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_LOOKDIR: unit->set_dir(bl, (enum unit_dir)val); break; case UDT_STR: - nd->status.str = (unsigned short) val; + nd->status.str = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_AGI: - nd->status.agi = (unsigned short) val; + nd->status.agi = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_VIT: - nd->status.vit = (unsigned short) val; + nd->status.vit = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_INT: - nd->status.int_ = (unsigned short) val; + nd->status.int_ = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_DEX: - nd->status.dex = (unsigned short) val; + nd->status.dex = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_LUK: - nd->status.luk = (unsigned short) val; + nd->status.luk = (unsigned short)val; status->calc_misc(bl, &nd->status, nd->level); break; case UDT_STATPOINT: - nd->stat_point = (unsigned short) val; + nd->stat_point = (unsigned short)val; break; case UDT_ATKRANGE: - nd->status.rhw.range = (unsigned short) val; + nd->status.rhw.range = (unsigned short)val; break; case UDT_ATKMIN: - nd->status.rhw.atk = (unsigned short) val; + nd->status.rhw.atk = (unsigned short)val; break; case UDT_ATKMAX: - nd->status.rhw.atk2 = (unsigned short) val; + nd->status.rhw.atk2 = (unsigned short)val; break; case UDT_MATKMIN: - nd->status.matk_min = (unsigned short) val; + nd->status.matk_min = (unsigned short)val; break; case UDT_MATKMAX: - nd->status.matk_max = (unsigned short) val; + nd->status.matk_max = (unsigned short)val; break; case UDT_DEF: - nd->status.def = (defType) val; + nd->status.def = (defType)val; break; case UDT_MDEF: - nd->status.mdef = (defType) val; + nd->status.mdef = (defType)val; break; case UDT_HIT: - nd->status.hit = (short) val; + nd->status.hit = (short)val; break; case UDT_FLEE: - nd->status.flee = (short) val; + nd->status.flee = (short)val; break; case UDT_PDODGE: - nd->status.flee2 = (short) val; + nd->status.flee2 = (short)val; break; case UDT_CRIT: - nd->status.cri = (short) val; + nd->status.cri = (short)val; break; case UDT_RACE: - nd->status.race = (unsigned char) val; + nd->status.race = (unsigned char)val; break; case UDT_ELETYPE: - nd->status.def_ele = (unsigned char) val; + nd->status.def_ele = (unsigned char)val; break; case UDT_ELELEVEL: - nd->status.ele_lv = (unsigned char) val; + nd->status.ele_lv = (unsigned char)val; break; case UDT_AMOTION: - nd->status.amotion = (unsigned short) val; + nd->status.amotion = (unsigned short)val; break; case UDT_ADELAY: - nd->status.adelay = (unsigned short) val; + nd->status.adelay = (unsigned short)val; break; case UDT_DMOTION: - nd->status.dmotion = (unsigned short) val; + nd->status.dmotion = (unsigned short)val; break; case UDT_SEX: nd->vd.sex = (char)val; @@ -20624,19 +20977,21 @@ static BUILDIN(setunitdata) clif->changelook(bl, LOOK_BODY2, val); break; default: - ShowWarning("buildin_setunitdata: Invalid data type '%s' for NPC unit.\n", udtype); + ShowWarning("buildin_setunitdata: Invalid data type '%d' for NPC unit.\n", type); script_pushint(st, 0); return false; } - } + break; + } default: ShowError("buildin_setunitdata: Unknown object!\n"); script_pushint(st, 0); return false; - } // end of bl->type switch + } // End of bl->type switch. script_pushint(st, 1); + return true; } @@ -21511,7 +21866,10 @@ static BUILDIN(unitskilluseid) } else { status_calc_npc(nd, SCO_NONE); } + } else if (bl->type == BL_PC) { + pc->autocast_clear(BL_UCAST(BL_PC, bl)); } + unit->skilluse_id(bl, target_id, skill_id, skill_lv); } @@ -21547,7 +21905,10 @@ static BUILDIN(unitskillusepos) } else { status_calc_npc(nd, SCO_NONE); } + } else if (bl->type == BL_PC) { + pc->autocast_clear(BL_UCAST(BL_PC, bl)); } + unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv); } @@ -22103,12 +22464,13 @@ static BUILDIN(setquestinfo) return false; } - qi = &VECTOR_LAST(nd->qi_data); - if (qi == NULL) { + if (VECTOR_LENGTH(nd->qi_data) == 0) { ShowWarning("buildin_setquestinfo: no valide questinfo data has been found for this npc.\n"); return false; } + qi = &VECTOR_LAST(nd->qi_data); + switch (type) { case QINFO_JOB: { @@ -27167,8 +27529,8 @@ static void script_parse_builtin(void) BUILDIN_DEF(pcfollow,"ii"), BUILDIN_DEF(pcstopfollow,"i"), BUILDIN_DEF_DEPRECATED(pcblockmove,"ii"), // Deprecated 2018-05-04 - BUILDIN_DEF(setpcblock, "ii"), - BUILDIN_DEF(checkpcblock, ""), + BUILDIN_DEF(setpcblock, "ii?"), + BUILDIN_DEF(checkpcblock, "?"), // <--- [zBuffer] List of player cont commands // [zBuffer] List of mob control commands ---> BUILDIN_DEF(getunittype,"i"), @@ -27407,6 +27769,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 @@ -27418,7 +27782,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; @@ -27429,6 +27793,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++; } @@ -27793,6 +28158,23 @@ static void script_hardcoded_constants(void) script->set_constant("PETINFO_EVO_EGGID", PETINFO_EVO_EGGID, false, false); script->set_constant("PETINFO_AUTOFEED", PETINFO_AUTOFEED, false, false); + script->constdb_comment("Pet hunger levels"); + script->set_constant("PET_HUNGER_STARVING", PET_HUNGER_STARVING, false, false); + script->set_constant("PET_HUNGER_VERY_HUNGRY", PET_HUNGER_VERY_HUNGRY, false, false); + script->set_constant("PET_HUNGER_HUNGRY", PET_HUNGER_HUNGRY, false, false); + script->set_constant("PET_HUNGER_NEUTRAL", PET_HUNGER_NEUTRAL, false, false); + script->set_constant("PET_HUNGER_SATISFIED", PET_HUNGER_SATISFIED, false, false); + script->set_constant("PET_HUNGER_STUFFED", PET_HUNGER_STUFFED, false, false); + + script->constdb_comment("Pet intimacy levels"); + script->set_constant("PET_INTIMACY_NONE", PET_INTIMACY_NONE, false, false); + script->set_constant("PET_INTIMACY_AWKWARD", PET_INTIMACY_AWKWARD, false, false); + script->set_constant("PET_INTIMACY_SHY", PET_INTIMACY_SHY, false, false); + script->set_constant("PET_INTIMACY_NEUTRAL", PET_INTIMACY_NEUTRAL, false, false); + script->set_constant("PET_INTIMACY_CORDIAL", PET_INTIMACY_CORDIAL, false, false); + script->set_constant("PET_INTIMACY_LOYAL", PET_INTIMACY_LOYAL, false, false); + script->set_constant("PET_INTIMACY_MAX", PET_INTIMACY_MAX, false, false); + script->constdb_comment("monster skill states"); script->set_constant("MSS_ANY", MSS_ANY, false, false); script->set_constant("MSS_IDLE", MSS_IDLE, false, false); @@ -27830,6 +28212,7 @@ static void script_hardcoded_constants(void) script->set_constant("MSC_MASTERATTACKED", MSC_MASTERATTACKED, false, false); script->set_constant("MSC_ALCHEMIST", MSC_ALCHEMIST, false, false); script->set_constant("MSC_SPAWN", MSC_SPAWN, false, false); + script->set_constant("MSC_MAGICATTACKED", MSC_MAGICATTACKED, false, false); script->constdb_comment("monster skill targets"); script->set_constant("MST_TARGET", MST_TARGET, false, false); @@ -27847,6 +28230,11 @@ static void script_hardcoded_constants(void) script->set_constant("MST_AROUND4", MST_AROUND4, false, false); script->set_constant("MST_AROUND", MST_AROUND , false, false); + script->constdb_comment("Monster group constants"); + script->set_constant("ALL_MOBS_NONBOSS", ALL_MOBS_NONBOSS, false, false); + script->set_constant("ALL_MOBS_BOSS", ALL_MOBS_BOSS, false, false); + script->set_constant("ALL_MOBS", ALL_MOBS, false, false); + script->constdb_comment("pc block constants, use with *setpcblock* and *checkpcblock*"); script->set_constant("PCBLOCK_NONE", PCBLOCK_NONE, false, false); script->set_constant("PCBLOCK_MOVE", PCBLOCK_MOVE, false, false); @@ -28218,6 +28606,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; @@ -28250,6 +28639,7 @@ void script_defaults(void) script->load_parameters = script_load_parameters; script->print_line = script_print_line; script->errorwarning_sub = script_errorwarning_sub; + script->is_permanent_variable = script_is_permanent_variable; script->set_reg = set_reg; script->set_reg_ref_str = set_reg_npcscope_str; script->set_reg_pc_ref_str = set_reg_pc_ref_str; @@ -28321,6 +28711,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; |