summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/char/char.c25
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/HPM.c348
-rw-r--r--src/common/HPM.h83
-rw-r--r--src/common/HPMi.h67
-rw-r--r--src/common/Makefile.in2
-rw-r--r--src/common/console.c223
-rw-r--r--src/common/console.h24
-rw-r--r--src/common/core.c16
-rw-r--r--src/common/core.h17
-rw-r--r--src/common/db.c20
-rw-r--r--src/common/ers.c9
-rw-r--r--src/common/netbuffer.c8
-rw-r--r--src/common/showmsg.c17
-rw-r--r--src/common/showmsg.h32
-rw-r--r--src/login/login.c57
-rw-r--r--src/map/atcommand.c90
-rw-r--r--src/map/atcommand.h12
-rw-r--r--src/map/clif.c42
-rw-r--r--src/map/map.c199
-rw-r--r--src/map/npc_chat.c12
-rw-r--r--src/map/pc_groups.c11
-rw-r--r--src/map/script.c1484
-rw-r--r--src/map/script.h129
-rw-r--r--src/plugins/CMakeLists.txt36
-rw-r--r--src/plugins/Makefile.in28
-rw-r--r--src/plugins/sample.c74
28 files changed, 1984 insertions, 1085 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 94ccf4183..100958358 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,3 +17,4 @@ add_subdirectory( login )
add_subdirectory( char )
add_subdirectory( map )
add_subdirectory( tool )
+add_subdirectory( plugins ) \ No newline at end of file
diff --git a/src/char/char.c b/src/char/char.c
index d5064eee2..f674cc0c7 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -4349,26 +4349,6 @@ int parse_char(int fd)
return 0;
}
-// Console Command Parser [Wizputer]
-int parse_console(const char* command)
-{
- ShowNotice("Console command: %s\n", command);
-
- if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 )
- runflag = 0;
- else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
- ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
- else if( strcmpi("help", command) == 0 )
- {
- ShowInfo("To shutdown the server:\n");
- ShowInfo(" 'shutdown|exit|quit|end'\n");
- ShowInfo("To know if server is alive:\n");
- ShowInfo(" 'alive|status'\n");
- }
-
- return 0;
-}
-
int mapif_sendall(unsigned char *buf, unsigned int len)
{
int i, c;
@@ -4904,9 +4884,8 @@ void do_abort(void)
{
}
-void set_server_type(void)
-{
- SERVER_TYPE = ATHENA_SERVER_CHAR;
+void set_server_type(void) {
+ SERVER_TYPE = SERVER_TYPE_CHAR;
}
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 508154c00..dbc30734c 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -68,6 +68,8 @@ set( COMMON_BASE_HEADERS
"${COMMON_SOURCE_DIR}/des.h"
"${COMMON_SOURCE_DIR}/ers.h"
"${COMMON_SOURCE_DIR}/grfio.h"
+ "${COMMON_SOURCE_DIR}/HPM.h"
+ "${COMMON_SOURCE_DIR}/HPMi.h"
"${COMMON_SOURCE_DIR}/malloc.h"
"${COMMON_SOURCE_DIR}/mapindex.h"
"${COMMON_SOURCE_DIR}/md5calc.h"
@@ -94,6 +96,7 @@ set( COMMON_BASE_SOURCES
"${COMMON_SOURCE_DIR}/des.c"
"${COMMON_SOURCE_DIR}/ers.c"
"${COMMON_SOURCE_DIR}/grfio.c"
+ "${COMMON_SOURCE_DIR}/HPM.c"
"${COMMON_SOURCE_DIR}/malloc.c"
"${COMMON_SOURCE_DIR}/mapindex.c"
"${COMMON_SOURCE_DIR}/md5calc.c"
diff --git a/src/common/HPM.c b/src/common/HPM.c
new file mode 100644
index 000000000..ec5ba888e
--- /dev/null
+++ b/src/common/HPM.c
@@ -0,0 +1,348 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/core.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/timer.h"
+#include "../common/conf.h"
+#include "../common/utils.h"
+#include "../common/console.h"
+#include "HPM.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+void hplugin_trigger_event(enum hp_event_types type) {
+ unsigned int i;
+ for( i = 0; i < HPM->plugin_count; i++ ) {
+ if( HPM->plugins[i]->hpi->event[type] != NULL )
+ (HPM->plugins[i]->hpi->event[type])();
+ }
+}
+
+void hplugin_export_symbol(void *var, char *name) {
+ RECREATE(HPM->symbols, struct hpm_symbol *, ++HPM->symbol_count);
+ CREATE(HPM->symbols[HPM->symbol_count - 1] ,struct hpm_symbol, 1);
+ HPM->symbols[HPM->symbol_count - 1]->name = name;
+ HPM->symbols[HPM->symbol_count - 1]->ptr = var;
+}
+
+void *hplugin_import_symbol(char *name) {
+ unsigned int i;
+
+ for( i = 0; i < HPM->symbol_count; i++ ) {
+ if( strcmp(HPM->symbols[i]->name,name) == 0 )
+ return HPM->symbols[i]->ptr;
+ }
+
+ ShowError("HPM:get_symbol: '"CL_WHITE"%s"CL_RESET"' not found!\n",name);
+ return NULL;
+}
+
+bool hplugin_iscompatible(char* version) {
+ unsigned int req_major = 0, req_minor = 0;
+
+ if( version == NULL )
+ return false;
+
+ sscanf(version, "%d.%d", &req_major, &req_minor);
+
+ return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false;
+}
+
+bool hplugin_exists(const char *filename) {
+ unsigned int i;
+ for(i = 0; i < HPM->plugin_count; i++) {
+ if( strcmpi(HPM->plugins[i]->filename,filename) == 0 )
+ return true;
+ }
+ return false;
+}
+struct hplugin *hplugin_create(void) {
+ RECREATE(HPM->plugins, struct hplugin *, ++HPM->plugin_count);
+ CREATE(HPM->plugins[HPM->plugin_count - 1], struct hplugin, 1);
+ HPM->plugins[HPM->plugin_count - 1]->idx = HPM->plugin_count - 1;
+ HPM->plugins[HPM->plugin_count - 1]->filename = NULL;
+ return HPM->plugins[HPM->plugin_count - 1];
+}
+bool hplugin_showmsg_populate(struct hplugin *plugin, const char *filename) {
+ void **ShowSub;
+ const char* ShowSubNames[9] = {
+ "ShowMessage",
+ "ShowStatus",
+ "ShowSQL",
+ "ShowInfo",
+ "ShowNotice",
+ "ShowWarning",
+ "ShowDebug",
+ "ShowError",
+ "ShowFatalError",
+ };
+ void* ShowSubRef[9] = {
+ ShowMessage,
+ ShowStatus,
+ ShowSQL,
+ ShowInfo,
+ ShowNotice,
+ ShowWarning,
+ ShowDebug,
+ ShowError,
+ ShowFatalError,
+ };
+ int i;
+ for(i = 0; i < 9; i++) {
+ if( !( ShowSub = plugin_import(plugin->dll, ShowSubNames[i],void **) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve '%s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", ShowSubNames[i], filename);
+ HPM->unload(plugin);
+ return false;
+ }
+ *ShowSub = ShowSubRef[i];
+ }
+ return true;
+}
+void hplugin_load(const char* filename) {
+ struct hplugin *plugin;
+ struct hplugin_info *info;
+ struct HPMi_interface **HPMi;
+ bool anyEvent = false;
+ void **import_symbol_ref;
+
+ if( HPM->exists(filename) ) {
+ ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ return;
+ }
+
+ plugin = HPM->create();
+
+ if( !( plugin->dll = plugin_open(filename) ) ){
+ ShowWarning("HPM:plugin_load: failed to load '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !( info = plugin_import(plugin->dll, "pinfo",struct hplugin_info*) ) ) {
+ ShowDebug("HPM:plugin_load: failed to retrieve 'plugin_info' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !(info->type & SERVER_TYPE) ) {
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !HPM->iscompatible(info->req_version) ) {
+ ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' incompatible version '%s' -> '%s', skipping...\n", filename, info->req_version, HPM_VERSION);
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !( import_symbol_ref = plugin_import(plugin->dll, "import_symbol",void **) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve 'import_symbol' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+
+ *import_symbol_ref = HPM->import_symbol;
+
+ if( !( HPMi = plugin_import(plugin->dll, "HPMi",struct HPMi_interface **) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !( *HPMi = plugin_import(plugin->dll, "HPMi_s",struct HPMi_interface *) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi_s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+ plugin->hpi = *HPMi;
+
+ if( ( plugin->hpi->event[HPET_INIT] = plugin_import(plugin->dll, "plugin_init",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( ( plugin->hpi->event[HPET_FINAL] = plugin_import(plugin->dll, "plugin_final",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( ( plugin->hpi->event[HPET_READY] = plugin_import(plugin->dll, "server_online",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( !anyEvent ) {
+ ShowWarning("HPM:plugin_load: no events found for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ HPM->unload(plugin);
+ return;
+ }
+
+ if( !HPM->showmsg_pop(plugin,filename) )
+ return;
+
+ if( SERVER_TYPE == SERVER_TYPE_MAP ) {
+ plugin->hpi->addCommand = HPM->import_symbol("addCommand");
+ plugin->hpi->addScript = HPM->import_symbol("addScript");
+ plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand");
+ }
+
+ plugin->info = info;
+ plugin->filename = aStrdup(filename);
+
+ return;
+}
+
+void hplugin_unload(struct hplugin* plugin) {
+ unsigned int i = plugin->idx, cursor = 0;
+
+ if( plugin->filename )
+ aFree(plugin->filename);
+ if( plugin->dll )
+ plugin_close(plugin->dll);
+
+ aFree(plugin);
+ if( !HPM->off ) {
+ HPM->plugins[i] = NULL;
+ for(i = 0; i < HPM->plugin_count; i++) {
+ if( HPM->plugins[i] == NULL )
+ continue;
+ if( cursor != i )
+ HPM->plugins[cursor] = HPM->plugins[i];
+ cursor++;
+ }
+ if( !(HPM->plugin_count = cursor) ) {
+ aFree(HPM->plugins);
+ HPM->plugins = NULL;
+ }
+ }
+}
+
+void hplugins_config_read(void) {
+ config_t plugins_conf;
+ config_setting_t *plist = NULL;
+ const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
+
+ if (conf_read_file(&plugins_conf, config_filename))
+ return;
+
+ if( HPM->symbol_defaults_sub )
+ HPM->symbol_defaults_sub();
+
+ plist = config_lookup(&plugins_conf, "plugins_list");
+
+ if (plist != NULL) {
+ int length = config_setting_length(plist), i;
+ char filename[60];
+ for(i = 0; i < length; i++) {
+ snprintf(filename, 60, "plugins/%s%s", config_setting_get_string_elem(plist,i), DLL_EXT);
+ HPM->load(filename);
+ }
+ config_destroy(&plugins_conf);
+ }
+
+ if( HPM->plugin_count )
+ ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count);
+}
+void hplugins_share_defaults(void) {
+ /* console */
+ HPM->share(console->addCommand,"addCPCommand");
+ /* core */
+ HPM->share(&runflag,"runflag");
+ HPM->share(arg_v,"arg_v");
+ HPM->share(&arg_c,"arg_c");
+ HPM->share(SERVER_NAME,"SERVER_NAME");
+ HPM->share(&SERVER_TYPE,"SERVER_TYPE");
+ HPM->share((void*)get_svn_revision,"get_svn_revision");
+ HPM->share((void*)get_git_hash,"get_git_hash");
+ /* socket */
+ HPM->share(RFIFOSKIP,"RFIFOSKIP");
+ HPM->share(WFIFOSET,"WFIFOSET");
+ HPM->share(do_close,"do_close");
+ HPM->share(make_connection,"make_connection");
+ HPM->share(session,"session");
+ HPM->share(&fd_max,"fd_max");
+ HPM->share(addr_,"addr");
+ /* timer */
+ HPM->share(gettick,"gettick");
+ HPM->share(add_timer,"add_timer");
+ HPM->share(add_timer_interval,"add_timer_interval");
+ HPM->share(add_timer_func_list,"add_timer_func_list");
+ HPM->share(delete_timer,"delete_timer");
+ HPM->share(get_uptime,"get_uptime");
+}
+CPCMD(plugins) {
+ if( HPM->plugin_count == 0 ) {
+ ShowInfo("HPC: there are no plugins loaded\n");
+ } else {
+ unsigned int i;
+
+ ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count);
+
+ for(i = 0; i < HPM->plugin_count; i++) {
+ ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename);
+ }
+ }
+}
+void hpm_init(void) {
+ HPM->symbols = NULL;
+ HPM->plugins = NULL;
+ HPM->plugin_count = HPM->symbol_count = 0;
+ HPM->off = false;
+
+ sscanf(HPM_VERSION, "%d.%d", &HPM->version[0], &HPM->version[1]);
+
+ if( HPM->version[0] == 0 && HPM->version[1] == 0 ) {
+ ShowError("HPM:init:failed to retrieve HPM version!!\n");
+ return;
+ }
+ HPM->symbol_defaults();
+
+ console->addCommand("plugins",CPCMD_A(plugins));
+
+ return;
+}
+
+void hpm_final(void) {
+ unsigned int i;
+
+ HPM->off = true;
+
+ for( i = 0; i < HPM->plugin_count; i++ ) {
+ HPM->unload(HPM->plugins[i]);
+ }
+
+ if( HPM->plugins )
+ aFree(HPM->plugins);
+
+ for( i = 0; i < HPM->symbol_count; i++ ) {
+ aFree(HPM->symbols[i]);
+ }
+
+ if( HPM->symbols )
+ aFree(HPM->symbols);
+
+ return;
+}
+void hpm_defaults(void) {
+ HPM = &HPM_s;
+
+ HPM->init = hpm_init;
+ HPM->final = hpm_final;
+
+ HPM->create = hplugin_create;
+ HPM->load = hplugin_load;
+ HPM->unload = hplugin_unload;
+ HPM->event = hplugin_trigger_event;
+ HPM->exists = hplugin_exists;
+ HPM->iscompatible = hplugin_iscompatible;
+ HPM->import_symbol = hplugin_import_symbol;
+ HPM->share = hplugin_export_symbol;
+ HPM->symbol_defaults = hplugins_share_defaults;
+ HPM->config_read = hplugins_config_read;
+ HPM->showmsg_pop = hplugin_showmsg_populate;
+ HPM->symbol_defaults_sub = NULL;
+} \ No newline at end of file
diff --git a/src/common/HPM.h b/src/common/HPM.h
new file mode 100644
index 000000000..ac2c4050f
--- /dev/null
+++ b/src/common/HPM.h
@@ -0,0 +1,83 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef _HPM_H_
+#define _HPM_H_
+
+#include "../common/cbasetypes.h"
+#include "../common/HPMi.h"
+
+#ifdef WIN32
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #define plugin_open(x) LoadLibraryA(x)
+ #define plugin_import(x,y,z) (z)GetProcAddress(x,y)
+ #define plugin_close(x) FreeLibrary(x)
+
+ #define DLL_EXT ".dll"
+ #define DLL HINSTANCE
+#else
+ #include <dlfcn.h>
+ #define plugin_open(x) dlopen(x,RTLD_NOW)
+ #define plugin_import(x,y,z) (z)dlsym(x,y)
+ #define plugin_close(x) dlclose(x)
+
+ #ifdef CYGWIN
+ #define DLL_EXT ".dll"
+ #else
+ #define DLL_EXT ".so"
+ #endif
+
+ #define DLL void *
+
+ #include <string.h> // size_t
+
+#endif
+
+struct hplugin {
+ DLL dll;
+ unsigned int idx;
+ char *filename;
+ struct hplugin_info *info;
+ struct HPMi_interface *hpi;
+};
+
+struct hpm_symbol {
+ char *name;
+ void *ptr;
+};
+
+/* Hercules Plugin Manager Interface */
+struct HPM_interface {
+ /* vars */
+ unsigned int version[2];
+ bool off;
+ /* data */
+ struct hplugin **plugins;
+ unsigned int plugin_count;
+ struct hpm_symbol **symbols;
+ unsigned int symbol_count;
+ /* funcs */
+ void (*init) (void);
+ void (*final) (void);
+ struct hplugin * (*create) (void);
+ void (*load) (const char* filename);
+ void (*unload) (struct hplugin* plugin);
+ bool (*exists) (const char *filename);
+ bool (*iscompatible) (char* version);
+ void (*event) (enum hp_event_types type);
+ void *(*import_symbol) (char *);
+ void (*share) (void *, char *);
+ void (*symbol_defaults) (void);
+ void (*config_read) (void);
+ bool (*showmsg_pop) (struct hplugin *plugin,const char *filename);
+ void (*symbol_defaults_sub) (void);
+} HPM_s;
+
+struct HPM_interface *HPM;
+
+void hpm_defaults(void);
+
+#endif /* _HPM_H_ */ \ No newline at end of file
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
new file mode 100644
index 000000000..517d9125d
--- /dev/null
+++ b/src/common/HPMi.h
@@ -0,0 +1,67 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef _HPMi_H_
+#define _HPMi_H_
+
+#include "../common/cbasetypes.h"
+#include "../common/core.h"
+#include "../common/console.h"
+
+struct script_state;
+struct AtCommandInfo;
+
+#ifdef WIN32
+ #define HPExport __declspec(dllexport)
+#else
+ #define HPExport
+#endif
+
+#ifndef _SHOWMSG_H_
+ HPExport void (*ShowMessage) (const char *, ...);
+ HPExport void (*ShowStatus) (const char *, ...);
+ HPExport void (*ShowSQL) (const char *, ...);
+ HPExport void (*ShowInfo) (const char *, ...);
+ HPExport void (*ShowNotice) (const char *, ...);
+ HPExport void (*ShowWarning) (const char *, ...);
+ HPExport void (*ShowDebug) (const char *, ...);
+ HPExport void (*ShowError) (const char *, ...);
+ HPExport void (*ShowFatalError) (const char *, ...);
+#endif
+
+/* after */
+#include "../common/showmsg.h"
+
+#define HPM_VERSION "0.1"
+
+struct hplugin_info {
+ char* name;
+ enum server_types type;
+ char* version;
+ char* req_version;
+};
+
+HPExport void *(*import_symbol) (char *name);
+#define GET_SYMBOL(n) import_symbol(n)
+
+#define SERVER_TYPE_ALL SERVER_TYPE_LOGIN|SERVER_TYPE_CHAR|SERVER_TYPE_MAP
+
+enum hp_event_types {
+ HPET_INIT,/* server starts */
+ HPET_FINAL,/* server is shutting down */
+ HPET_READY,/* server is ready (online) */
+ HPET_MAX,
+};
+
+/* Hercules Plugin Mananger Include Interface */
+struct HPMi_interface {
+ void (*event[HPET_MAX]) (void);
+ bool (*addCommand) (char *name, bool (*func)(const int fd, struct map_session_data* sd, const char* command, const char* message,struct AtCommandInfo *info));
+ bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st));
+ void (*addCPCommand) (char *name, CParseFunc func);
+} HPMi_s;
+#ifndef _HPM_H_
+ struct HPMi_interface *HPMi;
+#endif
+
+#endif /* _HPMi_H_ */ \ No newline at end of file
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index 26cae3e51..279f82e5f 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -1,5 +1,5 @@
-COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o \
+COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/HPM.o \
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \
diff --git a/src/common/console.c b/src/common/console.c
index 67897ee81..db914db98 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -8,6 +8,8 @@
#include "console.h"
#ifndef MINICORE
+ #include "../common/ers.h"
+ #include "../common/malloc.h"
#include "../common/atomic.h"
#include "../common/spinlock.h"
#include "../common/thread.h"
@@ -77,7 +79,212 @@ int console_parse_key_pressed(void) {
return FD_ISSET(STDIN_FILENO, &fds);
}
#endif /* _WIN32 */
+CPCMD(exit) {
+ runflag = 0;
+}
+CPCMD(ers_report) {
+ ers_report();
+}
+CPCMD(help) {
+ unsigned int i = 0;
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( console->cmd_list[i]->next_count ) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->cmd_list[i]->cmd);
+ console->parse_list_subs(console->cmd_list[i],2);
+ } else {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->cmd_list[i]->cmd);
+ }
+ }
+}
+/* [Ind/Hercules] */
+CPCMD(malloc_usage) {
+ unsigned int val = (unsigned int)malloc_usage();
+ ShowInfo("malloc_usage: %.2f MB\n",(double)(val)/1024);
+}
+#define CP_DEF_C(x) { #x , NULL , NULL, NULL }
+#define CP_DEF_C2(x,y) { #x , NULL , #y, NULL }
+#define CP_DEF_S(x,y) { #x , console_parse_ ## x , #y, NULL }
+#define CP_DEF(x) { #x , console_parse_ ## x , NULL, NULL }
+void console_load_defaults(void) {
+ struct {
+ char *name;
+ CParseFunc func;
+ char *connect;
+ struct CParseEntry *self;
+ } default_list[] = {
+ CP_DEF(help),
+ CP_DEF_C(server),
+ CP_DEF_S(ers_report,server),
+ CP_DEF_S(malloc_usage,server),
+ CP_DEF_S(exit,server),
+ };
+ unsigned int i, len = ARRAYLENGTH(default_list);
+ struct CParseEntry *cmd;
+
+ RECREATE(console->cmds,struct CParseEntry *, len);
+
+ for(i = 0; i < len; i++) {
+ CREATE(cmd, struct CParseEntry, 1);
+
+ safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH);
+
+ if( default_list[i].func )
+ cmd->u.func = default_list[i].func;
+ else
+ cmd->u.next = NULL;
+
+ cmd->next_count = 0;
+
+ console->cmd_count++;
+ console->cmds[i] = cmd;
+ default_list[i].self = cmd;
+ if( !default_list[i].connect ) {
+ RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count);
+ console->cmd_list[console->cmd_list_count - 1] = cmd;
+ }
+ }
+
+ for(i = 0; i < len; i++) {
+ unsigned int k;
+ if( !default_list[i].connect )
+ continue;
+ for(k = 0; k < console->cmd_count; k++) {
+ if( strcmpi(default_list[i].connect,console->cmds[k]->cmd) == 0 ) {
+ cmd = default_list[i].self;
+ RECREATE(console->cmds[k]->u.next, struct CParseEntry *, ++console->cmds[k]->next_count);
+ console->cmds[k]->u.next[console->cmds[k]->next_count - 1] = cmd;
+ break;
+ }
+ }
+ }
+}
+void console_parse_create(char *name, CParseFunc func) {
+ unsigned int i;
+ char *tok;
+ char sublist[CP_CMD_LENGTH * 5];
+ struct CParseEntry *cmd;
+
+ safestrncpy(sublist, name, CP_CMD_LENGTH * 5);
+ tok = strtok(sublist,":");
+
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
+ break;
+ }
+ if( i == console->cmd_list_count ) {
+ RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count);
+ CREATE(cmd, struct CParseEntry, 1);
+ safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH);
+ cmd->next_count = 0;
+ console->cmds[console->cmd_count - 1] = cmd;
+ RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count);
+ console->cmd_list[console->cmd_list_count - 1] = cmd;
+ i = console->cmd_list_count - 1;
+ }
+
+ cmd = console->cmd_list[i];
+ while( ( tok = strtok(NULL, ":") ) != NULL ) {
+
+ for(i = 0; i < cmd->next_count; i++) {
+ if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
+ break;
+ }
+
+ if ( i == cmd->next_count ) {
+ RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count);
+ CREATE(console->cmds[console->cmd_count-1], struct CParseEntry, 1);
+ safestrncpy(console->cmds[console->cmd_count-1]->cmd, tok, CP_CMD_LENGTH);
+ console->cmds[console->cmd_count-1]->next_count = 0;
+ RECREATE(cmd->u.next, struct CParseEntry *, ++cmd->next_count);
+ cmd->u.next[cmd->next_count - 1] = console->cmds[console->cmd_count-1];
+ cmd = console->cmds[console->cmd_count-1];
+ continue;
+ }
+
+ }
+ cmd->u.func = func;
+}
+void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) {
+ unsigned int i;
+ char msg[CP_CMD_LENGTH * 2];
+ for( i = 0; i < cmd->next_count; i++ ) {
+ if( cmd->u.next[i]->next_count ) {
+ memset(msg, '-', depth);
+ snprintf(msg + depth,CP_CMD_LENGTH * 2, " '"CL_WHITE"%s"CL_RESET"'",cmd->u.next[i]->cmd);
+ ShowInfo("%s subs\n",msg);
+ console->parse_list_subs(cmd->u.next[i],depth + 1);
+ } else {
+ memset(msg, '-', depth);
+ snprintf(msg + depth,CP_CMD_LENGTH * 2, " %s",cmd->u.next[i]->cmd);
+ ShowInfo("%s\n",msg);
+ }
+ }
+}
+void console_parse_sub(char *line) {
+ struct CParseEntry *cmd;
+ char bline[200];
+ char *tok;
+ char sublist[CP_CMD_LENGTH * 5];
+ unsigned int i, len = 0;
+ memcpy(bline, line, 200);
+ tok = strtok(line, " ");
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
+ break;
+ }
+
+ if( i == console->cmd_list_count ) {
+ ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line);
+ return;
+ }
+
+ cmd = console->cmd_list[i];
+
+ len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd) + 1;
+
+ if( cmd->next_count == 0 && console->cmd_list[i]->u.func ) {
+ char *r = NULL;
+ if( (tok = strtok(NULL, " ")) ) {
+ r = bline;
+ r += len + 1;
+ }
+ cmd->u.func(r);
+ } else {
+ while( ( tok = strtok(NULL, " ") ) != NULL ) {
+ for( i = 0; i < cmd->next_count; i++ ) {
+ if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
+ break;
+ }
+ if( i == cmd->next_count ) {
+ if( strcmpi("help",tok) == 0 ) {
+ if( cmd->next_count ) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist);
+ console->parse_list_subs(cmd,2);
+ } else {
+ ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist);
+ }
+ return;
+ }
+ ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd);
+ ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+ return;
+ }
+ if( cmd->u.next[i]->next_count == 0 && cmd->u.next[i]->u.func ) {
+ char *r = NULL;
+ if( (tok = strtok(NULL, " ")) ) {
+ r = bline;
+ r += len + strlen(cmd->u.next[i]->cmd) + 1;
+ }
+ cmd->u.next[i]->u.func(r);
+ return;
+ } else
+ cmd = cmd->u.next[i];
+ len += snprintf(sublist + len,CP_CMD_LENGTH * 5,":%s", cmd->cmd);
+ }
+ ShowError("it is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+ }
+}
void console_parse(char* line) {
int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */
@@ -122,7 +329,7 @@ int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) {
int i;
EnterSpinLock(&console->ptlock);
for(i = 0; i < cinput.count; i++) {
- parse_console(cinput.queue[i]);
+ console->parse_sub(cinput.queue[i]);
}
cinput.count = 0;
LeaveSpinLock(&console->ptlock);
@@ -163,12 +370,22 @@ void console_parse_init(void) {
void console_init (void) {
#ifdef CONSOLE_INPUT
+ console->cmd_count = console->cmd_list_count = 0;
+ console->load_defaults();
console->parse_init();
#endif
}
void console_final(void) {
#ifdef CONSOLE_INPUT
+ int i;
console->parse_final();
+ for( i = 0; i < console->cmd_count; i++ ) {
+ if( console->cmds[i]->next_count )
+ aFree(console->cmds[i]->u.next);
+ aFree(console->cmds[i]);
+ }
+ aFree(console->cmds);
+ aFree(console->cmd_list);
#endif
}
void console_defaults(void) {
@@ -182,6 +399,10 @@ void console_defaults(void) {
console->parse_timer = console_parse_timer;
console->pthread_main = cThread_main;
console->parse = console_parse;
+ console->parse_sub = console_parse_sub;
console->key_pressed = console_parse_key_pressed;
+ console->load_defaults = console_load_defaults;
+ console->parse_list_subs = console_parse_list_subs;
+ console->addCommand = console_parse_create;
#endif
}
diff --git a/src/common/console.h b/src/common/console.h
index 7f1490084..ebce013f7 100644
--- a/src/common/console.h
+++ b/src/common/console.h
@@ -14,6 +14,21 @@
* why is there a limit, why not make it dynamic? - I'm playing it safe, I'd rather not play with memory management between threads
**/
#define CONSOLE_PARSE_SIZE 10
+
+typedef void (*CParseFunc)(char *line);
+#define CPCMD(x) void console_parse_ ##x (char *line)
+#define CPCMD_A(x) console_parse_ ##x
+
+#define CP_CMD_LENGTH 20
+struct CParseEntry {
+ char cmd[CP_CMD_LENGTH];
+ union {
+ CParseFunc func;
+ struct CParseEntry **next;
+ } u;
+ unsigned short next_count;
+};
+
struct {
char queue[CONSOLE_PARSE_SIZE][MAX_CONSOLE_INPUT];
unsigned short count;
@@ -31,12 +46,21 @@ struct console_interface {
ramutex ptmutex;/* parse thread mutex */
racond ptcond;/* parse thread cond */
/* */
+ struct CParseEntry **cmd_list;
+ struct CParseEntry **cmds;
+ unsigned int cmd_count;
+ unsigned int cmd_list_count;
+ /* */
void (*parse_init) (void);
void (*parse_final) (void);
int (*parse_timer) (int tid, unsigned int tick, int id, intptr_t data);
void *(*pthread_main) (void *x);
void (*parse) (char* line);
+ void (*parse_sub) (char* line);
int (*key_pressed) (void);
+ void (*load_defaults) (void);
+ void (*parse_list_subs) (struct CParseEntry *cmd, unsigned char depth);
+ void (*addCommand) (char *name, CParseFunc func);
#endif
};
diff --git a/src/common/core.c b/src/common/core.c
index da4e4ccf9..9fd9747aa 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -17,6 +17,7 @@
#include "../common/sql.h"
#include "../config/core.h"
#include "../common/strlib.h"
+ #include "../common/HPM.h"
#endif
#include <stdio.h>
@@ -37,7 +38,6 @@ int arg_c = 0;
char **arg_v = NULL;
char *SERVER_NAME = NULL;
-char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef MINICORE // minimalist Core
// Added by Gabuzomeu
@@ -295,6 +295,9 @@ int main (int argc, char **argv)
arg_c = argc;
arg_v = argv;
}
+#ifndef MINICORE
+ hpm_defaults();
+#endif
console_defaults();
malloc_init();// needed for Show* in display_title() [FlavioJS]
@@ -320,13 +323,16 @@ int main (int argc, char **argv)
#endif
timer_init();
-
+
console->init();
+
+#ifndef MINICORE
+ HPM->init();
+#endif
socket_init();
do_init(argc,argv);
-
{// Main runtime cycle
int next;
while (runflag != CORE_ST_STOP) {
@@ -338,7 +344,9 @@ int main (int argc, char **argv)
console->final();
do_final();
-
+#ifndef MINICORE
+ HPM->final();
+#endif
timer_final();
socket_final();
db_final();
diff --git a/src/common/core.h b/src/common/core.h
index 21da18938..8fdcdcfc3 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -23,17 +23,15 @@ extern char **arg_v;
extern int runflag;
extern char *SERVER_NAME;
-enum {
- ATHENA_SERVER_NONE = 0, // not defined
- ATHENA_SERVER_LOGIN = 1, // login server
- ATHENA_SERVER_CHAR = 2, // char server
- ATHENA_SERVER_INTER = 4, // inter server
- ATHENA_SERVER_MAP = 8, // map server
+enum server_types {
+ SERVER_TYPE_UNKNOWN = 0x0,
+ SERVER_TYPE_LOGIN = 0x1,
+ SERVER_TYPE_CHAR = 0x2,
+ SERVER_TYPE_MAP = 0x4,
};
-extern char SERVER_TYPE;
+enum server_types SERVER_TYPE;
-extern int parse_console(const char* buf);
const char *get_svn_revision(void);
const char *get_git_hash (void);
extern int do_init(int,char**);
@@ -42,8 +40,7 @@ extern void do_abort(void);
extern void do_final(void);
/// The main loop continues until runflag is CORE_ST_STOP
-enum E_CORE_ST
-{
+enum E_CORE_ST {
CORE_ST_STOP = 0,
CORE_ST_RUN,
CORE_ST_LAST
diff --git a/src/common/db.c b/src/common/db.c
index 204c6d2ea..7ac9b2dc7 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -47,6 +47,7 @@
* - create a db that organizes itself by splaying
*
* HISTORY:
+ * 2013/04/27 - Added ERS to speed up iterator memory allocation [Ind/Hercules]
* 2012/03/09 - Added enum for data types (int, uint, void*)
* 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly.
* 2007/11/09 - Added an iterator to the database.
@@ -319,6 +320,10 @@ static struct db_stats {
#define DB_COUNTSTAT(token)
#endif /* !defined(DB_ENABLE_STATS) */
+/* [Ind/Hercules] */
+struct eri *db_iterator_ers;
+struct eri *db_alloc_ers;
+
/*****************************************************************************\
* (2) Section of private functions used by the database system. *
* db_rotate_left - Rotate a tree node to the left. *
@@ -1366,7 +1371,7 @@ void dbit_obj_destroy(DBIterator* self)
// unlock the database
db_free_unlock(it->db);
// free iterator
- aFree(self);
+ ers_free(db_iterator_ers,self);
}
/**
@@ -1384,7 +1389,7 @@ static DBIterator* db_obj_iterator(DBMap* self)
DBIterator_impl* it;
DB_COUNTSTAT(db_iterator);
- CREATE(it, struct DBIterator_impl, 1);
+ it = ers_alloc(db_iterator_ers, struct DBIterator_impl);
/* Interface of the iterator **/
it->vtable.first = dbit_obj_first;
it->vtable.last = dbit_obj_last;
@@ -2127,7 +2132,7 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args)
db->free_max = 0;
ers_destroy(db->nodes);
db_free_unlock(db);
- aFree(db);
+ ers_free(db_alloc_ers, db);
return sum;
}
@@ -2409,7 +2414,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break;
}
#endif /* DB_ENABLE_STATS */
- CREATE(db, struct DBMap_impl, 1);
+ db = ers_alloc(db_alloc_ers, struct DBMap_impl);
options = db_fix_options(type, options);
/* Interface of the database */
@@ -2602,8 +2607,9 @@ void* db_data2ptr(DBData *data)
* @public
* @see #db_final(void)
*/
-void db_init(void)
-{
+void db_init(void) {
+ db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE);
+ db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE);
DB_COUNTSTAT(db_init);
}
@@ -2696,6 +2702,8 @@ void db_final(void)
stats.db_data2ui, stats.db_data2ptr,
stats.db_init, stats.db_final);
#endif /* DB_ENABLE_STATS */
+ ers_destroy(db_iterator_ers);
+ ers_destroy(db_alloc_ers);
}
// Link DB System - jAthena
diff --git a/src/common/ers.c b/src/common/ers.c
index 3b354166e..13e54b393 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -1,7 +1,7 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
/*****************************************************************************\
- * Copyright (c) Athena Dev Teams - Licensed under GNU GPL *
- * For more information, see LICENCE in the main folder *
- * *
* <H1>Entry Reusage System</H1> *
* *
* There are several root entry managers, each with a different entry size. *
@@ -48,8 +48,7 @@
#ifndef DISABLE_ERS
-#define ERS_ROOT_SIZE 256
-#define ERS_BLOCK_ENTRIES 4096
+#define ERS_BLOCK_ENTRIES 2048
struct ers_list
{
diff --git a/src/common/netbuffer.c b/src/common/netbuffer.c
index 57742d612..60a299aa9 100644
--- a/src/common/netbuffer.c
+++ b/src/common/netbuffer.c
@@ -52,10 +52,10 @@ void netbuffer_init(){
// Set localsection name according to running serverype.
switch(SERVER_TYPE){
- case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break;
- case ATHENA_SERVER_CHAR: strcpy(localsection, "char-netbuffer"); break;
- case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break;
- case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break;
+ case SERVER_TYPE_LOGIN: strcpy(localsection, "login-netbuffer"); break;
+ case SERVER_TYPE_CHAR: strcpy(localsection, "char-netbuffer"); break;
+ //case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break;
+ case SERVER_TYPE_MAP: strcpy(localsection, "map-netbuffer"); break;
default: strcpy(localsection, "unsupported_type"); break;
}
diff --git a/src/common/showmsg.c b/src/common/showmsg.c
index 609ae3c50..50fa972f0 100644
--- a/src/common/showmsg.c
+++ b/src/common/showmsg.c
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#include "../common/cbasetypes.h"
#include "../common/strlib.h" // StringBuf
@@ -687,22 +688,12 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap)
ShowError("Empty string passed to _vShowMessage().\n");
return 1;
}
- /**
- * For the buildbot, these result in a EXIT_FAILURE from core.c when done reading the params.
- **/
-#if defined(BUILDBOT)
- if( flag == MSG_WARNING ||
- flag == MSG_ERROR ||
- flag == MSG_SQL ) {
- buildbotflag = 1;
- }
-#endif
if(
( flag == MSG_WARNING && console_msg_log&1 ) ||
( ( flag == MSG_ERROR || flag == MSG_SQL ) && console_msg_log&2 ) ||
( flag == MSG_DEBUG && console_msg_log&4 ) ) {//[Ind]
FILE *log = NULL;
- if( (log = fopen(SERVER_TYPE == ATHENA_SERVER_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) {
+ if( (log = fopen(SERVER_TYPE == SERVER_TYPE_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) {
char timestring[255];
time_t curtime;
time(&curtime);
diff --git a/src/common/showmsg.h b/src/common/showmsg.h
index 0d6cb5c9f..a88985770 100644
--- a/src/common/showmsg.h
+++ b/src/common/showmsg.h
@@ -1,11 +1,13 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _SHOWMSG_H_
#define _SHOWMSG_H_
-#include "libconfig.h"
-
+#ifndef _HPMi_H_
+ #include "libconfig.h"
+#endif
// for help with the console colors look here:
// http://www.edoceo.com/liberum/?doc=printf-with-color
// some code explanation (used here):
@@ -85,15 +87,17 @@ enum msg_type {
};
extern void ClearScreen(void);
-extern void ShowMessage(const char *, ...);
-extern void ShowStatus(const char *, ...);
-extern void ShowSQL(const char *, ...);
-extern void ShowInfo(const char *, ...);
-extern void ShowNotice(const char *, ...);
-extern void ShowWarning(const char *, ...);
-extern void ShowDebug(const char *, ...);
-extern void ShowError(const char *, ...);
-extern void ShowFatalError(const char *, ...);
-extern void ShowConfigWarning(config_setting_t *config, const char *string, ...);
+#ifndef _HPMi_H_
+ extern void ShowMessage(const char *, ...);
+ extern void ShowStatus(const char *, ...);
+ extern void ShowSQL(const char *, ...);
+ extern void ShowInfo(const char *, ...);
+ extern void ShowNotice(const char *, ...);
+ extern void ShowWarning(const char *, ...);
+ extern void ShowDebug(const char *, ...);
+ extern void ShowError(const char *, ...);
+ extern void ShowFatalError(const char *, ...);
+ extern void ShowConfigWarning(config_setting_t *config, const char *string, ...);
+#endif
#endif /* _SHOWMSG_H_ */
diff --git a/src/login/login.c b/src/login/login.c
index 2b96eefec..09dd938db 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -360,58 +360,6 @@ int login_lan_config_read(const char *lancfgName)
return 0;
}
-//-----------------------
-// Console Command Parser [Wizputer]
-//-----------------------
-int parse_console(const char* command)
-{
- ShowNotice("Console command: %s\n", command);
-
- if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 )
- runflag = 0;
- else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
- ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
- else if( strcmpi("help", command) == 0 )
- {
- ShowInfo("To shutdown the server:\n");
- ShowInfo(" 'shutdown|exit|quit|end'\n");
- ShowInfo("To know if server is alive:\n");
- ShowInfo(" 'alive|status'\n");
- ShowInfo("To create a new account:\n");
- ShowInfo(" 'create'\n");
- }
- else
- {// commands with parameters
- char cmd[128], params[256];
-
- if( sscanf(command, "%127s %255[^\r\n]", cmd, params) < 2 )
- {
- return 0;
- }
-
- if( strcmpi(cmd, "create") == 0 )
- {
- char username[NAME_LENGTH], password[NAME_LENGTH], sex;
-
- if( sscanf(params, "%23s %23s %c", username, password, &sex) < 3 || strnlen(username, sizeof(username)) < 4 || strnlen(password, sizeof(password)) < 1 )
- {
- ShowWarning("Console: Invalid parameters for '%s'. Usage: %s <username> <password> <sex:F/M>\n", cmd, cmd);
- return 0;
- }
-
- if( mmo_auth_new(username, password, TOUPPER(sex), "0.0.0.0") != -1 )
- {
- ShowError("Console: Account creation failed.\n");
- return 0;
- }
- ShowStatus("Console: Account '%s' created successfully.\n", username);
- }
- }
-
- return 0;
-}
-
-
//--------------------------------
// Packet parsing for char-servers
//--------------------------------
@@ -1836,9 +1784,8 @@ void do_abort(void)
{
}
-void set_server_type(void)
-{
- SERVER_TYPE = ATHENA_SERVER_LOGIN;
+void set_server_type(void) {
+ SERVER_TYPE = SERVER_TYPE_LOGIN;
}
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 <string.h>
#include <math.h>
-
-#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 <packet len>.W <message>.?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.
@@ -3264,80 +3269,6 @@ 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:<gm command>:<map of \"gm\"> <x> <y>\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 <map of \"gm\"> <x> <y> 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...)
*------------------------------------------*/
int map_config_read(char *cfgName)
@@ -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 <optional params>"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 <setjmp.h>
#include <errno.h>
-
-///////////////////////////////////////////////////////////////////////////////
-//## 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)
{// <func name>
syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN;
*/
- } else
- {// <func name> <arg list>
+ } else {// <func name> <arg list>
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) )
{// "<item name>"
- 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) ) {// <item id>
- 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);// <item id>
+ it.nameid = script->conv_num(st,data);// <item id>
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);// <item id>
+ it.nameid = script->conv_num(st,data);// <item id>
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,""), // <Agit>
- BUILDIN_DEF(agitend,""),
- BUILDIN_DEF(agitcheck,""), // <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,""), // <Agit>
+ BUILDIN_DEF(agitend,""),
+ BUILDIN_DEF(agitcheck,""), // <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_ */
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
new file mode 100644
index 000000000..4e4851bc5
--- /dev/null
+++ b/src/plugins/CMakeLists.txt
@@ -0,0 +1,36 @@
+#
+# setup
+#
+get_property( CAN_BUILD_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS )
+if( NOT CAN_BUILD_SHARED_LIBS )
+ return()
+endif()
+
+#
+# sample
+#
+option( BUILD_PLUGIN_sample "build sample plugin" OFF )
+if( BUILD_PLUGIN_sample )
+message( STATUS "Creating target sample" )
+set( SAMPLE_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/sample.c"
+ )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
+set( SOURCE_FILES ${SAMPLE_SOURCES} )
+source_group( sample FILES ${SAMPLE_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_library( sample SHARED ${SOURCE_FILES} )
+target_link_libraries( sample ${LIBRARIES} )
+set_target_properties( sample PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
+set_target_properties( sample PROPERTIES PREFIX "" )
+if( INSTALL_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_sample DESCRIPTION "sample plugin" DISPLAY_NAME "sample" GROUP Runtime )
+ install( TARGETS sample
+ DESTINATION "plugins"
+ COMPONENT Runtime_sample )
+endif( INSTALL_COMPONENT_RUNTIME )
+set( TARGET_LIST ${TARGET_LIST} sample CACHE INTERNAL "" )
+message( STATUS "Creating target sample - done" )
+endif( BUILD_PLUGIN_sample ) \ No newline at end of file
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
new file mode 100644
index 000000000..71b743dca
--- /dev/null
+++ b/src/plugins/Makefile.in
@@ -0,0 +1,28 @@
+
+COMMON_H = ../common/HPMi.h ../common/cbasetypes.h
+
+PLUGINS = sample
+
+@SET_MAKE@
+
+#####################################################################
+.PHONY : all $(PLUGINS) sample clean help
+
+all: $(PLUGINS)
+
+sample: sample@DLLEXT@
+
+clean:
+ @echo " CLEAN plugins"
+ @rm -rf *.o
+
+help:
+ @echo "possible targets are $(PLUGINS:%='%') 'all' 'clean' 'help'"
+ @echo "'sample' - sample plugin"
+ @echo "'help' - outputs this message"
+
+#####################################################################
+
+%@DLLEXT@: %.c $(COMMON_H)
+ @echo " CC $<"
+ @@CC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o ../../plugins/$@ $< \ No newline at end of file
diff --git a/src/plugins/sample.c b/src/plugins/sample.c
new file mode 100644
index 000000000..8e6b8fc86
--- /dev/null
+++ b/src/plugins/sample.c
@@ -0,0 +1,74 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Sample Hercules Plugin
+
+#include <stdio.h>
+#include <string.h>
+#include "../common/HPMi.h"
+#include "../map/script.h"
+#include "../map/pc.h"
+
+HPExport struct hplugin_info pinfo = {
+ "Sample", // Plugin name
+ SERVER_TYPE_MAP,// Which server types this plugin works with?
+ "0.1", // Plugin version
+ HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
+};
+ACMD(sample) {//@sample command - 5 params: const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info
+ printf("I'm being run! message -> '%s' by %s\n",message,sd->status.name);
+ return true;
+}
+BUILDIN(sample) {//script command 'sample(num);' - 1 param: struct script_state* st
+ int arg = script_getnum(st,2);
+ ShowInfo("I'm being run! arg -> '%d'\n",arg);
+ return true;
+}
+CPCMD(sample) {//console command 'sample' - 1 param: char *line
+ ShowInfo("I'm being run! arg -> '%s'\n",line?line:"NONE");
+}
+struct script_interface *script;/* used by script commands */
+/* run when server starts */
+HPExport void plugin_init (void) {
+ char *server_type;
+ char *server_name;
+
+ //get the symbols from the server
+ server_type = GET_SYMBOL("SERVER_TYPE");
+ server_name = GET_SYMBOL("SERVER_NAME");
+
+ script = GET_SYMBOL("script");
+
+ if( !(script = GET_SYMBOL("script")) ) {
+ ShowError("Failed to load script interface var!\n");
+ }
+
+ ShowInfo ("Server type is ");
+
+ switch (*server_type) {
+ case SERVER_TYPE_LOGIN: printf ("Login Server\n"); break;
+ case SERVER_TYPE_CHAR: printf ("Char Server\n"); break;
+ case SERVER_TYPE_MAP: printf ("Map Server\n"); break;
+ }
+
+ ShowInfo ("I'm being run from the '%s' filename\n", server_name);
+
+ if( HPMi->addCommand != NULL ) {//link our '@sample' command
+ HPMi->addCommand("sample",ACMD_A(sample));
+ }
+
+ if( HPMi->addScript != NULL ) {//link our 'sample' script command
+ HPMi->addScript("sample","i",BUILDIN_A(sample));
+ }
+
+ if( HPMi->addCPCommand != NULL ) {//link our 'sample' console command
+ HPMi->addCPCommand("this:is:a:sample",CPCMD_A(sample));
+ }
+}
+/* run when server is ready (online) */
+HPExport void server_online (void) {
+
+}
+/* run when server is shutting down */
+HPExport void plugin_final (void) {
+ ShowInfo ("%s says ~Bye world\n",pinfo.name);
+} \ No newline at end of file