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.c618
1 files changed, 605 insertions, 13 deletions
diff --git a/src/map/script.c b/src/map/script.c
index f5d4008c8..d5cf58946 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -62,6 +62,8 @@
#include <sys/time.h>
#endif
+struct script_interface script_s;
+
static inline int GETVALUE(const unsigned char* buf, int i) {
return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0));
}
@@ -71,7 +73,29 @@ static inline void SETVALUE(unsigned char* buf, int i, int n) {
buf[i+2] = GetByte(n, 2);
}
-struct script_interface script_s;
+static inline void script_string_buf_ensure(struct script_string_buf *buf, size_t ensure) {
+ if( buf->pos+ensure >= buf->size ) {
+ do {
+ buf->size += 512;
+ } while ( buf->pos+ensure >= buf->size );
+ RECREATE(buf->ptr, char, buf->size);
+ }
+}
+
+static inline void script_string_buf_addb(struct script_string_buf *buf,uint8 b) {
+ if( buf->pos+1 >= buf->size ) {
+ buf->size += 512;
+ RECREATE(buf->ptr, char, buf->size);
+ }
+
+ buf->ptr[buf->pos++] = b;
+}
+
+static inline void script_string_buf_destroy(struct script_string_buf *buf) {
+ if( buf->ptr )
+ aFree(buf->ptr);
+ memset(buf,0,sizeof(struct script_string_buf));
+}
const char* script_op2name(int op) {
#define RETURN_OP_NAME(type) case type: return #type
@@ -91,6 +115,7 @@ const char* script_op2name(int op) {
RETURN_OP_NAME(C_USERFUNC_POS);
RETURN_OP_NAME(C_REF);
+ RETURN_OP_NAME(C_LSTR);
// operators
RETURN_OP_NAME(C_OP3);
@@ -771,13 +796,30 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
char *arg = NULL;
char null_arg = '\0';
int func;
+ bool nested_call = false, macro = false;
// is need add check for arg null pointer below?
func = script->add_word(p);
if( script->str_data[func].type == C_FUNC ) {
- // buildin function
- script->addl(func);
- script->addc(C_ARG);
+ /** only when unset (-1), valid values are >= 0 **/
+ if( script->syntax.last_func == -1 )
+ script->syntax.last_func = script->str_data[func].val;
+ else { //Nested function call
+ script->syntax.nested_call++;
+ nested_call = true;
+
+ if( script->str_data[func].val == script->buildin_lang_macro_offset ) {
+ script->syntax.lang_macro_active = true;
+ macro = true;
+ }
+ }
+
+ if( !macro ) {
+ // buildin function
+ script->addl(func);
+ script->addc(C_ARG);
+ }
+
arg = script->buildin[script->str_data[func].val];
if (script->str_data[func].deprecated)
DeprecationWarning(p);
@@ -861,8 +903,19 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
if( *p != ')' )
disp_error_message("parse_callfunc: expected ')' to close argument list",p);
++p;
+
+ if( script->str_data[func].val == script->buildin_lang_macro_offset )
+ script->syntax.lang_macro_active = false;
}
- script->addc(C_FUNC);
+
+ if( nested_call )
+ script->syntax.nested_call--;
+
+ if( !script->syntax.nested_call )
+ script->syntax.last_func = -1;
+
+ if( !macro )
+ script->addc(C_FUNC);
return p;
}
@@ -1090,6 +1143,24 @@ bool is_number(const char *p) {
return false;
}
+/**
+ *
+ **/
+int script_string_dup(char *str) {
+ size_t len = strlen(str);
+ int pos = script->string_list_pos;
+
+ while( pos+len+1 >= script->string_list_size ) {
+ script->string_list_size += (1024*1024)/2;
+ RECREATE(script->string_list,char,script->string_list_size);
+ }
+
+ safestrncpy(script->string_list+pos, str, len+1);
+ script->string_list_pos += len+1;
+
+ return pos;
+}
+
/*==========================================
* Analysis section
*------------------------------------------*/
@@ -1133,7 +1204,11 @@ const char* parse_simpleexpr(const char *p)
script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
p=np;
} else if(*p=='"') {
- script->addc(C_STR);
+ struct string_translation *st = NULL;
+ const char *start_point = p;
+ bool duplicate = true;
+ struct script_string_buf *sbuf = &script->parse_simpleexpr_str;
+
do {
p++;
while( *p && *p != '"' ) {
@@ -1144,19 +1219,121 @@ const char* parse_simpleexpr(const char *p)
if( n != 1 )
ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
p += len;
- script->addb(*buf);
+ script_string_buf_addb(sbuf, *buf);
continue;
} else if( *p == '\n' ) {
disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
}
- script->addb(*p++);
+ script_string_buf_addb(sbuf, *p++);
}
if(!*p)
disp_error_message("parse_simpleexpr: unexpected end of file @ string",p);
p++; //'"'
p = script->skip_space(p);
} while( *p && *p == '"' );
- script->addb(0);
+
+ script_string_buf_addb(sbuf, 0);
+
+ if( !(script->syntax.translation_db && (st = strdb_get(script->syntax.translation_db, sbuf->ptr))) ) {
+ script->addc(C_STR);
+
+ if( script->pos+sbuf->pos >= script->size ) {
+ do {
+ script->size += SCRIPT_BLOCK_SIZE;
+ } while( script->pos+sbuf->pos >= script->size );
+ RECREATE(script->buf,unsigned char,script->size);
+ }
+
+ memcpy(script->buf+script->pos, sbuf->ptr, sbuf->pos);
+ script->pos += sbuf->pos;
+
+ } else {
+ int expand = sizeof(int) + sizeof(uint8);
+ unsigned char j;
+ unsigned int st_cursor = 0;
+
+ script->addc(C_LSTR);
+
+ expand += (sizeof(char*) + sizeof(uint8)) * st->translations;
+
+ while( script->pos+expand >= script->size ) {
+ script->size += SCRIPT_BLOCK_SIZE;
+ RECREATE(script->buf,unsigned char,script->size);
+ }
+
+ *((int *)(&script->buf[script->pos])) = st->string_id;
+ *((uint8 *)(&script->buf[script->pos + sizeof(int)])) = st->translations;
+
+ script->pos += sizeof(int) + sizeof(uint8);
+
+ for(j = 0; j < st->translations; j++) {
+ *((uint8 *)(&script->buf[script->pos])) = RBUFB(st->buf, st_cursor);
+ *((char **)(&script->buf[script->pos+sizeof(uint8)])) = &st->buf[st_cursor + sizeof(uint8)];
+ script->pos += sizeof(char*) + sizeof(uint8);
+ st_cursor += sizeof(uint8);
+ while(st->buf[st_cursor++]);
+ st_cursor += sizeof(uint8);
+ }
+ }
+
+ /* When exporting we don't know what is a translation and what isn't */
+ if( script->lang_export_fp && sbuf->pos > 1 ) {//sbuf->pos will always be at least 1 because of the '\0'
+ if( !script->syntax.strings ) {
+ script->syntax.strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0);
+ }
+
+ if( !strdb_exists(script->syntax.strings,sbuf->ptr) ) {
+ strdb_put(script->syntax.strings, sbuf->ptr, NULL);
+ duplicate = false;
+ }
+ }
+
+ if( script->lang_export_fp && !duplicate &&
+ ( ( ( script->syntax.last_func == script->buildin_mes_offset ||
+ script->syntax.last_func == script->buildin_select_offset ) && !script->syntax.nested_call
+ ) || script->syntax.lang_macro_active ) ) {
+ const char *line_start = start_point;
+ const char *line_end = start_point;
+ struct script_string_buf *lbuf = &script->lang_export_line_buf;
+ size_t line_length;
+
+ while( line_start > script->parser_current_src ) {
+ if( *line_start != '\n' )
+ line_start--;
+ else
+ break;
+ }
+
+ while( *line_end != '\n' && *line_end != '\0' )
+ line_end++;
+
+ line_length = (size_t)(line_end - line_start);
+
+ if( line_length > 0 ) {
+ script_string_buf_ensure(lbuf,line_length + 1);
+
+ memcpy(lbuf->ptr, line_start, line_length);
+ lbuf->pos = line_length;
+ script_string_buf_addb(lbuf, 0);
+
+ normalize_name(lbuf->ptr, "\r\n\t ");
+ }
+
+ fprintf(script->lang_export_fp, "#: %s\n"
+ "# %s\n"
+ "msgctxt \"%s\"\n"
+ "msgid \"%s\"\n"
+ "msgstr \"\"\n",
+ script->parser_current_file ? script->parser_current_file : "Unknown File",
+ lbuf->ptr,
+ script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC",
+ sbuf->ptr
+ );
+
+ lbuf->pos = 0;
+ }
+
+ sbuf->pos = 0;
} else {
int l;
const char* pv;
@@ -2234,7 +2411,21 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
if( src == NULL )
return NULL;// empty script
+ if( script->parse_cleanup_timer_id == INVALID_TIMER ) {
+ script->parse_cleanup_timer_id = timer->add(timer->gettick() + 10, script->parse_cleanup_timer, 0, 0);
+ }
+
+ if( script->syntax.strings ) /* used only when generating translation file */
+ db_destroy(script->syntax.strings);
+
memset(&script->syntax,0,sizeof(script->syntax));
+ script->syntax.last_func = -1;/* as valid values are >= 0 */
+ if( script->parser_current_npc_name ) {
+ if( !script->translation_db )
+ script->load_translations();
+ if( script->translation_db )
+ script->syntax.translation_db = strdb_get(script->translation_db, script->parser_current_npc_name);
+ }
script->buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
script->pos=0;
@@ -4014,6 +4205,36 @@ void run_script_main(struct script_state *st) {
script->push_str(stack,C_CONSTSTR,(char*)(st->script->script_buf+st->pos));
while(st->script->script_buf[st->pos++]);
break;
+ case C_LSTR:
+ {
+ int string_id = *((int *)(&st->script->script_buf[st->pos]));
+ uint8 translations = *((uint8 *)(&st->script->script_buf[st->pos+sizeof(int)]));
+ struct map_session_data *lsd = NULL;
+
+ st->pos += sizeof(int) + sizeof(uint8);
+
+ if( (!st->rid || !(lsd = map->id2sd(st->rid)) || !lsd->lang_id) && !map->default_lang_id )
+ script->push_str(stack,C_CONSTSTR,script->string_list+string_id);
+ else {
+ uint8 k, wlang_id = lsd ? lsd->lang_id : map->default_lang_id;
+ int offset = st->pos;
+
+ for(k = 0; k < translations; k++) {
+ uint8 lang_id = *(uint8 *)(&st->script->script_buf[offset]);
+ offset += sizeof(uint8);
+ if( lang_id == wlang_id )
+ break;
+ offset += sizeof(char*);
+ }
+
+ script->push_str(stack,C_CONSTSTR,
+ ( k == translations ) ? script->string_list+string_id : *(char**)(&st->script->script_buf[offset]) );
+
+ }
+
+ st->pos += ( ( sizeof(char*) + sizeof(uint8) ) * translations );
+ }
+ break;
case C_FUNC:
script->run_func(st);
if(st->state==GOTO) {
@@ -4430,11 +4651,355 @@ void do_final_script(void) {
if( script->generic_ui_array )
aFree(script->generic_ui_array);
+
+ script->clear_translations(false);
+
+ script->parser_clean_leftovers();
+
+ if( script->lang_export_file )
+ aFree(script->lang_export_file);
}
+
+/**
+ *
+ **/
+uint8 script_add_language(const char *name) {
+ uint8 lang_id = script->max_lang_id;
+
+ RECREATE(script->languages, char *, ++script->max_lang_id);
+
+ script->languages[lang_id] = aStrdup(name);
+
+ return lang_id;
+}
+/**
+ * Goes thru db/translations.conf file
+ **/
+void script_load_translations(void) {
+ config_t translations_conf;
+ const char *config_filename = "db/translations.conf"; // FIXME hardcoded name
+ config_setting_t *translations = NULL;
+ int i, size;
+ uint32 total = 0;
+ uint8 lang_id = 0, k;
+
+ script->translation_db = strdb_alloc(DB_OPT_DUP_KEY, NAME_LENGTH*2+1);
+
+ if( script->languages ) {
+ for(i = 0; i < script->max_lang_id; i++)
+ aFree(script->languages[i]);
+ aFree(script->languages);
+ }
+ script->languages = NULL;
+ script->max_lang_id = 0;
+
+ script->add_language("English");/* 0 is default, which is whatever is in the npc files hardcoded (in our case, English) */
+
+ if (libconfig->read_file(&translations_conf, config_filename)) {
+ ShowError("load_translations: can't read '%s'\n", config_filename);
+ return;
+ }
+
+ if( !(translations = libconfig->lookup(&translations_conf, "translations")) ) {
+ ShowError("load_translations: invalid format on '%s'\n",config_filename);
+ return;
+ }
+
+ if( script->string_list )
+ aFree(script->string_list);
+
+ script->string_list = NULL;
+ script->string_list_pos = 0;
+ script->string_list_size = 0;
+
+ size = libconfig->setting_length(translations);
+
+ for(i = 0; i < size; i++) {
+ const char *translation_file = libconfig->setting_get_string_elem(translations, i);
+
+ script->load_translation(translation_file, ++lang_id, &total);
+ }
+
+ if( total ) {
+ DBIterator *main_iter;
+ DBIterator *sub_iter;
+ DBMap *string_db;
+ struct string_translation *st = NULL;
+ uint32 j = 0;
+
+
+ CREATE(script->translation_buf, char *, total);
+ script->translation_buf_size = total;
+
+ main_iter = db_iterator(script->translation_db);
+
+ for( string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter) ) {
+ sub_iter = db_iterator(string_db);
+
+ for( st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter) ) {
+ script->translation_buf[j++] = st->buf;
+ }
+
+ dbi_destroy(sub_iter);
+ }
+
+ dbi_destroy(main_iter);
+ }
+
+ for(k = 0; k < script->max_lang_id; k++) {
+ if( !strcmpi(script->languages[k],map->default_lang_str) ) {
+ break;
+ }
+ }
+
+ if( k == script->max_lang_id ) {
+ ShowError("load_translations: map server default_language setting '%s' is not a loaded language\n",map->default_lang_str);
+ map->default_lang_id = 0;
+ } else {
+ map->default_lang_id = k;
+ }
+}
+
+/**
+ *
+ **/
+const char * script_get_translation_file_name(const char *file) {
+ static char file_name[200];
+ int i, len = (int)strlen(file), last_bar = -1, last_dot = -1;
+
+ for(i = 0; i < len; i++) {
+ if( file[i] == '/' || file[i] == '\\' )
+ last_bar = i;
+ else if ( file[i] == '.' )
+ last_dot = i;
+ }
+
+ if( last_bar != -1 || last_dot != -1 ) {
+ if( last_bar != -1 && last_dot < last_bar )
+ last_dot = -1;
+ safestrncpy(file_name, file+(last_bar >= 0 ? last_bar+1 : 0), ( last_dot >= 0 ? ( last_bar >= 0 ? last_dot - last_bar : last_dot ) : sizeof(file_name) ));
+ return file_name;
+ }
+
+ return file;
+}
+
+/**
+ * Parses a individual translation file
+ **/
+void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
+ uint32 translations = 0;
+ char line[1024];
+ char msgctxt[NAME_LENGTH*2+1] = { 0 };
+ DBMap *string_db;
+ size_t i;
+ FILE *fp;
+ struct script_string_buf msgid = { 0 }, msgstr = { 0 };
+
+ if( !(fp = fopen(file,"rb")) ) {
+ ShowError("load_translation: failed to open '%s' for reading\n",file);
+ return;
+ }
+
+ script->add_language(script->get_translation_file_name(file));
+ if( lang_id >= atcommand->max_message_table )
+ atcommand->expand_message_table();
+
+ while(fgets(line, sizeof(line), fp)) {
+ size_t len = strlen(line), cursor = 0;
+
+ if( len <= 1 )
+ continue;
+
+ if( line[0] == '#' )
+ continue;
+
+ if( strncasecmp(line,"msgctxt \"", 9) == 0 ) {
+ for(i = 9; i < len - 2; i++) {
+ if( line[i] == '\\' && line[i+1] == '"' ) {
+ msgctxt[cursor] = '"';
+ i++;
+ } else
+ msgctxt[cursor] = line[i];
+ if( ++cursor >= sizeof(msgctxt) - 1 )
+ break;
+ }
+ msgctxt[cursor] = '\0';
+ } else if ( strncasecmp(line, "msgid \"", 7) == 0 ) {
+ for(i = 7; i < len - 2; i++) {
+ if( line[i] == '\\' && line[i+1] == '"' ) {
+ script_string_buf_addb(&msgid, '"');
+ i++;
+ } else
+ script_string_buf_addb(&msgid, line[i]);
+ }
+ script_string_buf_addb(&msgid,0);
+ } else if ( len > 9 && line[9] != '"' && strncasecmp(line, "msgstr \"",8) == 0 ) {
+ for(i = 8; i < len - 2; i++) {
+ if( line[i] == '\\' && line[i+1] == '"' ) {
+ script_string_buf_addb(&msgstr, '"');
+ i++;
+ } else
+ script_string_buf_addb(&msgstr, line[i]);
+ }
+ script_string_buf_addb(&msgstr,0);
+ }
+
+ if( msgctxt[0] && msgid.pos > 1 && msgstr.pos > 1 ) {
+ size_t msgstr_len = msgstr.pos;
+ unsigned int inner_len = 1 + (uint32)msgstr_len + 1; //uint8 lang_id + msgstr_len + '\0'
+
+ if( strcasecmp(msgctxt, "messages.conf") == 0 ) {
+ int k;
+
+ for(k = 0; k < MAX_MSG; k++) {
+ if( atcommand->msg_table[0][k] && strcmpi(atcommand->msg_table[0][k],msgid.ptr) == 0 ) {
+ if( atcommand->msg_table[lang_id][k] )
+ aFree(atcommand->msg_table[lang_id][k]);
+ atcommand->msg_table[lang_id][k] = aStrdup(msgstr.ptr);
+ break;
+ }
+ }
+
+ } else {
+ struct string_translation *st = NULL;
+
+ if( !( string_db = strdb_get(script->translation_db, msgctxt) ) ) {
+ string_db = strdb_alloc(DB_OPT_DUP_KEY, 0);
+
+ strdb_put(script->translation_db, msgctxt, string_db);
+ }
+
+ if( !(st = strdb_get(string_db, msgid.ptr) ) ) {
+ CREATE(st, struct string_translation, 1);
+
+ st->string_id = script->string_dup(msgid.ptr);
+
+ strdb_put(string_db, msgid.ptr, st);
+ }
+
+ RECREATE(st->buf, char, st->len + inner_len);
+
+ WBUFB(st->buf, st->len) = lang_id;
+ safestrncpy((char*)WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1);
+
+ st->translations++;
+ st->len += inner_len;
+ }
+
+ msgctxt[0] = '\0';
+ msgid.pos = msgstr.pos = 0;
+ translations++;
+ }
+ }
+
+ *total += translations;
+
+ fclose(fp);
+
+ script_string_buf_destroy(&msgid);
+ script_string_buf_destroy(&msgstr);
+
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", translations, file);
+}
+
+/**
+ *
+ **/
+void script_clear_translations(bool reload) {
+ uint32 i;
+
+ if( script->string_list )
+ aFree(script->string_list);
+
+ script->string_list = NULL;
+ script->string_list_pos = 0;
+ script->string_list_size = 0;
+
+ if( script->translation_buf ) {
+ for(i = 0; i < script->translation_buf_size; i++) {
+ aFree(script->translation_buf[i]);
+ }
+ aFree(script->translation_buf);
+ }
+
+ script->translation_buf = NULL;
+ script->translation_buf_size = 0;
+
+ if( script->languages ) {
+ for(i = 0; i < script->max_lang_id; i++)
+ aFree(script->languages[i]);
+ aFree(script->languages);
+ }
+ script->languages = NULL;
+ script->max_lang_id = 0;
+
+ if( script->translation_db ) {
+ script->translation_db->clear(script->translation_db,script->translation_db_destroyer);
+ }
+
+ if( reload )
+ script->load_translations();
+}
+
+/**
+ *
+ **/
+int script_translation_db_destroyer(DBKey key, DBData *data, va_list ap) {
+ DBMap *string_db = DB->data2ptr(data);
+
+ if( db_size(string_db) ) {
+ DBIterator *iter = db_iterator(string_db);
+ struct string_translation *st = NULL;
+
+ for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
+ aFree(st);
+ }
+
+ dbi_destroy(iter);
+ }
+
+ db_destroy(string_db);
+ return 0;
+}
+
+/**
+ *
+ **/
+void script_parser_clean_leftovers(void) {
+ if( script->translation_db ) {
+ script->translation_db->destroy(script->translation_db,script->translation_db_destroyer);
+ script->translation_db = NULL;
+ }
+
+ if( script->syntax.strings ) { /* used only when generating translation file */
+ db_destroy(script->syntax.strings);
+ script->syntax.strings = NULL;
+ }
+
+ script_string_buf_destroy(&script->parse_simpleexpr_str);
+ script_string_buf_destroy(&script->lang_export_line_buf);
+}
+
+/**
+ * Performs cleanup after all parsing is processed
+ **/
+int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) {
+
+ script->parser_clean_leftovers();
+
+ script->parse_cleanup_timer_id = INVALID_TIMER;
+
+ return 0;
+}
+
+
/*==========================================
* Initialization
*------------------------------------------*/
void do_init_script(bool minimal) {
+ script->parse_cleanup_timer_id = INVALID_TIMER;
+
script->st_db = idb_alloc(DB_OPT_BASE);
script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
script->autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
@@ -4454,6 +5019,8 @@ void do_init_script(bool minimal) {
return;
mapreg->init();
+
+ script->load_translations();
}
int script_reload(void) {
@@ -4486,6 +5053,13 @@ int script_reload(void) {
atcommand->binding_count = 0;
db_clear(script->st_db);
+
+ script->clear_translations(true);
+
+ if( script->parse_cleanup_timer_id != INVALID_TIMER ) {
+ timer->delete(script->parse_cleanup_timer_id,script->parse_cleanup_timer);
+ script->parse_cleanup_timer_id = INVALID_TIMER;
+ }
mapreg->reload();
@@ -12985,7 +13559,7 @@ BUILDIN(recovery)
status->revive(&sd->bl, 100, 100);
else
status_percent_heal(&sd->bl, 100, 100);
- clif->message(sd->fd,msg_txt(880)); // "You have been recovered!"
+ clif->message(sd->fd,msg_sd(sd,880)); // "You have been recovered!"
}
mapit->free(iter);
return true;
@@ -18132,16 +18706,16 @@ BUILDIN(montransform) {
return true;
if( battle_config.mon_trans_disable_in_gvg && map_flag_gvg2(sd->bl.m) ) {
- clif->message(sd->fd, msg_txt(1488)); // Transforming into monster is not allowed in Guild Wars.
+ clif->message(sd->fd, msg_sd(sd,1488)); // Transforming into monster is not allowed in Guild Wars.
return true;
}
if( sd->disguise != -1 ) {
- clif->message(sd->fd, msg_txt(1486)); // Cannot transform into monster while in disguise.
+ clif->message(sd->fd, msg_sd(sd,1486)); // Cannot transform into monster while in disguise.
return true;
}
- sprintf(msg, msg_txt(1485), monster->name); // Traaaansformation-!! %s form!!
+ sprintf(msg, msg_sd(sd,1485), monster->name); // Traaaansformation-!! %s form!!
clif->ShowScript(&sd->bl, msg);
status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous
sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick);
@@ -19043,6 +19617,11 @@ BUILDIN(channelmes)
return true;
}
+/** place holder for the translation macro **/
+BUILDIN(_) {
+ return true;
+}
+
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
BUILDIN(defpattern);
@@ -19118,6 +19697,9 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
else if( strcmp(buildin->name, "callsub") == 0 ) script->buildin_callsub_ref = n;
else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n;
else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n;
+ else if( strcmp(buildin->name, "mes") == 0 ) script->buildin_mes_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "select") == 0 ) script->buildin_select_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "_") == 0 ) script->buildin_lang_macro_offset = script->buildin_count;
offset = script->buildin_count;
@@ -19670,6 +20252,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(shopcount, "i"),
BUILDIN_DEF(channelmes, "ss"),
+ BUILDIN_DEF(_,"s"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
@@ -20046,5 +20629,14 @@ void script_defaults(void) {
/* */
script->hardcoded_constants = script_hardcoded_constants;
script->mapindexname2id = script_mapindexname2id;
+ script->string_dup = script_string_dup;
+ script->load_translations = script_load_translations;
+ script->load_translation = script_load_translation;
+ script->translation_db_destroyer = script_translation_db_destroyer;
+ script->clear_translations = script_clear_translations;
+ script->parse_cleanup_timer = script_parse_cleanup_timer;
+ script->add_language = script_add_language;
+ script->get_translation_file_name = script_get_translation_file_name;
+ script->parser_clean_leftovers = script_parser_clean_leftovers;
}