From a2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 2 May 2013 17:14:01 -0300 Subject: Introducing Hercules Plugin Mananger http://hercules.ws/board/topic/549-introducing-hercules-plugin-manager/ Signed-off-by: shennetsind --- src/map/atcommand.c | 90 ++-- src/map/atcommand.h | 12 +- src/map/clif.c | 42 +- src/map/map.c | 199 +++---- src/map/npc_chat.c | 12 +- src/map/pc_groups.c | 11 +- src/map/script.c | 1484 ++++++++++++++++++++++++--------------------------- src/map/script.h | 129 ++++- 8 files changed, 1030 insertions(+), 949 deletions(-) (limited to 'src/map') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 85332905e..5b82666fb 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -51,12 +51,7 @@ #include #include - -#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) - static char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) -static DBMap* atcommand_db = NULL; //name -> AtCommandInfo -static DBMap* atcommand_alias_db = NULL; //alias -> AtCommandInfo static char atcmd_output[CHAT_SIZE_MAX]; static char atcmd_player_name[NAME_LENGTH]; @@ -1436,7 +1431,7 @@ ACMD(help) { StringBuf_Init(&buf); StringBuf_AppendStr(&buf, msg_txt(990)); // Available aliases: command_info = get_atcommandinfo_byname(command_name); - iter = db_iterator(atcommand_alias_db); + iter = db_iterator(atcommand->alias_db); for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) { if (alias_info->command == command_info) { StringBuf_Printf(&buf, " %s", alias_info->alias); @@ -8433,7 +8428,7 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At char line_buff[CHATBOX_SIZE]; char* cur = line_buff; AtCommandInfo* cmd; - DBIterator *iter = db_iterator(atcommand_db); + DBIterator *iter = db_iterator(atcommand->db); int count = 0; memset(line_buff,' ',CHATBOX_SIZE); @@ -9699,7 +9694,7 @@ void atcommand_basecommands(void) { }; AtCommandInfo* cmd; int i; - + for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { if(atcommand->exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); @@ -9709,7 +9704,7 @@ void atcommand_basecommands(void) { safestrncpy(cmd->command, atcommand_base[i].command, sizeof(cmd->command)); cmd->func = atcommand_base[i].func; cmd->help = NULL;/* start as null dear */ - strdb_put(atcommand_db, cmd->command, cmd); + strdb_put(atcommand->db, cmd->command, cmd); } return; } @@ -9718,20 +9713,20 @@ void atcommand_basecommands(void) { * Command lookup functions *------------------------------------------*/ AtCommandInfo* atcommand_exists(const char* name) { - return strdb_get(atcommand_db, name); + return strdb_get(atcommand->db, name); } -static AtCommandInfo* get_atcommandinfo_byname(const char *name) -{ - if (strdb_exists(atcommand_db, name)) - return (AtCommandInfo*)strdb_get(atcommand_db, name); +static AtCommandInfo* get_atcommandinfo_byname(const char *name) { + AtCommandInfo *cmd; + if ((cmd = strdb_get(atcommand->db, name))) + return cmd; return NULL; } static const char* atcommand_checkalias(const char *aliasname) { AliasInfo *alias_info = NULL; - if ((alias_info = (AliasInfo*)strdb_get(atcommand_alias_db, aliasname)) != NULL) + if ((alias_info = (AliasInfo*)strdb_get(atcommand->alias_db, aliasname)) != NULL) return alias_info->command->command; return aliasname; } @@ -9752,8 +9747,8 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n if (!battle_config.atcommand_suggestions_enabled) return; - atcommand_iter = db_iterator(atcommand_db); - alias_iter = db_iterator(atcommand_alias_db); + atcommand_iter = db_iterator(atcommand->db); + alias_iter = db_iterator(atcommand->alias_db); // Build the matches for (command_info = dbi_first(atcommand_iter); dbi_exists(atcommand_iter); command_info = dbi_next(atcommand_iter)) { @@ -10050,14 +10045,14 @@ static void atcommand_config_read(const char* config_filename) { const char *alias = config_setting_get_string_elem(command, j); if (alias != NULL) { AliasInfo *alias_info; - if (strdb_exists(atcommand_alias_db, alias)) { + if (strdb_exists(atcommand->alias_db, alias)) { ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias); continue; } CREATE(alias_info, AliasInfo, 1); alias_info->command = commandinfo; safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias)); - strdb_put(atcommand_alias_db, alias, alias_info); + strdb_put(atcommand->alias_db, alias, alias_info); ++num_aliases; } } @@ -10116,8 +10111,8 @@ static void atcommand_config_read(const char* config_filename) { config_destroy(&atcommand_config); return; } -void atcommand_db_load_groups(int* group_ids) { - DBIterator *iter = db_iterator(atcommand_db); +void atcommand_db_load_groups(void) { + DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo* cmd; int i; @@ -10125,11 +10120,11 @@ void atcommand_db_load_groups(int* group_ids) { cmd->at_groups = aMalloc( pc_group_max * sizeof(char) ); cmd->char_groups = aMalloc( pc_group_max * sizeof(char) ); for(i = 0; i < pc_group_max; i++) { - if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_ATCOMMAND ) ) + if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_ATCOMMAND ) ) cmd->at_groups[i] = 1; else cmd->at_groups[i] = 0; - if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) ) + if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) ) cmd->char_groups[i] = 1; else cmd->char_groups[i] = 0; @@ -10166,11 +10161,35 @@ bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtComm return false; } - +bool atcommand_hp_add(char *name, AtCommandFunc func) { + AtCommandInfo* cmd; + + if( runflag == MAPSERVER_ST_RUNNING ) { + ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name); + return false; + } + + if( !atcommand->db ) + atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + + if( atcommand->exists(name) ) { + ShowDebug("atcommand_hp_add: duplicate command '%s', skipping...\n", name); + return false; + } + + CREATE(cmd, AtCommandInfo, 1); + + safestrncpy(cmd->command, name, sizeof(cmd->command)); + cmd->func = func; + cmd->help = NULL;/* start as null dear */ + + strdb_put(atcommand->db, cmd->command, cmd); + return true; +} void atcommand_db_clear(void) { - if (atcommand_db != NULL) { - DBIterator *iter = db_iterator(atcommand_db); + if (atcommand->db != NULL) { + DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo* cmd; for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { @@ -10182,16 +10201,18 @@ void atcommand_db_clear(void) { dbi_destroy(iter); - db_destroy(atcommand_db); + db_destroy(atcommand->db); } - if (atcommand_alias_db != NULL) - db_destroy(atcommand_alias_db); + if (atcommand->alias_db != NULL) + db_destroy(atcommand->alias_db); } void atcommand_doload(void) { - atcommand_db_clear(); - atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); - atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + if( runflag >= MAPSERVER_ST_RUNNING ) + atcommand_db_clear(); + if( !atcommand->db ) + atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + atcommand->alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); atcommand_basecommands(); //fills initial atcommand_db with known commands atcommand_config_read(ATCOMMAND_CONF_FILENAME); } @@ -10206,17 +10227,22 @@ void do_init_atcommand(void) { void do_final_atcommand(void) { atcommand_db_clear(); + if( atcommand->group_ids ) + aFree(atcommand->group_ids); } void atcommand_defaults(void) { atcommand = &atcommand_s; + atcommand->db = NULL; + atcommand->init = do_init_atcommand; atcommand->final = do_final_atcommand; atcommand->parse = is_atcommand; atcommand->can_use = atcommand_can_use; atcommand->can_use2 = atcommand_can_use2; + atcommand->create = atcommand_hp_add; atcommand->load_groups = atcommand_db_load_groups; atcommand->exists = atcommand_exists; atcommand->msg_read = msg_config_read; diff --git a/src/map/atcommand.h b/src/map/atcommand.h index cea59a416..f09b1f2b8 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -5,6 +5,8 @@ #ifndef _ATCOMMAND_H_ #define _ATCOMMAND_H_ +#include "../common/db.h" + /** * Declarations **/ @@ -66,14 +68,19 @@ struct atcommand_interface { /* atcommand binding */ struct atcmd_binding_data** binding; int binding_count; + unsigned int *group_ids; + /* other vars */ + DBMap* db; //name -> AtCommandInfo + DBMap* alias_db; //alias -> AtCommandInfo /* */ void (*init) (void); void (*final) (void); /* */ bool (*parse) (const int fd, struct map_session_data* sd, const char* message, int type); + bool (*create) (char *name, AtCommandFunc func); bool (*can_use) (struct map_session_data *sd, const char *command); bool (*can_use2) (struct map_session_data *sd, const char *command, AtCommandType type); - void (*load_groups) (int* group_ids); + void (*load_groups) (void); AtCommandInfo* (*exists) (const char* name); int (*msg_read) (const char* cfgName); void (*final_msg) (void); @@ -85,5 +92,8 @@ struct atcommand_interface *atcommand; const char* msg_txt(int msg_number); void atcommand_defaults(void); +/* stay here */ +#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) +#define ACMD_A(x) atcommand_ ## x #endif /* _ATCOMMAND_H_ */ diff --git a/src/map/clif.c b/src/map/clif.c index 10c1a0d47..160de3adc 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -5640,38 +5640,27 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val p.val2 = val2; p.val3 = val3; #endif - + ShowDebug("Sending type %d; aid %d; state %d; total %d; left %d; v1 %d; v2 %d; v3 %d;\n",p.index,p.AID,p.state,p.Total,p.Left,p.val1,p.val2,p.val3); clif->send(&p,sizeof(p), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); } /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT). /// 008e .W .?B -void clif_displaymessage(const int fd, const char* mes) -{ +void clif_displaymessage(const int fd, const char* mes) { nullpo_retv(mes); - //Scrapped, as these are shared by disconnected players =X [Skotlex] - if (fd == 0) - ; - else { - char *message, *line; - - message = aStrdup(mes); - line = strtok(message, "\n"); - while(line != NULL) { - // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) - int len = strnlen(line, 255); - - if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOHEAD(fd, 5 + len); - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate - safestrncpy((char *)WFIFOP(fd,4), line, len + 1); - WFIFOSET(fd, 5 + len); - } - line = strtok(NULL, "\n"); + if( fd == -2 ) { + ShowInfo("HCP: %s\n",mes); + } else if ( fd > 0 ) { + int len; + + if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line. + WFIFOHEAD(fd, 5 + len); + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + safestrncpy((char *)WFIFOP(fd,4), mes, len + 1); + WFIFOSET(fd, 5 + len); } - aFree(message); } } @@ -16873,9 +16862,10 @@ int clif_parse(int fd) { set_eof(fd); return 0; } - // determine real packet length packet_len = packet_db[cmd].len; + if(sd) + ShowWarning("clif_parse: Received packet 0x%04x with packet_len = %d (%d).\n", cmd, packet_len,RFIFOREST(fd)); if (packet_len == -1) { // variable-length packet if (RFIFOREST(fd) < 4) return 0; @@ -16892,7 +16882,7 @@ int clif_parse(int fd) { } if ((int)RFIFOREST(fd) < packet_len) return 0; // not enough data received to form the packet - + if( packet_db[cmd].func == clif->pDebug ) packet_db[cmd].func(fd, sd); else if( packet_db[cmd].func != NULL ) { diff --git a/src/map/map.c b/src/map/map.c index 1bbad1d40..ed4eba209 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -15,6 +15,8 @@ #include "../common/strlib.h" #include "../common/utils.h" #include "../common/conf.h" +#include "../common/console.h" +#include "../common/HPM.h" #include "map.h" #include "path.h" @@ -160,6 +162,9 @@ char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] +/* [Ind/Hercules] */ +struct eri *map_iterator_ers; + /*========================================== * server player count (of all mapservers) *------------------------------------------*/ @@ -2040,7 +2045,7 @@ struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) { struct s_mapiterator* mapit; - CREATE(mapit, struct s_mapiterator, 1); + mapit = ers_alloc(map_iterator_ers, struct s_mapiterator); mapit->flags = flags; mapit->types = types; if( types == BL_PC ) mapit->dbi = db_iterator(pc_db); @@ -2057,7 +2062,7 @@ void mapit_free(struct s_mapiterator* mapit) nullpo_retv(mapit); dbi_destroy(mapit->dbi); - aFree(mapit); + ers_free(map_iterator_ers, mapit); } /// Returns the first block_list that matches the description. @@ -3263,80 +3268,6 @@ int map_readallmaps (void) static int map_ip_set = 0; static int char_ip_set = 0; -/*========================================== - * Console Command Parser [Wizputer] - *------------------------------------------*/ -int parse_console(const char* buf) -{ - char type[64]; - char command[64]; - char map[64]; - int16 x = 0; - int16 y = 0; - int16 m; - int n; - struct map_session_data sd; - - memset(&sd, 0, sizeof(struct map_session_data)); - strcpy(sd.status.name, "console"); - - if( ( n = sscanf(buf, "%63[^:]:%63[^:]:%63s %hd %hd[^\n]", type, command, map, &x, &y) ) < 5 ) - { - if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 ) - { - n = sscanf(buf, "%63[^\n]", type); - } - } - - if( n == 5 ) - { - m = map_mapname2mapid(map); - if( m < 0 ) - { - ShowWarning("Console: Unknown map.\n"); - return 0; - } - sd.bl.m = m; - map_search_freecell(&sd.bl, m, &sd.bl.x, &sd.bl.y, -1, -1, 0); - if( x > 0 ) - sd.bl.x = x; - if( y > 0 ) - sd.bl.y = y; - } - else - { - map[0] = '\0'; - if( n < 2 ) - command[0] = '\0'; - if( n < 1 ) - type[0] = '\0'; - } - - ShowNotice("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y); - - if( n == 5 && strcmpi("admin",type) == 0 ) { - if( !atcommand->parse(sd.fd, &sd, command, 0) ) - ShowInfo("Console: not atcommand\n"); - } else if( n == 2 && strcmpi("server", type) == 0 ) { - if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ) { - runflag = 0; - } - } else if( strcmpi("ers_report", type) == 0 ) - ers_report(); - else if( strcmpi("help", type) == 0 ) { - ShowInfo("To use GM commands:\n"); - ShowInfo(" admin:: \n"); - ShowInfo("You can use any GM command that doesn't require the GM.\n"); - ShowInfo("No using @item or @warp however you can use @charwarp\n"); - ShowInfo("The is for commands that need coords of the GM\n"); - ShowInfo("IE: @spawn\n"); - ShowInfo("To shutdown the server:\n"); - ShowInfo(" server:shutdown\n"); - } - - return 0; -} - /*========================================== * Read map server configuration files (conf/map_server.conf...) *------------------------------------------*/ @@ -4999,6 +4930,7 @@ void do_final(void) ShowStatus("Terminating...\n"); hChSys.closing = true; + HPM->event(HPET_FINAL); //Ladies and babies first. iter = mapit_getallusers(); @@ -5027,7 +4959,7 @@ void do_final(void) ircbot->final();/* before clif. */ clif->final(); do_final_npc(); - do_final_script(); + script->final(); do_final_instance(); do_final_itemdb(); do_final_storage(); @@ -5062,6 +4994,7 @@ void do_final(void) regen_db->destroy(regen_db, NULL); map_sql_close(); + ers_destroy(map_iterator_ers); ShowStatus("Finished.\n"); } @@ -5123,22 +5056,19 @@ static void map_helpscreen(bool do_exit) /*====================================================== * Map-Server Version Screen [MC Cameri] *------------------------------------------------------*/ -static void map_versionscreen(bool do_exit) -{ - ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision()); - ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n"); - ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rathena.net/#rathena\n"); +static void map_versionscreen(bool do_exit) { + const char *svn = get_svn_revision(); + const char *git = get_git_hash(); + ShowInfo(CL_WHITE"Hercules version: %s" CL_RESET"\n", git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown"); + ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n"); + ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n"); ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n"); if( do_exit ) exit(EXIT_SUCCESS); } -/*====================================================== - * Map-Server Init and Command-line Arguments [Valaris] - *------------------------------------------------------*/ -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_MAP; +void set_server_type(void) { + SERVER_TYPE = SERVER_TYPE_MAP; } @@ -5163,14 +5093,80 @@ void do_shutdown(void) static bool map_arg_next_value(const char* option, int i, int argc) { - if( i >= argc-1 ) - { + if( i >= argc-1 ) { ShowWarning("Missing value for option '%s'.\n", option); return false; } return true; } +struct map_session_data cpsd; +CPCMD(gm_position) { + int x = 0, y = 0, m = 0; + char map_name[25]; + + if( line == NULL || sscanf(line, "%d %d %24s",&x,&y,map_name) < 3 ) { + ShowError("gm:info invalid syntax. use '"CL_WHITE"gm:info xCord yCord map_name"CL_RESET"'\n"); + return; + } + + if ( (m = map_mapname2mapid(map_name) <= 0 ) ) { + ShowError("gm:info '"CL_WHITE"%s"CL_RESET"' is not a known map\n",map_name); + return; + } + + if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) { + ShowError("gm:info '"CL_WHITE"%d %d"CL_RESET"' is out of '"CL_WHITE"%s"CL_RESET"' map bounds!\n",x,y,map_name); + return; + } + + ShowInfo("HCP: updated console's game position to '"CL_WHITE"%d %d %s"CL_RESET"'\n",x,y,map_name); + cpsd.bl.x = x; + cpsd.bl.y = y; + cpsd.bl.m = m; +} +CPCMD(gm_use) { + + if( line == NULL ) { + ShowError("gm:use invalid syntax. use '"CL_WHITE"gm:use @command "CL_RESET"'\n"); + return; + } + cpsd.fd = -2; + if( !atcommand->parse(cpsd.fd, &cpsd, line, 0) ) + ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' failed\n",line); + else + ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' was used\n",line); + cpsd.fd = 0; + +} +/* Hercules Console Parser */ +void map_cp_defaults(void) { + /* default HCP data */ + memset(&cpsd, 0, sizeof(struct map_session_data)); + strcpy(cpsd.status.name, "Hercules Console"); + cpsd.bl.x = 150; + cpsd.bl.y = 150; + cpsd.bl.m = map_mapname2mapid("prontera"); + + console->addCommand("gm:info",CPCMD_A(gm_position)); + console->addCommand("gm:use",CPCMD_A(gm_use)); +} +/* Hercules Plugin Mananger */ +void map_hp_symbols(void) { + /* full interfaces */ + HPM->share(atcommand,"atcommand"); + HPM->share(buyingstore,"buyingstore"); + HPM->share(clif,"clif"); + HPM->share(ircbot,"ircbot"); + HPM->share(logs,"logs"); + HPM->share(script,"script"); + HPM->share(searchstore,"searchstore"); + HPM->share(skill,"skill"); + HPM->share(vending,"vending"); + /* specific */ + HPM->share(atcommand->create,"addCommand"); + HPM->share(script->addScript,"addScript"); +} void load_defaults(void) { atcommand_defaults(); battle_defaults(); @@ -5178,6 +5174,7 @@ void load_defaults(void) { clif_defaults(); ircbot_defaults(); log_defaults(); + script_defaults(); searchstore_defaults(); skill_defaults(); vending_defaults(); @@ -5332,6 +5329,7 @@ int do_init(int argc, char *argv[]) iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH); + map_iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_NONE); map_sql_init(); if (logs->config.sql_logs) @@ -5347,14 +5345,18 @@ int do_init(int argc, char *argv[]) add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer"); add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); add_timer_interval(gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); - + + HPM->symbol_defaults_sub = map_hp_symbols; + HPM->config_read(); + HPM->event(HPET_INIT); + atcommand->init(); battle->init(); do_init_instance(); do_init_chrif(); clif->init(); ircbot->init(); - do_init_script(); + script->init(); do_init_itemdb(); skill->init(); read_map_zone_db();/* read after item and skill initalization */ @@ -5384,15 +5386,14 @@ int do_init(int argc, char *argv[]) ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); - if( runflag != CORE_ST_STOP ) - { + if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; runflag = MAPSERVER_ST_RUNNING; } -#if defined(BUILDBOT) - if( buildbotflag ) - exit(EXIT_FAILURE); -#endif - + + map_cp_defaults(); + + HPM->event(HPET_READY); + return 0; } diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 64d0fe5e9..81373bbb6 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -408,9 +408,9 @@ int npc_chat_sub(struct block_list* bl, va_list ap) int buildin_defpattern(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); - const char* pattern = conv_str(st,& (st->stack->stack_data[st->start+3])); - const char* label = conv_str(st,& (st->stack->stack_data[st->start+4])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); + const char* pattern = script->conv_str(st,& (st->stack->stack_data[st->start+3])); + const char* label = script->conv_str(st,& (st->stack->stack_data[st->start+4])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); npc_chat_def_pattern(nd, setid, pattern, label); @@ -420,7 +420,7 @@ int buildin_defpattern(struct script_state* st) int buildin_activatepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); activate_pcreset(nd, setid); @@ -430,7 +430,7 @@ int buildin_activatepset(struct script_state* st) int buildin_deactivatepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); deactivate_pcreset(nd, setid); @@ -440,7 +440,7 @@ int buildin_deactivatepset(struct script_state* st) int buildin_deletepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); delete_pcreset(nd, setid); diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 2fd143b53..42a068693 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -14,7 +14,6 @@ #include "pc_groups.h" #include "pc.h" // e_pc_permission - typedef struct GroupSettings GroupSettings; // Cached config settings/pointers for quick lookup @@ -278,16 +277,18 @@ static void read_config(void) { if( ( pc_group_max = group_count ) ) { DBIterator *iter = db_iterator(pc_group_db); GroupSettings *group_settings = NULL; - int* group_ids = aMalloc( pc_group_max * sizeof(int) ); + unsigned int* group_ids = aMalloc( pc_group_max * sizeof(unsigned int) ); int i = 0; for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { group_ids[i++] = group_settings->id; } - atcommand->load_groups(group_ids); - - aFree(group_ids); + if( atcommand->group_ids ) + aFree(atcommand->group_ids); + atcommand->group_ids = group_ids; + atcommand->load_groups(); + dbi_destroy(iter); } diff --git a/src/map/script.c b/src/map/script.c index fbe3a31df..3b1533f74 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -63,103 +63,6 @@ #include #include - -/////////////////////////////////////////////////////////////////////////////// -//## TODO possible enhancements: [FlavioJS] -// - 'callfunc' supporting labels in the current npc "::LabelName" -// - 'callfunc' supporting labels in other npcs "NpcName::LabelName" -// - 'function FuncName;' function declarations reverting to global functions -// if local label isn't found -// - join callfunc and callsub's functionality -// - remove dynamic allocation in add_word() -// - remove GETVALUE / SETVALUE -// - clean up the set_reg / set_val / setd_sub mess -// - detect invalid label references at parse-time - -// -// struct script_state* st; -// - -/// Returns the script_data at the target index -#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) ) -/// Returns if the stack contains data at the target index -#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) ) -/// Returns the index of the last data in the stack -#define script_lastdata(st) ( (st)->end - (st)->start - 1 ) -/// Pushes an int into the stack -#define script_pushint(st,val) push_val((st)->stack, C_INT, (val)) -/// Pushes a string into the stack (script engine frees it automatically) -#define script_pushstr(st,val) push_str((st)->stack, C_STR, (val)) -/// Pushes a copy of a string into the stack -#define script_pushstrcopy(st,val) push_str((st)->stack, C_STR, aStrdup(val)) -/// Pushes a constant string into the stack (must never change or be freed) -#define script_pushconststr(st,val) push_str((st)->stack, C_CONSTSTR, (val)) -/// Pushes a nil into the stack -#define script_pushnil(st) push_val((st)->stack, C_NOP, 0) -/// Pushes a copy of the data in the target index -#define script_pushcopy(st,i) push_copy((st)->stack, (st)->start + (i)) - -#define script_isstring(st,i) data_isstring(script_getdata(st,i)) -#define script_isint(st,i) data_isint(script_getdata(st,i)) - -#define script_getnum(st,val) conv_num(st, script_getdata(st,val)) -#define script_getstr(st,val) conv_str(st, script_getdata(st,val)) -#define script_getref(st,val) ( script_getdata(st,val)->ref ) - -// Note: "top" functions/defines use indexes relative to the top of the stack -// -1 is the index of the data at the top - -/// Returns the script_data at the target index relative to the top of the stack -#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) ) -/// Pushes a copy of the data in the target index relative to the top of the stack -#define script_pushcopytop(st,i) push_copy((st)->stack, (st)->stack->sp + (i)) -/// Removes the range of values [start,end[ relative to the top of the stack -#define script_removetop(st,start,end) ( pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) ) - -// -// struct script_data* data; -// - -/// Returns if the script data is a string -#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR ) -/// Returns if the script data is an int -#define data_isint(data) ( (data)->type == C_INT ) -/// Returns if the script data is a reference -#define data_isreference(data) ( (data)->type == C_NAME ) -/// Returns if the script data is a label -#define data_islabel(data) ( (data)->type == C_POS ) -/// Returns if the script data is an internal script function label -#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS ) - -/// Returns if this is a reference to a constant -#define reference_toconstant(data) ( str_data[reference_getid(data)].type == C_INT ) -/// Returns if this a reference to a param -#define reference_toparam(data) ( str_data[reference_getid(data)].type == C_PARAM ) -/// Returns if this a reference to a variable -//##TODO confirm it's C_NAME [FlavioJS] -#define reference_tovariable(data) ( str_data[reference_getid(data)].type == C_NAME ) -/// Returns the unique id of the reference (id and index) -#define reference_getuid(data) ( (data)->u.num ) -/// Returns the id of the reference -#define reference_getid(data) ( (int32)(reference_getuid(data) & 0x00ffffff) ) -/// Returns the array index of the reference -#define reference_getindex(data) ( (int32)(((uint32)(reference_getuid(data) & 0xff000000)) >> 24) ) -/// Returns the name of the reference -#define reference_getname(data) ( str_buf + str_data[reference_getid(data)].str ) -/// Returns the linked list of uid-value pairs of the reference (can be NULL) -#define reference_getref(data) ( (data)->ref ) -/// Returns the value of the constant -#define reference_getconstant(data) ( str_data[reference_getid(data)].val ) -/// Returns the type of param -#define reference_getparamtype(data) ( str_data[reference_getid(data)].val ) - -/// Composes the uid of a reference from the id and the index -#define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) ) - -#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'') -#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' ) -#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) - #define FETCH(n, t) \ if( script_hasdata(st,n) ) \ (t)=script_getnum(st,n); @@ -298,14 +201,6 @@ int potion_target=0; c_op get_com(unsigned char *script,int *pos); int get_num(unsigned char *script,int *pos); -typedef struct script_function { - bool (*func)(struct script_state *st); - const char *name; - const char *arg; -} script_function; - -extern script_function BUILDIN[]; - static struct linkdb_node* sleep_db;// int oid -> struct script_state* /*========================================== @@ -472,20 +367,19 @@ static void script_reportsrc(struct script_state *st) if( bl == NULL ) return; - switch( bl->type ) - { - case BL_NPC: - if( bl->m >= 0 ) - ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); - break; - default: - if( bl->m >= 0 ) - ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); - break; + switch( bl->type ) { + case BL_NPC: + if( bl->m >= 0 ) + ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); + break; + default: + if( bl->m >= 0 ) + ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); + break; } } @@ -494,54 +388,43 @@ static void script_reportdata(struct script_data* data) { if( data == NULL ) return; - switch( data->type ) - { - case C_NOP:// no value - ShowDebug("Data: nothing (nil)\n"); - break; - case C_INT:// number - ShowDebug("Data: number value=%d\n", data->u.num); - break; - case C_STR: - case C_CONSTSTR:// string - if( data->u.str ) - { - ShowDebug("Data: string value=\"%s\"\n", data->u.str); - } - else - { - ShowDebug("Data: string value=NULL\n"); - } - break; - case C_NAME:// reference - if( reference_tovariable(data) ) - {// variable - const char* name = reference_getname(data); - if( not_array_variable(*name) ) - ShowDebug("Data: variable name='%s'\n", name); - else - ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); - } - else if( reference_toconstant(data) ) - {// constant - ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); - } - else if( reference_toparam(data) ) - {// param - ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); - } - else - {// ??? - ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); - ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); - } - break; - case C_POS:// label - ShowDebug("Data: label pos=%d\n", data->u.num); - break; - default: - ShowDebug("Data: %s\n", script_op2name(data->type)); - break; + switch( data->type ) { + case C_NOP:// no value + ShowDebug("Data: nothing (nil)\n"); + break; + case C_INT:// number + ShowDebug("Data: number value=%d\n", data->u.num); + break; + case C_STR: + case C_CONSTSTR:// string + if( data->u.str ) { + ShowDebug("Data: string value=\"%s\"\n", data->u.str); + } else { + ShowDebug("Data: string value=NULL\n"); + } + break; + case C_NAME:// reference + if( reference_tovariable(data) ) {// variable + const char* name = reference_getname(data); + if( not_array_variable(*name) ) + ShowDebug("Data: variable name='%s'\n", name); + else + ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); + } else if( reference_toconstant(data) ) {// constant + ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); + } else if( reference_toparam(data) ) {// param + ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); + } else {// ??? + ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); + ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); + } + break; + case C_POS:// label + ShowDebug("Data: label pos=%d\n", data->u.num); + break; + default: + ShowDebug("Data: %s\n", script_op2name(data->type)); + break; } } @@ -773,33 +656,33 @@ static void add_scriptl(int l) int backpatch = str_data[l].backpatch; switch(str_data[l].type){ - case C_POS: - case C_USERFUNC_POS: - add_scriptc(C_POS); - add_scriptb(str_data[l].label); - add_scriptb(str_data[l].label>>8); - add_scriptb(str_data[l].label>>16); - break; - case C_NOP: - case C_USERFUNC: - // Embedded data backpatch there is a possibility of label - add_scriptc(C_NAME); - str_data[l].backpatch = script_pos; - add_scriptb(backpatch); - add_scriptb(backpatch>>8); - add_scriptb(backpatch>>16); - break; - case C_INT: - add_scripti(abs(str_data[l].val)); - if( str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce) - add_scriptc(C_NEG); - break; - default: // assume C_NAME - add_scriptc(C_NAME); - add_scriptb(l); - add_scriptb(l>>8); - add_scriptb(l>>16); - break; + case C_POS: + case C_USERFUNC_POS: + add_scriptc(C_POS); + add_scriptb(str_data[l].label); + add_scriptb(str_data[l].label>>8); + add_scriptb(str_data[l].label>>16); + break; + case C_NOP: + case C_USERFUNC: + // Embedded data backpatch there is a possibility of label + add_scriptc(C_NAME); + str_data[l].backpatch = script_pos; + add_scriptb(backpatch); + add_scriptb(backpatch>>8); + add_scriptb(backpatch>>16); + break; + case C_INT: + add_scripti(abs(str_data[l].val)); + if( str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce) + add_scriptc(C_NEG); + break; + default: // assume C_NAME + add_scriptc(C_NAME); + add_scriptb(l); + add_scriptb(l>>8); + add_scriptb(l>>16); + break; } } @@ -927,8 +810,8 @@ int add_word(const char* p) static const char* parse_callfunc(const char* p, int require_paren, int is_custom) { - const char* p2; - const char* arg=NULL; + const char *p2; + char *arg = NULL; int func; func = add_word(p); @@ -936,13 +819,13 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) // buildin function add_scriptl(func); add_scriptc(C_ARG); - arg = BUILDIN[str_data[func].val].arg; + arg = script->buildin[str_data[func].val]; } else if( str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS ){ // script defined function add_scriptl(buildin_callsub_ref); add_scriptc(C_ARG); add_scriptl(func); - arg = BUILDIN[str_data[buildin_callsub_ref].val].arg; + arg = script->buildin[str_data[buildin_callsub_ref].val]; if( *arg == 0 ) disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p); if( *arg != '*' ) @@ -960,7 +843,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) add_scriptc(C_STR); while( *name ) add_scriptb(*name ++); add_scriptb(0); - arg = BUILDIN[str_data[buildin_callfunc_ref].val].arg; + arg = script->buildin[str_data[buildin_callfunc_ref].val]; if( *arg != '*' ) ++ arg; } #endif @@ -982,8 +865,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) {// syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; */ - } else - {// + } else {// if( require_paren ){ if( *p != '(' ) disp_error_message("need '('",p); @@ -1009,7 +891,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) } --syntax.curly_count; } - if( *arg && *arg != '?' && *arg != '*' ) + if( arg && *arg && *arg != '?' && *arg != '*' ) disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum); if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST ) disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); @@ -2087,45 +1969,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag) } } -/*========================================== - * Added built-in functions - *------------------------------------------*/ -static void add_BUILDIN(void) -{ - int i,n; - const char* p; - for( i = 0; BUILDIN[i].func; i++ ) - { - // arg must follow the pattern: (v|s|i|r|l)*\?*\*? - // 'v' - value (either string or int or reference) - // 's' - string - // 'i' - int - // 'r' - reference (of a variable) - // 'l' - label - // '?' - one optional parameter - // '*' - unknown number of optional parameters - p = BUILDIN[i].arg; - while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p; - while( *p == '?' ) ++p; - if( *p == '*' ) ++p; - if( *p != 0){ - ShowWarning("add_BUILDIN: ignoring function \"%s\" with invalid arg \"%s\".\n", BUILDIN[i].name, BUILDIN[i].arg); - } else if( *skip_word(BUILDIN[i].name) != 0 ){ - ShowWarning("add_BUILDIN: ignoring function with invalid name \"%s\" (must be a word).\n", BUILDIN[i].name); - } else { - n = add_str(BUILDIN[i].name); - str_data[n].type = C_FUNC; - str_data[n].val = i; - str_data[n].func = BUILDIN[i].func; - - if (!strcmp(BUILDIN[i].name, "set")) buildin_set_ref = n; - else if (!strcmp(BUILDIN[i].name, "callsub")) buildin_callsub_ref = n; - else if (!strcmp(BUILDIN[i].name, "callfunc")) buildin_callfunc_ref = n; - else if( !strcmp(BUILDIN[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n; - } - } -} - /// Retrieves the value of a constant. bool script_get_constant(const char* name, int* value) { @@ -2254,7 +2097,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o const char *p,*tmpp; int i; struct script_code* code = NULL; - static int first=1; char end; bool unresolved_names = false; @@ -2262,11 +2104,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o return NULL;// empty script memset(&syntax,0,sizeof(syntax)); - if(first){ - add_BUILDIN(); - read_constdb(); - first=0; - } script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char)); script_pos=0; @@ -2754,8 +2591,7 @@ const char* conv_str(struct script_state* st, struct script_data* data) } /// Converts the data to an int -int conv_num(struct script_state* st, struct script_data* data) -{ +int conv_num(struct script_state* st, struct script_data* data) { char* p; long num; @@ -3215,11 +3051,11 @@ void op_2(struct script_state *st, int op) case C_ADD: if( data_isint(left) && data_isstring(right) ) {// convert int-string to string-string - conv_str(st, left); + script->conv_str(st, left); } else if( data_isstring(left) && data_isint(right) ) {// convert string-int to string-string - conv_str(st, right); + script->conv_str(st, right); } break; } @@ -3306,26 +3142,20 @@ static void script_check_buildin_argtype(struct script_state* st, int func) { char type; int idx, invalid = 0; - script_function* sf = &BUILDIN[str_data[func].val]; + char* sf = script->buildin[str_data[func].val]; - for( idx = 2; script_hasdata(st, idx); idx++ ) - { + for( idx = 2; script_hasdata(st, idx); idx++ ) { struct script_data* data = script_getdata(st, idx); - type = sf->arg[idx-2]; - - if( type == '?' || type == '*' ) - {// optional argument or unknown number of optional parameters ( no types are after this ) + type = sf[idx-2]; + + if( type == '?' || type == '*' ) {// optional argument or unknown number of optional parameters ( no types are after this ) break; - } - else if( type == 0 ) - {// more arguments than necessary ( should not happen, as it is checked before ) + } else if( type == 0 ) {// more arguments than necessary ( should not happen, as it is checked before ) ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script_op2name(data->type)); invalid++; break; - } - else - { + } else { const char* name = NULL; if( data_isreference(data) ) @@ -3333,8 +3163,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func) name = reference_getname(data); } - switch( type ) - { + switch( type ) { case 'v': if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) ) {// variant @@ -3379,8 +3208,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func) } } - if(invalid) - { + if(invalid) { ShowDebug("Function: %s\n", get_str(func)); script_reportsrc(st); } @@ -3929,7 +3757,7 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 /*========================================== * Destructor *------------------------------------------*/ -int do_final_script() { +void do_final_script(void) { int i; #ifdef DEBUG_HASH if (battle_config.etc_log) @@ -4012,19 +3840,27 @@ int do_final_script() { if( atcommand->binding_count != 0 ) aFree(atcommand->binding); + + for( i = 0; i < script->buildin_count; i++) { + if( script->buildin[i] ) { + aFree(script->buildin[i]); + script->buildin[i] = NULL; + } + } + + aFree(script->buildin); - return 0; } /*========================================== * Initialization *------------------------------------------*/ -int do_init_script() { - userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); - scriptlabel_db=strdb_alloc(DB_OPT_DUP_KEY,50); +void do_init_script(void) { + userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0); + scriptlabel_db = strdb_alloc(DB_OPT_DUP_KEY,50); autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); - + script->parse_builtin(); + read_constdb(); mapreg_init(); - return 0; } int script_reload() { @@ -4061,7 +3897,6 @@ int script_reload() { #define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args } #define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args } -#define BUILDIN(x) bool buildin_ ## x (struct script_state* st) ///////////////////////////////////////////////////////////////////// // NPC interaction @@ -5768,11 +5603,11 @@ BUILDIN(countitem) if( data_isstring(data) ) {// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } if( id == NULL ) @@ -5815,11 +5650,11 @@ BUILDIN(countitem2) if( data_isstring(data) ) {// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } if( id == NULL ) @@ -5882,9 +5717,9 @@ BUILDIN(checkweight) data = script_getdata(st,i); get_val(st, data); // convert into value in case of a variable if( data_isstring(data) ){// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } if( id == NULL ) { ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was @@ -6055,14 +5890,14 @@ BUILDIN(getitem) get_val(st,data); if( data_isstring(data) ) {// "" - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); if( (item_data = itemdb_searchname(name)) == NULL ){ ShowError("buildin_getitem: Nonexistant item %s requested.\n", name); return false; //No item created. } nameid=item_data->nameid; } else if( data_isint(data) ) {// - nameid=conv_num(st,data); + nameid=script->conv_num(st,data); //Violet Box, Blue Box, etc - random item pick if( nameid < 0 ) { nameid = -nameid; @@ -6142,14 +5977,14 @@ BUILDIN(getitem2) data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data ) nameid=item_data->nameid; else nameid=UNKNOWN_ITEM_ID; }else - nameid=conv_num(st,data); + nameid=script->conv_num(st,data); amount=script_getnum(st,3); iden=script_getnum(st,4); @@ -6238,7 +6073,7 @@ BUILDIN(rentitem) if( data_isstring(data) ) { - const char *name = conv_str(st,data); + const char *name = script->conv_str(st,data); struct item_data *itd = itemdb_searchname(name); if( itd == NULL ) { @@ -6249,7 +6084,7 @@ BUILDIN(rentitem) } else if( data_isint(data) ) { - nameid = conv_num(st,data); + nameid = script->conv_num(st,data); if( nameid <= 0 || !itemdb_exists(nameid) ) { ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid); @@ -6300,7 +6135,7 @@ BUILDIN(getnameditem) data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data == NULL) { //Failed @@ -6309,7 +6144,7 @@ BUILDIN(getnameditem) } nameid = item_data->nameid; }else - nameid = conv_num(st,data); + nameid = script->conv_num(st,data); if(!itemdb_exists(nameid)/* || itemdb_isstackable(nameid)*/) { //Even though named stackable items "could" be risky, they are required for certain quests. @@ -6320,9 +6155,9 @@ BUILDIN(getnameditem) data=script_getdata(st,3); get_val(st,data); if( data_isstring(data) ) //Char Name - tsd=map_nick2sd(conv_str(st,data)); + tsd=map_nick2sd(script->conv_str(st,data)); else //Char Id was given - tsd=map_charid2sd(conv_num(st,data)); + tsd=map_charid2sd(script->conv_num(st,data)); if( tsd == NULL ) { //Failed @@ -6374,13 +6209,13 @@ BUILDIN(makeitem) data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); if( (item_data = itemdb_searchname(name)) ) nameid=item_data->nameid; else nameid=UNKNOWN_ITEM_ID; } else { - nameid=conv_num(st,data); + nameid=script->conv_num(st,data); if( nameid <= 0 || !(item_data = itemdb_exists(nameid)) ){ ShowError("makeitem: Nonexistant item %d requested.\n", nameid); return false; //No item created. @@ -6587,7 +6422,7 @@ BUILDIN(delitem) get_val(st,data); if( data_isstring(data) ) { - const char* item_name = conv_str(st,data); + const char* item_name = script->conv_str(st,data); struct item_data* id = itemdb_searchname(item_name); if( id == NULL ) { @@ -6599,7 +6434,7 @@ BUILDIN(delitem) } else { - it.nameid = conv_num(st,data);// + it.nameid = script->conv_num(st,data);// if( !itemdb_exists( it.nameid ) ) { ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); @@ -6656,7 +6491,7 @@ BUILDIN(delitem2) get_val(st,data); if( data_isstring(data) ) { - const char* item_name = conv_str(st,data); + const char* item_name = script->conv_str(st,data); struct item_data* id = itemdb_searchname(item_name); if( id == NULL ) { @@ -6668,7 +6503,7 @@ BUILDIN(delitem2) } else { - it.nameid = conv_num(st,data);// + it.nameid = script->conv_num(st,data);// if( !itemdb_exists( it.nameid ) ) { ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); @@ -9004,11 +8839,11 @@ BUILDIN(initnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { @@ -9052,11 +8887,11 @@ BUILDIN(startnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { @@ -9098,11 +8933,11 @@ BUILDIN(stopnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { @@ -9332,14 +9167,14 @@ BUILDIN(itemeffect) { get_val( st, data ); if( data_isstring( data ) ){ - const char *name = conv_str( st, data ); + const char *name = script->conv_str( st, data ); if( ( item_data = itemdb_searchname( name ) ) == NULL ){ ShowError( "buildin_itemeffect: Nonexistant item %s requested.\n", name ); return false; } } else if( data_isint( data ) ){ - int nameid = conv_num( st, data ); + int nameid = script->conv_num( st, data ); if( ( item_data = itemdb_exists( nameid ) ) == NULL ){ ShowError("buildin_itemeffect: Nonexistant item %d requested.\n", nameid ); @@ -9567,13 +9402,13 @@ BUILDIN(getareadropitem) data=script_getdata(st,7); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); item=UNKNOWN_ITEM_ID; if( item_data ) item=item_data->nameid; }else - item=conv_num(st,data); + item=script->conv_num(st,data); if( (m=map_mapname2mapid(str))< 0){ script_pushint(st,-1); @@ -11631,12 +11466,12 @@ BUILDIN(getitemname) get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data ) item_id=item_data->nameid; }else - item_id=conv_num(st,data); + item_id=script->conv_num(st,data); i_data = itemdb_exists(item_id); if (i_data == NULL) @@ -14162,9 +13997,9 @@ BUILDIN(setnpcdisplay) get_val(st, data); if( data_isstring(data) ) - newname = conv_str(st,data); + newname = script->conv_str(st,data); else if( data_isint(data) ) - class_ = conv_num(st,data); + class_ = script->conv_num(st,data); else { ShowError("script:setnpcdisplay: expected a string or number\n"); @@ -14634,17 +14469,17 @@ BUILDIN(npcshopattach) BUILDIN(setitemscript) { int item_id,n=0; - const char *script; + const char *new_bonus_script; struct item_data *i_data; struct script_code **dstscript; item_id = script_getnum(st,2); - script = script_getstr(st,3); + new_bonus_script = script_getstr(st,3); if( script_hasdata(st,4) ) n=script_getnum(st,4); i_data = itemdb_exists(item_id); - if (!i_data || script==NULL || ( script[0] && script[0]!='{' )) { + if (!i_data || new_bonus_script==NULL || ( new_bonus_script[0] && new_bonus_script[0]!='{' )) { script_pushint(st,0); return true; } @@ -14662,7 +14497,7 @@ BUILDIN(setitemscript) if(*dstscript) script_free_code(*dstscript); - *dstscript = script[0] ? parse_script(script, "script_setitemscript", 0, 0) : NULL; + *dstscript = new_bonus_script[0] ? parse_script(new_bonus_script, "script_setitemscript", 0, 0) : NULL; script_pushint(st,1); return true; } @@ -15094,11 +14929,11 @@ BUILDIN(unitattack) get_val(st, data); if( data_isstring(data) ) { - TBL_PC* sd = map_nick2sd(conv_str(st, data)); + TBL_PC* sd = map_nick2sd(script->conv_str(st, data)); if( sd != NULL ) target_bl = &sd->bl; } else - target_bl = map_id2bl(conv_num(st, data)); + target_bl = map_id2bl(script->conv_num(st, data)); // request the attack if( target_bl == NULL ) { @@ -17158,466 +16993,565 @@ BUILDIN(npcskill) return true; } - // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT -BUILDIN(defpattern); -BUILDIN(activatepset); -BUILDIN(deactivatepset); -BUILDIN(deletepset); + BUILDIN(defpattern); + BUILDIN(activatepset); + BUILDIN(deactivatepset); + BUILDIN(deletepset); #endif -/// script command definitions -/// for an explanation on args, see add_BUILDIN -struct script_function BUILDIN[] = { - // NPC interaction - BUILDIN_DEF(mes,"s*"), - BUILDIN_DEF(next,""), - BUILDIN_DEF(close,""), - BUILDIN_DEF(close2,""), - BUILDIN_DEF(menu,"sl*"), - BUILDIN_DEF(select,"s*"), //for future jA script compatibility - BUILDIN_DEF(prompt,"s*"), - // - BUILDIN_DEF(goto,"l"), - BUILDIN_DEF(callsub,"l*"), - BUILDIN_DEF(callfunc,"s*"), - BUILDIN_DEF(return,"?"), - BUILDIN_DEF(getarg,"i?"), - BUILDIN_DEF(jobchange,"i?"), - BUILDIN_DEF(jobname,"i"), - BUILDIN_DEF(input,"r??"), - BUILDIN_DEF(warp,"sii"), - BUILDIN_DEF(areawarp,"siiiisii??"), - BUILDIN_DEF(warpchar,"siii"), // [LuzZza] - BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] - BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] - BUILDIN_DEF(setlook,"ii"), - BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it - BUILDIN_DEF(set,"rv"), - BUILDIN_DEF(setarray,"rv*"), - BUILDIN_DEF(cleararray,"rvi"), - BUILDIN_DEF(copyarray,"rri"), - BUILDIN_DEF(getarraysize,"r"), - BUILDIN_DEF(deletearray,"r?"), - BUILDIN_DEF(getelementofarray,"ri"), - BUILDIN_DEF(getitem,"vi?"), - BUILDIN_DEF(rentitem,"vi"), - BUILDIN_DEF(getitem2,"viiiiiiii?"), - BUILDIN_DEF(getnameditem,"vv"), - BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), - BUILDIN_DEF(makeitem,"visii"), - BUILDIN_DEF(delitem,"vi?"), - BUILDIN_DEF(delitem2,"viiiiiiii?"), - BUILDIN_DEF2(enableitemuse,"enable_items",""), - BUILDIN_DEF2(disableitemuse,"disable_items",""), - BUILDIN_DEF(cutin,"si"), - BUILDIN_DEF(viewpoint,"iiiii"), - BUILDIN_DEF(heal,"ii"), - BUILDIN_DEF(itemheal,"ii"), - BUILDIN_DEF(percentheal,"ii"), - BUILDIN_DEF(rand,"i?"), - BUILDIN_DEF(countitem,"v"), - BUILDIN_DEF(countitem2,"viiiiiii"), - BUILDIN_DEF(checkweight,"vi*"), - BUILDIN_DEF(checkweight2,"rr"), - BUILDIN_DEF(readparam,"i?"), - BUILDIN_DEF(getcharid,"i?"), - BUILDIN_DEF(getnpcid,"i?"), - BUILDIN_DEF(getpartyname,"i"), - BUILDIN_DEF(getpartymember,"i?"), - BUILDIN_DEF(getpartyleader,"i?"), - BUILDIN_DEF(getguildname,"i"), - BUILDIN_DEF(getguildmaster,"i"), - BUILDIN_DEF(getguildmasterid,"i"), - BUILDIN_DEF(strcharinfo,"i"), - BUILDIN_DEF(strnpcinfo,"i"), - BUILDIN_DEF(getequipid,"i"), - BUILDIN_DEF(getequipname,"i"), - BUILDIN_DEF(getbrokenid,"i"), // [Valaris] - BUILDIN_DEF(repair,"i"), // [Valaris] - BUILDIN_DEF(repairall,""), - BUILDIN_DEF(getequipisequiped,"i"), - BUILDIN_DEF(getequipisenableref,"i"), - BUILDIN_DEF(getequipisidentify,"i"), - BUILDIN_DEF(getequiprefinerycnt,"i"), - BUILDIN_DEF(getequipweaponlv,"i"), - BUILDIN_DEF(getequippercentrefinery,"i"), - BUILDIN_DEF(successrefitem,"i"), - BUILDIN_DEF(failedrefitem,"i"), - BUILDIN_DEF(downrefitem,"i"), - BUILDIN_DEF(statusup,"i"), - BUILDIN_DEF(statusup2,"ii"), - BUILDIN_DEF(bonus,"iv"), - BUILDIN_DEF2(bonus,"bonus2","ivi"), - BUILDIN_DEF2(bonus,"bonus3","ivii"), - BUILDIN_DEF2(bonus,"bonus4","ivvii"), - BUILDIN_DEF2(bonus,"bonus5","ivviii"), - BUILDIN_DEF(autobonus,"sii??"), - BUILDIN_DEF(autobonus2,"sii??"), - BUILDIN_DEF(autobonus3,"siiv?"), - BUILDIN_DEF(skill,"vi?"), - BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] - BUILDIN_DEF(guildskill,"vi"), - BUILDIN_DEF(getskilllv,"v"), - BUILDIN_DEF(getgdskilllv,"iv"), - BUILDIN_DEF(basicskillcheck,""), - BUILDIN_DEF(getgmlevel,""), - BUILDIN_DEF(getgroupid,""), - BUILDIN_DEF(end,""), - BUILDIN_DEF(checkoption,"i"), - BUILDIN_DEF(setoption,"i?"), - BUILDIN_DEF(setcart,"?"), - BUILDIN_DEF(checkcart,""), - BUILDIN_DEF(setfalcon,"?"), - BUILDIN_DEF(checkfalcon,""), - BUILDIN_DEF(setriding,"?"), - BUILDIN_DEF(checkriding,""), - BUILDIN_DEF(checkwug,""), - BUILDIN_DEF(checkmadogear,""), - BUILDIN_DEF(setmadogear,"?"), - BUILDIN_DEF2(savepoint,"save","sii"), - BUILDIN_DEF(savepoint,"sii"), - BUILDIN_DEF(gettimetick,"i"), - BUILDIN_DEF(gettime,"i"), - BUILDIN_DEF(gettimestr,"si"), - BUILDIN_DEF(openstorage,""), - BUILDIN_DEF(guildopenstorage,""), - BUILDIN_DEF(itemskill,"vi"), - BUILDIN_DEF(produce,"i"), - BUILDIN_DEF(cooking,"i"), - BUILDIN_DEF(monster,"siisii???"), - BUILDIN_DEF(getmobdrops,"i"), - BUILDIN_DEF(areamonster,"siiiisii???"), - BUILDIN_DEF(killmonster,"ss?"), - BUILDIN_DEF(killmonsterall,"s?"), - BUILDIN_DEF(clone,"siisi????"), - BUILDIN_DEF(doevent,"s"), - BUILDIN_DEF(donpcevent,"s"), - BUILDIN_DEF(cmdothernpc,"ss"), - BUILDIN_DEF(addtimer,"is"), - BUILDIN_DEF(deltimer,"s"), - BUILDIN_DEF(addtimercount,"si"), - BUILDIN_DEF(initnpctimer,"??"), - BUILDIN_DEF(stopnpctimer,"??"), - BUILDIN_DEF(startnpctimer,"??"), - BUILDIN_DEF(setnpctimer,"i?"), - BUILDIN_DEF(getnpctimer,"i?"), - BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] - BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] - BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] - BUILDIN_DEF(announce,"si?????"), - BUILDIN_DEF(mapannounce,"ssi?????"), - BUILDIN_DEF(areaannounce,"siiiisi?????"), - BUILDIN_DEF(getusers,"i"), - BUILDIN_DEF(getmapguildusers,"si"), - BUILDIN_DEF(getmapusers,"s"), - BUILDIN_DEF(getareausers,"siiii"), - BUILDIN_DEF(getareadropitem,"siiiiv"), - BUILDIN_DEF(enablenpc,"s"), - BUILDIN_DEF(disablenpc,"s"), - BUILDIN_DEF(hideoffnpc,"s"), - BUILDIN_DEF(hideonnpc,"s"), - BUILDIN_DEF(sc_start,"iii?"), - BUILDIN_DEF(sc_start2,"iiii?"), - BUILDIN_DEF(sc_start4,"iiiiii?"), - BUILDIN_DEF(sc_end,"i?"), - BUILDIN_DEF(getstatus, "i?"), - BUILDIN_DEF(getscrate,"ii?"), - BUILDIN_DEF(debugmes,"s"), - BUILDIN_DEF2(catchpet,"pet","i"), - BUILDIN_DEF2(birthpet,"bpet",""), - BUILDIN_DEF(resetlvl,"i"), - BUILDIN_DEF(resetstatus,""), - BUILDIN_DEF(resetskill,""), - BUILDIN_DEF(skillpointcount,""), - BUILDIN_DEF(changebase,"i?"), - BUILDIN_DEF(changesex,""), - BUILDIN_DEF(waitingroom,"si?????"), - BUILDIN_DEF(delwaitingroom,"?"), - BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), - BUILDIN_DEF(enablewaitingroomevent,"?"), - BUILDIN_DEF(disablewaitingroomevent,"?"), - BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT - BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT - BUILDIN_DEF(getwaitingroomstate,"i?"), - BUILDIN_DEF(warpwaitingpc,"sii?"), - BUILDIN_DEF(attachrid,"i"), - BUILDIN_DEF(detachrid,""), - BUILDIN_DEF(isloggedin,"i?"), - BUILDIN_DEF(setmapflagnosave,"ssii"), - BUILDIN_DEF(getmapflag,"si"), - BUILDIN_DEF(setmapflag,"si?"), - BUILDIN_DEF(removemapflag,"si?"), - BUILDIN_DEF(pvpon,"s"), - BUILDIN_DEF(pvpoff,"s"), - BUILDIN_DEF(gvgon,"s"), - BUILDIN_DEF(gvgoff,"s"), - BUILDIN_DEF(emotion,"i??"), - BUILDIN_DEF(maprespawnguildid,"sii"), - BUILDIN_DEF(agitstart,""), // - BUILDIN_DEF(agitend,""), - BUILDIN_DEF(agitcheck,""), // - BUILDIN_DEF(flagemblem,"i"), // Flag Emblem - BUILDIN_DEF(getcastlename,"s"), - BUILDIN_DEF(getcastledata,"si"), - BUILDIN_DEF(setcastledata,"sii"), - BUILDIN_DEF(requestguildinfo,"i?"), - BUILDIN_DEF(getequipcardcnt,"i"), - BUILDIN_DEF(successremovecards,"i"), - BUILDIN_DEF(failedremovecards,"ii"), - BUILDIN_DEF(marriage,"s"), - BUILDIN_DEF2(wedding_effect,"wedding",""), - BUILDIN_DEF(divorce,""), - BUILDIN_DEF(ispartneron,""), - BUILDIN_DEF(getpartnerid,""), - BUILDIN_DEF(getchildid,""), - BUILDIN_DEF(getmotherid,""), - BUILDIN_DEF(getfatherid,""), - BUILDIN_DEF(warppartner,"sii"), - BUILDIN_DEF(getitemname,"v"), - BUILDIN_DEF(getitemslots,"i"), - BUILDIN_DEF(makepet,"i"), - BUILDIN_DEF(getexp,"ii"), - BUILDIN_DEF(getinventorylist,""), - BUILDIN_DEF(getskilllist,""), - BUILDIN_DEF(clearitem,""), - BUILDIN_DEF(classchange,"ii"), - BUILDIN_DEF(misceffect,"i"), - BUILDIN_DEF(playBGM,"s"), - BUILDIN_DEF(playBGMall,"s?????"), - BUILDIN_DEF(soundeffect,"si"), - BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] - BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] - BUILDIN_DEF(guardian,"siisi??"), // summon guardians - BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] - BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] - BUILDIN_DEF(petrecovery,"ii"), // [Valaris] - BUILDIN_DEF(petloot,"i"), // [Valaris] - BUILDIN_DEF(petheal,"iiii"), // [Valaris] - BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] - BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] - BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] - BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] - BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] - BUILDIN_DEF(nude,""), // nude command [Valaris] - BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT - BUILDIN_DEF(atcommand,"s"), // [MouseJstr] - BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] - BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] - BUILDIN_DEF(message,"ss"), // [MouseJstr] - BUILDIN_DEF(npctalk,"s"), // [Valaris] - BUILDIN_DEF(mobcount,"ss"), - BUILDIN_DEF(getlook,"i"), - BUILDIN_DEF(getsavepoint,"i"), - BUILDIN_DEF(npcspeed,"i"), // [Valaris] - BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] - BUILDIN_DEF(npcstop,""), // [Valaris] - BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] - BUILDIN_DEF(checkoption1,"i"), - BUILDIN_DEF(checkoption2,"i"), - BUILDIN_DEF(guildgetexp,"i"), - BUILDIN_DEF(guildchangegm,"is"), - BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] - BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] - BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] - BUILDIN_DEF(isday,""), // check whether it is day time [Celest] - BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] - BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] - BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] - BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] - BUILDIN_DEF(night,""), // sets the server to night time - BUILDIN_DEF(day,""), // sets the server to day time +bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)) { + int n = add_str(name), i = 0; + + if( str_data[n].type == C_FUNC ) { + str_data[n].func = func; + i = str_data[n].val; + if( args ) { + int slen = strlen(args); + if( script->buildin[i] ) { + aFree(script->buildin[i]); + } + CREATE(script->buildin[i], char, slen + 1); + safestrncpy(script->buildin[i], args, slen + 1); + } else { + if( script->buildin[i] ) + aFree(script->buildin[i]); + script->buildin[i] = NULL; + } + + } else { + i = script->buildin_count; + str_data[n].type = C_FUNC; + str_data[n].val = i; + str_data[n].func = func; + + RECREATE(script->buildin, char *, ++script->buildin_count); + + /* we only store the arguments, its the only thing used out of this */ + if( args != NULL ) { + int slen = strlen(args); + CREATE(script->buildin[i], char, slen + 1); + safestrncpy(script->buildin[i], args, slen + 1); + } else + script->buildin[i] = NULL; + } + + return true; +} + +void script_parse_builtin(void) { + struct script_function BUILDIN[] = { + // NPC interaction + BUILDIN_DEF(mes,"s*"), + BUILDIN_DEF(next,""), + BUILDIN_DEF(close,""), + BUILDIN_DEF(close2,""), + BUILDIN_DEF(menu,"sl*"), + BUILDIN_DEF(select,"s*"), //for future jA script compatibility + BUILDIN_DEF(prompt,"s*"), + // + BUILDIN_DEF(goto,"l"), + BUILDIN_DEF(callsub,"l*"), + BUILDIN_DEF(callfunc,"s*"), + BUILDIN_DEF(return,"?"), + BUILDIN_DEF(getarg,"i?"), + BUILDIN_DEF(jobchange,"i?"), + BUILDIN_DEF(jobname,"i"), + BUILDIN_DEF(input,"r??"), + BUILDIN_DEF(warp,"sii"), + BUILDIN_DEF(areawarp,"siiiisii??"), + BUILDIN_DEF(warpchar,"siii"), // [LuzZza] + BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] + BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] + BUILDIN_DEF(setlook,"ii"), + BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it + BUILDIN_DEF(set,"rv"), + BUILDIN_DEF(setarray,"rv*"), + BUILDIN_DEF(cleararray,"rvi"), + BUILDIN_DEF(copyarray,"rri"), + BUILDIN_DEF(getarraysize,"r"), + BUILDIN_DEF(deletearray,"r?"), + BUILDIN_DEF(getelementofarray,"ri"), + BUILDIN_DEF(getitem,"vi?"), + BUILDIN_DEF(rentitem,"vi"), + BUILDIN_DEF(getitem2,"viiiiiiii?"), + BUILDIN_DEF(getnameditem,"vv"), + BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), + BUILDIN_DEF(makeitem,"visii"), + BUILDIN_DEF(delitem,"vi?"), + BUILDIN_DEF(delitem2,"viiiiiiii?"), + BUILDIN_DEF2(enableitemuse,"enable_items",""), + BUILDIN_DEF2(disableitemuse,"disable_items",""), + BUILDIN_DEF(cutin,"si"), + BUILDIN_DEF(viewpoint,"iiiii"), + BUILDIN_DEF(heal,"ii"), + BUILDIN_DEF(itemheal,"ii"), + BUILDIN_DEF(percentheal,"ii"), + BUILDIN_DEF(rand,"i?"), + BUILDIN_DEF(countitem,"v"), + BUILDIN_DEF(countitem2,"viiiiiii"), + BUILDIN_DEF(checkweight,"vi*"), + BUILDIN_DEF(checkweight2,"rr"), + BUILDIN_DEF(readparam,"i?"), + BUILDIN_DEF(getcharid,"i?"), + BUILDIN_DEF(getnpcid,"i?"), + BUILDIN_DEF(getpartyname,"i"), + BUILDIN_DEF(getpartymember,"i?"), + BUILDIN_DEF(getpartyleader,"i?"), + BUILDIN_DEF(getguildname,"i"), + BUILDIN_DEF(getguildmaster,"i"), + BUILDIN_DEF(getguildmasterid,"i"), + BUILDIN_DEF(strcharinfo,"i"), + BUILDIN_DEF(strnpcinfo,"i"), + BUILDIN_DEF(getequipid,"i"), + BUILDIN_DEF(getequipname,"i"), + BUILDIN_DEF(getbrokenid,"i"), // [Valaris] + BUILDIN_DEF(repair,"i"), // [Valaris] + BUILDIN_DEF(repairall,""), + BUILDIN_DEF(getequipisequiped,"i"), + BUILDIN_DEF(getequipisenableref,"i"), + BUILDIN_DEF(getequipisidentify,"i"), + BUILDIN_DEF(getequiprefinerycnt,"i"), + BUILDIN_DEF(getequipweaponlv,"i"), + BUILDIN_DEF(getequippercentrefinery,"i"), + BUILDIN_DEF(successrefitem,"i"), + BUILDIN_DEF(failedrefitem,"i"), + BUILDIN_DEF(downrefitem,"i"), + BUILDIN_DEF(statusup,"i"), + BUILDIN_DEF(statusup2,"ii"), + BUILDIN_DEF(bonus,"iv"), + BUILDIN_DEF2(bonus,"bonus2","ivi"), + BUILDIN_DEF2(bonus,"bonus3","ivii"), + BUILDIN_DEF2(bonus,"bonus4","ivvii"), + BUILDIN_DEF2(bonus,"bonus5","ivviii"), + BUILDIN_DEF(autobonus,"sii??"), + BUILDIN_DEF(autobonus2,"sii??"), + BUILDIN_DEF(autobonus3,"siiv?"), + BUILDIN_DEF(skill,"vi?"), + BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] + BUILDIN_DEF(guildskill,"vi"), + BUILDIN_DEF(getskilllv,"v"), + BUILDIN_DEF(getgdskilllv,"iv"), + BUILDIN_DEF(basicskillcheck,""), + BUILDIN_DEF(getgmlevel,""), + BUILDIN_DEF(getgroupid,""), + BUILDIN_DEF(end,""), + BUILDIN_DEF(checkoption,"i"), + BUILDIN_DEF(setoption,"i?"), + BUILDIN_DEF(setcart,"?"), + BUILDIN_DEF(checkcart,""), + BUILDIN_DEF(setfalcon,"?"), + BUILDIN_DEF(checkfalcon,""), + BUILDIN_DEF(setriding,"?"), + BUILDIN_DEF(checkriding,""), + BUILDIN_DEF(checkwug,""), + BUILDIN_DEF(checkmadogear,""), + BUILDIN_DEF(setmadogear,"?"), + BUILDIN_DEF2(savepoint,"save","sii"), + BUILDIN_DEF(savepoint,"sii"), + BUILDIN_DEF(gettimetick,"i"), + BUILDIN_DEF(gettime,"i"), + BUILDIN_DEF(gettimestr,"si"), + BUILDIN_DEF(openstorage,""), + BUILDIN_DEF(guildopenstorage,""), + BUILDIN_DEF(itemskill,"vi"), + BUILDIN_DEF(produce,"i"), + BUILDIN_DEF(cooking,"i"), + BUILDIN_DEF(monster,"siisii???"), + BUILDIN_DEF(getmobdrops,"i"), + BUILDIN_DEF(areamonster,"siiiisii???"), + BUILDIN_DEF(killmonster,"ss?"), + BUILDIN_DEF(killmonsterall,"s?"), + BUILDIN_DEF(clone,"siisi????"), + BUILDIN_DEF(doevent,"s"), + BUILDIN_DEF(donpcevent,"s"), + BUILDIN_DEF(cmdothernpc,"ss"), + BUILDIN_DEF(addtimer,"is"), + BUILDIN_DEF(deltimer,"s"), + BUILDIN_DEF(addtimercount,"si"), + BUILDIN_DEF(initnpctimer,"??"), + BUILDIN_DEF(stopnpctimer,"??"), + BUILDIN_DEF(startnpctimer,"??"), + BUILDIN_DEF(setnpctimer,"i?"), + BUILDIN_DEF(getnpctimer,"i?"), + BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] + BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] + BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] + BUILDIN_DEF(announce,"si?????"), + BUILDIN_DEF(mapannounce,"ssi?????"), + BUILDIN_DEF(areaannounce,"siiiisi?????"), + BUILDIN_DEF(getusers,"i"), + BUILDIN_DEF(getmapguildusers,"si"), + BUILDIN_DEF(getmapusers,"s"), + BUILDIN_DEF(getareausers,"siiii"), + BUILDIN_DEF(getareadropitem,"siiiiv"), + BUILDIN_DEF(enablenpc,"s"), + BUILDIN_DEF(disablenpc,"s"), + BUILDIN_DEF(hideoffnpc,"s"), + BUILDIN_DEF(hideonnpc,"s"), + BUILDIN_DEF(sc_start,"iii?"), + BUILDIN_DEF(sc_start2,"iiii?"), + BUILDIN_DEF(sc_start4,"iiiiii?"), + BUILDIN_DEF(sc_end,"i?"), + BUILDIN_DEF(getstatus, "i?"), + BUILDIN_DEF(getscrate,"ii?"), + BUILDIN_DEF(debugmes,"s"), + BUILDIN_DEF2(catchpet,"pet","i"), + BUILDIN_DEF2(birthpet,"bpet",""), + BUILDIN_DEF(resetlvl,"i"), + BUILDIN_DEF(resetstatus,""), + BUILDIN_DEF(resetskill,""), + BUILDIN_DEF(skillpointcount,""), + BUILDIN_DEF(changebase,"i?"), + BUILDIN_DEF(changesex,""), + BUILDIN_DEF(waitingroom,"si?????"), + BUILDIN_DEF(delwaitingroom,"?"), + BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), + BUILDIN_DEF(enablewaitingroomevent,"?"), + BUILDIN_DEF(disablewaitingroomevent,"?"), + BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT + BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT + BUILDIN_DEF(getwaitingroomstate,"i?"), + BUILDIN_DEF(warpwaitingpc,"sii?"), + BUILDIN_DEF(attachrid,"i"), + BUILDIN_DEF(detachrid,""), + BUILDIN_DEF(isloggedin,"i?"), + BUILDIN_DEF(setmapflagnosave,"ssii"), + BUILDIN_DEF(getmapflag,"si"), + BUILDIN_DEF(setmapflag,"si?"), + BUILDIN_DEF(removemapflag,"si?"), + BUILDIN_DEF(pvpon,"s"), + BUILDIN_DEF(pvpoff,"s"), + BUILDIN_DEF(gvgon,"s"), + BUILDIN_DEF(gvgoff,"s"), + BUILDIN_DEF(emotion,"i??"), + BUILDIN_DEF(maprespawnguildid,"sii"), + BUILDIN_DEF(agitstart,""), // + BUILDIN_DEF(agitend,""), + BUILDIN_DEF(agitcheck,""), // + BUILDIN_DEF(flagemblem,"i"), // Flag Emblem + BUILDIN_DEF(getcastlename,"s"), + BUILDIN_DEF(getcastledata,"si"), + BUILDIN_DEF(setcastledata,"sii"), + BUILDIN_DEF(requestguildinfo,"i?"), + BUILDIN_DEF(getequipcardcnt,"i"), + BUILDIN_DEF(successremovecards,"i"), + BUILDIN_DEF(failedremovecards,"ii"), + BUILDIN_DEF(marriage,"s"), + BUILDIN_DEF2(wedding_effect,"wedding",""), + BUILDIN_DEF(divorce,""), + BUILDIN_DEF(ispartneron,""), + BUILDIN_DEF(getpartnerid,""), + BUILDIN_DEF(getchildid,""), + BUILDIN_DEF(getmotherid,""), + BUILDIN_DEF(getfatherid,""), + BUILDIN_DEF(warppartner,"sii"), + BUILDIN_DEF(getitemname,"v"), + BUILDIN_DEF(getitemslots,"i"), + BUILDIN_DEF(makepet,"i"), + BUILDIN_DEF(getexp,"ii"), + BUILDIN_DEF(getinventorylist,""), + BUILDIN_DEF(getskilllist,""), + BUILDIN_DEF(clearitem,""), + BUILDIN_DEF(classchange,"ii"), + BUILDIN_DEF(misceffect,"i"), + BUILDIN_DEF(playBGM,"s"), + BUILDIN_DEF(playBGMall,"s?????"), + BUILDIN_DEF(soundeffect,"si"), + BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] + BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] + BUILDIN_DEF(guardian,"siisi??"), // summon guardians + BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] + BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] + BUILDIN_DEF(petrecovery,"ii"), // [Valaris] + BUILDIN_DEF(petloot,"i"), // [Valaris] + BUILDIN_DEF(petheal,"iiii"), // [Valaris] + BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] + BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] + BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] + BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] + BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] + BUILDIN_DEF(nude,""), // nude command [Valaris] + BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT + BUILDIN_DEF(atcommand,"s"), // [MouseJstr] + BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] + BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] + BUILDIN_DEF(message,"ss"), // [MouseJstr] + BUILDIN_DEF(npctalk,"s"), // [Valaris] + BUILDIN_DEF(mobcount,"ss"), + BUILDIN_DEF(getlook,"i"), + BUILDIN_DEF(getsavepoint,"i"), + BUILDIN_DEF(npcspeed,"i"), // [Valaris] + BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] + BUILDIN_DEF(npcstop,""), // [Valaris] + BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] + BUILDIN_DEF(checkoption1,"i"), + BUILDIN_DEF(checkoption2,"i"), + BUILDIN_DEF(guildgetexp,"i"), + BUILDIN_DEF(guildchangegm,"is"), + BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] + BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] + BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] + BUILDIN_DEF(isday,""), // check whether it is day time [Celest] + BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] + BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] + BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] + BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] + BUILDIN_DEF(night,""), // sets the server to night time + BUILDIN_DEF(day,""), // sets the server to day time #ifdef PCRE_SUPPORT - BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] - BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] - BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] - BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] + BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] + BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] + BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] + BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] #endif - BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] - BUILDIN_DEF(getusersname,""), - BUILDIN_DEF(recovery,""), - BUILDIN_DEF(getpetinfo,"i"), - BUILDIN_DEF(gethominfo,"i"), - BUILDIN_DEF(getmercinfo,"i?"), - BUILDIN_DEF(checkequipedcard,"i"), - BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility - BUILDIN_DEF(globalmes,"s?"), //end jA addition - BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] - BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] - BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] - BUILDIN_DEF(charat,"si"), - BUILDIN_DEF(setchar,"ssi"), - BUILDIN_DEF(insertchar,"ssi"), - BUILDIN_DEF(delchar,"si"), - BUILDIN_DEF(strtoupper,"s"), - BUILDIN_DEF(strtolower,"s"), - BUILDIN_DEF(charisupper, "si"), - BUILDIN_DEF(charislower, "si"), - BUILDIN_DEF(substr,"sii"), - BUILDIN_DEF(explode, "rss"), - BUILDIN_DEF(implode, "r?"), - BUILDIN_DEF(sprintf,"s*"), // [Mirei] - BUILDIN_DEF(sscanf,"ss*"), // [Mirei] - BUILDIN_DEF(strpos,"ss?"), - BUILDIN_DEF(replacestr,"sss??"), - BUILDIN_DEF(countstr,"ss?"), - BUILDIN_DEF(setnpcdisplay,"sv??"), - BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. - BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info - BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info - BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item - // [zBuffer] List of mathematics commands ---> - BUILDIN_DEF(sqrt,"i"), - BUILDIN_DEF(pow,"ii"), - BUILDIN_DEF(distance,"iiii"), - // <--- [zBuffer] List of mathematics commands - BUILDIN_DEF(md5,"s"), - // [zBuffer] List of dynamic var commands ---> - BUILDIN_DEF(getd,"s"), - BUILDIN_DEF(setd,"sv"), - // <--- [zBuffer] List of dynamic var commands - BUILDIN_DEF(petstat,"i"), - BUILDIN_DEF(callshop,"s?"), // [Skotlex] - BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] - BUILDIN_DEF(npcshopadditem,"sii*"), - BUILDIN_DEF(npcshopdelitem,"si*"), - BUILDIN_DEF(npcshopattach,"s?"), - BUILDIN_DEF(equip,"i"), - BUILDIN_DEF(autoequip,"ii"), - BUILDIN_DEF(setbattleflag,"si"), - BUILDIN_DEF(getbattleflag,"s"), - BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus - BUILDIN_DEF(disguise,"i"), //disguise player. Lupus - BUILDIN_DEF(undisguise,""), //undisguise player. Lupus - BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus - BUILDIN_DEF(axtoi,"s"), - BUILDIN_DEF(query_sql,"s*"), - BUILDIN_DEF(query_logsql,"s*"), - BUILDIN_DEF(escape_sql,"v"), - BUILDIN_DEF(atoi,"s"), - // [zBuffer] List of player cont commands ---> - BUILDIN_DEF(rid2name,"i"), - BUILDIN_DEF(pcfollow,"ii"), - BUILDIN_DEF(pcstopfollow,"i"), - BUILDIN_DEF(pcblockmove,"ii"), - // <--- [zBuffer] List of player cont commands - // [zBuffer] List of mob control commands ---> - BUILDIN_DEF(unitwalk,"ii?"), - BUILDIN_DEF(unitkill,"i"), - BUILDIN_DEF(unitwarp,"isii"), - BUILDIN_DEF(unitattack,"iv?"), - BUILDIN_DEF(unitstop,"i"), - BUILDIN_DEF(unittalk,"is"), - BUILDIN_DEF(unitemote,"ii"), - BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] - BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] -// <--- [zBuffer] List of mob control commands - BUILDIN_DEF(sleep,"i"), - BUILDIN_DEF(sleep2,"i"), - BUILDIN_DEF(awake,"s"), - BUILDIN_DEF(getvariableofnpc,"rs"), - BUILDIN_DEF(warpportal,"iisii"), - BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] - BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), - BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] - BUILDIN_DEF(eaclass,"?"), //[Skotlex] - BUILDIN_DEF(roclass,"i?"), //[Skotlex] - BUILDIN_DEF(checkvending,"?"), - BUILDIN_DEF(checkchatting,"?"), - BUILDIN_DEF(checkidle,"?"), - BUILDIN_DEF(openmail,""), - BUILDIN_DEF(openauction,""), - BUILDIN_DEF(checkcell,"siii"), - BUILDIN_DEF(setcell,"siiiiii"), - BUILDIN_DEF(setwall,"siiiiis"), - BUILDIN_DEF(delwall,"s"), - BUILDIN_DEF(searchitem,"rs"), - BUILDIN_DEF(mercenary_create,"ii"), - BUILDIN_DEF(mercenary_heal,"ii"), - BUILDIN_DEF(mercenary_sc_start,"iii"), - BUILDIN_DEF(mercenary_get_calls,"i"), - BUILDIN_DEF(mercenary_get_faith,"i"), - BUILDIN_DEF(mercenary_set_calls,"ii"), - BUILDIN_DEF(mercenary_set_faith,"ii"), - BUILDIN_DEF(readbook,"ii"), - BUILDIN_DEF(setfont,"i"), - BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), - BUILDIN_DEF(progressbar,"si"), - BUILDIN_DEF(pushpc,"ii"), - BUILDIN_DEF(buyingstore,"i"), - BUILDIN_DEF(searchstores,"ii"), - BUILDIN_DEF(showdigit,"i?"), - // WoE SE - BUILDIN_DEF(agitstart2,""), - BUILDIN_DEF(agitend2,""), - BUILDIN_DEF(agitcheck2,""), - // BattleGround - BUILDIN_DEF(waitingroom2bg,"siiss?"), - BUILDIN_DEF(waitingroom2bg_single,"isiis"), - BUILDIN_DEF(bg_team_setxy,"iii"), - BUILDIN_DEF(bg_warp,"isii"), - BUILDIN_DEF(bg_monster,"isiisi?"), - BUILDIN_DEF(bg_monster_set_team,"ii"), - BUILDIN_DEF(bg_leave,""), - BUILDIN_DEF(bg_destroy,"i"), - BUILDIN_DEF(areapercentheal,"siiiiii"), - BUILDIN_DEF(bg_get_data,"ii"), - BUILDIN_DEF(bg_getareausers,"isiiii"), - BUILDIN_DEF(bg_updatescore,"sii"), - - // Instancing - BUILDIN_DEF(instance_create,"si"), - BUILDIN_DEF(instance_destroy,"?"), - BUILDIN_DEF(instance_attachmap,"si?"), - BUILDIN_DEF(instance_detachmap,"s?"), - BUILDIN_DEF(instance_attach,"i"), - BUILDIN_DEF(instance_id,"?"), - BUILDIN_DEF(instance_set_timeout,"ii?"), - BUILDIN_DEF(instance_init,"i"), - BUILDIN_DEF(instance_announce,"isi?????"), - BUILDIN_DEF(instance_npcname,"s?"), - BUILDIN_DEF(has_instance,"s?"), - BUILDIN_DEF(instance_warpall,"sii?"), - BUILDIN_DEF(instance_check_party,"i???"), - /** - * 3rd-related - **/ - BUILDIN_DEF(makerune,"i"), - BUILDIN_DEF(checkdragon,""),//[Ind] - BUILDIN_DEF(setdragon,"?"),//[Ind] - BUILDIN_DEF(ismounting,""),//[Ind] - BUILDIN_DEF(setmounting,""),//[Ind] - BUILDIN_DEF(checkre,"i"), - /** - * rAthena and beyond! - **/ - BUILDIN_DEF(getargcount,""), - BUILDIN_DEF(getcharip,"?"), - BUILDIN_DEF(is_function,"s"), - BUILDIN_DEF(get_revision,""), - BUILDIN_DEF(freeloop,"i"), - BUILDIN_DEF(getrandgroupitem,"ii"), - BUILDIN_DEF(cleanmap,"s"), - BUILDIN_DEF2(cleanmap,"cleanarea","siiii"), - BUILDIN_DEF(npcskill,"viii"), - BUILDIN_DEF(itemeffect,"v"), - BUILDIN_DEF(delequip,"i"), - /** - * @commands (script based) - **/ - BUILDIN_DEF(bindatcmd, "ss???"), - BUILDIN_DEF(unbindatcmd, "s"), - BUILDIN_DEF(useatcmd, "s"), - - //Quest Log System [Inkfish] - BUILDIN_DEF(setquest, "i"), - BUILDIN_DEF(erasequest, "i"), - BUILDIN_DEF(completequest, "i"), - BUILDIN_DEF(checkquest, "i?"), - BUILDIN_DEF(changequest, "ii"), - BUILDIN_DEF(showevent, "ii"), - {NULL,NULL,NULL}, -}; + BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] + BUILDIN_DEF(getusersname,""), + BUILDIN_DEF(recovery,""), + BUILDIN_DEF(getpetinfo,"i"), + BUILDIN_DEF(gethominfo,"i"), + BUILDIN_DEF(getmercinfo,"i?"), + BUILDIN_DEF(checkequipedcard,"i"), + BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility + BUILDIN_DEF(globalmes,"s?"), //end jA addition + BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] + BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] + BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] + BUILDIN_DEF(charat,"si"), + BUILDIN_DEF(setchar,"ssi"), + BUILDIN_DEF(insertchar,"ssi"), + BUILDIN_DEF(delchar,"si"), + BUILDIN_DEF(strtoupper,"s"), + BUILDIN_DEF(strtolower,"s"), + BUILDIN_DEF(charisupper, "si"), + BUILDIN_DEF(charislower, "si"), + BUILDIN_DEF(substr,"sii"), + BUILDIN_DEF(explode, "rss"), + BUILDIN_DEF(implode, "r?"), + BUILDIN_DEF(sprintf,"s*"), // [Mirei] + BUILDIN_DEF(sscanf,"ss*"), // [Mirei] + BUILDIN_DEF(strpos,"ss?"), + BUILDIN_DEF(replacestr,"sss??"), + BUILDIN_DEF(countstr,"ss?"), + BUILDIN_DEF(setnpcdisplay,"sv??"), + BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. + BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info + BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info + BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item + // [zBuffer] List of mathematics commands ---> + BUILDIN_DEF(sqrt,"i"), + BUILDIN_DEF(pow,"ii"), + BUILDIN_DEF(distance,"iiii"), + // <--- [zBuffer] List of mathematics commands + BUILDIN_DEF(md5,"s"), + // [zBuffer] List of dynamic var commands ---> + BUILDIN_DEF(getd,"s"), + BUILDIN_DEF(setd,"sv"), + // <--- [zBuffer] List of dynamic var commands + BUILDIN_DEF(petstat,"i"), + BUILDIN_DEF(callshop,"s?"), // [Skotlex] + BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] + BUILDIN_DEF(npcshopadditem,"sii*"), + BUILDIN_DEF(npcshopdelitem,"si*"), + BUILDIN_DEF(npcshopattach,"s?"), + BUILDIN_DEF(equip,"i"), + BUILDIN_DEF(autoequip,"ii"), + BUILDIN_DEF(setbattleflag,"si"), + BUILDIN_DEF(getbattleflag,"s"), + BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus + BUILDIN_DEF(disguise,"i"), //disguise player. Lupus + BUILDIN_DEF(undisguise,""), //undisguise player. Lupus + BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus + BUILDIN_DEF(axtoi,"s"), + BUILDIN_DEF(query_sql,"s*"), + BUILDIN_DEF(query_logsql,"s*"), + BUILDIN_DEF(escape_sql,"v"), + BUILDIN_DEF(atoi,"s"), + // [zBuffer] List of player cont commands ---> + BUILDIN_DEF(rid2name,"i"), + BUILDIN_DEF(pcfollow,"ii"), + BUILDIN_DEF(pcstopfollow,"i"), + BUILDIN_DEF(pcblockmove,"ii"), + // <--- [zBuffer] List of player cont commands + // [zBuffer] List of mob control commands ---> + BUILDIN_DEF(unitwalk,"ii?"), + BUILDIN_DEF(unitkill,"i"), + BUILDIN_DEF(unitwarp,"isii"), + BUILDIN_DEF(unitattack,"iv?"), + BUILDIN_DEF(unitstop,"i"), + BUILDIN_DEF(unittalk,"is"), + BUILDIN_DEF(unitemote,"ii"), + BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] + BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] + // <--- [zBuffer] List of mob control commands + BUILDIN_DEF(sleep,"i"), + BUILDIN_DEF(sleep2,"i"), + BUILDIN_DEF(awake,"s"), + BUILDIN_DEF(getvariableofnpc,"rs"), + BUILDIN_DEF(warpportal,"iisii"), + BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] + BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), + BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] + BUILDIN_DEF(eaclass,"?"), //[Skotlex] + BUILDIN_DEF(roclass,"i?"), //[Skotlex] + BUILDIN_DEF(checkvending,"?"), + BUILDIN_DEF(checkchatting,"?"), + BUILDIN_DEF(checkidle,"?"), + BUILDIN_DEF(openmail,""), + BUILDIN_DEF(openauction,""), + BUILDIN_DEF(checkcell,"siii"), + BUILDIN_DEF(setcell,"siiiiii"), + BUILDIN_DEF(setwall,"siiiiis"), + BUILDIN_DEF(delwall,"s"), + BUILDIN_DEF(searchitem,"rs"), + BUILDIN_DEF(mercenary_create,"ii"), + BUILDIN_DEF(mercenary_heal,"ii"), + BUILDIN_DEF(mercenary_sc_start,"iii"), + BUILDIN_DEF(mercenary_get_calls,"i"), + BUILDIN_DEF(mercenary_get_faith,"i"), + BUILDIN_DEF(mercenary_set_calls,"ii"), + BUILDIN_DEF(mercenary_set_faith,"ii"), + BUILDIN_DEF(readbook,"ii"), + BUILDIN_DEF(setfont,"i"), + BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), + BUILDIN_DEF(progressbar,"si"), + BUILDIN_DEF(pushpc,"ii"), + BUILDIN_DEF(buyingstore,"i"), + BUILDIN_DEF(searchstores,"ii"), + BUILDIN_DEF(showdigit,"i?"), + // WoE SE + BUILDIN_DEF(agitstart2,""), + BUILDIN_DEF(agitend2,""), + BUILDIN_DEF(agitcheck2,""), + // BattleGround + BUILDIN_DEF(waitingroom2bg,"siiss?"), + BUILDIN_DEF(waitingroom2bg_single,"isiis"), + BUILDIN_DEF(bg_team_setxy,"iii"), + BUILDIN_DEF(bg_warp,"isii"), + BUILDIN_DEF(bg_monster,"isiisi?"), + BUILDIN_DEF(bg_monster_set_team,"ii"), + BUILDIN_DEF(bg_leave,""), + BUILDIN_DEF(bg_destroy,"i"), + BUILDIN_DEF(areapercentheal,"siiiiii"), + BUILDIN_DEF(bg_get_data,"ii"), + BUILDIN_DEF(bg_getareausers,"isiiii"), + BUILDIN_DEF(bg_updatescore,"sii"), + + // Instancing + BUILDIN_DEF(instance_create,"si"), + BUILDIN_DEF(instance_destroy,"?"), + BUILDIN_DEF(instance_attachmap,"si?"), + BUILDIN_DEF(instance_detachmap,"s?"), + BUILDIN_DEF(instance_attach,"i"), + BUILDIN_DEF(instance_id,"?"), + BUILDIN_DEF(instance_set_timeout,"ii?"), + BUILDIN_DEF(instance_init,"i"), + BUILDIN_DEF(instance_announce,"isi?????"), + BUILDIN_DEF(instance_npcname,"s?"), + BUILDIN_DEF(has_instance,"s?"), + BUILDIN_DEF(instance_warpall,"sii?"), + BUILDIN_DEF(instance_check_party,"i???"), + /** + * 3rd-related + **/ + BUILDIN_DEF(makerune,"i"), + BUILDIN_DEF(checkdragon,""),//[Ind] + BUILDIN_DEF(setdragon,"?"),//[Ind] + BUILDIN_DEF(ismounting,""),//[Ind] + BUILDIN_DEF(setmounting,""),//[Ind] + BUILDIN_DEF(checkre,"i"), + /** + * rAthena and beyond! + **/ + BUILDIN_DEF(getargcount,""), + BUILDIN_DEF(getcharip,"?"), + BUILDIN_DEF(is_function,"s"), + BUILDIN_DEF(get_revision,""), + BUILDIN_DEF(freeloop,"i"), + BUILDIN_DEF(getrandgroupitem,"ii"), + BUILDIN_DEF(cleanmap,"s"), + BUILDIN_DEF2(cleanmap,"cleanarea","siiii"), + BUILDIN_DEF(npcskill,"viii"), + BUILDIN_DEF(itemeffect,"v"), + BUILDIN_DEF(delequip,"i"), + /** + * @commands (script based) + **/ + BUILDIN_DEF(bindatcmd, "ss???"), + BUILDIN_DEF(unbindatcmd, "s"), + BUILDIN_DEF(useatcmd, "s"), + + //Quest Log System [Inkfish] + BUILDIN_DEF(setquest, "i"), + BUILDIN_DEF(erasequest, "i"), + BUILDIN_DEF(completequest, "i"), + BUILDIN_DEF(checkquest, "i?"), + BUILDIN_DEF(changequest, "ii"), + BUILDIN_DEF(showevent, "ii"), + }; + int i,n, len = ARRAYLENGTH(BUILDIN), start = script->buildin_count; + char* p; + RECREATE(script->buildin, char *, start + len); + for( i = 0; i < len; i++ ) { + // arg must follow the pattern: (v|s|i|r|l)*\?*\*? + // 'v' - value (either string or int or reference) + // 's' - string + // 'i' - int + // 'r' - reference (of a variable) + // 'l' - label + // '?' - one optional parameter + // '*' - unknown number of optional parameters + p = BUILDIN[i].arg; + while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p; + while( *p == '?' ) ++p; + if( *p == '*' ) ++p; + if( *p != 0 ){ + ShowWarning("script_parse_builtin: ignoring function \"%s\" with invalid arg \"%s\".\n", BUILDIN[i].name, BUILDIN[i].arg); + } else if( *skip_word(BUILDIN[i].name) != 0 ){ + ShowWarning("script_parse_builtin: ignoring function with invalid name \"%s\" (must be a word).\n", BUILDIN[i].name); + } else { + int slen = strlen(BUILDIN[i].arg), offset = start + i; + n = add_str(BUILDIN[i].name); + + if (!strcmp(BUILDIN[i].name, "set")) buildin_set_ref = n; + else if (!strcmp(BUILDIN[i].name, "callsub")) buildin_callsub_ref = n; + else if (!strcmp(BUILDIN[i].name, "callfunc")) buildin_callfunc_ref = n; + else if (!strcmp(BUILDIN[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n; + + if( str_data[n].func && str_data[n].func != BUILDIN[i].func ) + continue;/* something replaced it, skip. */ + + str_data[n].type = C_FUNC; + str_data[n].val = offset; + str_data[n].func = BUILDIN[i].func; + + /* we only store the arguments, its the only thing used out of this */ + if( slen ) { + CREATE(script->buildin[offset], char, slen + 1); + safestrncpy(script->buildin[offset], BUILDIN[i].arg, slen + 1); + } else + script->buildin[offset] = NULL; + + script->buildin_count++; + + } + } +} + +void script_defaults(void) { + script = &script_s; + + script->buildin_count = 0; + script->buildin = NULL; + + script->init = do_init_script; + script->final = do_final_script; + + script->parse_builtin = script_parse_builtin; + script->addScript = script_hp_add; + script->conv_num = conv_num; + script->conv_str = conv_str; +} diff --git a/src/map/script.h b/src/map/script.h index 4a12a3f7f..a0d282bfe 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -159,8 +159,6 @@ void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char void run_script(struct script_code*,int,int,int); int set_var(struct map_session_data *sd, char *name, void *val); -int conv_num(struct script_state *st,struct script_data *data); -const char* conv_str(struct script_state *st,struct script_data *data); int run_script_timer(int tid, unsigned int tick, int id, intptr_t data); void run_script_main(struct script_state *st); @@ -182,13 +180,134 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache); int script_config_read(char *cfgName); -int do_init_script(void); -int do_final_script(void); int add_str(const char* p); const char* get_str(int id); int script_reload(void); // @commands (script based) -void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref); +void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct DBMap **ref); + +/////////////////////////////////////////////////////////////////////////////// +//## TODO possible enhancements: [FlavioJS] +// - 'callfunc' supporting labels in the current npc "::LabelName" +// - 'callfunc' supporting labels in other npcs "NpcName::LabelName" +// - 'function FuncName;' function declarations reverting to global functions +// if local label isn't found +// - join callfunc and callsub's functionality +// - remove dynamic allocation in add_word() +// - remove GETVALUE / SETVALUE +// - clean up the set_reg / set_val / setd_sub mess +// - detect invalid label references at parse-time + +// +// struct script_state* st; +// + +/// Returns the script_data at the target index +#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) ) +/// Returns if the stack contains data at the target index +#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) ) +/// Returns the index of the last data in the stack +#define script_lastdata(st) ( (st)->end - (st)->start - 1 ) +/// Pushes an int into the stack +#define script_pushint(st,val) push_val((st)->stack, C_INT, (val)) +/// Pushes a string into the stack (script engine frees it automatically) +#define script_pushstr(st,val) push_str((st)->stack, C_STR, (val)) +/// Pushes a copy of a string into the stack +#define script_pushstrcopy(st,val) push_str((st)->stack, C_STR, aStrdup(val)) +/// Pushes a constant string into the stack (must never change or be freed) +#define script_pushconststr(st,val) push_str((st)->stack, C_CONSTSTR, (val)) +/// Pushes a nil into the stack +#define script_pushnil(st) push_val((st)->stack, C_NOP, 0) +/// Pushes a copy of the data in the target index +#define script_pushcopy(st,i) push_copy((st)->stack, (st)->start + (i)) + +#define script_isstring(st,i) data_isstring(script_getdata(st,i)) +#define script_isint(st,i) data_isint(script_getdata(st,i)) + +#define script_getnum(st,val) script->conv_num(st, script_getdata(st,val)) +#define script_getstr(st,val) script->conv_str(st, script_getdata(st,val)) +#define script_getref(st,val) ( script_getdata(st,val)->ref ) + +// Note: "top" functions/defines use indexes relative to the top of the stack +// -1 is the index of the data at the top + +/// Returns the script_data at the target index relative to the top of the stack +#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) ) +/// Pushes a copy of the data in the target index relative to the top of the stack +#define script_pushcopytop(st,i) push_copy((st)->stack, (st)->stack->sp + (i)) +/// Removes the range of values [start,end[ relative to the top of the stack +#define script_removetop(st,start,end) ( pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) ) + +// +// struct script_data* data; +// + +/// Returns if the script data is a string +#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR ) +/// Returns if the script data is an int +#define data_isint(data) ( (data)->type == C_INT ) +/// Returns if the script data is a reference +#define data_isreference(data) ( (data)->type == C_NAME ) +/// Returns if the script data is a label +#define data_islabel(data) ( (data)->type == C_POS ) +/// Returns if the script data is an internal script function label +#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS ) + +/// Returns if this is a reference to a constant +#define reference_toconstant(data) ( str_data[reference_getid(data)].type == C_INT ) +/// Returns if this a reference to a param +#define reference_toparam(data) ( str_data[reference_getid(data)].type == C_PARAM ) +/// Returns if this a reference to a variable +//##TODO confirm it's C_NAME [FlavioJS] +#define reference_tovariable(data) ( str_data[reference_getid(data)].type == C_NAME ) +/// Returns the unique id of the reference (id and index) +#define reference_getuid(data) ( (data)->u.num ) +/// Returns the id of the reference +#define reference_getid(data) ( (int32)(reference_getuid(data) & 0x00ffffff) ) +/// Returns the array index of the reference +#define reference_getindex(data) ( (int32)(((uint32)(reference_getuid(data) & 0xff000000)) >> 24) ) +/// Returns the name of the reference +#define reference_getname(data) ( str_buf + str_data[reference_getid(data)].str ) +/// Returns the linked list of uid-value pairs of the reference (can be NULL) +#define reference_getref(data) ( (data)->ref ) +/// Returns the value of the constant +#define reference_getconstant(data) ( str_data[reference_getid(data)].val ) +/// Returns the type of param +#define reference_getparamtype(data) ( str_data[reference_getid(data)].val ) + +/// Composes the uid of a reference from the id and the index +#define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) ) + +#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'') +#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' ) +#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) + +#define BUILDIN(x) bool buildin_ ## x (struct script_state* st) +#define BUILDIN_A(x) buildin_ ## x + +struct script_function { + bool (*func)(struct script_state *st); + char *name; + char *arg; +}; +/* script.c interface (incomplete) */ +struct script_interface { + /* */ + char **buildin; + unsigned int buildin_count; + /* */ + void (*init) (void); + void (*final) (void); + /* */ + void (*parse_builtin) (void); + bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st)); + int (*conv_num) (struct script_state *st,struct script_data *data); + const char* (*conv_str) (struct script_state *st,struct script_data *data); +} script_s; + +struct script_interface *script; + +void script_defaults(void); #endif /* _SCRIPT_H_ */ -- cgit v1.2.3-60-g2f50