summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/char/CMakeLists.txt51
-rw-r--r--src/char/Makefile.in21
-rw-r--r--src/char/char.c397
-rw-r--r--src/char/char.h10
-rw-r--r--src/char/int_homun.c2
-rw-r--r--src/char_sql/CMakeLists.txt57
-rw-r--r--src/char_sql/Makefile.in21
-rw-r--r--src/char_sql/char.c398
-rw-r--r--src/char_sql/char.h11
-rw-r--r--src/char_sql/int_auction.c4
-rw-r--r--src/char_sql/int_guild.c2
-rw-r--r--src/common/CMakeLists.txt144
-rw-r--r--src/common/Makefile.in25
-rw-r--r--src/common/cbasetypes.h111
-rw-r--r--src/common/core.c14
-rw-r--r--src/common/core.h13
-rw-r--r--src/common/db.c91
-rw-r--r--src/common/db.h20
-rw-r--r--src/common/ers.h2
-rw-r--r--src/common/grfio.c36
-rw-r--r--src/common/grfio.h5
-rw-r--r--src/common/malloc.c10
-rw-r--r--src/common/mmo.h19
-rw-r--r--src/common/plugin.h2
-rw-r--r--src/common/plugins.h3
-rw-r--r--src/common/random.c83
-rw-r--r--src/common/random.h18
-rw-r--r--src/common/socket.c5
-rw-r--r--src/common/socket.h2
-rw-r--r--src/common/sql.c4
-rw-r--r--src/common/sql.h2
-rw-r--r--src/common/strlib.c136
-rw-r--r--src/common/strlib.h23
-rw-r--r--src/common/timer.c4
-rw-r--r--src/common/timer.h10
-rw-r--r--src/common/utils.h3
-rw-r--r--src/login/CMakeLists.txt12
-rw-r--r--src/login/Makefile.in33
-rw-r--r--src/login/account_txt.c6
-rw-r--r--src/login/ipban_sql.c4
-rw-r--r--src/login/login.c130
-rw-r--r--src/login/login.h8
-rw-r--r--src/login/sql/CMakeLists.txt43
-rw-r--r--src/login/txt/CMakeLists.txt43
-rw-r--r--src/map/CMakeLists.txt12
-rw-r--r--src/map/Makefile.in30
-rw-r--r--src/map/atcommand.c22
-rw-r--r--src/map/battle.c6
-rw-r--r--src/map/battle.h27
-rw-r--r--src/map/battleground.c2
-rw-r--r--src/map/buyingstore.c2
-rw-r--r--src/map/chrif.c114
-rw-r--r--src/map/chrif.h2
-rw-r--r--src/map/clif.c160
-rw-r--r--src/map/clif.h8
-rw-r--r--src/map/guild.c10
-rw-r--r--src/map/homunculus.c6
-rw-r--r--src/map/instance.c63
-rw-r--r--src/map/instance.h11
-rw-r--r--src/map/map.c41
-rw-r--r--src/map/map.h16
-rw-r--r--src/map/mapreg_sql.c2
-rw-r--r--src/map/mapreg_txt.c2
-rw-r--r--src/map/mercenary.c2
-rw-r--r--src/map/mob.c57
-rw-r--r--src/map/mob.h4
-rw-r--r--src/map/npc.c38
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/party.c16
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/pc.c139
-rw-r--r--src/map/pc.h12
-rw-r--r--src/map/pet.c17
-rw-r--r--src/map/pet.h8
-rw-r--r--src/map/quest.c2
-rw-r--r--src/map/script.c105
-rw-r--r--src/map/script.h2
-rw-r--r--src/map/skill.c133
-rw-r--r--src/map/skill.h83
-rw-r--r--src/map/sql/CMakeLists.txt110
-rw-r--r--src/map/status.c19
-rw-r--r--src/map/status.h78
-rw-r--r--src/map/txt/CMakeLists.txt110
-rw-r--r--src/map/unit.c18
-rw-r--r--src/plugins/console.c6
-rw-r--r--src/tool/CMakeLists.txt42
-rw-r--r--src/tool/mapcache.c4
88 files changed, 2572 insertions, 1020 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 000000000..0bf5b0eb6
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+add_subdirectory( common )
+add_subdirectory( login )
+add_subdirectory( char )
+add_subdirectory( char_sql )
+add_subdirectory( map )
+add_subdirectory( tool )
+#add_subdirectory( txt-converter )
+#add_subdirectory( plugins )
diff --git a/src/char/CMakeLists.txt b/src/char/CMakeLists.txt
new file mode 100644
index 000000000..9e0cbd9f4
--- /dev/null
+++ b/src/char/CMakeLists.txt
@@ -0,0 +1,51 @@
+
+#
+# char txt
+#
+if( HAVE_common_base )
+message( STATUS "Creating target char-server" )
+set( TXT_CHAR_HEADERS
+ "${CMAKE_CURRENT_SOURCE_DIR}/char.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_party.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_status.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/inter.h"
+ )
+set( TXT_CHAR_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/char.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_party.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_status.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/inter.c"
+ )
+set( DEPENDENCIES common_base )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} TXT_ONLY )
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_CHAR_HEADERS} ${TXT_CHAR_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} )
+source_group( char FILES ${TXT_CHAR_HEADERS} ${TXT_CHAR_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( char-server ${SOURCE_FILES} )
+add_dependencies( char-server ${DEPENDENCIES} )
+target_link_libraries( char-server ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( char-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_charserver_txt DESCRIPTION "char-server (txt version)" DISPLAY_NAME "char-server" GROUP Runtime )
+ install( TARGETS char-server
+ DESTINATION "."
+ COMPONENT Runtime_charserver_txt )
+endif()
+message( STATUS "Creating target char-server - done" )
+set( HAVE_char-server ON CACHE BOOL "char-server target is available" )
+mark_as_advanced( HAVE_char-server )
+else()
+message( STATUS "Skipping target char-server (requires common_base)" )
+unset( HAVE_char-server CACHE )
+endif()
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 359e19b01..ba8f4fe64 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -3,12 +3,16 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a
../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \
../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \
../common/obj_all/strlib.o ../common/obj_all/grfio.o \
- ../common/obj_all/mapindex.o ../common/obj_all/ers.o
+ ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h \
../common/strlib.h ../common/grfio.h \
- ../common/mapindex.h ../common/ers.h
+ ../common/mapindex.h ../common/ers.h ../common/random.h
+
+MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
+MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
+MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
CHAR_OBJ = obj_txt/char.o obj_txt/inter.o obj_txt/int_party.o obj_txt/int_guild.o \
obj_txt/int_storage.o obj_txt/int_status.o obj_txt/int_pet.o obj_txt/int_homun.o
@@ -21,8 +25,8 @@ CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_status.h int_p
all: char-server
-char-server: obj_txt $(CHAR_OBJ) $(COMMON_OBJ)
- @CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) @LIBS@
+char-server: obj_txt $(CHAR_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ)
+ @CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@
clean:
rm -rf *.o obj_txt ../../char-server@EXEEXT@
@@ -39,9 +43,12 @@ help:
obj_txt:
-mkdir obj_txt
-obj_txt/%.o: %.c $(CHAR_H) $(COMMON_H)
- @CC@ @CFLAGS@ -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_txt/%.o: %.c $(CHAR_H) $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-# missing common object files
+# missing object files
../common/obj_all/%.o:
@$(MAKE) -C ../common txt
+
+MT19937AR_OBJ:
+ @$(MAKE) -C ../../3rdparty/mt19937ar
diff --git a/src/char/char.c b/src/char/char.c
index 6599a6258..617e3d10c 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -176,7 +176,7 @@ struct online_char_data {
};
static DBMap* online_char_db; // int account_id -> struct online_char_data*
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data);
+static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
static void* create_online_char_data(DBKey key, va_list args)
{
@@ -571,8 +571,8 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p, struct global_reg *reg,
*(str_p++) = '\t';
for(i = 0; i < MAX_SKILL; i++)
- if (p->skill[i].id && p->skill[i].flag != 1) {
- str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == 0) ? p->skill[i].lv : p->skill[i].flag-2);
+ if (p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY) {
+ str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT) ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
}
*(str_p++) = '\t';
@@ -1229,7 +1229,7 @@ void mmo_char_sync(void)
//----------------------------------------------------
// Function to save (in a periodic way) datas in files
//----------------------------------------------------
-int mmo_char_sync_timer(int tid, unsigned int tick, int id, intptr data)
+int mmo_char_sync_timer(int tid, unsigned int tick, int id, intptr_t data)
{
if (save_log)
ShowInfo("Saving all files...\n");
@@ -1782,7 +1782,7 @@ int count_users(void)
int i, users;
users = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
if (server[i].fd > 0) {
users += server[i].users;
}
@@ -2060,24 +2060,74 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
// continues when account data is received...
}
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data);
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
+void mapif_server_reset(int id);
+
+
+/// Resets all the data.
+void loginif_reset(void)
+{
+ int id;
+ // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS]
+ for( id = 0; id < ARRAYLENGTH(server); ++id )
+ mapif_server_reset(id);
+ flush_fifos();
+ exit(EXIT_FAILURE);
+}
+
+
+/// Checks the conditions for the server to stop.
+/// If all the conditions are met, it stops the core loop.
+void loginif_check_shutdown(void)
+{
+ if( runflag != CHARSERVER_ST_SHUTDOWN )
+ return;
+ runflag = CORE_ST_STOP;
+}
+
+
+/// Called when the connection to Login Server is disconnected.
+void loginif_on_disconnect(void)
+{
+ ShowWarning("Connection to Login Server lost.\n\n");
+}
+
+
+/// Called when all the connection steps are completed.
+void loginif_on_ready(void)
+{
+ int i;
+
+ loginif_check_shutdown();
+
+ //Send online accounts to login server.
+ send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
+
+ // if no map-server already connected, display a message...
+ ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] );
+ if( i == ARRAYLENGTH(server) )
+ ShowStatus("Awaiting maps from map-server.\n");
+}
+
int parse_fromlogin(int fd)
{
+ struct char_session_data* sd = NULL;
int i;
- struct char_session_data *sd;
- // only login-server can have an access to here.
- // so, if it isn't the login-server, we disconnect the session.
+ // only process data from the login-server
if( fd != login_fd )
- set_eof(fd);
+ {
+ ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
+ do_close(fd);
+ return 0;
+ }
- if(session[fd]->flag.eof) {
- if (fd == login_fd) {
- ShowWarning("Connection to login-server lost (connection #%d).\n", fd);
- login_fd = -1;
- }
+ if( session[fd]->flag.eof )
+ {
do_close(fd);
+ login_fd = -1;
+ loginif_on_disconnect();
return 0;
}
@@ -2101,16 +2151,11 @@ int parse_fromlogin(int fd)
ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
ShowError("Also, please make sure your accounts file (default: accounts.txt) has the correct communication username/passwords and the gender of the account is S.\n");
ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
+ set_eof(fd);
+ return 0;
} else {
ShowStatus("Connected to login-server (connection #%d).\n", fd);
-
- //Send online accounts to login server.
- send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
-
- // if no map-server already connected, display a message...
- ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
- if( i == MAX_MAP_SERVERS )
- ShowStatus("Awaiting maps from map-server.\n");
+ loginif_on_ready();
}
RFIFOSKIP(fd,3);
break;
@@ -2226,7 +2271,7 @@ int parse_fromlogin(int fd)
}
// remove specifical skills of classes 19, 4020 and 4042
for(j = 315; j <= 322; j++) {
- if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
+ if (char_dat[i].status.skill[j].id > 0 && char_dat[i].status.skill[j].flag == SKILL_FLAG_PERMANENT) {
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
char_dat[i].status.skill[j].id = 0;
char_dat[i].status.skill[j].lv = 0;
@@ -2234,7 +2279,7 @@ int parse_fromlogin(int fd)
}
// remove specifical skills of classes 20, 4021 and 4043
for(j = 323; j <= 330; j++) {
- if (char_dat[i].status.skill[j].id > 0 && !char_dat[i].status.skill[j].flag) {
+ if (char_dat[i].status.skill[j].id > 0 && char_dat[i].status.skill[j].flag == SKILL_FLAG_PERMANENT) {
char_dat[i].status.skill_point += char_dat[i].status.skill[j].lv;
char_dat[i].status.skill[j].id = 0;
char_dat[i].status.skill[j].lv = 0;
@@ -2377,6 +2422,34 @@ int parse_fromlogin(int fd)
return 0;
}
+int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data);
+int ping_login_server(int tid, unsigned int tick, int id, intptr_t data);
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
+
+void do_init_loginif(void)
+{
+ // establish char-login connection if not present
+ add_timer_func_list(check_connect_login_server, "check_connect_login_server");
+ add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
+
+ // keep the char-login connection alive
+ add_timer_func_list(ping_login_server, "ping_login_server");
+ add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
+
+ // send a list of all online account IDs to login server
+ add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
+ add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
+}
+
+void do_final_loginif(void)
+{
+ if( login_fd != -1 )
+ {
+ do_close(login_fd);
+ login_fd = -1;
+ }
+}
+
int request_accreg2(int account_id, int char_id)
{
if (login_fd > 0) {
@@ -2592,36 +2665,76 @@ int char_loadName(int char_id, char* name)
int search_mapserver(unsigned short map, uint32 ip, uint16 port);
+
+/// Initializes a server structure.
+void mapif_server_init(int id)
+{
+ memset(&server[id], 0, sizeof(server[id]));
+ server[id].fd = -1;
+}
+
+
+/// Destroys a server structure.
+void mapif_server_destroy(int id)
+{
+ if( server[id].fd == -1 )
+ {
+ do_close(server[id].fd);
+ server[id].fd = -1;
+ }
+}
+
+
+/// Resets all the data related to a server.
+void mapif_server_reset(int id)
+{
+ int i,j;
+ unsigned char buf[16384];
+ int fd = server[id].fd;
+ //Notify other map servers that this one is gone. [Skotlex]
+ WBUFW(buf,0) = 0x2b20;
+ WBUFL(buf,4) = htonl(server[id].ip);
+ WBUFW(buf,8) = htons(server[id].port);
+ j = 0;
+ for(i = 0; i < MAX_MAP_PER_SERVER; i++)
+ if (server[id].map[i])
+ WBUFW(buf,10+(j++)*4) = server[id].map[i];
+ if (j > 0) {
+ WBUFW(buf,2) = j * 4 + 10;
+ mapif_sendallwos(fd, buf, WBUFW(buf,2));
+ }
+ online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
+ create_online_files();
+ mapif_server_destroy(id);
+ mapif_server_init(id);
+}
+
+
+/// Called when the connection to a Map Server is disconnected.
+void mapif_on_disconnect(int id)
+{
+ ShowStatus("Map-server #%d has disconnected.\n", id);
+ mapif_server_reset(id);
+}
+
+
int parse_frommap(int fd)
{
int i, j;
int id;
- ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
- if(id == MAX_MAP_SERVERS)
- set_eof(fd);
- if(session[fd]->flag.eof) {
- if (id < MAX_MAP_SERVERS) {
- unsigned char buf[16384];
- ShowStatus("Map-server %d (session #%d) has disconnected.\n", id, fd);
- //Notify other map servers that this one is gone. [Skotlex]
- WBUFW(buf,0) = 0x2b20;
- WBUFL(buf,4) = htonl(server[id].ip);
- WBUFW(buf,8) = htons(server[id].port);
- j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
- if (server[id].map[i])
- WBUFW(buf,10+(j++)*4) = server[id].map[i];
- if (j > 0) {
- WBUFW(buf,2) = j * 4 + 10;
- mapif_sendallwos(fd, buf, WBUFW(buf,2));
- }
- memset(&server[id], 0, sizeof(struct mmo_map_server));
- server[id].fd = -1;
- online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
- }
+ ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
+ if( id == ARRAYLENGTH(server) )
+ {// not a map server
+ ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd);
do_close(fd);
- create_online_files();
+ return 0;
+ }
+ if( session[fd]->flag.eof )
+ {
+ do_close(fd);
+ server[id].fd = -1;
+ mapif_on_disconnect(id);
return 0;
}
@@ -2672,14 +2785,14 @@ int parse_frommap(int fd)
mapif_sendallwos(fd, buf, WBUFW(buf,2));
}
// Transmitting the maps of the other map-servers to the new map-server
- for(x = 0; x < MAX_MAP_SERVERS; x++) {
+ for(x = 0; x < ARRAYLENGTH(server); x++) {
if (server[x].fd > 0 && x != id) {
- WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
+ WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server));
WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = htonl(server[x].ip);
WFIFOW(fd,8) = htons(server[x].port);
j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
+ for(i = 0; i < ARRAYLENGTH(server); i++)
if (server[x].map[i])
WFIFOW(fd,10+(j++)*4) = server[x].map[i];
if (j > 0) {
@@ -2802,26 +2915,37 @@ int parse_frommap(int fd)
uint32 ip = RFIFOL(fd,14);
RFIFOSKIP(fd,18);
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = account_id;
- node->char_id = 0;
- node->login_id1 = login_id1;
- node->login_id2 = login_id2;
- //node->sex = 0;
- node->ip = ntohl(ip);
- //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
- //node->gmlevel = 0;
- idb_put(auth_db, account_id, node);
-
- //Set char to "@ char select" in online db [Kevin]
- set_char_charselect(account_id);
-
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x2b03;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = 0;
- WFIFOSET(fd,7);
+ if( runflag != CHARSERVER_ST_RUNNING )
+ {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x2b03;
+ WFIFOL(fd,2) = account_id;
+ WFIFOB(fd,6) = 0;// not ok
+ WFIFOSET(fd,7);
+ }
+ else
+ {
+ // create temporary auth entry
+ CREATE(node, struct auth_node, 1);
+ node->account_id = account_id;
+ node->char_id = 0;
+ node->login_id1 = login_id1;
+ node->login_id2 = login_id2;
+ //node->sex = 0;
+ node->ip = ntohl(ip);
+ //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
+ //node->gmlevel = 0;
+ idb_put(auth_db, account_id, node);
+
+ //Set char to "@ char select" in online db [Kevin]
+ set_char_charselect(account_id);
+
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x2b03;
+ WFIFOL(fd,2) = account_id;
+ WFIFOB(fd,6) = 1;// ok
+ WFIFOSET(fd,7);
+ }
}
break;
@@ -2839,7 +2963,9 @@ int parse_frommap(int fd)
char_data = search_character(RFIFOL(fd,2), RFIFOL(fd,14));
- if (map_fd >= 0 && session[map_fd] && char_data)
+ if( runflag == CHARSERVER_ST_RUNNING &&
+ session_isActive(map_fd) &&
+ char_data )
{ //Send the map server the auth of this player.
struct auth_node* node;
@@ -3140,7 +3266,9 @@ int parse_frommap(int fd)
node = (struct auth_node*)idb_get(auth_db, account_id);
cd = search_character(account_id, char_id);
- if( node != NULL && cd != NULL &&
+ if( runflag == CHARSERVER_ST_RUNNING &&
+ cd != NULL &&
+ node != NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
node->login_id1 == login_id1 &&
@@ -3204,13 +3332,27 @@ int parse_frommap(int fd)
return 0;
}
+void do_init_mapif(void)
+{
+ int i;
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ mapif_server_init(i);
+}
+
+void do_final_mapif(void)
+{
+ int i;
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ mapif_server_destroy(i);
+}
+
// Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
// If found, returns the server's index in the 'server' array (otherwise returns -1).
int search_mapserver(unsigned short map, uint32 ip, uint16 port)
{
int i, j;
- for(i = 0; i < MAX_MAP_SERVERS; i++)
+ for(i = 0; i < ARRAYLENGTH(server); i++)
{
if (server[i].fd > 0
&& (ip == (uint32)-1 || server[i].ip == ip)
@@ -3526,6 +3668,15 @@ int parse_char(int fd)
WFIFOL(fd,0) = account_id;
WFIFOSET(fd,4);
+ if( runflag != CHARSERVER_ST_RUNNING )
+ {
+ WFIFOHEAD(fd,3);
+ WFIFOW(fd,0) = 0x6c;
+ WFIFOB(fd,2) = 0;// rejected from server
+ WFIFOSET(fd,3);
+ break;
+ }
+
// search authentification
node = (struct auth_node*)idb_get(auth_db, account_id);
if( node != NULL &&
@@ -3602,8 +3753,8 @@ int parse_char(int fd)
if (i < 0) {
unsigned short j;
//First check that there's actually a map server online.
- ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] );
- if (j == MAX_MAP_SERVERS) {
+ ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
+ if (j == ARRAYLENGTH(server)) {
ShowInfo("Connection Closed. No map servers available.\n");
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81;
@@ -3927,8 +4078,12 @@ int parse_char(int fd)
char* l_pass = (char*)RFIFOP(fd,26);
l_user[23] = '\0';
l_pass[23] = '\0';
- ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
- if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
+ ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
+ if( runflag != CHARSERVER_ST_RUNNING ||
+ i == ARRAYLENGTH(server) ||
+ strcmp(l_user, userid) != 0 ||
+ strcmp(l_pass, passwd) != 0 )
+ {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 3;
@@ -3991,7 +4146,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
int i, c;
c = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
int fd;
if ((fd = server[i].fd) > 0) {
WFIFOHEAD(fd,len);
@@ -4009,7 +4164,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
int i, c;
c = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
int fd;
if ((fd = server[i].fd) > 0 && fd != sfd) {
WFIFOHEAD(fd,len);
@@ -4027,8 +4182,8 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
int i;
if (fd >= 0) {
- ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd );
- if( i < MAX_MAP_SERVERS )
+ ARR_FIND( 0, ARRAYLENGTH(server), i, fd == server[i].fd );
+ if( i < ARRAYLENGTH(server) )
{
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
@@ -4039,7 +4194,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
return 0;
}
-int broadcast_user_count(int tid, unsigned int tick, int id, intptr data)
+int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data)
{
uint8 buf[6];
int users = count_users();
@@ -4085,7 +4240,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap)
return 0;
}
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data)
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd])
{
@@ -4103,7 +4258,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data)
return 0;
}
-int check_connect_login_server(int tid, unsigned int tick, int id, intptr data)
+int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd] != NULL)
return 0;
@@ -4136,7 +4291,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr data)
}
// sends a ping packet to login server (will receive pong 0x2718)
-int ping_login_server(int tid, unsigned int tick, int id, intptr data)
+int ping_login_server(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd] != NULL)
{
@@ -4151,7 +4306,7 @@ int ping_login_server(int tid, unsigned int tick, int id, intptr data)
//Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't
//replies/disconnect the player we tried to kick. [Skotlex]
//------------------------------------------------
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data)
+static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data)
{
struct online_char_data* character;
if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
@@ -4175,7 +4330,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap)
return 0;
}
-static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data)
+static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data)
{
online_char_db->foreach(online_char_db, online_data_cleanup_sub);
return 0;
@@ -4431,12 +4586,16 @@ int char_config_read(const char *cfgName)
#ifndef TXT_SQL_CONVERT
void do_final(void)
{
- ShowStatus("Terminating server.\n");
+ ShowStatus("Terminating...\n");
mmo_char_sync();
inter_save();
set_all_offline(-1);
flush_fifos();
+
+ do_final_mapif();
+ do_final_loginif();
+
// write online players files with no player
online_char_db->clear(online_char_db, NULL);
create_online_files();
@@ -4445,11 +4604,12 @@ void do_final(void)
auth_db->destroy(auth_db, NULL);
if(char_dat) aFree(char_dat);
-
- if (login_fd > 0)
- do_close(login_fd);
- if (char_fd > 0)
+
+ if( char_fd != -1 )
+ {
do_close(char_fd);
+ char_fd = -1;
+ }
#ifdef ENABLE_SC_SAVING
status_final();
@@ -4458,6 +4618,7 @@ void do_final(void)
mapindex_final();
char_log("----End of char-server (normal end with closing of all files).\n");
+ ShowStatus("Finished.\n");
}
//------------------------------
@@ -4473,15 +4634,27 @@ void set_server_type(void)
SERVER_TYPE = ATHENA_SERVER_CHAR;
}
-int do_init(int argc, char **argv)
-{
- int i;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
- memset(&server[i], 0, sizeof(struct mmo_map_server));
- server[i].fd = -1;
+/// Called when a terminate signal is received.
+void do_shutdown(void)
+{
+ if( runflag != CHARSERVER_ST_SHUTDOWN )
+ {
+ int id;
+ runflag = CHARSERVER_ST_SHUTDOWN;
+ ShowStatus("Shutting down...\n");
+ // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
+ for( id = 0; id < ARRAYLENGTH(server); ++id )
+ mapif_server_reset(id);
+ loginif_check_shutdown();
+ flush_fifos();
+ runflag = CORE_ST_STOP;
}
+}
+
+int do_init(int argc, char **argv)
+{
//Read map indexes
mapindex_init();
start_point.map = mapindex_name2id("new_zone01");
@@ -4512,8 +4685,6 @@ int do_init(int argc, char **argv)
inter_init_txt((argc > 2) ? argv[2] : inter_cfgName); // inter server 初期化
ShowInfo("char server initialized.\n");
- set_defaultparse(parse_char);
-
if ((naddr_ != 0) && (!login_ip || !char_ip))
{
char ip_str[16];
@@ -4533,22 +4704,13 @@ int do_init(int argc, char **argv)
}
}
- // establish char-login connection if not present
- add_timer_func_list(check_connect_login_server, "check_connect_login_server");
- add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
-
- // keep the char-login connection alive
- add_timer_func_list(ping_login_server, "ping_login_server");
- add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
+ do_init_loginif();
+ do_init_mapif();
// periodically update the overall user count on all mapservers + login server
add_timer_func_list(broadcast_user_count, "broadcast_user_count");
add_timer_interval(gettick() + 1000, broadcast_user_count, 0, 0, 5 * 1000);
- // send a list of all online account IDs to login server
- add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
- add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
-
// ???
add_timer_func_list(chardb_waiting_disconnect, "chardb_waiting_disconnect");
@@ -4564,10 +4726,17 @@ int do_init(int argc, char **argv)
{
//##TODO invoke a CONSOLE_START plugin event
}
-
+
+ set_defaultparse(parse_char);
char_fd = make_listen_bind(bind_ip, char_port);
char_log("The char-server is ready (Server is listening on the port %d).\n", char_port);
ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port);
+
+ if( runflag != CORE_ST_STOP )
+ {
+ shutdown_callback = do_shutdown;
+ runflag = CHARSERVER_ST_RUNNING;
+ }
return 0;
}
diff --git a/src/char/char.h b/src/char/char.h
index 18bb7b1b5..bb1a530f0 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -4,8 +4,18 @@
#ifndef _CHAR_H_
#define _CHAR_H_
+#include "../common/core.h" // CORE_ST_LAST
#include "../common/mmo.h"
+#ifndef TXT_SQL_CONVERT
+enum E_CHARSERVER_ST
+{
+ CHARSERVER_ST_RUNNING = CORE_ST_LAST,
+ CHARSERVER_ST_SHUTDOWN,
+ CHARSERVER_ST_LAST
+};
+#endif
+
#define MAX_MAP_SERVERS 30
#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
diff --git a/src/char/int_homun.c b/src/char/int_homun.c
index d547b60f7..ec22499d0 100644
--- a/src/char/int_homun.c
+++ b/src/char/int_homun.c
@@ -36,7 +36,7 @@ int inter_homun_tostr(char *str,struct s_homunculus *p)
for (i = 0; i < MAX_HOMUNSKILL; i++)
{
- if (p->hskill[i].id && !p->hskill[i].flag)
+ if (p->hskill[i].id && p->hskill[i].flag == SKILL_FLAG_PERMANENT)
str+=sprintf(str,"%d,%d,", p->hskill[i].id, p->hskill[i].lv);
}
diff --git a/src/char_sql/CMakeLists.txt b/src/char_sql/CMakeLists.txt
new file mode 100644
index 000000000..f2d1cd0f0
--- /dev/null
+++ b/src/char_sql/CMakeLists.txt
@@ -0,0 +1,57 @@
+
+#
+# char sql
+#
+if( HAVE_common_sql )
+message( STATUS "Creating target char-server_sql" )
+set( SQL_CHAR_HEADERS
+ "${CMAKE_CURRENT_SOURCE_DIR}/char.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_mail.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_mercenary.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_party.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.h"
+ "${CMAKE_CURRENT_SOURCE_DIR}/inter.h"
+ )
+set( SQL_CHAR_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/char.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_guild.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_homun.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_mail.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_mercenary.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_party.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_pet.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/inter.c"
+ )
+set( DEPENDENCIES common_sql )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_CHAR_HEADERS} ${SQL_CHAR_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} )
+source_group( char FILES ${SQL_CHAR_HEADERS} ${SQL_CHAR_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( char-server_sql ${SOURCE_FILES} )
+add_dependencies( char-server_sql ${DEPENDENCIES} )
+target_link_libraries( char-server_sql ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( char-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_charserver_sql DESCRIPTION "char-server (sql version)" DISPLAY_NAME "char-server_sql" GROUP Runtime )
+ install( TARGETS char-server_sql
+ DESTINATION "."
+ COMPONENT Runtime_charserver_sql )
+endif()
+message( STATUS "Creating target char-server_sql - done" )
+set( HAVE_char-server_sql ON CACHE BOOL "char-server_sql target is available" )
+mark_as_advanced( HAVE_char-server_sql )
+else()
+message( STATUS "Skipping target char-server_sql (requires common_sql)" )
+unset( HAVE_char-server_sql CACHE )
+endif()
diff --git a/src/char_sql/Makefile.in b/src/char_sql/Makefile.in
index 82c0a7c3f..a8cf8e08c 100644
--- a/src/char_sql/Makefile.in
+++ b/src/char_sql/Makefile.in
@@ -3,12 +3,16 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a
../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \
../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \
../common/obj_all/strlib.o ../common/obj_all/grfio.o \
- ../common/obj_all/mapindex.o ../common/obj_all/ers.o
+ ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h \
../common/strlib.h ../common/grfio.h \
- ../common/mapindex.h ../common/ers.h
+ ../common/mapindex.h ../common/ers.h ../common/random.h
+
+MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
+MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
+MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_H = ../common/sql.h
@@ -19,7 +23,7 @@ CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homu
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- CHAR_SERVER_SQL_DEPENDS=obj_sql $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ)
+ CHAR_SERVER_SQL_DEPENDS=obj_sql $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ)
else
CHAR_SERVER_SQL_DEPENDS=needs_mysql
endif
@@ -32,7 +36,7 @@ endif
all: char-server_sql
char-server_sql: $(CHAR_SERVER_SQL_DEPENDS)
- @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @MYSQL_LIBS@
+ @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@
clean:
rm -rf *.o obj_sql ../../char-server_sql@EXEEXT@
@@ -53,12 +57,15 @@ needs_mysql:
obj_sql:
-mkdir obj_sql
-obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H)
- @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-# missing common object files
+# missing object files
../common/obj_all/%.o:
@$(MAKE) -C ../common sql
../common/obj_sql/%.o:
@$(MAKE) -C ../common sql
+
+MT19937AR_OBJ:
+ @$(MAKE) -C ../../3rdparty/mt19937ar
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index 5ad5a273b..b1c171ebf 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -194,7 +194,7 @@ struct online_char_data {
};
static DBMap* online_char_db; // int account_id -> struct online_char_data*
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data);
+static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
static void* create_online_char_data(DBKey key, va_list args)
{
@@ -590,11 +590,11 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//insert here.
for( i = 0, count = 0; i < MAX_SKILL; ++i )
{
- if(p->skill[i].id && p->skill[i].flag!=1)
+ if(p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY)
{
if( count )
StringBuf_AppendStr(&buf, ",");
- StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == 0 ? p->skill[i].lv : p->skill[i].flag - 2));
+ StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0));
++count;
}
}
@@ -1107,7 +1107,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_skill.lv, 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
- tmp_skill.flag = 0;
+ tmp_skill.flag = SKILL_FLAG_PERMANENT;
for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
{
@@ -1543,7 +1543,7 @@ int count_users(void)
int i, users;
users = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
if (server[i].fd > 0) {
users += server[i].users;
}
@@ -1778,24 +1778,75 @@ static void char_auth_ok(int fd, struct char_session_data *sd)
// continues when account data is received...
}
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data);
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
+void mapif_server_reset(int id);
-int parse_fromlogin(int fd)
+
+/// Resets all the data.
+void loginif_reset(void)
+{
+ int id;
+ // TODO kick everyone out and reset everything or wait for connect and try to reaquire locks [FlavioJS]
+ for( id = 0; id < ARRAYLENGTH(server); ++id )
+ mapif_server_reset(id);
+ flush_fifos();
+ exit(EXIT_FAILURE);
+}
+
+
+/// Checks the conditions for the server to stop.
+/// Releases the cookie when all characters are saved.
+/// If all the conditions are met, it stops the core loop.
+void loginif_check_shutdown(void)
+{
+ if( runflag != CHARSERVER_ST_SHUTDOWN )
+ return;
+ runflag = CORE_ST_STOP;
+}
+
+
+/// Called when the connection to Login Server is disconnected.
+void loginif_on_disconnect(void)
+{
+ ShowWarning("Connection to Login Server lost.\n\n");
+}
+
+
+/// Called when all the connection steps are completed.
+void loginif_on_ready(void)
{
int i;
- struct char_session_data *sd;
- // only login-server can have an access to here.
- // so, if it isn't the login-server, we disconnect the session.
+ loginif_check_shutdown();
+
+ //Send online accounts to login server.
+ send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
+
+ // if no map-server already connected, display a message...
+ ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] );
+ if( i == ARRAYLENGTH(server) )
+ ShowStatus("Awaiting maps from map-server.\n");
+}
+
+
+int parse_fromlogin(int fd)
+{
+ struct char_session_data* sd = NULL;
+ int i;
+
+ // only process data from the login-server
if( fd != login_fd )
- set_eof(fd);
+ {
+ ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
+ do_close(fd);
+ return 0;
+ }
- if(session[fd]->flag.eof) {
- if (fd == login_fd) {
- ShowWarning("Connection to login-server lost (connection #%d).\n", fd);
- login_fd = -1;
- }
+ if( session[fd]->flag.eof )
+ {
do_close(fd);
+ login_fd = -1;
+ loginif_on_disconnect();
return 0;
}
@@ -1819,16 +1870,11 @@ int parse_fromlogin(int fd)
ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
+ set_eof(fd);
+ return 0;
} else {
ShowStatus("Connected to login-server (connection #%d).\n", fd);
-
- //Send online accounts to login server.
- send_accounts_tologin(INVALID_TIMER, gettick(), 0, 0);
-
- // if no map-server already connected, display a message...
- ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] );
- if( i == MAX_MAP_SERVERS )
- ShowStatus("Awaiting maps from map-server.\n");
+ loginif_on_ready();
}
RFIFOSKIP(fd,3);
break;
@@ -2096,6 +2142,34 @@ int parse_fromlogin(int fd)
return 0;
}
+int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data);
+int ping_login_server(int tid, unsigned int tick, int id, intptr_t data);
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data);
+
+void do_init_loginif(void)
+{
+ // establish char-login connection if not present
+ add_timer_func_list(check_connect_login_server, "check_connect_login_server");
+ add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
+
+ // keep the char-login connection alive
+ add_timer_func_list(ping_login_server, "ping_login_server");
+ add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
+
+ // send a list of all online account IDs to login server
+ add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
+ add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
+}
+
+void do_final_loginif(void)
+{
+ if( login_fd != -1 )
+ {
+ do_close(login_fd);
+ login_fd = -1;
+ }
+}
+
int request_accreg2(int account_id, int char_id)
{
if (login_fd > 0) {
@@ -2252,39 +2326,79 @@ int char_loadName(int char_id, char* name)
int search_mapserver(unsigned short map, uint32 ip, uint16 port);
+
+/// Initializes a server structure.
+void mapif_server_init(int id)
+{
+ memset(&server[id], 0, sizeof(server[id]));
+ server[id].fd = -1;
+}
+
+
+/// Destroys a server structure.
+void mapif_server_destroy(int id)
+{
+ if( server[id].fd == -1 )
+ {
+ do_close(server[id].fd);
+ server[id].fd = -1;
+ }
+}
+
+
+/// Resets all the data related to a server.
+void mapif_server_reset(int id)
+{
+ int i,j;
+ unsigned char buf[16384];
+ int fd = server[id].fd;
+ //Notify other map servers that this one is gone. [Skotlex]
+ WBUFW(buf,0) = 0x2b20;
+ WBUFL(buf,4) = htonl(server[id].ip);
+ WBUFW(buf,8) = htons(server[id].port);
+ j = 0;
+ for(i = 0; i < MAX_MAP_PER_SERVER; i++)
+ if (server[id].map[i])
+ WBUFW(buf,10+(j++)*4) = server[id].map[i];
+ if (j > 0) {
+ WBUFW(buf,2) = j * 4 + 10;
+ mapif_sendallwos(fd, buf, WBUFW(buf,2));
+ }
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) )
+ Sql_ShowDebug(sql_handle);
+ online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
+ mapif_server_destroy(id);
+ mapif_server_init(id);
+}
+
+
+/// Called when the connection to a Map Server is disconnected.
+void mapif_on_disconnect(int id)
+{
+ ShowStatus("Map-server #%d has disconnected.\n", id);
+ mapif_server_reset(id);
+}
+
+
int parse_frommap(int fd)
{
int i, j;
int id;
- ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
- if(id == MAX_MAP_SERVERS)
- set_eof(fd);
- if(session[fd]->flag.eof) {
- if (id < MAX_MAP_SERVERS) {
- unsigned char buf[16384];
- ShowStatus("Map-server %d (session #%d) has disconnected.\n", id, fd);
- //Notify other map servers that this one is gone. [Skotlex]
- WBUFW(buf,0) = 0x2b20;
- WBUFL(buf,4) = htonl(server[id].ip);
- WBUFW(buf,8) = htons(server[id].port);
- j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
- if (server[id].map[i])
- WBUFW(buf,10+(j++)*4) = server[id].map[i];
- if (j > 0) {
- WBUFW(buf,2) = j * 4 + 10;
- mapif_sendallwos(fd, buf, WBUFW(buf,2));
- }
- memset(&server[id], 0, sizeof(struct mmo_map_server));
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) )
- Sql_ShowDebug(sql_handle);
- server[id].fd = -1;
- online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
- }
+ ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
+ if( id == ARRAYLENGTH(server) )
+ {// not a map server
+ ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd);
do_close(fd);
return 0;
}
+ if( session[fd]->flag.eof )
+ {
+ do_close(fd);
+ server[id].fd = -1;
+ mapif_on_disconnect(id);
+ return 0;
+ }
while(RFIFOREST(fd) >= 2)
{
@@ -2330,14 +2444,14 @@ int parse_frommap(int fd)
mapif_sendallwos(fd, buf, WBUFW(buf,2));
}
// Transmitting the maps of the other map-servers to the new map-server
- for(x = 0; x < MAX_MAP_SERVERS; x++) {
+ for(x = 0; x < ARRAYLENGTH(server); x++) {
if (server[x].fd > 0 && x != id) {
- WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
+ WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server));
WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = htonl(server[x].ip);
WFIFOW(fd,8) = htons(server[x].port);
j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
+ for(i = 0; i < ARRAYLENGTH(server); i++)
if (server[x].map[i])
WFIFOW(fd,10+(j++)*4) = server[x].map[i];
if (j > 0) {
@@ -2491,27 +2605,38 @@ int parse_frommap(int fd)
uint32 login_id2 = RFIFOL(fd,10);
uint32 ip = RFIFOL(fd,14);
RFIFOSKIP(fd,18);
-
- // create temporary auth entry
- CREATE(node, struct auth_node, 1);
- node->account_id = account_id;
- node->char_id = 0;
- node->login_id1 = login_id1;
- node->login_id2 = login_id2;
- //node->sex = 0;
- node->ip = ntohl(ip);
- //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
- //node->gmlevel = 0;
- idb_put(auth_db, account_id, node);
-
- //Set char to "@ char select" in online db [Kevin]
- set_char_charselect(account_id);
-
- WFIFOHEAD(fd,7);
- WFIFOW(fd,0) = 0x2b03;
- WFIFOL(fd,2) = account_id;
- WFIFOB(fd,6) = 0;
- WFIFOSET(fd,7);
+
+ if( runflag != CHARSERVER_ST_RUNNING )
+ {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x2b03;
+ WFIFOL(fd,2) = account_id;
+ WFIFOB(fd,6) = 0;// not ok
+ WFIFOSET(fd,7);
+ }
+ else
+ {
+ // create temporary auth entry
+ CREATE(node, struct auth_node, 1);
+ node->account_id = account_id;
+ node->char_id = 0;
+ node->login_id1 = login_id1;
+ node->login_id2 = login_id2;
+ //node->sex = 0;
+ node->ip = ntohl(ip);
+ //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
+ //node->gmlevel = 0;
+ idb_put(auth_db, account_id, node);
+
+ //Set char to "@ char select" in online db [Kevin]
+ set_char_charselect(account_id);
+
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x2b03;
+ WFIFOL(fd,2) = account_id;
+ WFIFOB(fd,6) = 1;// ok
+ WFIFOSET(fd,7);
+ }
}
break;
@@ -2534,8 +2659,10 @@ int parse_frommap(int fd)
mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
}
-
- if (map_fd >= 0 && session[map_fd] && char_data)
+
+ if( runflag == CHARSERVER_ST_RUNNING &&
+ session_isActive(map_fd) &&
+ char_data )
{ //Send the map server the auth of this player.
struct auth_node* node;
@@ -2879,7 +3006,9 @@ int parse_frommap(int fd)
mmo_char_fromsql(char_id, &char_dat, true);
cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id);
}
- if( node != NULL && cd != NULL &&
+ if( runflag == CHARSERVER_ST_RUNNING &&
+ cd != NULL &&
+ node != NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
node->login_id1 == login_id1 &&
@@ -2942,13 +3071,27 @@ int parse_frommap(int fd)
return 0;
}
+void do_init_mapif(void)
+{
+ int i;
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ mapif_server_init(i);
+}
+
+void do_final_mapif(void)
+{
+ int i;
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ mapif_server_destroy(i);
+}
+
// Searches for the mapserver that has a given map (and optionally ip/port, if not -1).
// If found, returns the server's index in the 'server' array (otherwise returns -1).
int search_mapserver(unsigned short map, uint32 ip, uint16 port)
{
int i, j;
- for(i = 0; i < MAX_MAP_SERVERS; i++)
+ for(i = 0; i < ARRAYLENGTH(server); i++)
{
if (server[i].fd > 0
&& (ip == (uint32)-1 || server[i].ip == ip)
@@ -3276,6 +3419,15 @@ int parse_char(int fd)
WFIFOL(fd,0) = account_id;
WFIFOSET(fd,4);
+ if( runflag != CHARSERVER_ST_RUNNING )
+ {
+ WFIFOHEAD(fd,3);
+ WFIFOW(fd,0) = 0x6c;
+ WFIFOB(fd,2) = 0;// rejected from server
+ WFIFOSET(fd,3);
+ break;
+ }
+
// search authentification
node = (struct auth_node*)idb_get(auth_db, account_id);
if( node != NULL &&
@@ -3361,8 +3513,8 @@ int parse_char(int fd)
if (i < 0) {
unsigned short j;
//First check that there's actually a map server online.
- ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] );
- if (j == MAX_MAP_SERVERS) {
+ ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] );
+ if (j == ARRAYLENGTH(server)) {
ShowInfo("Connection Closed. No map servers available.\n");
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81;
@@ -3665,8 +3817,12 @@ int parse_char(int fd)
char* l_pass = (char*)RFIFOP(fd,26);
l_user[23] = '\0';
l_pass[23] = '\0';
- ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
- if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
+ ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
+ if( runflag != CHARSERVER_ST_RUNNING ||
+ i == ARRAYLENGTH(server) ||
+ strcmp(l_user, userid) != 0 ||
+ strcmp(l_pass, passwd) != 0 )
+ {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 3;
@@ -3729,7 +3885,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
int i, c;
c = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
int fd;
if ((fd = server[i].fd) > 0) {
WFIFOHEAD(fd,len);
@@ -3747,7 +3903,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
int i, c;
c = 0;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
+ for(i = 0; i < ARRAYLENGTH(server); i++) {
int fd;
if ((fd = server[i].fd) > 0 && fd != sfd) {
WFIFOHEAD(fd,len);
@@ -3765,8 +3921,8 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
int i;
if (fd >= 0) {
- ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd );
- if( i < MAX_MAP_SERVERS )
+ ARR_FIND( 0, ARRAYLENGTH(server), i, fd == server[i].fd );
+ if( i < ARRAYLENGTH(server) )
{
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
@@ -3777,7 +3933,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
return 0;
}
-int broadcast_user_count(int tid, unsigned int tick, int id, intptr data)
+int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data)
{
uint8 buf[6];
int users = count_users();
@@ -3820,7 +3976,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap)
return 0;
}
-int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data)
+int send_accounts_tologin(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd])
{
@@ -3838,7 +3994,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, intptr data)
return 0;
}
-int check_connect_login_server(int tid, unsigned int tick, int id, intptr data)
+int check_connect_login_server(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd] != NULL)
return 0;
@@ -3871,7 +4027,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, intptr data)
}
// sends a ping packet to login server (will receive pong 0x2718)
-int ping_login_server(int tid, unsigned int tick, int id, intptr data)
+int ping_login_server(int tid, unsigned int tick, int id, intptr_t data)
{
if (login_fd > 0 && session[login_fd] != NULL)
{
@@ -3886,7 +4042,7 @@ int ping_login_server(int tid, unsigned int tick, int id, intptr data)
//Invoked 15 seconds after mapif_disconnectplayer in case the map server doesn't
//replies/disconnect the player we tried to kick. [Skotlex]
//------------------------------------------------
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr data)
+static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data)
{
struct online_char_data* character;
if ((character = (struct online_char_data*)idb_get(online_char_db, id)) != NULL && character->waiting_disconnect == tid)
@@ -3910,7 +4066,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap)
return 0;
}
-static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data)
+static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data)
{
online_char_db->foreach(online_char_db, online_data_cleanup_sub);
return 0;
@@ -4211,7 +4367,7 @@ int char_config_read(const char* cfgName)
void do_final(void)
{
- ShowStatus("Terminating server.\n");
+ ShowStatus("Terminating...\n");
set_all_offline(-1);
set_all_offline_sql();
@@ -4219,6 +4375,9 @@ void do_final(void)
inter_final();
flush_fifos();
+
+ do_final_mapif();
+ do_final_loginif();
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo`") )
Sql_ShowDebug(sql_handle);
@@ -4227,13 +4386,16 @@ void do_final(void)
online_char_db->destroy(online_char_db, NULL);
auth_db->destroy(auth_db, NULL);
- if (login_fd > 0)
- do_close(login_fd);
- if (char_fd > 0)
+ if( char_fd != -1 )
+ {
do_close(char_fd);
+ char_fd = -1;
+ }
Sql_Free(sql_handle);
mapindex_final();
+
+ ShowStatus("Finished.\n");
}
//------------------------------
@@ -4249,15 +4411,27 @@ void set_server_type(void)
SERVER_TYPE = ATHENA_SERVER_CHAR;
}
-int do_init(int argc, char **argv)
-{
- int i;
- for(i = 0; i < MAX_MAP_SERVERS; i++) {
- memset(&server[i], 0, sizeof(struct mmo_map_server));
- server[i].fd = -1;
+/// Called when a terminate signal is received.
+void do_shutdown(void)
+{
+ if( runflag != CHARSERVER_ST_SHUTDOWN )
+ {
+ int id;
+ runflag = CHARSERVER_ST_SHUTDOWN;
+ ShowStatus("Shutting down...\n");
+ // TODO proper shutdown procedure; wait for acks?, kick all characters, ... [FlavoJS]
+ for( id = 0; id < ARRAYLENGTH(server); ++id )
+ mapif_server_reset(id);
+ loginif_check_shutdown();
+ flush_fifos();
+ runflag = CORE_ST_STOP;
}
+}
+
+int do_init(int argc, char **argv)
+{
//Read map indexes
mapindex_init();
start_point.map = mapindex_name2id("new_zone01");
@@ -4284,8 +4458,6 @@ int do_init(int argc, char **argv)
char_read_fame_list(); //Read fame lists.
ShowInfo("char server initialized.\n");
- set_defaultparse(parse_char);
-
if ((naddr_ != 0) && (!login_ip || !char_ip))
{
char ip_str[16];
@@ -4305,22 +4477,13 @@ int do_init(int argc, char **argv)
}
}
- // establish char-login connection if not present
- add_timer_func_list(check_connect_login_server, "check_connect_login_server");
- add_timer_interval(gettick() + 1000, check_connect_login_server, 0, 0, 10 * 1000);
-
- // keep the char-login connection alive
- add_timer_func_list(ping_login_server, "ping_login_server");
- add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
+ do_init_loginif();
+ do_init_mapif();
// periodically update the overall user count on all mapservers + login server
add_timer_func_list(broadcast_user_count, "broadcast_user_count");
add_timer_interval(gettick() + 1000, broadcast_user_count, 0, 0, 5 * 1000);
- // send a list of all online account IDs to login server
- add_timer_func_list(send_accounts_tologin, "send_accounts_tologin");
- add_timer_interval(gettick() + 1000, send_accounts_tologin, 0, 0, 3600 * 1000); //Sync online accounts every hour
-
// ???
add_timer_func_list(chardb_waiting_disconnect, "chardb_waiting_disconnect");
@@ -4351,9 +4514,16 @@ int do_init(int argc, char **argv)
ShowInfo("End of char server initilization function.\n");
+ set_defaultparse(parse_char);
ShowInfo("open port %d.....\n",char_port);
char_fd = make_listen_bind(bind_ip, char_port);
ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port);
+
+ if( runflag != CORE_ST_STOP )
+ {
+ shutdown_callback = do_shutdown;
+ runflag = CHARSERVER_ST_RUNNING;
+ }
return 0;
}
diff --git a/src/char_sql/char.h b/src/char_sql/char.h
index a40340cfb..c9ec54a16 100644
--- a/src/char_sql/char.h
+++ b/src/char_sql/char.h
@@ -4,6 +4,17 @@
#ifndef _CHAR_SQL_H_
#define _CHAR_SQL_H_
+#include "../common/core.h" // CORE_ST_LAST
+
+#ifndef TXT_SQL_CONVERT
+enum E_CHARSERVER_ST
+{
+ CHARSERVER_ST_RUNNING = CORE_ST_LAST,
+ CHARSERVER_ST_SHUTDOWN,
+ CHARSERVER_ST_LAST
+};
+#endif
+
struct mmo_charstatus;
#define MAX_MAP_SERVERS 30
diff --git a/src/char_sql/int_auction.c b/src/char_sql/int_auction.c
index bba693256..04e321062 100644
--- a/src/char_sql/int_auction.c
+++ b/src/char_sql/int_auction.c
@@ -21,7 +21,7 @@
static DBMap* auction_db_ = NULL; // int auction_id -> struct auction_data*
void auction_delete(struct auction_data *auction);
-static int auction_end_timer(int tid, unsigned int tick, int id, intptr data);
+static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data);
static int auction_count(int char_id, bool buy)
{
@@ -136,7 +136,7 @@ static void mapif_Auction_message(int char_id, unsigned char result)
mapif_sendall(buf,7);
}
-static int auction_end_timer(int tid, unsigned int tick, int id, intptr data)
+static int auction_end_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct auction_data *auction;
if( (auction = (struct auction_data *)idb_get(auction_db_, id)) != NULL )
diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c
index 0b3d77f07..9b5692689 100644
--- a/src/char_sql/int_guild.c
+++ b/src/char_sql/int_guild.c
@@ -47,7 +47,7 @@ int mapif_guild_info(int fd,struct guild *g);
int guild_break_sub(int key,void *data,va_list ap);
int inter_guild_tosql(struct guild *g,int flag);
-static int guild_save_timer(int tid, unsigned int tick, int id, intptr data)
+static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data)
{
static int last_id = 0; //To know in which guild we were.
int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving.
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
new file mode 100644
index 000000000..21feb53f9
--- /dev/null
+++ b/src/common/CMakeLists.txt
@@ -0,0 +1,144 @@
+
+#
+# Create svnversion.h
+#
+message( STATUS "Creating svnversion.h" )
+if( SVNVERSION )
+ file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h
+ "#ifndef SVNVERSION\n#define SVNVERSION ${SVNVERSION}\n#endif\n" )
+else()
+ file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h "" )
+endif()
+set( GLOBAL_INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "" )
+set( SVNVERSION ${SVNVERSION}
+ CACHE STRING "SVN version of the source code" )
+if( WITH_COMPONENT_DEVELOPMENT )
+ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h
+ DESTINATION "src/common"
+ COMPONENT Development_base )
+endif()
+message( STATUS "Creating svnversion.h - done" )
+
+
+#####################################################################
+# setup
+#
+set( COMMON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
+ CACHE PATH "common source directory" )
+mark_as_advanced( COMMON_SOURCE_DIR )
+
+set( COMMON_ALL_HEADERS
+ "${CMAKE_CURRENT_BINARY_DIR}/svnversion.h"
+ "${COMMON_SOURCE_DIR}/cbasetypes.h"
+ "${COMMON_SOURCE_DIR}/mmo.h"
+ "${COMMON_SOURCE_DIR}/plugin.h"
+ "${COMMON_SOURCE_DIR}/version.h"
+ )
+
+set( COMMON_MINI_HEADERS
+ ${COMMON_ALL_HEADERS}
+ "${COMMON_SOURCE_DIR}/core.h"
+ "${COMMON_SOURCE_DIR}/malloc.h"
+ "${COMMON_SOURCE_DIR}/showmsg.h"
+ "${COMMON_SOURCE_DIR}/strlib.h"
+ CACHE INTERNAL "" )
+set( COMMON_MINI_SOURCES
+ "${COMMON_SOURCE_DIR}/core.c"
+ "${COMMON_SOURCE_DIR}/malloc.c"
+ "${COMMON_SOURCE_DIR}/showmsg.c"
+ "${COMMON_SOURCE_DIR}/strlib.c"
+ CACHE INTERNAL "" )
+set( COMMON_MINI_DEFINITIONS MINICORE CACHE INTERNAL "" )
+
+
+#
+# common_base
+#
+if( WITH_ZLIB )
+message( STATUS "Creating target common_base" )
+set( COMMON_BASE_HEADERS
+ ${COMMON_ALL_HEADERS}
+ "${COMMON_SOURCE_DIR}/core.h"
+ "${COMMON_SOURCE_DIR}/db.h"
+ "${COMMON_SOURCE_DIR}/ers.h"
+ "${COMMON_SOURCE_DIR}/grfio.h"
+ "${COMMON_SOURCE_DIR}/lock.h"
+ "${COMMON_SOURCE_DIR}/malloc.h"
+ "${COMMON_SOURCE_DIR}/mapindex.h"
+ "${COMMON_SOURCE_DIR}/md5calc.h"
+ "${COMMON_SOURCE_DIR}/nullpo.h"
+ "${COMMON_SOURCE_DIR}/plugins.h"
+ "${COMMON_SOURCE_DIR}/random.h"
+ "${COMMON_SOURCE_DIR}/showmsg.h"
+ "${COMMON_SOURCE_DIR}/socket.h"
+ "${COMMON_SOURCE_DIR}/strlib.h"
+ "${COMMON_SOURCE_DIR}/timer.h"
+ "${COMMON_SOURCE_DIR}/utils.h"
+ CACHE INTERNAL "common_base headers" )
+set( COMMON_BASE_SOURCES
+ "${COMMON_SOURCE_DIR}/core.c"
+ "${COMMON_SOURCE_DIR}/db.c"
+ "${COMMON_SOURCE_DIR}/ers.c"
+ "${COMMON_SOURCE_DIR}/grfio.c"
+ "${COMMON_SOURCE_DIR}/lock.c"
+ "${COMMON_SOURCE_DIR}/malloc.c"
+ "${COMMON_SOURCE_DIR}/mapindex.c"
+ "${COMMON_SOURCE_DIR}/md5calc.c"
+ "${COMMON_SOURCE_DIR}/nullpo.c"
+ "${COMMON_SOURCE_DIR}/plugins.c"
+ "${COMMON_SOURCE_DIR}/random.c"
+ "${COMMON_SOURCE_DIR}/showmsg.c"
+ "${COMMON_SOURCE_DIR}/socket.c"
+ "${COMMON_SOURCE_DIR}/strlib.c"
+ "${COMMON_SOURCE_DIR}/timer.c"
+ "${COMMON_SOURCE_DIR}/utils.c"
+ CACHE INTERNAL "common_base sources" )
+set( LIBRARIES ${ZLIB_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MT19937AR_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
+set( SOURCE_FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} )
+source_group( mt19937ar FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} )
+add_library( common_base ${SOURCE_FILES} )
+target_link_libraries( common_base ${LIBRARIES} )
+set_target_properties( common_base PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+include_directories( ${INCLUDE_DIRS} )
+message( STATUS "Creating target common_base - done" )
+set( HAVE_common_base ON CACHE BOOL "common_base target is available" )
+mark_as_advanced( HAVE_common_base )
+else()
+message( STATUS "Skipping target common_base (requires ZLIB)" )
+unset( HAVE_common_base CACHE )
+endif()
+
+
+#
+# common_sql
+#
+if( HAVE_common_base AND WITH_MYSQL )
+message( STATUS "Creating target common_sql" )
+set( COMMON_SQL_HEADERS
+ ${COMMON_ALL_HEADERS}
+ "${CMAKE_CURRENT_SOURCE_DIR}/sql.h"
+ CACHE INTERNAL "common_sql headers" )
+set( COMMON_SQL_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/sql.c"
+ CACHE INTERNAL "common_sql sources" )
+set( DEPENDENCIES common_base )
+set( LIBRARIES ${MYSQL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MYSQL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
+set( SOURCE_FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} )
+source_group( common FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} )
+add_library( common_sql ${SOURCE_FILES} )
+add_dependencies( common_sql ${DEPENDENCIES} )
+target_link_libraries( common_sql ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( common_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+include_directories( ${INCLUDE_DIRS} )
+message( STATUS "Creating target common_sql - done" )
+set( HAVE_common_sql ON CACHE BOOL "common_sql target is available" )
+mark_as_advanced( HAVE_common_sql )
+else()
+message( STATUS "Skipping target common_sql (requires common_base and MYSQL)" )
+unset( HAVE_common_sql CACHE )
+endif()
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index bda9e1911..37606dde2 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -2,15 +2,19 @@
COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.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/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o
COMMON_H = svnversion.h mmo.h plugin.h version.h \
core.h socket.h timer.h db.h plugins.h lock.h \
nullpo.h malloc.h showmsg.h strlib.h utils.h \
- grfio.h mapindex.h ers.h md5calc.h
+ grfio.h mapindex.h ers.h md5calc.h random.h
COMMON_SQL_OBJ = obj_sql/sql.o
COMMON_SQL_H = sql.h
+MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
+MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
+MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
+
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
ALL_DEPENDS=txt sql
@@ -19,6 +23,7 @@ else
ALL_TARGET=txt
SQL_DEPENDS=needs_mysql
endif
+TXT_DEPENDS=common
@SET_MAKE@
@@ -27,7 +32,7 @@ endif
all: $(ALL_DEPENDS)
-txt: common
+txt: $(TXT_DEPENDS)
sql: $(SQL_DEPENDS)
@@ -54,16 +59,16 @@ obj_all:
obj_sql:
-mkdir obj_sql
-common: obj_all $(COMMON_OBJ)
+common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ)
common_sql: obj_sql $(COMMON_SQL_OBJ)
-obj_all/%.o: %.c $(COMMON_H)
- @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_all/mini%.o: %.c $(COMMON_H)
- @CC@ @CFLAGS@ -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_all/mini%.o: %.c $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H)
@CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
@@ -80,3 +85,7 @@ else
svnversion.h:
@printf "\n" > svnversion.h
endif
+
+# missing object files
+MT19937AR_OBJ:
+ @$(MAKE) -C ../../3rdparty/mt19937ar
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index aee54a4bc..e2fe17555 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -78,14 +78,9 @@
// NOTE: Visual C++ uses <inttypes.h> and <stdint.h> provided in /3rdparty
//////////////////////////////////////////////////////////////////////////
#include <inttypes.h>
-
-//////////////////////////////////////////////////////////////////////////
-// typedefs to compensate type size change from 32bit to 64bit
-// MS implements LLP64 model, normal unix does LP64,
-// only Silicon Graphics/Cray goes ILP64 so don't care (and don't support)
-//////////////////////////////////////////////////////////////////////////
-
+#include <stdint.h>
#include <limits.h>
+
// ILP64 isn't supported, so always 32 bits?
#ifndef UINT_MAX
#define UINT_MAX 0xffffffff
@@ -95,49 +90,56 @@
// Integers with guaranteed _exact_ size.
//////////////////////////////////////////////////////////////////////////
-#define SIZEOF_LONG 4
-#define SIZEOF_INT 4
-#define HAVE_INT_8_16_32
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
-typedef char int8;
-typedef short int16;
-typedef int int32;
+typedef int8_t sint8;
+typedef int16_t sint16;
+typedef int32_t sint32;
+typedef int64_t sint64;
-typedef signed char sint8;
-typedef signed short sint16;
-typedef signed int sint32;
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
#undef UINT8_MIN
#undef UINT16_MIN
#undef UINT32_MIN
-#define UINT8_MIN ((uint8) 0)
-#define UINT16_MIN ((uint16)0)
-#define UINT32_MIN ((uint32)0)
+#undef UINT64_MIN
+#define UINT8_MIN ((uint8) UINT8_C(0x00))
+#define UINT16_MIN ((uint16)UINT16_C(0x0000))
+#define UINT32_MIN ((uint32)UINT32_C(0x00000000))
+#define UINT64_MIN ((uint64)UINT64_C(0x0000000000000000))
#undef UINT8_MAX
#undef UINT16_MAX
#undef UINT32_MAX
-#define UINT8_MAX ((uint8) 0xFF)
-#define UINT16_MAX ((uint16)0xFFFF)
-#define UINT32_MAX ((uint32)0xFFFFFFFF)
+#undef UINT64_MAX
+#define UINT8_MAX ((uint8) UINT8_C(0xFF))
+#define UINT16_MAX ((uint16)UINT16_C(0xFFFF))
+#define UINT32_MAX ((uint32)UINT32_C(0xFFFFFFFF))
+#define UINT64_MAX ((uint64)UINT64_C(0xFFFFFFFFFFFFFFFF))
#undef SINT8_MIN
#undef SINT16_MIN
#undef SINT32_MIN
-#define SINT8_MIN ((sint8) 0x80)
-#define SINT16_MIN ((sint16)0x8000)
-#define SINT32_MIN ((sint32)0x80000000)
+#undef SINT64_MIN
+#define SINT8_MIN ((sint8) INT8_C(0x80))
+#define SINT16_MIN ((sint16)INT16_C(0x8000))
+#define SINT32_MIN ((sint32)INT32_C(0x80000000))
+#define SINT64_MIN ((sint32)INT64_C(0x8000000000000000))
#undef SINT8_MAX
#undef SINT16_MAX
#undef SINT32_MAX
-#define SINT8_MAX ((sint8) 0x7F)
-#define SINT16_MAX ((sint16)0x7FFF)
-#define SINT32_MAX ((sint32)0x7FFFFFFF)
+#undef SINT64_MAX
+#define SINT8_MAX ((sint8) INT8_C(0x7F))
+#define SINT16_MAX ((sint16)INT16_C(0x7FFF))
+#define SINT32_MAX ((sint32)INT32_C(0x7FFFFFFF))
+#define SINT64_MAX ((sint64)INT64_C(0x7FFFFFFFFFFFFFFF))
//////////////////////////////////////////////////////////////////////////
// Integers with guaranteed _minimum_ size.
@@ -173,51 +175,10 @@ typedef int ssize_t;
//////////////////////////////////////////////////////////////////////////
-// portable 64-bit integers
-//////////////////////////////////////////////////////////////////////////
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef __int64 int64;
-typedef signed __int64 sint64;
-typedef unsigned __int64 uint64;
-#else
-typedef long long int64;
-typedef signed long long sint64;
-typedef unsigned long long uint64;
-#endif
-
-#ifndef INT64_MIN
-#define INT64_MIN (INT64_C(-9223372036854775807)-1)
-#endif
-#ifndef INT64_MAX
-#define INT64_MAX (INT64_C(9223372036854775807))
-#endif
-#ifndef UINT64_MAX
-#define UINT64_MAX (UINT64_C(18446744073709551615))
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////
// pointer sized integers
//////////////////////////////////////////////////////////////////////////
-#undef UINTPTR_MIN
-#undef UINTPTR_MAX
-#undef INTPTR_MIN
-#undef INTPTR_MAX
-#ifdef __64BIT__
-typedef uint64 uintptr;
-typedef int64 intptr;
-#define UINTPTR_MIN UINT64_MIN
-#define UINTPTR_MAX UINT64_MAX
-#define INTPTR_MIN INT64_MIN
-#define INTPTR_MAX INT64_MAX
-#else
-typedef uint32 uintptr;
-typedef int32 intptr;
-#define UINTPTR_MIN UINT32_MIN
-#define UINTPTR_MAX UINT32_MAX
-#define INTPTR_MIN INT32_MIN
-#define INTPTR_MAX INT32_MAX
-#endif
+typedef intptr_t intptr;
+typedef uintptr_t uintptr;
//////////////////////////////////////////////////////////////////////////
diff --git a/src/common/core.c b/src/common/core.c
index b89cc3841..bfa563d8c 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -24,7 +24,12 @@
#include <unistd.h>
#endif
-int runflag = 1;
+
+/// Called when a terminate signal is received.
+void (*shutdown_callback)(void) = NULL;
+
+
+int runflag = CORE_ST_RUN;
int arg_c = 0;
char **arg_v = NULL;
@@ -78,7 +83,10 @@ static void sig_proc(int sn)
case SIGTERM:
if (++is_called > 3)
exit(EXIT_SUCCESS);
- runflag = 0;
+ if( shutdown_callback != NULL )
+ shutdown_callback();
+ else
+ runflag = CORE_ST_STOP;// auto-shutdown
break;
case SIGSEGV:
case SIGFPE:
@@ -249,7 +257,7 @@ int main (int argc, char **argv)
{// Main runtime cycle
int next;
- while (runflag) {
+ while (runflag != CORE_ST_STOP) {
next = do_timer(gettick_nocache());
do_sockets(next);
}
diff --git a/src/common/core.h b/src/common/core.h
index fc4af3e3e..beb72d080 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -7,6 +7,7 @@
extern int arg_c;
extern char **arg_v;
+/// @see E_CORE_ST
extern int runflag;
extern char *SERVER_NAME;
extern char SERVER_TYPE;
@@ -18,4 +19,16 @@ extern void set_server_type(void);
extern void do_abort(void);
extern void do_final(void);
+/// The main loop continues until runflag is CORE_ST_STOP
+enum E_CORE_ST
+{
+ CORE_ST_STOP = 0,
+ CORE_ST_RUN,
+ CORE_ST_LAST
+};
+
+/// Called when a terminate signal is received. (Ctrl+C pressed)
+/// If NULL, runflag is set to CORE_ST_STOP instead.
+extern void (*shutdown_callback)(void);
+
#endif /* _CORE_H_ */
diff --git a/src/common/db.c b/src/common/db.c
index 595ed241d..c9b124455 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -67,13 +67,13 @@
\*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include "db.h"
#include "../common/mmo.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
#include "../common/ers.h"
+#include "../common/strlib.h"
/*****************************************************************************\
* (1) Private typedefs, enums, structures, defines and global variables of *
@@ -271,6 +271,7 @@ static struct db_stats {
uint32 dbit_remove;
uint32 dbit_destroy;
uint32 db_iterator;
+ uint32 db_exists;
uint32 db_get;
uint32 db_getall;
uint32 db_vgetall;
@@ -304,7 +305,7 @@ static struct db_stats {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define DB_COUNTSTAT(token) if (stats. ## token != UINT32_MAX) ++stats. ## token
#else /* !defined(DB_ENABLE_STATS) */
@@ -630,19 +631,17 @@ static int db_is_key_null(DBType type, DBKey key)
static DBKey db_dup_key(DBMap_impl* db, DBKey key)
{
char *str;
+ size_t len;
DB_COUNTSTAT(db_dup_key);
switch (db->type) {
case DB_STRING:
case DB_ISTRING:
- if (db->maxlen) {
- CREATE(str, char, db->maxlen +1);
- strncpy(str, key.str, db->maxlen);
- str[db->maxlen] = '\0';
- key.str = str;
- } else {
- key.str = (char *)aStrdup(key.str);
- }
+ len = strnlen(key.str, db->maxlen);
+ str = (char*)aMalloc(len + 1);
+ memcpy(str, key.str, len);
+ str[len] = '\0';
+ key.str = str;
return key;
default:
@@ -888,8 +887,6 @@ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
DB_COUNTSTAT(db_string_cmp);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
return strncmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
@@ -908,8 +905,6 @@ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen)
{
DB_COUNTSTAT(db_istring_cmp);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
return strncasecmp((const char *)key1.str, (const char *)key2.str, maxlen);
}
@@ -951,7 +946,6 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen)
/**
* Default hasher for DB_STRING databases.
- * If maxlen if 0, the maximum number of maxlen is used instead.
* @param key Key to be hashed
* @param maxlen Maximum length of the key to hash
* @return hash of the key
@@ -966,8 +960,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
unsigned short i;
DB_COUNTSTAT(db_string_hash);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
for (i = 0; *k; ++i) {
hash = (hash*33 + ((unsigned char)*k))^(hash>>24);
@@ -981,7 +973,6 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen)
/**
* Default hasher for DB_ISTRING databases.
- * If maxlen if 0, the maximum number of maxlen is used instead.
* @param key Key to be hashed
* @param maxlen Maximum length of the key to hash
* @return hash of the key
@@ -995,8 +986,6 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen)
unsigned short i;
DB_COUNTSTAT(db_istring_hash);
- if (maxlen == 0)
- maxlen = UINT16_MAX;
for (i = 0; *k; i++) {
hash = (hash*33 + ((unsigned char)TOLOWER(*k)))^(hash>>24);
@@ -1087,6 +1076,7 @@ static void db_release_both(DBKey key, void *data, DBRelease which)
* dbit_obj_destroy - Destroys the iterator, unlocking the database and *
* freeing used memory. *
* db_obj_iterator - Return a new databse iterator. *
+ * db_obj_exists - Checks if an entry exists. *
* db_obj_get - Get the data identified by the key. *
* db_obj_vgetall - Get the data of the matched entries. *
* db_obj_getall - Get the data of the matched entries. *
@@ -1402,6 +1392,57 @@ static DBIterator* db_obj_iterator(DBMap* self)
}
/**
+ * Returns true if the entry exists.
+ * @param self Interface of the database
+ * @param key Key that identifies the entry
+ * @return true is the entry exists
+ * @protected
+ * @see DBMap#exists
+ */
+static bool db_obj_exists(DBMap* self, DBKey key)
+{
+ DBMap_impl* db = (DBMap_impl*)self;
+ DBNode node;
+ int c;
+ bool found = false;
+
+ DB_COUNTSTAT(db_exists);
+ if (db == NULL) return false; // nullpo candidate
+ if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) {
+ return false; // nullpo candidate
+ }
+
+ if (db->cache && db->cmp(key, db->cache->key, db->maxlen) == 0) {
+#if defined(DEBUG)
+ if (db->cache->deleted) {
+ ShowDebug("db_exists: Cache contains a deleted node. Please report this!!!\n");
+ return false;
+ }
+#endif
+ return true; // cache hit
+ }
+
+ db_free_lock(db);
+ node = db->ht[db->hash(key, db->maxlen)%HASH_SIZE];
+ while (node) {
+ c = db->cmp(key, node->key, db->maxlen);
+ if (c == 0) {
+ if (!(node->deleted)) {
+ db->cache = node;
+ found = true;
+ }
+ break;
+ }
+ if (c < 0)
+ node = node->left;
+ else
+ node = node->right;
+ }
+ db_free_unlock(db);
+ return found;
+}
+
+/**
* Get the data of the entry identifid by the key.
* @param self Interface of the database
* @param key Key that identifies the entry
@@ -2326,7 +2367,7 @@ DBReleaser db_custom_release(DBRelease which)
* @param type Type of database
* @param options Options of the database
* @param maxlen Maximum length of the string to be used as key in string
- * databases
+ * databases. If 0, the maximum number of maxlen is used (64K).
* @return The interface of the database
* @public
* @see #DBMap_impl
@@ -2351,6 +2392,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
options = db_fix_options(type, options);
/* Interface of the database */
db->vtable.iterator = db_obj_iterator;
+ db->vtable.exists = db_obj_exists;
db->vtable.get = db_obj_get;
db->vtable.getall = db_obj_getall;
db->vtable.vgetall = db_obj_vgetall;
@@ -2389,6 +2431,9 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
db->maxlen = maxlen;
db->global_lock = 0;
+ if( db->maxlen == 0 && (type == DB_STRING || type == DB_ISTRING) )
+ db->maxlen = UINT16_MAX;
+
return &db->vtable;
}
@@ -2493,7 +2538,7 @@ void db_final(void)
"dbit_next %10u, dbit_prev %10u,\n"
"dbit_exists %10u, dbit_remove %10u,\n"
"dbit_destroy %10u, db_iterator %10u,\n"
- "db_get %10u,\n"
+ "db_exits %10u, db_get %10u,\n"
"db_getall %10u, db_vgetall %10u,\n"
"db_ensure %10u, db_vensure %10u,\n"
"db_put %10u, db_remove %10u,\n"
@@ -2523,7 +2568,7 @@ void db_final(void)
stats.dbit_next, stats.dbit_prev,
stats.dbit_exists, stats.dbit_remove,
stats.dbit_destroy, stats.db_iterator,
- stats.db_get,
+ stats.db_exists, stats.db_get,
stats.db_getall, stats.db_vgetall,
stats.db_ensure, stats.db_vensure,
stats.db_put, stats.db_remove,
diff --git a/src/common/db.h b/src/common/db.h
index c1b224bcd..d33b8ec2e 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -205,8 +205,6 @@ typedef int (*DBMatcher)(DBKey key, void* data, va_list args);
/**
* Format of the comparators used internally by the database system.
* Compares key1 to key2.
- * <code>maxlen</code> is the maximum number of character used in DB_STRING and
- * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K).
* Returns 0 is equal, negative if lower and positive is higher.
* @param key1 Key being compared
* @param key2 Key we are comparing to
@@ -221,8 +219,6 @@ typedef int (*DBComparator)(DBKey key1, DBKey key2, unsigned short maxlen);
/**
* Format of the hashers used internally by the database system.
* Creates the hash of the key.
- * <code>maxlen</code> is the maximum number of character used in DB_STRING and
- * DB_ISTRING databases. If 0, the maximum number of maxlen is used (64K).
* @param key Key being hashed
* @param maxlen Maximum number of characters used in DB_STRING and DB_ISTRING
* databases.
@@ -360,6 +356,15 @@ struct DBMap {
DBIterator* (*iterator)(DBMap* self);
/**
+ * Returns true if the entry exists.
+ * @param self Database
+ * @param key Key that identifies the entry
+ * @return true is the entry exists
+ * @protected
+ */
+ bool (*exists)(DBMap* self, DBKey key);
+
+ /**
* Get the data of the entry identifid by the key.
* @param self Database
* @param key Key that identifies the entry
@@ -580,6 +585,11 @@ struct DBMap {
# define str2key(k) ((DBKey)(const char *)(k))
#endif /* not DB_MANUAL_CAST_TO_UNION */
+#define db_exists(db,k) ( (db)->exists((db),(k)) )
+#define idb_exists(db,k) ( (db)->exists((db),i2key(k)) )
+#define uidb_exists(db,k) ( (db)->exists((db),ui2key(k)) )
+#define strdb_exists(db,k) ( (db)->exists((db),str2key(k)) )
+
#define db_get(db,k) ( (db)->get((db),(k)) )
#define idb_get(db,k) ( (db)->get((db),i2key(k)) )
#define uidb_get(db,k) ( (db)->get((db),ui2key(k)) )
@@ -707,7 +717,7 @@ DBReleaser db_custom_release(DBRelease which);
* @param type Type of database
* @param options Options of the database
* @param maxlen Maximum length of the string to be used as key in string
- * databases
+ * databases. If 0, the maximum number of maxlen is used (64K).
* @return The interface of the database
* @public
* @see #DBType
diff --git a/src/common/ers.h b/src/common/ers.h
index 47a076e6e..9e120c313 100644
--- a/src/common/ers.h
+++ b/src/common/ers.h
@@ -40,9 +40,7 @@
#ifndef _ERS_H_
#define _ERS_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
/*****************************************************************************\
* (1) All public parts of the Entry Reusage System. *
diff --git a/src/common/grfio.c b/src/common/grfio.c
index e7549ecb4..cb242fe5d 100644
--- a/src/common/grfio.c
+++ b/src/common/grfio.c
@@ -1,19 +1,18 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "grfio.h"
-
#include "../common/cbasetypes.h"
#include "../common/showmsg.h"
#include "../common/malloc.h"
#include "../common/strlib.h"
#include "../common/utils.h"
+#include "grfio.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <zlib.h>
//----------------------------
// file entry table struct
@@ -221,6 +220,23 @@ unsigned long grfio_crc32 (const unsigned char* buf, unsigned int len)
return crc32(crc32(0L, Z_NULL, 0), buf, len);
}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Grf data sub : zip decode
+int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen)
+{
+ return uncompress(dest, destLen, source, sourceLen);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+/// Grf data sub : zip encode
+int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen)
+{
+ return compress(dest, destLen, source, sourceLen);
+}
+
+
/***********************************************************
*** File List Subroutines ***
***********************************************************/
@@ -431,9 +447,9 @@ void* grfio_reads(char* fname, int* size)
if (entry->cycle >= 0)
decode_des_etc(buf, entry->srclen_aligned, entry->cycle == 0, entry->cycle);
len = entry->declen;
- uncompress(buf2, &len, buf, entry->srclen);
+ decode_zip(buf2, &len, buf, entry->srclen);
if (len != (uLong)entry->declen) {
- ShowError("uncompress size mismatch err: %d != %d\n", (int)len, entry->declen);
+ ShowError("decode_zip size mismatch err: %d != %d\n", (int)len, entry->declen);
aFree(buf);
aFree(buf2);
return NULL;
@@ -580,7 +596,7 @@ static int grfio_entryread(char* grfname, int gentry)
grf_filelist = (unsigned char *)aMallocA(eSize); // Get a Extend Size
fread(rBuf,1,rSize,fp);
fclose(fp);
- uncompress(grf_filelist, &eSize, rBuf, rSize); // Decode function
+ decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function
list_size = eSize;
aFree(rBuf);
diff --git a/src/common/grfio.h b/src/common/grfio.h
index d5334ccf3..d0baa6609 100644
--- a/src/common/grfio.h
+++ b/src/common/grfio.h
@@ -4,8 +4,6 @@
#ifndef _GRFIO_H_
#define _GRFIO_H_
-#include <zlib.h>
-
void grfio_init(char*); // GRFIO Initialize
void grfio_final(void); // GRFIO Finalize
void* grfio_reads(char*,int*); // GRFIO data file read & size get
@@ -16,4 +14,7 @@ char *grfio_find_file(char *fname);
int grfio_size(char*); // GRFIO data file size get
unsigned long grfio_crc32(const unsigned char *buf, unsigned int len);
+int decode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
+int encode_zip(unsigned char* dest, unsigned long* destLen, const unsigned char* source, unsigned long sourceLen);
+
#endif /* _GRFIO_H_ */
diff --git a/src/common/malloc.c b/src/common/malloc.c
index b566e689f..f80d11fb4 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -222,7 +222,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
if (((long) size) < 0) {
ShowError("_mmalloc: %d\n", size);
- return 0;
+ return NULL;
}
if(size == 0) {
@@ -380,7 +380,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
{
ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
} else {
- head->size = -1;
+ head->size = 0xFFFF;
if(head_large->prev) {
head_large->prev->next = head_large->next;
} else {
@@ -428,7 +428,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
hash_unfill[ block->unit_hash ] = block;
}
head->size = block->unit_unfill;
- block->unit_unfill = (unsigned short)(((uintptr)head - (uintptr)block->data) / block->unit_size);
+ block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size);
}
}
}
@@ -636,7 +636,6 @@ static void memmgr_final (void)
fclose(log_fp);
}
#endif /* LOG_MEMMGR */
- return;
}
static void memmgr_init (void)
@@ -646,7 +645,6 @@ static void memmgr_init (void)
ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
memset(hash_unfill, 0, sizeof(hash_unfill));
#endif /* LOG_MEMMGR */
- return;
}
#endif /* USE_MEMMGR */
@@ -679,7 +677,6 @@ void malloc_final (void)
#ifdef USE_MEMMGR
memmgr_final ();
#endif
- return;
}
void malloc_init (void)
@@ -687,5 +684,4 @@ void malloc_init (void)
#ifdef USE_MEMMGR
memmgr_init ();
#endif
- return;
}
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 0bc30ea47..f9037e913 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -207,8 +207,19 @@ struct point {
short x,y;
};
+enum e_skill_flag
+{
+ SKILL_FLAG_PERMANENT,
+ SKILL_FLAG_TEMPORARY,
+ SKILL_FLAG_PLAGIARIZED,
+ SKILL_FLAG_REPLACED_LV_0, // temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0'
+ //...
+};
+
struct s_skill {
- unsigned short id,lv,flag;
+ unsigned short id;
+ unsigned short lv;
+ unsigned short flag; // see enum e_skill_flag
};
struct global_reg {
@@ -508,12 +519,6 @@ struct guild_castle {
int temp_guardians_max;
};
-// for Brandish Spear calculations
-struct square {
- int val1[5];
- int val2[5];
-};
-
struct fame_list {
int id;
int fame;
diff --git a/src/common/plugin.h b/src/common/plugin.h
index fd01be762..a367d2537 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -4,9 +4,7 @@
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
////// Plugin functions ///////////////
diff --git a/src/common/plugins.h b/src/common/plugins.h
index e71a4e8c5..c1cf17afd 100644
--- a/src/common/plugins.h
+++ b/src/common/plugins.h
@@ -4,10 +4,7 @@
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
-
#include "../common/plugin.h"
////// Dynamic Link Library functions ///////////////
diff --git a/src/common/random.c b/src/common/random.c
new file mode 100644
index 000000000..b7f2c080c
--- /dev/null
+++ b/src/common/random.c
@@ -0,0 +1,83 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/timer.h" // gettick
+#include "random.h"
+#if defined(WIN32)
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+#elif defined(HAVE_GETPID) || defined(HAVE_GETTID)
+ #include <sys/types.h>
+ #include <unistd.h>
+#endif
+#include <time.h> // time
+#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53
+
+
+/// Initializes the random number generator with an appropriate seed.
+void rnd_init(void)
+{
+ uint32 seed = gettick();
+ seed += (uint32)time(NULL);
+#if defined(WIN32)
+ seed += GetCurrentProcessId();
+ seed += GetCurrentThreadId();
+#else
+#if defined(HAVE_GETPID)
+ seed += (uint32)getpid();
+#endif // HAVE_GETPID
+#if defined(HAVE_GETTID)
+ seed += (uint32)gettid();
+#endif // HAVE_GETTID
+#endif
+ init_genrand(seed);
+}
+
+
+/// Initializes the random number generator.
+void rnd_seed(uint32 seed)
+{
+ init_genrand(seed);
+}
+
+
+/// Generates a random number in the interval [0, UINT32_MAX]
+uint32 rnd(void)
+{
+ return (uint32)genrand_int32();
+}
+
+
+/// Generates a random number in the interval [0, dice_faces)
+/// NOTE: interval is open ended, so dice_faces is excluded (unless it's 0)
+uint32 rnd_roll(uint32 dice_faces)
+{
+ return (uint32)(rnd_uniform()*dice_faces);
+}
+
+
+/// Generates a random number in the interval [min, max]
+/// Returns min if range is invalid.
+int32 rnd_value(int32 min, int32 max)
+{
+ if( min >= max )
+ return min;
+ return min + (int32)(rnd_uniform()*(max-min+1));
+}
+
+
+/// Generates a random number in the interval [0.0, 1.0)
+/// NOTE: interval is open ended, so 1.0 is excluded
+double rnd_uniform(void)
+{
+ return ((uint32)genrand_int32())*(1.0/4294967296.0);// divided by 2^32
+}
+
+
+/// Generates a random number in the interval [0.0, 1.0) with 53-bit resolution
+/// NOTE: interval is open ended, so 1.0 is excluded
+/// NOTE: 53 bits is the maximum precision of a double
+double rnd_uniform53(void)
+{
+ return genrand_res53();
+}
diff --git a/src/common/random.h b/src/common/random.h
new file mode 100644
index 000000000..59b609464
--- /dev/null
+++ b/src/common/random.h
@@ -0,0 +1,18 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _RANDOM_H_
+#define _RANDOM_H_
+
+#include "../common/cbasetypes.h"
+
+void rnd_init(void);
+void rnd_seed(uint32);
+
+uint32 rnd(void);// [0, UINT32_MAX]
+uint32 rnd_roll(uint32 dice_faces);// [0, dice_faces)
+int32 rnd_value(int32 min, int32 max);// [min, max]
+double rnd_uniform(void);// [0.0, 1.0)
+double rnd_uniform53(void);// [0.0, 1.0)
+
+#endif /* _RANDOM_H_ */
diff --git a/src/common/socket.c b/src/common/socket.c
index 262351dcf..81ea19468 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -938,7 +938,7 @@ static int connect_check_(uint32 ip)
/// Timer function.
/// Deletes old connection history records.
-static int connect_check_clear(int tid, unsigned int tick, int id, intptr data)
+static int connect_check_clear(int tid, unsigned int tick, int id, intptr_t data)
{
int i;
int clear = 0;
@@ -1118,6 +1118,9 @@ void socket_final(void)
/// Closes a socket.
void do_close(int fd)
{
+ if( fd <= 0 ||fd >= FD_SETSIZE )
+ return;// invalid
+
flush_fifo(fd); // Try to send what's left (although it might not succeed since it's a nonblocking socket)
sFD_CLR(fd, &readfds);// this needs to be done before closing the socket
sShutdown(fd, SHUT_RDWR); // Disallow further reads/writes
diff --git a/src/common/socket.h b/src/common/socket.h
index 2f0ec6081..a5d519d0e 100644
--- a/src/common/socket.h
+++ b/src/common/socket.h
@@ -4,9 +4,7 @@
#ifndef _SOCKET_H_
#define _SOCKET_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN // otherwise winsock2.h includes full windows.h
diff --git a/src/common/sql.c b/src/common/sql.c
index d8e397e8d..edac5a297 100644
--- a/src/common/sql.c
+++ b/src/common/sql.c
@@ -182,7 +182,7 @@ int Sql_Ping(Sql* self)
/// Wrapper function for Sql_Ping.
///
/// @private
-static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr data)
+static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr_t data)
{
Sql* self = (Sql*)data;
ShowInfo("Pinging SQL server to keep connection alive...\n");
@@ -212,7 +212,7 @@ static int Sql_P_Keepalive(Sql* self)
// establish keepalive
ping_interval = timeout - 30; // 30-second reserve
//add_timer_func_list(Sql_P_KeepaliveTimer, "Sql_P_KeepaliveTimer");
- return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr)self, ping_interval*1000);
+ return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (intptr_t)self, ping_interval*1000);
}
diff --git a/src/common/sql.h b/src/common/sql.h
index ef76b2ec5..5b318ab4d 100644
--- a/src/common/sql.h
+++ b/src/common/sql.h
@@ -4,9 +4,7 @@
#ifndef _COMMON_SQL_H_
#define _COMMON_SQL_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
#include <stdarg.h>// va_list
diff --git a/src/common/strlib.c b/src/common/strlib.c
index 66f281ffc..097f499e6 100644
--- a/src/common/strlib.c
+++ b/src/common/strlib.c
@@ -441,30 +441,13 @@ bool bin2hex(char* output, unsigned char* input, size_t count)
/////////////////////////////////////////////////////////////////////
-/// Parses a delim-separated string.
-/// Starts parsing at startoff and fills the pos array with position pairs.
-/// out_pos[0] and out_pos[1] are the start and end of line.
-/// Other position pairs are the start and end of fields.
-/// Returns the number of fields found or -1 if an error occurs.
-///
-/// out_pos can be NULL.
-/// If a line terminator is found, the end position is placed there.
-/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5]
-/// for the seconds field and so on.
-/// Unfilled positions are set to -1.
-///
-/// @param str String to parse
-/// @param len Length of the string
-/// @param startoff Where to start parsing
-/// @param delim Field delimiter
-/// @param out_pos Array of resulting positions
-/// @param npos Size of the pos array
-/// @param opt Options that determine the parsing behaviour
-/// @return Number of fields found in the string or -1 if an error occured
-int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt)
+/// Parses a single field in a delim-separated string.
+/// The delimiter after the field is skipped.
+///
+/// @param sv Parse state
+/// @return 1 if a field was parsed, 0 if already done, -1 on error.
+int sv_parse_next(struct s_svstate* sv)
{
- int i;
- int count;
enum {
START_OF_FIELD,
PARSING_FIELD,
@@ -473,27 +456,37 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
TERMINATE,
END
} state;
+ const char* str;
+ int len;
+ enum e_svopt opt;
+ char delim;
+ int i;
- // check pos/npos
- if( out_pos == NULL ) npos = 0;
- for( i = 0; i < npos; ++i )
- out_pos[i] = -1;
+ if( sv == NULL )
+ return -1;// error
+
+ str = sv->str;
+ len = sv->len;
+ opt = sv->opt;
+ delim = sv->delim;
// check opt
if( delim == '\n' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_LF)) )
{
- ShowError("sv_parse: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n");
+ ShowError("sv_parse_next: delimiter '\\n' is not compatible with options SV_TERMINATE_LF or SV_TERMINATE_CRLF.\n");
return -1;// error
}
if( delim == '\r' && (opt&(SV_TERMINATE_CRLF|SV_TERMINATE_CR)) )
{
- ShowError("sv_parse: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n");
+ ShowError("sv_parse_next: delimiter '\\r' is not compatible with options SV_TERMINATE_CR or SV_TERMINATE_CRLF.\n");
return -1;// error
}
- // check str
- if( str == NULL )
+ if( sv->done || str == NULL )
+ {
+ sv->done = true;
return 0;// nothing to parse
+ }
#define IS_END() ( i >= len )
#define IS_DELIM() ( str[i] == delim )
@@ -502,16 +495,13 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
((opt&SV_TERMINATE_CR) && str[i] == '\r') || \
((opt&SV_TERMINATE_CRLF) && i+1 < len && str[i] == '\r' && str[i+1] == '\n') )
#define IS_C_ESCAPE() ( (opt&SV_ESCAPE_C) && str[i] == '\\' )
-#define SET_FIELD_START() if( npos > count*2+2 ) out_pos[count*2+2] = i
-#define SET_FIELD_END() if( npos > count*2+3 ) out_pos[count*2+3] = i; ++count
+#define SET_FIELD_START() sv->start = i
+#define SET_FIELD_END() sv->end = i
- i = startoff;
- count = 0;
+ i = sv->off;
state = START_OF_FIELD;
- if( npos > 0 ) out_pos[0] = startoff;// start
while( state != END )
{
- if( npos > 1 ) out_pos[1] = i;// end
switch( state )
{
case START_OF_FIELD:// record start of field and start parsing it
@@ -533,7 +523,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
++i;// '\\'
if( IS_END() )
{
- ShowError("sv_parse: empty escape sequence\n");
+ ShowError("sv_parse_next: empty escape sequence\n");
return -1;
}
if( str[i] == 'x' )
@@ -541,7 +531,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
++i;// 'x'
if( IS_END() || !ISXDIGIT(str[i]) )
{
- ShowError("sv_parse: \\x with no following hex digits\n");
+ ShowError("sv_parse_next: \\x with no following hex digits\n");
return -1;
}
do{
@@ -562,26 +552,22 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
}
else
{
- ShowError("sv_parse: unknown escape sequence \\%c\n", str[i]);
+ ShowError("sv_parse_next: unknown escape sequence \\%c\n", str[i]);
return -1;
}
state = PARSING_FIELD;
break;
}
- case END_OF_FIELD:// record end of field and continue
+ case END_OF_FIELD:// record end of field and stop
SET_FIELD_END();
+ state = END;
if( IS_END() )
- state = END;
+ ;// nothing else
else if( IS_DELIM() )
- {
++i;// delim
- state = START_OF_FIELD;
- }
else if( IS_TERMINATOR() )
state = TERMINATE;
- else
- state = START_OF_FIELD;
break;
case TERMINATE:
@@ -592,10 +578,14 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
else
++i;// CR or LF
#endif
+ sv->done = true;
state = END;
break;
}
}
+ if( IS_END() )
+ sv->done = true;
+ sv->off = i;
#undef IS_END
#undef IS_DELIM
@@ -604,6 +594,58 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i
#undef SET_FIELD_START
#undef SET_FIELD_END
+ return 1;
+}
+
+
+/// Parses a delim-separated string.
+/// Starts parsing at startoff and fills the pos array with position pairs.
+/// out_pos[0] and out_pos[1] are the start and end of line.
+/// Other position pairs are the start and end of fields.
+/// Returns the number of fields found or -1 if an error occurs.
+///
+/// out_pos can be NULL.
+/// If a line terminator is found, the end position is placed there.
+/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5]
+/// for the seconds field and so on.
+/// Unfilled positions are set to -1.
+///
+/// @param str String to parse
+/// @param len Length of the string
+/// @param startoff Where to start parsing
+/// @param delim Field delimiter
+/// @param out_pos Array of resulting positions
+/// @param npos Size of the pos array
+/// @param opt Options that determine the parsing behaviour
+/// @return Number of fields found in the string or -1 if an error occured
+int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt)
+{
+ struct s_svstate sv;
+ int count;
+
+ // initialize
+ if( out_pos == NULL ) npos = 0;
+ for( count = 0; count < npos; ++count )
+ out_pos[count] = -1;
+ sv.str = str;
+ sv.len = len;
+ sv.off = startoff;
+ sv.opt = opt;
+ sv.delim = delim;
+ sv.done = false;
+
+ // parse
+ count = 0;
+ if( npos > 0 ) out_pos[0] = startoff;
+ while( !sv.done )
+ {
+ ++count;
+ if( sv_parse_next(&sv) <= 0 )
+ return -1;// error
+ if( npos > count*2 ) out_pos[count*2] = sv.start;
+ if( npos > count*2+1 ) out_pos[count*2+1] = sv.end;
+ }
+ if( npos > 1 ) out_pos[1] = sv.off;
return count;
}
diff --git a/src/common/strlib.h b/src/common/strlib.h
index 3f4f984cf..bbc2c6105 100644
--- a/src/common/strlib.h
+++ b/src/common/strlib.h
@@ -4,9 +4,7 @@
#ifndef _STRLIB_H_
#define _STRLIB_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
#include <stdarg.h>
#define __USE_GNU // required to enable strnlen on some platforms
@@ -78,6 +76,27 @@ typedef enum e_svopt
/// Other escape sequences supported by the C compiler.
#define SV_ESCAPE_C_SUPPORTED "abtnvfr\?\"'\\"
+/// Parse state.
+/// The field is [start,end[
+struct s_svstate
+{
+ const char* str; //< string to parse
+ int len; //< string length
+ int off; //< current offset in the string
+ int start; //< where the field starts
+ int end; //< where the field ends
+ enum e_svopt opt; //< parse options
+ char delim; //< field delimiter
+ bool done; //< if all the text has been parsed
+};
+
+/// Parses a single field in a delim-separated string.
+/// The delimiter after the field is skipped.
+///
+/// @param sv Parse state
+/// @return 1 if a field was parsed, 0 if done, -1 on error.
+int sv_parse_next(struct s_svstate* sv);
+
/// Parses a delim-separated string.
/// Starts parsing at startoff and fills the pos array with position pairs.
/// out_pos[0] and out_pos[1] are the start and end of line.
diff --git a/src/common/timer.c b/src/common/timer.c
index 86e148ee3..05c53b8a3 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -241,7 +241,7 @@ static int acquire_timer(void)
/// Starts a new timer that is deleted once it expires (single-use).
/// Returns the timer's id.
-int add_timer(unsigned int tick, TimerFunc func, int id, intptr data)
+int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data)
{
int tid;
@@ -259,7 +259,7 @@ int add_timer(unsigned int tick, TimerFunc func, int id, intptr data)
/// Starts a new timer that automatically restarts itself (infinite loop until manually removed).
/// Returns the timer's id, or INVALID_TIMER if it fails.
-int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval)
+int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval)
{
int tid;
diff --git a/src/common/timer.h b/src/common/timer.h
index 354a71113..a615a5874 100644
--- a/src/common/timer.h
+++ b/src/common/timer.h
@@ -4,9 +4,7 @@
#ifndef _TIMER_H_
#define _TIMER_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
#define DIFF_TICK(a,b) ((int)((a)-(b)))
@@ -19,7 +17,7 @@
// Struct declaration
-typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data);
+typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data);
struct TimerData {
unsigned int tick;
@@ -30,7 +28,7 @@ struct TimerData {
// general-purpose storage
int id;
- intptr data;
+ intptr_t data;
};
// Function prototype declaration
@@ -38,8 +36,8 @@ struct TimerData {
unsigned int gettick(void);
unsigned int gettick_nocache(void);
-int add_timer(unsigned int tick, TimerFunc func, int id, intptr data);
-int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, int interval);
+int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data);
+int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval);
const struct TimerData* get_timer(int tid);
int delete_timer(int tid, TimerFunc func);
diff --git a/src/common/utils.h b/src/common/utils.h
index 2fe078615..8e39f2655 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -4,10 +4,7 @@
#ifndef _UTILS_H_
#define _UTILS_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
-
#include <stdio.h> // FILE*
// generate a hex dump of the first 'length' bytes of 'buffer'
diff --git a/src/login/CMakeLists.txt b/src/login/CMakeLists.txt
new file mode 100644
index 000000000..afa4e5f20
--- /dev/null
+++ b/src/login/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+#
+# setup
+#
+set( LOGIN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
+
+
+#
+# targets
+#
+add_subdirectory( txt )
+add_subdirectory( sql )
diff --git a/src/login/Makefile.in b/src/login/Makefile.in
index c153d95b3..fa1933964 100644
--- a/src/login/Makefile.in
+++ b/src/login/Makefile.in
@@ -3,16 +3,20 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a
../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \
../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \
../common/obj_all/strlib.o ../common/obj_all/grfio.o ../common/obj_all/mapindex.o \
- ../common/obj_all/ers.o ../common/obj_all/md5calc.o
+ ../common/obj_all/ers.o ../common/obj_all/md5calc.o ../common/obj_all/random.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
../common/grfio.h ../common/mapindex.h \
- ../common/ers.h ../common/md5calc.h
+ ../common/ers.h ../common/md5calc.h ../common/random.h
COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_SQL_H = ../common/sql.h
+MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
+MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
+MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
+
LOGIN_OBJ = login.o
LOGIN_TXT_OBJ = $(LOGIN_OBJ:%=obj_txt/%) \
obj_txt/account_txt.o obj_txt/ipban_txt.o obj_txt/loginlog_txt.o
@@ -22,10 +26,11 @@ LOGIN_H = login.h account.h ipban.h loginlog.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ)
+ LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ)
else
LOGIN_SERVER_SQL_DEPENDS=needs_mysql
endif
+LOGIN_SERVER_TXT_DEPENDS=obj_txt $(LOGIN_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ)
@SET_MAKE@
@@ -63,19 +68,25 @@ obj_sql:
test -d obj_sql || mkdir obj_sql
#executables
-login-server: $(LOGIN_TXT_OBJ) $(COMMON_OBJ)
- @CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_TXT_OBJ) $(COMMON_OBJ) @LIBS@
+login-server: $(LOGIN_SERVER_TXT_DEPENDS)
+ @CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@
login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS)
- @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @MYSQL_LIBS@
+ @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@
# login object files
-obj_txt/%.o: %.c $(LOGIN_H) $(COMMON_H)
- @CC@ @CFLAGS@ -DWITH_TXT @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_txt/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DWITH_TXT @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H)
- @CC@ @CFLAGS@ -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-# missing common object files
+# missing object files
../common/obj_all/%.o:
+ @$(MAKE) -C ../common txt
+
+../common/obj_sql/%.o:
@$(MAKE) -C ../common sql
+
+MT19937AR_OBJ:
+ @$(MAKE) -C ../../3rdparty/mt19937ar
diff --git a/src/login/account_txt.c b/src/login/account_txt.c
index 758a2c24e..821e26df5 100644
--- a/src/login/account_txt.c
+++ b/src/login/account_txt.c
@@ -58,7 +58,7 @@ static bool account_db_txt_iter_next(AccountDBIterator* self, struct mmo_account
static bool mmo_auth_fromstr(struct mmo_account* acc, char* str, unsigned int version);
static bool mmo_auth_tostr(const struct mmo_account* acc, char* str);
static void mmo_auth_sync(AccountDB_TXT* self);
-static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data);
+static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr_t data);
/// public constructor
AccountDB* account_db_txt(void)
@@ -183,7 +183,7 @@ static bool account_db_txt_init(AccountDB* self)
// initialize data saving timer
add_timer_func_list(mmo_auth_sync_timer, "mmo_auth_sync_timer");
- db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr)db, AUTH_SAVING_INTERVAL);
+ db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr_t)db, AUTH_SAVING_INTERVAL);
return true;
}
@@ -634,7 +634,7 @@ static void mmo_auth_sync(AccountDB_TXT* db)
db->auths_before_save = AUTHS_BEFORE_SAVE;
}
-static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data)
+static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr_t data)
{
AccountDB_TXT* db = (AccountDB_TXT*)data;
diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c
index ef463905e..c75a1f956 100644
--- a/src/login/ipban_sql.c
+++ b/src/login/ipban_sql.c
@@ -35,7 +35,7 @@ static Sql* sql_handle = NULL;
static int cleanup_timer_id = INVALID_TIMER;
static bool ipban_inited = false;
-int ipban_cleanup(int tid, unsigned int tick, int id, intptr data);
+int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data);
// initialize
@@ -246,7 +246,7 @@ void ipban_log(uint32 ip)
}
// remove expired bans
-int ipban_cleanup(int tid, unsigned int tick, int id, intptr data)
+int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data)
{
if( !login_config.ipban )
return 0;// ipban disabled
diff --git a/src/login/login.c b/src/login/login.c
index 6d8043baf..e57293a4c 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -101,7 +101,7 @@ struct online_login_data {
};
static DBMap* online_db; // int account_id -> struct online_login_data*
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data);
+static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
static void* create_online_user(DBKey key, va_list args)
{
@@ -138,7 +138,7 @@ void remove_online_user(int account_id)
idb_remove(online_db, account_id);
}
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data)
+static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
@@ -176,7 +176,7 @@ static int online_data_cleanup_sub(DBKey key, void *data, va_list ap)
return 0;
}
-static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data)
+static int online_data_cleanup(int tid, unsigned int tick, int id, intptr_t data)
{
online_db->foreach(online_db, online_data_cleanup_sub);
return 0;
@@ -190,7 +190,7 @@ int charif_sendallwos(int sfd, uint8* buf, size_t len)
{
int i, c;
- for( i = 0, c = 0; i < MAX_SERVERS; ++i )
+ for( i = 0, c = 0; i < ARRAYLENGTH(server); ++i )
{
int fd = server[i].fd;
if( session_isValid(fd) && fd != sfd )
@@ -206,10 +206,46 @@ int charif_sendallwos(int sfd, uint8* buf, size_t len)
}
+/// Initializes a server structure.
+void chrif_server_init(int id)
+{
+ memset(&server[id], 0, sizeof(server[id]));
+ server[id].fd = -1;
+}
+
+
+/// Destroys a server structure.
+void chrif_server_destroy(int id)
+{
+ if( server[id].fd != -1 )
+ {
+ do_close(server[id].fd);
+ server[id].fd = -1;
+ }
+}
+
+
+/// Resets all the data related to a server.
+void chrif_server_reset(int id)
+{
+ online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
+ chrif_server_destroy(id);
+ chrif_server_init(id);
+}
+
+
+/// Called when the connection to Char Server is disconnected.
+void chrif_on_disconnect(int id)
+{
+ ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
+ chrif_server_reset(id);
+}
+
+
//-----------------------------------------------------
// periodic ip address synchronization
//-----------------------------------------------------
-static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr data)
+static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data)
{
uint8 buf[2];
ShowInfo("IP Sync in progress...\n");
@@ -381,9 +417,10 @@ int parse_fromchar(int fd)
uint32 ipl;
char ip[16];
- ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd );
- if( id == MAX_SERVERS )
+ ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd );
+ if( id == ARRAYLENGTH(server) )
{// not a char server
+ ShowDebug("parse_fromchar: Disconnecting invalid session #%d (is not a char-server)\n", fd);
set_eof(fd);
do_close(fd);
return 0;
@@ -391,11 +428,9 @@ int parse_fromchar(int fd)
if( session[fd]->flag.eof )
{
- ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
- online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
- memset(&server[id], 0, sizeof(struct mmo_char_server));
- server[id].fd = -1;
do_close(fd);
+ server[id].fd = -1;
+ chrif_on_disconnect(id);
return 0;
}
@@ -424,8 +459,9 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,23);
node = (struct auth_node*)idb_get(auth_db, account_id);
- if( node != NULL &&
- node->account_id == account_id &&
+ if( runflag == LOGINSERVER_ST_RUNNING &&
+ node != NULL &&
+ node->account_id == account_id &&
node->login_id1 == login_id1 &&
node->login_id2 == login_id2 &&
node->sex == sex_num2str(sex) /*&&
@@ -1059,6 +1095,16 @@ void login_auth_ok(struct login_session_data* sd)
struct auth_node* node;
int i;
+ if( runflag != LOGINSERVER_ST_RUNNING )
+ {
+ // players can only login while running
+ WFIFOHEAD(fd,3);
+ WFIFOW(fd,0) = 0x81;
+ WFIFOB(fd,2) = 1;// server closed
+ WFIFOSET(fd,3);
+ return;
+ }
+
if( sd->level < login_config.min_level_to_connect )
{
ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d).\n", login_config.min_level_to_connect, sd->userid, sd->level);
@@ -1070,8 +1116,8 @@ void login_auth_ok(struct login_session_data* sd)
}
server_num = 0;
- for( i = 0; i < MAX_SERVERS; ++i )
- if( session_isValid(server[i].fd) )
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ if( session_isActive(server[i].fd) )
server_num++;
if( server_num == 0 )
@@ -1133,7 +1179,7 @@ void login_auth_ok(struct login_session_data* sd)
memset(WFIFOP(fd,20), 0, 24);
WFIFOW(fd,44) = 0; // unknown
WFIFOB(fd,46) = sex_str2num(sd->sex);
- for( i = 0, n = 0; i < MAX_SERVERS; ++i )
+ for( i = 0, n = 0; i < ARRAYLENGTH(server); ++i )
{
if( !session_isValid(server[i].fd) )
continue;
@@ -1404,7 +1450,11 @@ int parse_login(int fd)
login_log(session[fd]->client_addr, sd->userid, 100, message);
result = mmo_auth(sd);
- if( result == -1 && sd->sex == 'S' && sd->account_id < MAX_SERVERS && server[sd->account_id].fd == -1 )
+ if( runflag == LOGINSERVER_ST_RUNNING &&
+ result == -1 &&
+ sd->sex == 'S' &&
+ sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(server) &&
+ !session_isValid(server[sd->account_id].fd) )
{
ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name));
@@ -1592,7 +1642,7 @@ static AccountDB* get_account_engine(void)
//--------------------------------------
void do_final(void)
{
- int i, fd;
+ int i;
login_log(0, "login server", 100, "login server shutdown");
ShowStatus("Terminating...\n");
@@ -1614,15 +1664,15 @@ void do_final(void)
accounts = NULL; // destroyed in account_engines
online_db->destroy(online_db, NULL);
auth_db->destroy(auth_db, NULL);
+
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ chrif_server_destroy(i);
- for (i = 0; i < MAX_SERVERS; i++) {
- if ((fd = server[i].fd) >= 0) {
- memset(&server[i], 0, sizeof(struct mmo_char_server));
- server[i].fd = -1;
- do_close(fd);
- }
+ if( login_fd != -1 )
+ {
+ do_close(login_fd);
+ login_fd = -1;
}
- do_close(login_fd);
ShowStatus("Finished.\n");
}
@@ -1640,6 +1690,24 @@ void set_server_type(void)
SERVER_TYPE = ATHENA_SERVER_LOGIN;
}
+
+/// Called when a terminate signal is received.
+void do_shutdown(void)
+{
+ if( runflag != LOGINSERVER_ST_SHUTDOWN )
+ {
+ int id;
+ runflag = LOGINSERVER_ST_SHUTDOWN;
+ ShowStatus("Shutting down...\n");
+ // TODO proper shutdown procedure; kick all characters, wait for acks, ... [FlavioJS]
+ for( id = 0; id < ARRAYLENGTH(server); ++id )
+ chrif_server_reset(id);
+ flush_fifos();
+ runflag = CORE_ST_STOP;
+ }
+}
+
+
//------------------------------
// Login server initialization
//------------------------------
@@ -1657,9 +1725,9 @@ int do_init(int argc, char** argv)
login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME);
srand((unsigned int)time(NULL));
-
- for( i = 0; i < MAX_SERVERS; i++ )
- server[i].fd = -1;
+
+ for( i = 0; i < ARRAYLENGTH(server); ++i )
+ chrif_server_init(i);
// initialize logging
if( login_config.log_login )
@@ -1713,6 +1781,12 @@ int do_init(int argc, char** argv)
// server port open & binding
login_fd = make_listen_bind(login_config.login_ip, login_config.login_port);
+
+ if( runflag != CORE_ST_STOP )
+ {
+ shutdown_callback = do_shutdown;
+ runflag = LOGINSERVER_ST_RUNNING;
+ }
ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port);
login_log(0, "login server", 100, "login server started");
diff --git a/src/login/login.h b/src/login/login.h
index f338a09e1..07f05f18b 100644
--- a/src/login/login.h
+++ b/src/login/login.h
@@ -5,6 +5,14 @@
#define _LOGIN_H_
#include "../common/mmo.h" // NAME_LENGTH,SEX_*
+#include "../common/core.h" // CORE_ST_LAST
+
+enum E_LOGINSERVER_ST
+{
+ LOGINSERVER_ST_RUNNING = CORE_ST_LAST,
+ LOGINSERVER_ST_SHUTDOWN,
+ LOGINSERVER_ST_LAST
+};
#define LOGIN_CONF_NAME "conf/login_athena.conf"
#define LAN_CONF_NAME "conf/subnet_athena.conf"
diff --git a/src/login/sql/CMakeLists.txt b/src/login/sql/CMakeLists.txt
new file mode 100644
index 000000000..ac7d464c9
--- /dev/null
+++ b/src/login/sql/CMakeLists.txt
@@ -0,0 +1,43 @@
+
+#
+# login sql
+#
+if( HAVE_common_sql )
+message( STATUS "Creating target login-server_sql" )
+set( SQL_LOGIN_HEADERS
+ "${LOGIN_SOURCE_DIR}/account.h"
+ "${LOGIN_SOURCE_DIR}/ipban.h"
+ "${LOGIN_SOURCE_DIR}/login.h"
+ "${LOGIN_SOURCE_DIR}/loginlog.h"
+ )
+set( SQL_LOGIN_SOURCES
+ "${LOGIN_SOURCE_DIR}/account_sql.c"
+ "${LOGIN_SOURCE_DIR}/ipban_sql.c"
+ "${LOGIN_SOURCE_DIR}/login.c"
+ "${LOGIN_SOURCE_DIR}/loginlog_sql.c"
+ )
+set( DEPENDENCIES common_sql )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} WITH_SQL )
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_LOGIN_HEADERS} ${SQL_LOGIN_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} )
+source_group( login FILES ${SQL_LOGIN_HEADERS} ${SQL_LOGIN_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( login-server_sql ${SOURCE_FILES} )
+add_dependencies( login-server_sql ${DEPENDENCIES} )
+target_link_libraries( login-server_sql ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( login-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_loginserver_sql DESCRIPTION "login-server (sql version)" DISPLAY_NAME "login-server_sql" GROUP Runtime )
+ install( TARGETS login-server_sql
+ DESTINATION "."
+ COMPONENT Runtime_loginserver_sql )
+endif()
+message( STATUS "Creating target login-server_sql - done" )
+set( HAVE_login-server_sql ON CACHE BOOL "login-server_sql target is available" )
+mark_as_advanced( HAVE_login-server_sql )
+else()
+message( STATUS "Skipping target login-server_sql (requires common_sql)" )
+unset( HAVE_login-server_sql CACHE )
+endif()
diff --git a/src/login/txt/CMakeLists.txt b/src/login/txt/CMakeLists.txt
new file mode 100644
index 000000000..9d57103e9
--- /dev/null
+++ b/src/login/txt/CMakeLists.txt
@@ -0,0 +1,43 @@
+
+#
+# login txt
+#
+if( HAVE_common_base )
+message( STATUS "Creating target login-server" )
+set( TXT_LOGIN_HEADERS
+ "${LOGIN_SOURCE_DIR}/account.h"
+ "${LOGIN_SOURCE_DIR}/ipban.h"
+ "${LOGIN_SOURCE_DIR}/login.h"
+ "${LOGIN_SOURCE_DIR}/loginlog.h"
+ )
+set( TXT_LOGIN_SOURCES
+ "${LOGIN_SOURCE_DIR}/account_txt.c"
+ "${LOGIN_SOURCE_DIR}/ipban_txt.c"
+ "${LOGIN_SOURCE_DIR}/login.c"
+ "${LOGIN_SOURCE_DIR}/loginlog_txt.c"
+ )
+set( DEPENDENCIES common_base )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} WITH_TXT )
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_LOGIN_HEADERS} ${TXT_LOGIN_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} )
+source_group( login FILES ${TXT_LOGIN_HEADERS} ${TXT_LOGIN_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( login-server ${SOURCE_FILES} )
+add_dependencies( login-server ${DEPENDENCIES} )
+target_link_libraries( login-server ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( login-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_loginserver_txt DESCRIPTION "login-server (txt version)" DISPLAY_NAME "login-server" GROUP Runtime )
+ install( TARGETS login-server
+ DESTINATION "."
+ COMPONENT Runtime_loginserver_txt )
+endif()
+message( STATUS "Creating target login-server - done" )
+set( HAVE_login-server ON CACHE BOOL "login-server target is available" )
+mark_as_advanced( HAVE_login-server )
+else()
+message( STATUS "Skipping target login-server (requires common_base)" )
+unset( HAVE_login-server CACHE )
+endif()
diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt
new file mode 100644
index 000000000..9199702be
--- /dev/null
+++ b/src/map/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+#
+# setup
+#
+set( MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )
+
+
+#
+# targets
+#
+add_subdirectory( txt )
+add_subdirectory( sql )
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index 7070a0a9d..09e92dde2 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -3,16 +3,22 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a
../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \
../common/obj_all/nullpo.o ../common/obj_all/malloc.o ../common/obj_all/showmsg.o \
../common/obj_all/utils.o ../common/obj_all/strlib.o ../common/obj_all/grfio.o \
- ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/md5calc.o
+ ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/md5calc.o \
+ ../common/obj_all/random.o
COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h \
../common/db.h ../common/plugins.h ../common/lock.h \
../common/nullpo.h ../common/malloc.h ../common/showmsg.h \
../common/utils.h ../common/strlib.h ../common/grfio.h \
- ../common/mapindex.h ../common/ers.h ../common/md5calc.h
+ ../common/mapindex.h ../common/ers.h ../common/md5calc.h \
+ ../common/random.h
COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_SQL_H = ../common/sql.h
+MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
+MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
+MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
+
MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
npc_chat.o chat.o path.o itemdb.o mob.o script.o \
storage.o skill.o atcommand.o battle.o battleground.o \
@@ -38,6 +44,7 @@ else
ALL_TARGET=txt
SQL_DEPENDS=needs_mysql
endif
+TXT_DEPENDS=map-server
HAVE_PCRE=@HAVE_PCRE@
ifeq ($(HAVE_PCRE),yes)
@@ -53,7 +60,7 @@ endif
all: $(ALL_DEPENDS)
-txt: map-server
+txt: $(TXT_DEPENDS)
sql: $(SQL_DEPENDS)
@@ -87,21 +94,24 @@ obj_sql:
# executables
map-server: obj_txt $(MAP_TXT_OBJ) $(COMMON_OBJ)
- @CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_TXT_OBJ) $(COMMON_OBJ) @LIBS@ @PCRE_LIBS@
+ @CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_TXT_OBJ) $(COMMON_OBJ) $(MT19937AR_OBJ) @LIBS@ @PCRE_LIBS@
map-server_sql: obj_sql $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ)
- @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
+ @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
# map object files
-obj_txt/%.o: %.c $(MAP_H) $(COMMON_H)
- @CC@ @CFLAGS@ $(PCRE_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_txt/%.o: %.c $(MAP_H) $(COMMON_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(PCRE_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H)
- @CC@ @CFLAGS@ $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H)
+ @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-# missing common object files
+# missing object files
../common/obj_all/%.o:
@$(MAKE) -C ../common txt
../common/obj_sql/%.o:
@$(MAKE) -C ../common sql
+
+MT19937AR_OBJ:
+ @$(MAKE) -C ../../3rdparty/mt19937ar
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 664430b18..32c2cabf7 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3988,23 +3988,9 @@ ACMD_FUNC(agitend2)
*------------------------------------------*/
ACMD_FUNC(mapexit)
{
- struct map_session_data* pl_sd;
- struct s_mapiterator* iter;
-
nullpo_retr(-1, sd);
- iter = mapit_getallusers();
- for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
- if (sd->status.account_id != pl_sd->status.account_id)
- clif_GM_kick(NULL, pl_sd);
- mapit_free(iter);
-
- clif_GM_kick(NULL, sd);
-
- flush_fifos();
-
- runflag = 0;
-
+ do_shutdown();
return 0;
}
@@ -7098,9 +7084,9 @@ ACMD_FUNC(mobinfo)
if (mob->mvpitem[i].p > 0) {
j++;
if (j == 1)
- sprintf(atcmd_output2, " %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100);
+ sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100);
else
- sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100);
+ sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100);
strcat(atcmd_output, atcmd_output2);
}
}
@@ -7117,7 +7103,7 @@ ACMD_FUNC(mobinfo)
* @showmobs by KarLaeda
* => For 5 sec displays the mobs on minimap
*------------------------------------------*/
-int atshowmobs_timer(int tid, unsigned int tick, int id, intptr data)
+int atshowmobs_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data* sd = map_id2sd(id);
if( sd == NULL )
diff --git a/src/map/battle.c b/src/map/battle.c
index aea2f2da4..ca5662dd7 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -154,7 +154,7 @@ struct delay_damage {
unsigned short attack_type;
};
-int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data)
+int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data)
{
struct delay_damage *dat = (struct delay_damage *)data;
struct block_list *target = map_id2bl(dat->target);
@@ -208,7 +208,7 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src,
dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
if (src->type != BL_PC && amotion > 1000)
amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
- add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr)dat);
+ add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr_t)dat);
return 0;
}
@@ -1620,7 +1620,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case AS_SPLASHER:
skillratio += 400+50*skill_lv;
if(sd)
- skillratio += 30 * pc_checkskill(sd,AS_POISONREACT);
+ skillratio += 20 * pc_checkskill(sd,AS_POISONREACT);
break;
case ASC_BREAKER:
skillratio += 100*skill_lv-100;
diff --git a/src/map/battle.h b/src/map/battle.h
index 8d014c5f9..d54d49c0a 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -72,20 +72,19 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang
int battle_gettarget(struct block_list *bl);
int battle_getcurrentskill(struct block_list *bl);
-//New definitions [Skotlex]
-#define BCT_ENEMY 0x020000
-//This should be (~BCT_ENEMY&BCT_ALL)
-#define BCT_NOENEMY 0x1d0000
-#define BCT_PARTY 0x040000
-//This should be (~BCT_PARTY&BCT_ALL)
-#define BCT_NOPARTY 0x1b0000
-#define BCT_GUILD 0x080000
-//This should be (~BCT_GUILD&BCT_ALL)
-#define BCT_NOGUILD 0x170000
-#define BCT_ALL 0x1f0000
-#define BCT_NOONE 0x000000
-#define BCT_SELF 0x010000
-#define BCT_NEUTRAL 0x100000
+enum e_battle_check_target
+{//New definitions [Skotlex]
+ BCT_ENEMY = 0x020000,
+ BCT_NOENEMY = 0x1d0000, //This should be (~BCT_ENEMY&BCT_ALL)
+ BCT_PARTY = 0x040000,
+ BCT_NOPARTY = 0x1b0000, //This should be (~BCT_PARTY&BCT_ALL)
+ BCT_GUILD = 0x080000,
+ BCT_NOGUILD = 0x170000, //This should be (~BCT_GUILD&BCT_ALL)
+ BCT_ALL = 0x1f0000,
+ BCT_NOONE = 0x000000,
+ BCT_SELF = 0x010000,
+ BCT_NEUTRAL = 0x100000,
+};
#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru]
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 13f62a042..b456a868a 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -236,7 +236,7 @@ int bg_send_xy_timer_sub(DBKey key, void *data, va_list ap)
return 0;
}
-int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr data)
+int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
return 0;
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 5b9734819..94f390c10 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -145,7 +145,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
if( i )
{// duplicate check. as the client does this too, only malicious intent should be caught here
- ARR_FIND( 0, i, listidx, sd->buyingstore.items[i].nameid == nameid );
+ ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid );
if( listidx != i )
{// duplicate
ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
diff --git a/src/map/chrif.c b/src/map/chrif.c
index c4eeea3d9..a14200a36 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -31,6 +31,8 @@
#include <sys/types.h>
#include <time.h>
+static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data);
+
static struct eri *auth_db_ers; //For reutilizing player login structures.
static DBMap* auth_db; // int id -> struct auth_node*
@@ -94,7 +96,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2b27: Incoming, chrif_authfail -> 'client authentication failed'
int chrif_connected = 0;
-int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex]
+int char_fd = -1;
int srvinfo;
static char char_ip_str[128];
static uint32 char_ip = 0;
@@ -110,6 +112,28 @@ int other_mapserver_count=0; //Holds count of how many other map servers are onl
//This define should spare writing the check in every function. [Skotlex]
#define chrif_check(a) { if(!chrif_isconnected()) return a; }
+
+/// Resets all the data.
+void chrif_reset(void)
+{
+ // TODO kick everyone out and reset everything [FlavioJS]
+ exit(EXIT_FAILURE);
+}
+
+
+/// Checks the conditions for the server to stop.
+/// Releases the cookie when all characters are saved.
+/// If all the conditions are met, it stops the core loop.
+void chrif_check_shutdown(void)
+{
+ if( runflag != MAPSERVER_ST_SHUTDOWN )
+ return;
+ if( auth_db->size(auth_db) > 0 )
+ return;
+ runflag = CORE_ST_STOP;
+}
+
+
struct auth_node* chrif_search(int account_id)
{
return (struct auth_node*)idb_get(auth_db, account_id);
@@ -244,9 +268,8 @@ int chrif_save(struct map_session_data *sd, int flag)
{
nullpo_retr(-1, sd);
- if (!flag) //The flag check is needed to prevent 'nosave' taking effect when a jailed player logs out.
- pc_makesavestatus(sd);
-
+ pc_makesavestatus(sd);
+
if (flag && sd->state.active) //Store player data which is quitting.
{
//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
@@ -363,6 +386,7 @@ int chrif_removemap(int fd)
static void chrif_save_ack(int fd)
{
chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT);
+ chrif_check_shutdown();
}
// request to move a character between mapservers
@@ -472,19 +496,13 @@ static int chrif_reconnect(DBKey key,void *data,va_list ap)
return 0;
}
-/*==========================================
- *
- *------------------------------------------*/
-int chrif_sendmapack(int fd)
-{
- if (RFIFOB(fd,2)) {
- ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
- exit(EXIT_FAILURE);
- }
- memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
- ShowStatus("Map sending complete. Map Server is now online.\n");
+/// Called when all the connection steps are completed.
+void chrif_on_ready(void)
+{
+ ShowStatus("Map Server is now online.\n");
chrif_state = 2;
+ chrif_check_shutdown();
//If there are players online, send them to the char-server. [Skotlex]
send_users_tochar();
@@ -494,7 +512,21 @@ int chrif_sendmapack(int fd)
//Re-save any storages that were modified in the disconnection time. [Skotlex]
do_reconnect_storage();
+}
+
+/*==========================================
+ *
+ *------------------------------------------*/
+int chrif_sendmapack(int fd)
+{
+ if (RFIFOB(fd,2)) {
+ ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
+ exit(EXIT_FAILURE);
+ }
+
+ memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
+ chrif_on_ready();
return 0;
}
@@ -592,7 +624,8 @@ void chrif_authok(int fd)
}
sd = node->sd;
- if(node->char_dat == NULL &&
+ if( runflag == MAPSERVER_ST_RUNNING &&
+ node->char_dat == NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
node->login_id1 == login_id1 )
@@ -661,7 +694,7 @@ int auth_db_cleanup_sub(DBKey key,void *data,va_list ap)
return 0;
}
-int auth_db_cleanup(int tid, unsigned int tick, int id, intptr data)
+int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data)
{
if(!chrif_isconnected()) return 0;
auth_db->foreach(auth_db, auth_db_cleanup_sub);
@@ -838,7 +871,7 @@ int chrif_changedsex(int fd)
if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) {
// remove specifical skills of Bard classes
for(i = 315; i <= 322; i++) {
- if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) {
+ if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
sd->status.skill_point += sd->status.skill[i].lv;
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
@@ -846,7 +879,7 @@ int chrif_changedsex(int fd)
}
// remove specifical skills of Dancer classes
for(i = 323; i <= 330; i++) {
- if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) {
+ if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
sd->status.skill_point += sd->status.skill[i].lv;
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
@@ -1292,22 +1325,22 @@ int chrif_char_online(struct map_session_data *sd)
return 0;
}
-int chrif_disconnect(int fd)
+
+/// Called when the connection to Char Server is disconnected.
+void chrif_on_disconnect(void)
{
- if(fd == char_fd) {
- char_fd = 0;
- ShowWarning("Map Server disconnected from Char Server.\n\n");
- chrif_connected = 0;
-
- other_mapserver_count=0; //Reset counter. We receive ALL maps from all map-servers on reconnect.
- map_eraseallipport();
+ if( chrif_connected != 1 )
+ ShowWarning("Connection to Char Server lost.\n\n");
+ chrif_connected = 0;
+
+ other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect.
+ map_eraseallipport();
- //Attempt to reconnect in a second. [Skotlex]
- add_timer(gettick() + 1000, check_connect_char_server, 0, 0);
- }
- return 0;
+ //Attempt to reconnect in a second. [Skotlex]
+ add_timer(gettick() + 1000, check_connect_char_server, 0, 0);
}
+
void chrif_update_ip(int fd)
{
uint32 new_ip;
@@ -1352,10 +1385,9 @@ int chrif_parse(int fd)
if (session[fd]->flag.eof)
{
- if (chrif_connected == 1)
- chrif_disconnect(fd);
-
do_close(fd);
+ char_fd = -1;
+ chrif_on_disconnect();
return 0;
}
@@ -1393,7 +1425,7 @@ int chrif_parse(int fd)
case 0x2afb: chrif_sendmapack(fd); break;
case 0x2afd: chrif_authok(fd); break;
case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
- case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break;
+ case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break;
case 0x2b04: chrif_recvmap(fd); break;
case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
@@ -1423,7 +1455,7 @@ int chrif_parse(int fd)
return 0;
}
-int ping_char_server(int tid, unsigned int tick, int id, intptr data)
+int ping_char_server(int tid, unsigned int tick, int id, intptr_t data)
{
chrif_check(-1);
chrif_keepalive(char_fd);
@@ -1431,7 +1463,7 @@ int ping_char_server(int tid, unsigned int tick, int id, intptr data)
}
// unused
-int send_usercount_tochar(int tid, unsigned int tick, int id, intptr data)
+int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data)
{
chrif_check(-1);
@@ -1476,7 +1508,7 @@ int send_users_tochar(void)
* timer関数
* char鯖との接続を確認し、もし切れていたら再度接続する
*------------------------------------------*/
-int check_connect_char_server(int tid, unsigned int tick, int id, intptr data)
+static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data)
{
static int displayed = 0;
if (char_fd <= 0 || session[char_fd] == NULL)
@@ -1491,7 +1523,6 @@ int check_connect_char_server(int tid, unsigned int tick, int id, intptr data)
char_fd = make_connection(char_ip, char_port);
if (char_fd == -1)
{ //Attempt to connect later. [Skotlex]
- char_fd = 0;
return 0;
}
@@ -1532,8 +1563,11 @@ int auth_db_final(DBKey k,void *d,va_list ap)
*------------------------------------------*/
int do_final_chrif(void)
{
- if (char_fd > 0)
+ if( char_fd != -1 )
+ {
do_close(char_fd);
+ char_fd = -1;
+ }
auth_db->destroy(auth_db, auth_db_final);
ers_destroy(auth_db_ers);
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 9ff5b9a0e..1f11cc6f2 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -25,6 +25,7 @@ int chrif_setip(const char* ip);
void chrif_setport(uint16 port);
int chrif_isconnected(void);
+void chrif_check_shutdown(void);
extern int chrif_connected;
extern int other_mapserver_count;
@@ -55,7 +56,6 @@ int send_users_tochar(void);
int chrif_char_online(struct map_session_data *sd);
int chrif_changesex(struct map_session_data *sd);
int chrif_chardisconnect(struct map_session_data *sd);
-int check_connect_char_server(int tid, unsigned int tick, int id, intptr data);
int chrif_divorce(int partner_id1, int partner_id2);
int do_final_chrif(void);
diff --git a/src/map/clif.c b/src/map/clif.c
index 81ab49799..8d2159823 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -581,10 +581,10 @@ int clif_authfail_fd(int fd, int type)
return 0;
}
-/*==========================================
- *
- *------------------------------------------*/
-int clif_charselectok(int id)
+/// Reply from char-server.
+/// Tells the player if it can connect to the char-server to select a character.
+/// ok=1 : client disconnects and tries to connect to the char-server
+int clif_charselectok(int id, uint8 ok)
{
struct map_session_data* sd;
int fd;
@@ -595,7 +595,7 @@ int clif_charselectok(int id)
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0xb3));
WFIFOW(fd,0) = 0xb3;
- WFIFOB(fd,2) = 1;
+ WFIFOB(fd,2) = ok;
WFIFOSET(fd,packet_len(0xb3));
return 0;
@@ -700,7 +700,7 @@ int clif_clearunit_area(struct block_list* bl, clr_type type)
return 0;
}
-static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr data)
+static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl = (struct block_list *)data;
clif_clearunit_area(bl, CLR_OUTSIGHT);
@@ -713,7 +713,7 @@ int clif_clearunit_delayed(struct block_list* bl, unsigned int tick)
struct block_list *tbl;
tbl = (struct block_list*)aMalloc(sizeof (struct block_list));
memcpy (tbl, bl, sizeof (struct block_list));
- add_timer(tick, clif_clearunit_delayed_sub, 0, (intptr)tbl);
+ add_timer(tick, clif_clearunit_delayed_sub, 0, (intptr_t)tbl);
return 0;
}
@@ -1376,6 +1376,12 @@ static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_
clif_specialeffect(&md->bl,421,AREA);
}
break;
+ case BL_PET:
+ if( vd->head_bottom )
+ {// needed to display pet equip properly
+ clif_pet_equip_area((TBL_PET*)bl);
+ }
+ break;
}
return;
}
@@ -1415,7 +1421,7 @@ void clif_move(struct unit_data *ud)
/*==========================================
* Delays the map_quit of a player after they are disconnected. [Skotlex]
*------------------------------------------*/
-static int clif_delayquit(int tid, unsigned int tick, int id, intptr data)
+static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd = NULL;
@@ -4192,7 +4198,7 @@ int clif_skillinfoblock(struct map_session_data *sd)
WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv);
WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->status.skill[i].lv);
safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH);
- if(sd->status.skill[i].flag == 0)
+ if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_))? 1:0;
else
WFIFOB(fd,len+36) = 0;
@@ -4229,7 +4235,7 @@ int clif_addskill(struct map_session_data *sd, int id )
WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv);
WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv);
safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH);
- if( sd->status.skill[id].flag == 0 )
+ if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0;
else
WFIFOB(fd,38) = 0;
@@ -4279,38 +4285,49 @@ int clif_skillup(struct map_session_data *sd,int skill_num)
return 0;
}
-/*==========================================
- * スキル詠唱エフェクトを送信する
- * pl:
- * 0 = Yellow cast aura
- * 1 = Water elemental cast aura
- * 2 = Earth elemental cast aura
- * 3 = Fire elemental cast aura
- * 4 = Wind elemental cast aura
- * 5 = Poison elemental cast aura
- * 6 = White cast aura
- * ? = like 0
- *------------------------------------------*/
-int clif_skillcasting(struct block_list* bl,
- int src_id,int dst_id,int dst_x,int dst_y,int skill_num,int pl, int casttime)
+
+/// Notifies clients, that an object is about to use a skill (ZC_USESKILL_ACK/ZC_USESKILL_ACK2)
+/// 013e <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L
+/// 07fb <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L <is disposable>.B
+/// property:
+/// 0 = Yellow cast aura
+/// 1 = Water elemental cast aura
+/// 2 = Earth elemental cast aura
+/// 3 = Fire elemental cast aura
+/// 4 = Wind elemental cast aura
+/// 5 = Poison elemental cast aura
+/// 6 = Holy elemental cast aura
+/// ? = like 0
+/// is disposable:
+/// 0 = yellow chat text "[src name] will use skill [skill name]."
+/// 1 = no text
+void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime)
{
+#if PACKETVER < 20091124
+ const int cmd = 0x13e;
+#else
+ const int cmd = 0x7fb;
+#endif
unsigned char buf[32];
- WBUFW(buf,0) = 0x13e;
+
+ WBUFW(buf,0) = cmd;
WBUFL(buf,2) = src_id;
WBUFL(buf,6) = dst_id;
WBUFW(buf,10) = dst_x;
WBUFW(buf,12) = dst_y;
WBUFW(buf,14) = skill_num;
- WBUFL(buf,16) = pl<0?0:pl; //Avoid sending negatives as element [Skotlex]
+ WBUFL(buf,16) = property<0?0:property; //Avoid sending negatives as element [Skotlex]
WBUFL(buf,20) = casttime;
+#if PACKETVER >= 20091124
+ WBUFB(buf,24) = 1; // isDisposable
+#endif
+
if (disguised(bl)) {
- clif_send(buf,packet_len(0x13e), bl, AREA_WOS);
+ clif_send(buf,packet_len(cmd), bl, AREA_WOS);
WBUFL(buf,2) = -src_id;
- clif_send(buf,packet_len(0x13e), bl, SELF);
+ clif_send(buf,packet_len(cmd), bl, SELF);
} else
- clif_send(buf,packet_len(0x13e), bl, AREA);
-
- return 0;
+ clif_send(buf,packet_len(cmd), bl, AREA);
}
/*==========================================
@@ -5821,28 +5838,32 @@ void clif_partyinvitationstate(struct map_session_data* sd)
WFIFOSET(fd, packet_len(0x2c9));
}
-/*==========================================
- * パーティ勧誘
- *------------------------------------------*/
-int clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd)
+/// Party invitation request (ZC_REQ_JOIN_GROUP/ZC_PARTY_JOIN_REQ)
+/// 00fe <party id>.L <party name>.24B
+/// 02c6 <party id>.L <party name>.24B
+void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd)
{
+#if PACKETVER < 20070821
+ const int cmd = 0xfe;
+#else
+ const int cmd = 0x2c6;
+#endif
int fd;
struct party_data *p;
- nullpo_ret(sd);
- nullpo_ret(tsd);
+ nullpo_retv(sd);
+ nullpo_retv(tsd);
fd=tsd->fd;
if( (p=party_search(sd->status.party_id))==NULL )
- return 0;
+ return;
- WFIFOHEAD(fd,packet_len(0xfe));
- WFIFOW(fd,0)=0xfe;
- WFIFOL(fd,2)=sd->status.account_id; // FIXME: This is party_id
+ WFIFOHEAD(fd,packet_len(cmd));
+ WFIFOW(fd,0)=cmd;
+ WFIFOL(fd,2)=sd->status.party_id;
memcpy(WFIFOP(fd,6),p->party.name,NAME_LENGTH);
- WFIFOSET(fd,packet_len(0xfe));
- return 0;
+ WFIFOSET(fd,packet_len(cmd));
}
/*==========================================
@@ -7643,6 +7664,8 @@ int clif_refresh(struct map_session_data *sd)
clif_weather_check(sd);
if( sd->chatID )
chat_leavechat(sd,0);
+ if( sd->state.vending )
+ clif_openvending(sd, sd->bl.id, sd->vending);
if( pc_issit(sd) )
clif_sitting(&sd->bl); // FIXME: just send to self, not area
if( pc_isdead(sd) ) //When you refresh, resend the death packet.
@@ -7650,6 +7673,9 @@ int clif_refresh(struct map_session_data *sd)
else
clif_changed_dir(&sd->bl, SELF);
+ // unlike vending, resuming buyingstore crashes the client.
+ buyingstore_close(sd);
+
#ifndef TXT_ONLY
mail_clear(sd);
#endif
@@ -8371,6 +8397,12 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd)
return;
}
+ if( runflag != MAPSERVER_ST_RUNNING )
+ {// not allowed
+ clif_authfail_fd(fd,1);// server closed
+ return;
+ }
+
//Check for double login.
bl = map_id2bl(account_id);
if(bl && bl->type != BL_PC) {
@@ -10620,12 +10652,12 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
party_invite(sd, t_sd);
}
-/*==========================================
- * Party invitation reply
- * S 00ff <account ID>.L <flag>.L
- * S 02c7 <account ID>.L <flag>.B
- * flag: 0-reject, 1-accept
- *------------------------------------------*/
+/// Party invitation reply (CZ_JOIN_GROUP/CZ_PARTY_JOIN_REQ_ACK)
+/// 00ff <party id>.L <flag>.L
+/// 02c7 <party id>.L <flag>.B
+/// flag:
+/// 0 = reject
+/// 1 = accept
void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd)
{
party_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6));
@@ -11995,6 +12027,11 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
return;
}
+ if( sd->bl.id == f_sd->bl.id )
+ {// adding oneself as friend
+ return;
+ }
+
// @noask [LuzZza]
if(f_sd->state.noask) {
clif_noask_sub(sd, f_sd, 5);
@@ -12037,6 +12074,11 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
char_id = RFIFOL(fd,6);
reply = RFIFOB(fd,10);
+ if( sd->bl.id == account_id )
+ {// adding oneself as friend
+ return;
+ }
+
f_sd = map_id2sd(account_id); //The account id is the same as the bl.id of players.
if (f_sd == NULL)
return;
@@ -12305,10 +12347,8 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
sd->menuskill_val = sd->menuskill_id = 0;
}
-/*==========================================
- * Question about Star Glaldiator save map [Komurka]
- *------------------------------------------*/
-void clif_parse_ReqFeel(int fd, struct map_session_data *sd, int skilllv)
+/// Star Gladiator's Feeling map confirmation prompt (ZC_STARPLACE)
+void clif_feel_req(int fd, struct map_session_data *sd, int skilllv)
{
WFIFOHEAD(fd,packet_len(0x253));
WFIFOW(fd,0)=0x253;
@@ -13957,11 +13997,11 @@ int clif_instance(int instance_id, int type, int flag)
switch( type )
{
case 1:
- // S 0x2cb <Instance name>.63B <Standby Position>.W
+ // S 0x2cb <Instance name>.61B <Standby Position>.W
// Required to start the instancing information window on Client
// This window re-appear each "refresh" of client automatically until type 4 is send to client.
WBUFW(buf,0) = 0x02CB;
- memcpy(WBUFP(buf,2),instance[instance_id].name,61);
+ memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH);
WBUFW(buf,63) = flag;
clif_send(buf,packet_len(0x02CB),&sd->bl,PARTY);
break;
@@ -13989,14 +14029,16 @@ int clif_instance(int instance_id, int type, int flag)
}
clif_send(buf,packet_len(0x02CD),&sd->bl,PARTY);
break;
- case 5: // R 02CE <message ID>.L
+ case 5:
// S 0x2ce <Message ID>.L
+ // 0 = Notification (EnterLimitDate update?)
// 1 = The Memorial Dungeon expired; it has been destroyed
// 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed
// 3 = The Memorial Dungeon has been removed.
- // 4 = Just remove the window, maybe party/guild leave
+ // 4 = Create failure (removes the instance window)
WBUFW(buf,0) = 0x02CE;
WBUFL(buf,2) = flag;
+ //WBUFL(buf,6) = EnterLimitDate;
clif_send(buf,packet_len(0x02CE),&sd->bl,PARTY);
break;
}
@@ -14911,7 +14953,7 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 0, 0, 0, 0, 0,
//#0x02C0
- 0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 0, 65, 4, 71, 10, 0,
+ 0, 0, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0,
0, 0, 0, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 59, 60, 8,
10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -15018,7 +15060,7 @@ static int packetdb_readdb(void)
6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54,
#endif
0, 0, 0, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 0, 0, 0, 26, 0,
+ 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0,
//#0x0800
#if PACKETVER < 20091229
-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20,
diff --git a/src/map/clif.h b/src/map/clif.h
index 70a7fdce8..0feeb22b5 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -220,7 +220,7 @@ uint16 clif_getport(void);
int clif_authok(struct map_session_data *);
int clif_authfail_fd(int fd,int type);
-int clif_charselectok(int);
+int clif_charselectok(int id, uint8 ok);
int clif_dropflooritem(struct flooritem_data *);
int clif_clearflooritem(struct flooritem_data *,int);
@@ -326,7 +326,7 @@ int clif_skillup(struct map_session_data *sd,int skill_num);
int clif_addskill(struct map_session_data *sd, int skill);
int clif_deleteskill(struct map_session_data *sd, int skill);
-int clif_skillcasting(struct block_list* bl,int src_id,int dst_id,int dst_x,int dst_y,int skill_num,int pl,int casttime);
+void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime);
int clif_skillcastcancel(struct block_list* bl);
int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype);
int clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick);
@@ -404,7 +404,7 @@ int clif_movetoattack(struct map_session_data *sd,struct block_list *bl);
int clif_party_created(struct map_session_data *sd,int result);
int clif_party_member_info(struct party_data *p, struct map_session_data *sd);
int clif_party_info(struct party_data *p, struct map_session_data *sd);
-int clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd);
+void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd);
void clif_party_inviteack(struct map_session_data* sd, const char* nick, int flag);
int clif_party_option(struct party_data *p,struct map_session_data *sd,int flag);
int clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag);
@@ -515,7 +515,7 @@ void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, un
int clif_party_xy_remove(struct map_session_data *sd); //Fix for minimap [Kevin]
void clif_gospel_info(struct map_session_data *sd, int type);
-void clif_parse_ReqFeel(int fd, struct map_session_data *sd, int skilllv);
+void clif_feel_req(int fd, struct map_session_data *sd, int skilllv);
void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result);
void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type);
void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type);
diff --git a/src/map/guild.c b/src/map/guild.c
index c80b124ef..0b77aa9a1 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -61,8 +61,8 @@ struct{
}need[6];
} guild_skill_tree[MAX_GUILDSKILL];
-int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data);
-static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data);
+int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data);
+static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
/*==========================================
* Retrieves and validates the sd pointer for this guild member [Skotlex]
@@ -308,7 +308,7 @@ int guild_payexp_timer_sub(DBKey dataid, void *data, va_list ap)
return 0;
}
-int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data)
+int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data)
{
guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub);
return 0;
@@ -336,7 +336,7 @@ int guild_send_xy_timer_sub(DBKey key,void *data,va_list ap)
}
//Code from party_send_xy_timer [Skotlex]
-static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data)
+static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick);
return 0;
@@ -1840,7 +1840,7 @@ int guild_castlealldataload(int len,struct guild_castle *gc)
}
// update mapserver castle data with new info
- memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((uintptr)&c->guild_id - (uintptr)c));
+ memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((uintptr_t)&c->guild_id - (uintptr_t)c));
if( c->guild_id )
{
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index 7bfb6081d..50b7c2c7a 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -45,7 +45,7 @@
struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn]
struct skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE];
-static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr data);
+static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data);
static unsigned int hexptbl[MAX_LEVEL];
@@ -196,7 +196,7 @@ void merc_hom_skillup(struct homun_data *hd,int skillnum)
i = skillnum - HM_SKILLBASE;
if(hd->homunculus.skillpts > 0 &&
hd->homunculus.hskill[i].id &&
- hd->homunculus.hskill[i].flag == 0 && //Don't allow raising while you have granted skills. [Skotlex]
+ hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->homunculus.class_)
)
{
@@ -480,7 +480,7 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd)
return 0;
}
-static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr data)
+static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
struct homun_data *hd;
diff --git a/src/map/instance.c b/src/map/instance.c
index e9ff2b409..d533a0188 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -28,6 +28,24 @@
int instance_start = 0; // To keep the last index + 1 of normal map inserted in the map[ARRAY]
struct s_instance instance[MAX_INSTANCE];
+
+/// Checks whether given instance id is valid or not.
+static bool instance_is_valid(int instance_id)
+{
+ if( instance_id < 1 || instance_id >= ARRAYLENGTH(instance) )
+ {// out of range
+ return false;
+ }
+
+ if( instance[instance_id].state == INSTANCE_FREE )
+ {// uninitialized/freed instance slot
+ return false;
+ }
+
+ return true;
+}
+
+
/*--------------------------------------
* name : instance name
* Return value could be
@@ -62,13 +80,13 @@ int instance_create(int party_id, const char *name)
instance[i].idle_timer = INVALID_TIMER;
instance[i].idle_timeout = instance[i].idle_timeoutval = 0;
instance[i].progress_timer = INVALID_TIMER;
- instance[i].progress_timeout = instance[i].progress_timeoutval = 0;
+ instance[i].progress_timeout = 0;
instance[i].users = 0;
instance[i].party_id = party_id;
instance[i].ivar = NULL;
instance[i].svar = NULL;
- memcpy( instance[i].name, name, sizeof(instance[i].name) );
+ safestrncpy( instance[i].name, name, sizeof(instance[i].name) );
memset( instance[i].map, 0x00, sizeof(instance[i].map) );
p->instance_id = i;
@@ -88,7 +106,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename)
if( m < 0 )
return -1; // source map not found
- if( instance[instance_id].state == INSTANCE_FREE )
+ if( !instance_is_valid(instance_id) )
{
ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id);
return -1;
@@ -158,6 +176,12 @@ int instance_add_map(const char *name, int instance_id, bool usebasename)
int instance_map2imap(int m, int instance_id)
{
int i;
+
+ if( !instance_is_valid(instance_id) )
+ {
+ return -1;
+ }
+
for( i = 0; i < instance[instance_id].num_map; i++ )
{
if( instance[instance_id].map[i] && map[instance[instance_id].map[i]].instance_src_map == m )
@@ -173,7 +197,6 @@ int instance_map2imap(int m, int instance_id)
*--------------------------------------*/
int instance_mapid2imapid(int m, int instance_id)
{
- int i, max;
if( map[m].flag.src4instance == 0 )
return m; // not instances found for this map
else if( map[m].instance_id )
@@ -182,16 +205,10 @@ int instance_mapid2imapid(int m, int instance_id)
return -1;
}
- if( instance_id <= 0 )
+ if( !instance_is_valid(instance_id) )
return -1;
- max = instance[instance_id].num_map;
-
- for( i = 0; i < max; i++ )
- if( map[instance[instance_id].map[i]].instance_src_map == m )
- return instance[instance_id].map[i];
-
- return -1;
+ return instance_map2imap(m, instance_id);
}
/*--------------------------------------
@@ -214,13 +231,13 @@ void instance_init(int instance_id)
{
int i;
- if( !instance_id )
+ if( !instance_is_valid(instance_id) )
return; // nothing to do
for( i = 0; i < instance[instance_id].num_map; i++ )
map_foreachinmap(instance_map_npcsub, map[instance[instance_id].map[i]].instance_src_map, BL_NPC, instance[instance_id].map[i]);
- instance[instance_id].state = INSTANCE_BUSSY;
+ instance[instance_id].state = INSTANCE_BUSY;
ShowInfo("[Instance] Initialized %s.\n", instance[instance_id].name);
}
@@ -294,7 +311,7 @@ void instance_destroy_freesvar(void *key, void *data, va_list args)
/*--------------------------------------
* Timer to destroy instance by process or idle
*--------------------------------------*/
-int instance_destroy_timer(int tid, unsigned int tick, int id, intptr data)
+int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
instance_destroy(id);
return 0;
@@ -309,7 +326,7 @@ void instance_destroy(int instance_id)
struct party_data *p;
time_t now = time(NULL);
- if( !instance_id || instance[instance_id].state == INSTANCE_FREE )
+ if( !instance_is_valid(instance_id) )
return; // nothing to do
if( instance[instance_id].progress_timeout && instance[instance_id].progress_timeout <= now )
@@ -361,7 +378,7 @@ void instance_check_idle(int instance_id)
bool idle = true;
time_t now = time(NULL);
- if( !instance_id || instance[instance_id].idle_timeoutval == 0 )
+ if( !instance_is_valid(instance_id) || instance[instance_id].idle_timeoutval == 0 )
return;
if( instance[instance_id].users )
@@ -389,7 +406,7 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign
{
time_t now = time(0);
- if( !instance_id )
+ if( !instance_is_valid(instance_id) )
return;
if( instance[instance_id].progress_timer != INVALID_TIMER )
@@ -399,13 +416,11 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign
if( progress_timeout )
{
- instance[instance_id].progress_timeoutval = progress_timeout;
instance[instance_id].progress_timeout = now + progress_timeout;
instance[instance_id].progress_timer = add_timer( gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0);
}
else
{
- instance[instance_id].progress_timeoutval = 0;
instance[instance_id].progress_timeout = 0;
instance[instance_id].progress_timer = INVALID_TIMER;
}
@@ -444,6 +459,14 @@ void instance_check_kick(struct map_session_data *sd)
}
}
+void do_final_instance(void)
+{
+ int i;
+
+ for( i = 1; i < MAX_INSTANCE; i++ )
+ instance_destroy(i);
+}
+
void do_init_instance(void)
{
memset(instance, 0x00, sizeof(instance));
diff --git a/src/map/instance.h b/src/map/instance.h
index c663503f5..e2b0354f9 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -7,10 +7,12 @@
#define MAX_MAP_PER_INSTANCE 10
#define MAX_INSTANCE 500
-typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSSY } instance_state;
+#define INSTANCE_NAME_LENGTH (60+1)
+
+typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSY } instance_state;
struct s_instance {
- char name[61]; // Instance Name - required for clif functions.
+ char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions.
instance_state state;
short instance_id;
int party_id;
@@ -22,7 +24,7 @@ struct s_instance {
struct linkdb_node *ivar, *svar; // Instance Variable for scripts
int progress_timer;
- time_t progress_timeout, progress_timeoutval;
+ time_t progress_timeout;
int idle_timer;
time_t idle_timeout, idle_timeoutval;
@@ -43,6 +45,7 @@ void instance_check_idle(int instance_id);
void instance_check_kick(struct map_session_data *sd);
void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout);
-void do_init_instance();
+void do_final_instance(void);
+void do_init_instance(void);
#endif
diff --git a/src/map/map.c b/src/map/map.c
index c086b73c0..bc9465781 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -240,7 +240,7 @@ int map_freeblock_unlock (void)
// この関数は、do_timer() のトップレベルから呼ばれるので、
// block_free_lock を直接いじっても支障無いはず。
-int map_freeblock_timer(int tid, unsigned int tick, int id, intptr data)
+int map_freeblock_timer(int tid, unsigned int tick, int id, intptr_t data)
{
if (block_free_lock > 0) {
ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock);
@@ -1217,7 +1217,7 @@ int map_get_new_object_id(void)
* 後者は、map_clearflooritem(id)へ
* map.h?で#defineしてある
*------------------------------------------*/
-int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr data)
+int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct flooritem_data* fitem = (struct flooritem_data*)idb_get(id_db, id);
if( fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid) )
@@ -2146,7 +2146,7 @@ int map_removemobs_sub(struct block_list *bl, va_list ap)
return 1;
}
-int map_removemobs_timer(int tid, unsigned int tick, int id, intptr data)
+int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data)
{
int count;
const int m = id;
@@ -2727,7 +2727,7 @@ int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer)
}
// TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo]
- uncompress(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len);
+ decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len);
CREATE(m->cell, struct mapcell, size);
@@ -3436,9 +3436,6 @@ void do_final(void)
for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
map_quit(sd);
mapit_free(iter);
-
- for( i = 0; i < MAX_INSTANCE; i++ )
- instance_destroy(i);
id_db->foreach(id_db,cleanup_db_sub);
chrif_char_reset_offline();
@@ -3449,6 +3446,7 @@ void do_final(void)
do_final_chrif();
do_final_npc();
do_final_script();
+ do_final_instance();
do_final_itemdb();
do_final_storage();
do_final_guild();
@@ -3491,7 +3489,7 @@ void do_final(void)
#ifndef TXT_ONLY
map_sql_close();
#endif /* not TXT_ONLY */
- ShowStatus("Successfully terminated.\n");
+ ShowStatus("Finished.\n");
}
static int map_abort_sub(struct map_session_data* sd, va_list ap)
@@ -3573,6 +3571,27 @@ void set_server_type(void)
SERVER_TYPE = ATHENA_SERVER_MAP;
}
+
+/// Called when a terminate signal is received.
+void do_shutdown(void)
+{
+ if( runflag != MAPSERVER_ST_SHUTDOWN )
+ {
+ runflag = MAPSERVER_ST_SHUTDOWN;
+ ShowStatus("Shutting down...\n");
+ {
+ struct map_session_data* sd;
+ struct s_mapiterator* iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
+ clif_GM_kick(NULL, sd);
+ mapit_free(iter);
+ flush_fifos();
+ }
+ chrif_check_shutdown();
+ }
+}
+
+
int do_init(int argc, char *argv[])
{
int i;
@@ -3710,6 +3729,12 @@ int do_init(int argc, char *argv[])
ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
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 )
+ {
+ shutdown_callback = do_shutdown;
+ runflag = MAPSERVER_ST_RUNNING;
+ }
return 0;
}
diff --git a/src/map/map.h b/src/map/map.h
index d572cec4c..36496280e 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -4,9 +4,8 @@
#ifndef _MAP_H_
#define _MAP_H_
-#ifndef _CBASETYPES_H_
#include "../common/cbasetypes.h"
-#endif
+#include "../common/core.h" // CORE_ST_LAST
#include "../common/mmo.h"
#include "../common/mapindex.h"
#include "../common/db.h"
@@ -16,6 +15,13 @@
struct npc_data;
struct item_data;
+enum E_MAPSERVER_ST
+{
+ MAPSERVER_ST_RUNNING = CORE_ST_LAST,
+ MAPSERVER_ST_SHUTDOWN,
+ MAPSERVER_ST_LAST
+};
+
//Uncomment to enable the Cell Stack Limit mod.
//It's only config is the battle_config cell_stack_limit.
//Only chars affected are those defined in BL_CHAR (mobs and players currently)
@@ -615,8 +621,8 @@ int map_quit(struct map_session_data *);
bool map_addnpc(int,struct npc_data *);
// 床アイテム関連
-int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr data);
-int map_removemobs_timer(int tid, unsigned int tick, int id, intptr data);
+int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data);
+int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data);
#define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1)
int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int first_charid,int second_charid,int third_charid,int flags);
@@ -739,4 +745,6 @@ extern char mob_db2_db[32];
#endif /* not TXT_ONLY */
+void do_shutdown(void);
+
#endif /* _MAP_H_ */
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index f80be56a2..455da0f49 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -184,7 +184,7 @@ static void script_save_mapreg(void)
mapreg_dirty = false;
}
-static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data)
+static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data)
{
if( mapreg_dirty )
script_save_mapreg();
diff --git a/src/map/mapreg_txt.c b/src/map/mapreg_txt.c
index 555b773ee..95be201e2 100644
--- a/src/map/mapreg_txt.c
+++ b/src/map/mapreg_txt.c
@@ -151,7 +151,7 @@ static void script_save_mapreg(void)
mapreg_dirty = false;
}
-static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr data)
+static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data)
{
if( mapreg_dirty )
script_save_mapreg();
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 8300628d5..f6fa6bdaa 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -215,7 +215,7 @@ int mercenary_save(struct mercenary_data *md)
return 1;
}
-static int merc_contract_end(int tid, unsigned int tick, int id, intptr data)
+static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
struct mercenary_data *md;
diff --git a/src/map/mob.c b/src/map/mob.c
index 4c8fa685a..5fb440b4f 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -81,7 +81,7 @@ const int mob_splendide[5] = { 1991, 1992, 1993, 1994, 1995 };
* Local prototype declaration (only required thing)
*------------------------------------------*/
static int mob_makedummymobdb(int);
-static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr data);
+static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data);
int mob_skillid2skillidx(int class_,int skillid);
/*==========================================
@@ -507,7 +507,7 @@ int mob_once_spawn_area(struct map_session_data* sd,int m,int x0,int y0,int x1,i
/*==========================================
* Set a Guardian's guild data [Skotlex]
*------------------------------------------*/
-static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr data)
+static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data)
{ //Needed because the guild_data may not be available at guardian spawn time.
struct block_list* bl = map_id2bl(id);
struct mob_data* md;
@@ -766,7 +766,7 @@ int mob_linksearch(struct block_list *bl,va_list ap)
/*==========================================
* mob spawn with delay (timer function)
*------------------------------------------*/
-int mob_delayspawn(int tid, unsigned int tick, int id, intptr data)
+int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list* bl = map_id2bl(id);
struct mob_data* md = BL_CAST(BL_MOB, bl);
@@ -1636,7 +1636,7 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
/*==========================================
* Negligent processing for mob outside PC field of view (interval timer function)
*------------------------------------------*/
-static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr data)
+static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data)
{
map_foreachmob(mob_ai_sub_lazy,tick);
return 0;
@@ -1645,7 +1645,7 @@ static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr data)
/*==========================================
* Serious processing for mob in PC field of view (interval timer function)
*------------------------------------------*/
-static int mob_ai_hard(int tid, unsigned int tick, int id, intptr data)
+static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data)
{
if (battle_config.mob_ai&0x20)
@@ -1684,7 +1684,7 @@ static struct item_drop* mob_setlootitem(struct item* item)
/*==========================================
* item drop with delay (timer function)
*------------------------------------------*/
-static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr data)
+static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data)
{
struct item_drop_list *list;
struct item_drop *ditem, *ditem_prev;
@@ -1744,7 +1744,7 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str
dlist->item = ditem;
}
-int mob_timer_delete(int tid, unsigned int tick, int id, intptr data)
+int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list* bl = map_id2bl(id);
struct mob_data* md = BL_CAST(BL_MOB, bl);
@@ -1791,7 +1791,7 @@ int mob_deleteslave(struct mob_data *md)
return 0;
}
// Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
-int mob_respawn(int tid, unsigned int tick, int id, intptr data)
+int mob_respawn(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl = map_id2bl(id);
@@ -2296,7 +2296,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
}
if (dlist->item) //There are drop items.
- add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr)dlist);
+ add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist);
else //No drops
ers_free(item_drop_list_ers, dlist);
} else if (md->lootitem && md->lootitem_count) { //Loot MUST drop!
@@ -2310,7 +2310,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
dlist->item = NULL;
for(i = 0; i < md->lootitem_count; i++)
mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
- add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr)dlist);
+ add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist);
}
if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai)
@@ -3407,7 +3407,7 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
*------------------------------------------*/
static bool mob_parse_dbrow(char** str)
{
- struct mob_db *db;
+ struct mob_db *db, entry;
struct status_data *status;
int class_, i, k;
double exp, maxhp;
@@ -3416,29 +3416,28 @@ static bool mob_parse_dbrow(char** str)
class_ = atoi(str[0]);
if (class_ <= 1000 || class_ > MAX_MOB_DB) {
- ShowWarning("Mob with ID: %d not loaded. ID must be in range [%d-%d]\n", class_, 1000, MAX_MOB_DB);
+ ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB);
return false;
}
if (pcdb_checkid(class_)) {
- ShowWarning("Mob with ID: %d not loaded. That ID is reserved for player classes.\n", class_);
+ ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_);
return false;
}
if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) {
- ShowWarning("Mob with ID: %d not loaded. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d)\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB);
+ ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB);
return false;
}
- if (mob_db_data[class_] == NULL)
- mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db));
+ memset(&entry, 0, sizeof(entry));
- db = mob_db_data[class_];
+ db = &entry;
status = &db->status;
db->vd.class_ = class_;
- strncpy(db->sprite, str[1], NAME_LENGTH);
- strncpy(db->jname, str[2], NAME_LENGTH);
- strncpy(db->name, str[3], NAME_LENGTH);
+ safestrncpy(db->sprite, str[1], sizeof(db->sprite));
+ safestrncpy(db->jname, str[2], sizeof(db->jname));
+ safestrncpy(db->name, str[3], sizeof(db->name));
db->lv = atoi(str[4]);
db->lv = cap_value(db->lv, 1, USHRT_MAX);
status->max_hp = atoi(str[5]);
@@ -3489,12 +3488,12 @@ static bool mob_parse_dbrow(char** str)
status->def_ele = i%10;
status->ele_lv = i/20;
if (status->def_ele >= ELE_MAX) {
- ShowWarning("Mob with ID: %d has invalid element type %d (max element is %d)\n", class_, status->def_ele, ELE_MAX-1);
- status->def_ele = ELE_NEUTRAL;
+ ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1);
+ return false;
}
if (status->ele_lv < 1 || status->ele_lv > 4) {
- ShowWarning("Mob with ID: %d has invalid element level %d (max is 4)\n", class_, status->ele_lv);
- status->ele_lv = 1;
+ ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_);
+ return false;
}
status->mode = (int)strtol(str[25], NULL, 0);
@@ -3512,7 +3511,8 @@ static bool mob_parse_dbrow(char** str)
status->dmotion = atoi(str[29]);
if(battle_config.monster_damage_delay_rate != 100)
status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100;
-
+
+ // Fill in remaining status data by using a dummy monster.
data.bl.type = BL_MOB;
data.level = db->lv;
memcpy(&data.status, status, sizeof(struct status_data));
@@ -3632,7 +3632,12 @@ static bool mob_parse_dbrow(char** str)
id->mob[k].id = class_;
}
}
-
+
+ // Finally insert monster's data into the database.
+ if (mob_db_data[class_] == NULL)
+ mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db));
+
+ memcpy(mob_db_data[class_], db, sizeof(struct mob_db));
return true;
}
diff --git a/src/map/mob.h b/src/map/mob.h
index 605439f12..9e86b8d63 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -239,7 +239,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist);
int mob_unlocktarget(struct mob_data *md, unsigned int tick);
struct mob_data* mob_spawn_dataset(struct spawn_data *data);
int mob_spawn(struct mob_data *md);
-int mob_delayspawn(int tid, unsigned int tick, int id, intptr data);
+int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data);
int mob_setdelayspawn(struct mob_data *md);
int mob_parse_dataset(struct spawn_data *data);
void mob_log_damage(struct mob_data *md, struct block_list *src, int damage);
@@ -256,7 +256,7 @@ void mob_clear_spawninfo();
int do_init_mob(void);
int do_final_mob(void);
-int mob_timer_delete(int tid, unsigned int tick, int id, intptr data);
+int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data);
int mob_deleteslave(struct mob_data *md);
int mob_random_class (int *value, size_t count);
diff --git a/src/map/npc.c b/src/map/npc.c
index d070b6886..dd3a671b0 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -356,7 +356,7 @@ bool npc_event_isspecial(const char* eventname)
/*==========================================
* 時計イベント実行
*------------------------------------------*/
-int npc_event_do_clock(int tid, unsigned int tick, int id, intptr data)
+int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data)
{
static struct tm ev_tm_b; // tracks previous execution time
time_t timer;
@@ -455,7 +455,7 @@ struct timer_event_data {
/*==========================================
* triger 'OnTimerXXXX' events
*------------------------------------------*/
-int npc_timerevent(int tid, unsigned int tick, int id, intptr data)
+int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
{
int next;
int old_rid, old_timer;
@@ -498,9 +498,9 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr data)
next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer;
ted->time += next;
if( sd )
- sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr)ted);
+ sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted);
else
- nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr)ted);
+ nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted);
}
else
{
@@ -570,13 +570,13 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
if( sd )
{
ted->rid = sd->bl.id; // Attach only the player if attachplayerrid was used.
- sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr)ted);
+ sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted);
}
else
{
ted->rid = 0;
nd->u.scr.timertick = tick; // Set when timer is started
- nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr)ted);
+ nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted);
}
return 0;
@@ -1164,8 +1164,8 @@ static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* i
// save list of bought items
for( i = 0; i < n; i++ )
{
- script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr)item_list[i*2+1], &key_nameid);
- script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr)item_list[i*2], &key_amount);
+ script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid);
+ script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount);
}
// invoke event
@@ -1369,8 +1369,9 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
// custom merchant shop exp bonus
if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 )
{
- if( sd->status.skill[MC_DISCOUNT].flag != 0 )
- skill = sd->status.skill[MC_DISCOUNT].flag - 2;
+ if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0;
+
if( skill > 0 )
{
z = z * (double)skill * (double)battle_config.shop_exp/10000.;
@@ -1401,8 +1402,8 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
{
idx = item_list[i*2]-2;
- script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr)sd->status.inventory[idx].nameid, &key_nameid);
- script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr)item_list[i*2+1], &key_amount);
+ script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid);
+ script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount);
}
// invoke event
@@ -1505,8 +1506,9 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
// custom merchant shop exp bonus
if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0)
{
- if( sd->status.skill[MC_OVERCHARGE].flag != 0 )
- skill = sd->status.skill[MC_OVERCHARGE].flag - 2;
+ if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0;
+
if( skill > 0 )
{
z = z * (double)skill * (double)battle_config.shop_exp/10000.;
@@ -2734,13 +2736,13 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
// check monster ID if exists!
if( mobdb_checkid(class_) == 0 )
{
- ShowError("npc_parse_mob: Unknown mob ID : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
if( num < 1 || num > 1000 )
{
- ShowError("npc_parse_mob: Invalid number of monsters (must be inside the range [1,1000]) : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
@@ -2786,7 +2788,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
}
if(mob.delay1>0xfffffff || mob.delay2>0xfffffff) {
- ShowError("npc_parse_mob: wrong monsters spawn delays : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mob.delay1, mob.delay2, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
@@ -2801,7 +2803,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
//Verify dataset.
if( !mob_parse_dataset(&mob) )
{
- ShowError("npc_parse_mob: Invalid dataset : %s %s (file '%s', line '%d').\n", w3, w4, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
diff --git a/src/map/npc.h b/src/map/npc.h
index 6e7c7cbeb..29e3d79cb 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -77,7 +77,7 @@ struct npc_data {
#define MAX_NPC_CLASS 1000
//Checks if a given id is a valid npc id. [Skotlex]
//Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001)
-#define npcdb_checkid(id) ((id >= 46 && id <= 125) || id == 139 || (id >= 400 && id <= MAX_NPC_CLASS) || id == INVISIBLE_CLASS)
+#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == 139 || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS )
#ifdef PCRE_SUPPORT
void npc_chat_finalize(struct npc_data* nd);
diff --git a/src/map/party.c b/src/map/party.c
index 47dba49e9..88f53bcb0 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -32,7 +32,7 @@ static DBMap* party_db; // int party_id -> struct party_data*
static DBMap* party_booking_db; // Party Booking [Spiria]
static unsigned long party_booking_nextid = 1;
-int party_send_xy_timer(int tid, unsigned int tick, int id, intptr data);
+int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
/*==========================================
* Fills the given party_member structure according to the sd provided.
@@ -369,11 +369,19 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
return 1;
}
-void party_reply_invite(struct map_session_data *sd,int account_id,int flag)
+void party_reply_invite(struct map_session_data *sd,int party_id,int flag)
{
- struct map_session_data *tsd= map_id2sd(account_id);
+ struct map_session_data* tsd;
struct party_member member;
+ if( sd->party_invite != party_id )
+ {// forged
+ sd->party_invite = 0;
+ sd->party_invite_account = 0;
+ return;
+ }
+ tsd = map_id2sd(sd->party_invite_account);
+
if( flag == 1 && !sd->party_creating && !sd->party_joining )
{// accepted and allowed
sd->party_joining = true;
@@ -832,7 +840,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, int skillid, in
return 0;
}
-int party_send_xy_timer(int tid, unsigned int tick, int id, intptr data)
+int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct party_data* p;
diff --git a/src/map/party.h b/src/map/party.h
index 31e46f5ec..1c59197b3 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -62,7 +62,7 @@ int party_member_added(int party_id,int account_id,int char_id,int flag);
int party_leave(struct map_session_data *sd);
int party_removemember(struct map_session_data *sd,int account_id,char *name);
int party_member_withdraw(int party_id,int account_id,int char_id);
-void party_reply_invite(struct map_session_data *sd,int account_id,int flag);
+void party_reply_invite(struct map_session_data *sd,int party_id,int flag);
int party_recv_noinfo(int party_id);
int party_recv_info(struct party *sp);
int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv);
diff --git a/src/map/pc.c b/src/map/pc.c
index 6d4002599..a9d798ade 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -85,7 +85,7 @@ int pc_isGM(struct map_session_data* sd)
return sd->gmlevel;
}
-static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr data)
+static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
@@ -123,7 +123,7 @@ void pc_delinvincibletimer(struct map_session_data* sd)
}
}
-static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr data)
+static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
int i;
@@ -295,7 +295,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type)
/*==========================================
Rental System
*------------------------------------------*/
-static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr data)
+static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd = map_id2sd(id);
if( sd == NULL )
@@ -695,7 +695,7 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd
return false;
}
- if( !(b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF) )
+ if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) )
return false;
return true;
@@ -1061,9 +1061,9 @@ int pc_reg_received(struct map_session_data *sd)
if (sd->cloneskill_id > 0) {
sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id;
sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV");
- if (i < sd->status.skill[sd->cloneskill_id].lv)
+ if (sd->status.skill[sd->cloneskill_id].lv > i)
sd->status.skill[sd->cloneskill_id].lv = i;
- sd->status.skill[sd->cloneskill_id].flag = 13; //cloneskill flag
+ sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED;
}
}
@@ -1124,11 +1124,11 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
) {
- if(!sd->status.skill[i].flag)
+ if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
skill_point += skill;
- else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) {
- skill_point += (sd->status.skill[i].flag - 2);
- }
+ else
+ if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0)
+ skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
}
}
}
@@ -1157,16 +1157,16 @@ int pc_calc_skilltree(struct map_session_data *sd)
for( i = 0; i < MAX_SKILL; i++ )
{
- if( sd->status.skill[i].flag != 13 ) //Don't touch plagiarized skills
+ if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills
sd->status.skill[i].id = 0; //First clear skills.
}
for( i = 0; i < MAX_SKILL; i++ )
{
- if( sd->status.skill[i].flag && sd->status.skill[i].flag != 13 )
+ if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
{ // Restore original level of skills after deleting earned skills.
- sd->status.skill[i].lv = (sd->status.skill[i].flag == 1)?0:sd->status.skill[i].flag-2;
- sd->status.skill[i].flag = 0;
+ sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
+ sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU )
@@ -1177,7 +1177,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
continue;
sd->status.skill[i].id = i;
sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
- sd->status.skill[i].flag = 1; // Tag it as a non-savable, non-uppable, bonus skill
+ sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
else
{ //Link bard skills to dancer.
@@ -1185,7 +1185,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
continue;
sd->status.skill[i-8].id = i - 8;
sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
- sd->status.skill[i-8].flag = 1; // Tag it as a non-savable, non-uppable, bonus skill
+ sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
}
}
@@ -1216,10 +1216,11 @@ int pc_calc_skilltree(struct map_session_data *sd)
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
if((k=skill_tree[c][i].need[j].id))
{
- if (!sd->status.skill[k].id || sd->status.skill[k].flag == 13)
+ if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED)
k = 0; //Not learned.
- else if (sd->status.skill[k].flag) //Real lerned level
- k = sd->status.skill[skill_tree[c][i].need[j].id].flag-2;
+ else
+ if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
+ k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
else
k = pc_checkskill(sd,k);
if (k < skill_tree[c][i].need[j].lv)
@@ -1249,7 +1250,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
if(inf2&INF2_SPIRIT_SKILL)
{ //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
sd->status.skill[id].lv = 1; // need to manually specify a skill level
- sd->status.skill[id].flag = 1; //So it is not saved, and tagged as a "bonus" skill.
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
}
flag = 1; // skill list has changed, perform another pass
}
@@ -1273,10 +1274,12 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( sd->status.skill[id].id == 0 )
{
sd->status.skill[id].id = id;
- sd->status.skill[id].flag = 1; // So it is not saved, and tagged as a "bonus" skill.
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
}
else
- sd->status.skill[id].flag = sd->status.skill[id].lv+2;
+ {
+ sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level
+ }
sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_);
}
@@ -1314,10 +1317,11 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill)
{
if( (k = skill_tree[c][i].need[j].id) )
{
- if( !sd->status.skill[k].id || sd->status.skill[k].flag == 13 )
+ if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED )
k = 0; //Not learned.
- else if( sd->status.skill[k].flag ) //Real lerned level
- k = sd->status.skill[skill_tree[c][i].need[j].id].flag - 2;
+ else
+ if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
+ k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
else
k = pc_checkskill(sd,k);
if( k < skill_tree[c][i].need[j].lv )
@@ -1352,13 +1356,15 @@ int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
for (i = 0; i < MAX_SKILL; i++){
- if (sd->status.skill[i].flag == 13 || sd->status.skill[i].flag == 1)
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED)
{
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
- } else if (sd->status.skill[i].flag){
- sd->status.skill[i].lv = sd->status.skill[i].flag-2;
+ }
+ else
+ if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){
+ sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = 0;
}
}
@@ -1716,14 +1722,14 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
}
- autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr)autobonus);
+ autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus);
sd->state.autobonus |= autobonus->pos;
status_calc_pc(sd,0);
return 0;
}
-int pc_endautobonus(int tid, unsigned int tick, int id, intptr data)
+int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd = map_id2sd(id);
struct s_autobonus *autobonus = (struct s_autobonus *)data;
@@ -2321,8 +2327,8 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
sd->right_weapon.hp_drain[RC_BOSS].value += val;
}
else if(sd->state.lr_flag == 1) {
- sd->right_weapon.hp_drain[RC_NONBOSS].value += val;
- sd->right_weapon.hp_drain[RC_BOSS].value += val;
+ sd->left_weapon.hp_drain[RC_NONBOSS].value += val;
+ sd->left_weapon.hp_drain[RC_BOSS].value += val;
}
break;
case SP_SP_DRAIN_VALUE:
@@ -3060,8 +3066,8 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
case 0: //Set skill data overwriting whatever was there before.
sd->status.skill[id].id = id;
sd->status.skill[id].lv = level;
- sd->status.skill[id].flag = 0;
- if( !level ) //Remove skill.
+ sd->status.skill[id].flag = SKILL_FLAG_PERMANENT;
+ if( level == 0 ) //Remove skill.
{
sd->status.skill[id].id = 0;
clif_deleteskill(sd,id);
@@ -3075,21 +3081,21 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
if( sd->status.skill[id].id == id ){
if( sd->status.skill[id].lv >= level )
return 0;
- if( !sd->status.skill[id].flag ) //Non-granted skill, store it's level.
- sd->status.skill[id].flag = sd->status.skill[id].lv + 2;
+ if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
+ sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv;
} else {
sd->status.skill[id].id = id;
- sd->status.skill[id].flag = 1;
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY;
}
sd->status.skill[id].lv = level;
break;
case 2: //Add skill bonus on top of what you had.
if( sd->status.skill[id].id == id ){
- if( !sd->status.skill[id].flag ) // Store previous level.
- sd->status.skill[id].flag = sd->status.skill[id].lv + 2;
+ if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
+ sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level.
} else {
sd->status.skill[id].id = id;
- sd->status.skill[id].flag = 1; //Set that this is a bonus skill.
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
}
sd->status.skill[id].lv += level;
break;
@@ -4789,7 +4795,8 @@ const char* job_name(int class_)
case JOB_WEDDING:
case JOB_SUPER_NOVICE:
-
+ case JOB_GUNSLINGER:
+ case JOB_NINJA:
case JOB_XMAS:
return msg_txt(570 - JOB_WEDDING+class_);
@@ -4870,11 +4877,6 @@ const char* job_name(int class_)
return msg_txt(617);
case JOB_SOUL_LINKER:
return msg_txt(618);
-
- case JOB_GUNSLINGER:
- return msg_txt(619);
- case JOB_NINJA:
- return msg_txt(620);
case JOB_RUNE_KNIGHT:
case JOB_WARLOCK:
@@ -4958,7 +4960,7 @@ const char* job_name(int class_)
}
}
-int pc_follow_timer(int tid, unsigned int tick, int id, intptr data)
+int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
struct block_list *tbl;
@@ -5507,7 +5509,7 @@ int pc_skillup(struct map_session_data *sd,int skill_num)
if( sd->status.skill_point > 0 &&
sd->status.skill[skill_num].id &&
- sd->status.skill[skill_num].flag == 0 && //Don't allow raising while you have granted skills. [Skotlex]
+ sd->status.skill[skill_num].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class_) )
{
sd->status.skill[skill_num].lv++;
@@ -5537,11 +5539,11 @@ int pc_allskillup(struct map_session_data *sd)
nullpo_ret(sd);
for(i=0;i<MAX_SKILL;i++){
- if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){
- sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2;
- sd->status.skill[i].flag=0;
- if (!sd->status.skill[i].lv)
- sd->status.skill[i].id=0;
+ if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
+ sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
+ sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
+ if (sd->status.skill[i].lv == 0)
+ sd->status.skill[i].id = 0;
}
}
@@ -5771,7 +5773,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE && (sd->class_&MAPID_UPPERMASK) != MAPID_BABY )
{ // Official server does not include Basic Skill to be resetted. [Jobbie]
sd->status.skill[i].lv = 9;
- sd->status.skill[i].flag = 0;
+ sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
continue;
}
@@ -5784,13 +5786,14 @@ int pc_resetskill(struct map_session_data* sd, int flag)
}
continue;
}
- if( !sd->status.skill[i].flag )
+ if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT )
skill_point += lv;
- else if( sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13 )
- skill_point += (sd->status.skill[i].flag - 2);
+ else
+ if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
if( !(flag&2) )
- {
+ {// reset
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
}
@@ -5896,7 +5899,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
}
-static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr data)
+static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd = map_id2sd(id);
if( sd != NULL )
@@ -6602,6 +6605,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
}
if(sd->cloneskill_id) {
+ if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
+ sd->status.skill[sd->cloneskill_id].id = 0;
+ sd->status.skill[sd->cloneskill_id].lv = 0;
+ sd->status.skill[sd->cloneskill_id].flag = 0;
+ clif_deleteskill(sd,sd->cloneskill_id);
+ }
sd->cloneskill_id = 0;
pc_setglobalreg(sd, "CLONE_SKILL", 0);
pc_setglobalreg(sd, "CLONE_SKILL_LV", 0);
@@ -7261,7 +7270,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v
/*==========================================
* イベントタイマ??理
*------------------------------------------*/
-static int pc_eventtimer(int tid, unsigned int tick, int id, intptr data)
+static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=map_id2sd(id);
char *p = (char *)data;
@@ -7295,7 +7304,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
if( i == MAX_EVENTTIMER )
return 0;
- sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr)aStrdup(name));
+ sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name));
sd->eventcount++;
return 1;
@@ -7761,7 +7770,7 @@ int pc_calc_pvprank(struct map_session_data *sd)
/*==========================================
* PVP順位計算(timer)
*------------------------------------------*/
-int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr data)
+int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=NULL;
@@ -7960,7 +7969,7 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
/*==========================================
* 自動セ?ブ (timer??)
*------------------------------------------*/
-int pc_autosave(int tid, unsigned int tick, int id, intptr data)
+int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
{
int interval;
struct s_mapiterator* iter;
@@ -8014,7 +8023,7 @@ static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
* timer to do the day [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_day_timer(int tid, unsigned int tick, int id, intptr data)
+int map_day_timer(int tid, unsigned int tick, int id, intptr_t data)
{
char tmp_soutput[1024];
@@ -8035,7 +8044,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr data)
* timer to do the night [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_night_timer(int tid, unsigned int tick, int id, intptr data)
+int map_night_timer(int tid, unsigned int tick, int id, intptr_t data)
{
char tmp_soutput[1024];
diff --git a/src/map/pc.h b/src/map/pc.h
index 271b3f6b0..fdf4094a1 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -582,8 +582,8 @@ int pc_calc_skilltree(struct map_session_data *sd);
int pc_calc_skilltree_normalize_job(struct map_session_data *sd);
int pc_clean_skilltree(struct map_session_data *sd);
-#define pc_checkoverhp(sd) (sd->battle_status.hp == sd->battle_status.max_hp)
-#define pc_checkoversp(sd) (sd->battle_status.sp == sd->battle_status.max_sp)
+#define pc_checkoverhp(sd) ((sd)->battle_status.hp == (sd)->battle_status.max_hp)
+#define pc_checkoversp(sd) ((sd)->battle_status.sp == (sd)->battle_status.max_sp)
int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype);
int pc_setsavepoint(struct map_session_data*,short,int,int);
@@ -621,7 +621,7 @@ int pc_updateweightstatus(struct map_session_data *sd);
int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
int pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus);
-int pc_endautobonus(int tid, unsigned int tick, int id, intptr data);
+int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data);
int pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore);
int pc_bonus(struct map_session_data*,int,int);
@@ -715,7 +715,7 @@ int pc_cleareventtimer(struct map_session_data *sd);
int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick);
int pc_calc_pvprank(struct map_session_data *sd);
-int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr data);
+int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data);
int pc_ismarried(struct map_session_data *sd);
int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd);
@@ -779,8 +779,8 @@ enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT};
// timer for night.day
extern int day_timer_tid;
extern int night_timer_tid;
-int map_day_timer(int tid, unsigned int tick, int id, intptr data); // by [yor]
-int map_night_timer(int tid, unsigned int tick, int id, intptr data); // by [yor]
+int map_day_timer(int tid, unsigned int tick, int id, intptr_t data); // by [yor]
+int map_night_timer(int tid, unsigned int tick, int id, intptr_t data); // by [yor]
// Rental System
void pc_inventory_rentals(struct map_session_data *sd);
diff --git a/src/map/pet.c b/src/map/pet.c
index 1f350ec4b..a0f652f2b 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -189,7 +189,7 @@ int pet_sc_check(struct map_session_data *sd, int type)
return 0;
}
-static int pet_hungry(int tid, unsigned int tick, int id, intptr data)
+static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd;
struct pet_data *pd;
@@ -858,6 +858,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
if (pd->ud.walktimer != INVALID_TIMER)
return 0; //Wait until the pet finishes walking back to master.
pd->status.speed = pd->petDB->speed;
+ pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1;
}
if (pd->target_id) {
@@ -934,7 +935,7 @@ static int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
return 0;
}
-static int pet_ai_hard(int tid, unsigned int tick, int id, intptr data)
+static int pet_ai_hard(int tid, unsigned int tick, int id, intptr_t data)
{
map_foreachpc(pet_ai_sub_foreachclient,tick);
@@ -968,7 +969,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
return 0;
}
-static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr data)
+static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data)
{
struct item_drop_list *list;
struct item_drop *ditem, *ditem_prev;
@@ -1029,7 +1030,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
pd->ud.canact_tick = gettick()+10000; // 10*1000msの間拾わない
if (dlist->item)
- add_timer(gettick()+540,pet_delay_item_drop,0,(intptr)dlist);
+ add_timer(gettick()+540,pet_delay_item_drop,0,(intptr_t)dlist);
else
ers_free(item_drop_list_ers, dlist);
return 1;
@@ -1038,7 +1039,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
/*==========================================
* pet bonus giving skills [Valaris] / Rewritten by [Skotlex]
*------------------------------------------*/
-int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data)
+int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=map_id2sd(id);
struct pet_data *pd;
@@ -1080,7 +1081,7 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data)
/*==========================================
* pet recovery skills [Valaris] / Rewritten by [Skotlex]
*------------------------------------------*/
-int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data)
+int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=map_id2sd(id);
struct pet_data *pd;
@@ -1108,7 +1109,7 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data)
return 0;
}
-int pet_heal_timer(int tid, unsigned int tick, int id, intptr data)
+int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=map_id2sd(id);
struct status_data *status;
@@ -1146,7 +1147,7 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr data)
/*==========================================
* pet support skills [Skotlex]
*------------------------------------------*/
-int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr data)
+int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd=map_id2sd(id);
struct pet_data *pd;
diff --git a/src/map/pet.h b/src/map/pet.h
index 729fdeb92..52f4999df 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -121,10 +121,10 @@ int pet_change_name_ack(struct map_session_data *sd, char* name, int flag);
int pet_equipitem(struct map_session_data *sd,int index);
int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd);
int pet_attackskill(struct pet_data *pd, int target_id);
-int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr data); // [Skotlex]
-int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris]
-int pet_recovery_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris]
-int pet_heal_timer(int tid, unsigned int tick, int id, intptr data); // [Valaris]
+int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data); // [Skotlex]
+int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
+int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
+int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
#define pet_stop_walking(pd, type) unit_stop_walking(&(pd)->bl, type)
#define pet_stop_attack(pd) unit_stop_attack(&(pd)->bl)
diff --git a/src/map/quest.c b/src/map/quest.c
index 4960d8a93..4c890ce9e 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -85,7 +85,7 @@ int quest_add(TBL_PC * sd, int quest_id)
i = sd->avail_quests;
memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
- memmove(sd->quest_index+i+1, sd->quest_log+i, sizeof(int)*(sd->num_quests-sd->avail_quests));
+ memmove(sd->quest_index+i+1, sd->quest_index+i, sizeof(int)*(sd->num_quests-sd->avail_quests));
memset(&sd->quest_log[i], 0, sizeof(struct quest));
sd->quest_log[i].quest_id = quest_db[j].id;
diff --git a/src/map/script.c b/src/map/script.c
index bf0b4f652..632dc0e14 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -246,9 +246,13 @@ enum curly_type {
TYPE_ARGLIST // function argument list
};
-#define ARGLIST_UNDEFINED 0
-#define ARGLIST_NO_PAREN 1
-#define ARGLIST_PAREN 2
+enum e_arglist
+{
+ ARGLIST_UNDEFINED = 0,
+ ARGLIST_NO_PAREN = 1,
+ ARGLIST_PAREN = 2,
+};
+
static struct {
struct {
enum curly_type type;
@@ -3315,7 +3319,7 @@ struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n)
/*==========================================
* sleep用タイマー関数
*------------------------------------------*/
-int run_script_timer(int tid, unsigned int tick, int id, intptr data)
+int run_script_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct script_state *st = (struct script_state *)data;
struct linkdb_node *node = (struct linkdb_node *)sleep_db;
@@ -3512,7 +3516,7 @@ void run_script_main(struct script_state *st)
sd = map_id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish]
st->sleep.charid = sd?sd->status.char_id:0;
st->sleep.timer = add_timer(gettick()+st->sleep.tick,
- run_script_timer, st->sleep.charid, (intptr)st);
+ run_script_timer, st->sleep.charid, (intptr_t)st);
linkdb_insert(&sleep_db, (void*)st->oid, st);
}
else if(st->state != END && st->rid){
@@ -4550,7 +4554,7 @@ BUILDIN_FUNC(warpchar)
*------------------------------------------*/
BUILDIN_FUNC(warpparty)
{
- TBL_PC *sd;
+ TBL_PC *sd = NULL;
TBL_PC *pl_sd;
struct party_data* p;
int type;
@@ -4565,22 +4569,21 @@ BUILDIN_FUNC(warpparty)
if ( script_hasdata(st,6) )
str2 = script_getstr(st,6);
- sd=script_rid2sd(st);
- if( sd == NULL )
- return 0;
p = party_search(p_id);
if(!p)
return 0;
- if(map[sd->bl.m].flag.noreturn || map[sd->bl.m].flag.nowarpto)
- return 0;
-
type = ( strcmp(str,"Random")==0 ) ? 0
: ( strcmp(str,"SavePointAll")==0 ) ? 1
: ( strcmp(str,"SavePoint")==0 ) ? 2
: ( strcmp(str,"Leader")==0 ) ? 3
: 4;
+ if( type == 2 && ( sd = script_rid2sd(st) ) == NULL )
+ {// "SavePoint" uses save point of the currently attached player
+ return 0;
+ }
+
for (i = 0; i < MAX_PARTY; i++)
{
if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id )
@@ -4638,7 +4641,7 @@ BUILDIN_FUNC(warpparty)
*------------------------------------------*/
BUILDIN_FUNC(warpguild)
{
- TBL_PC *sd;
+ TBL_PC *sd = NULL;
TBL_PC *pl_sd;
struct guild* g;
struct s_mapiterator* iter;
@@ -4649,21 +4652,20 @@ BUILDIN_FUNC(warpguild)
int y = script_getnum(st,4);
int gid = script_getnum(st,5);
- sd=script_rid2sd(st);
- if( sd == NULL )
- return 0;
g = guild_search(gid);
if( g == NULL )
return 0;
- if(map[sd->bl.m].flag.noreturn || map[sd->bl.m].flag.nowarpto)
- return 0;
-
type = ( strcmp(str,"Random")==0 ) ? 0
: ( strcmp(str,"SavePointAll")==0 ) ? 1
: ( strcmp(str,"SavePoint")==0 ) ? 2
: 3;
+ if( type == 2 && ( sd = script_rid2sd(st) ) == NULL )
+ {// "SavePoint" uses save point of the currently attached player
+ return 0;
+ }
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
{
@@ -11682,6 +11684,62 @@ BUILDIN_FUNC(gethominfo)
return 0;
}
+/// Retrieves information about character's mercenary
+/// getmercinfo <type>[,<char id>];
+BUILDIN_FUNC(getmercinfo)
+{
+ int type, char_id;
+ struct map_session_data* sd;
+ struct mercenary_data* md;
+
+ type = script_getnum(st,2);
+
+ if( script_hasdata(st,3) )
+ {
+ char_id = script_getnum(st,3);
+
+ if( ( sd = map_charid2sd(char_id) ) == NULL )
+ {
+ ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id);
+ script_pushnil(st);
+ return 1;
+ }
+ }
+ else
+ {
+ if( ( sd = script_rid2sd(st) ) == NULL )
+ {
+ script_pushnil(st);
+ return 0;
+ }
+ }
+
+ md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL;
+
+ switch( type )
+ {
+ case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break;
+ case 1: script_pushint(st,md ? md->mercenary.class_ : 0); break;
+ case 2:
+ if( md )
+ script_pushstrcopy(st,md->db->name);
+ else
+ script_pushconststr(st,"");
+ break;
+ case 3: script_pushint(st,md ? mercenary_get_faith(md) : 0); break;
+ case 4: script_pushint(st,md ? mercenary_get_calls(md) : 0); break;
+ case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break;
+ case 6: script_pushint(st,md ? mercenary_get_lifetime(md) : 0); break;
+ case 7: script_pushint(st,md ? md->db->lv : 0); break;
+ default:
+ ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id);
+ script_pushnil(st);
+ return 1;
+ }
+
+ return 0;
+}
+
/*==========================================
* Shows wether your inventory(and equips) contain
selected card or not.
@@ -11788,7 +11846,7 @@ BUILDIN_FUNC(movenpc)
return -1;
if (script_hasdata(st,5))
- nd->ud.dir = script_getnum(st,5);
+ nd->ud.dir = script_getnum(st,5) % 8;
npc_movenpc(nd, x, y);
return 0;
}
@@ -12871,7 +12929,7 @@ BUILDIN_FUNC(npcshopitem)
int n, i;
int amount;
- if( !nd || nd->subtype != SHOP )
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;
@@ -12900,7 +12958,7 @@ BUILDIN_FUNC(npcshopadditem)
int n, i;
int amount;
- if( !nd || nd->subtype != SHOP )
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;
@@ -12931,7 +12989,7 @@ BUILDIN_FUNC(npcshopdelitem)
int amount;
int size;
- if( !nd || nd->subtype != SHOP )
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
{ //Not found.
script_pushint(st,0);
return 0;
@@ -15141,6 +15199,7 @@ struct script_function buildin_func[] = {
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?"),
diff --git a/src/map/script.h b/src/map/script.h
index c272f2d32..2ed163a0f 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -153,7 +153,7 @@ 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 data);
+int run_script_timer(int tid, unsigned int tick, int id, intptr_t data);
void run_script_main(struct script_state *st);
void script_stop_sleeptimers(int id);
diff --git a/src/map/skill.c b/src/map/skill.c
index d95d04134..d33d35d6e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -43,11 +43,11 @@
// ranges reserved for mapping skill ids to skilldb offsets
#define GD_SKILLRANGEMIN 900
-#define GD_SKILLRANGEMAX GD_SKILLRANGEMIN+MAX_GUILDSKILL
+#define GD_SKILLRANGEMAX (GD_SKILLRANGEMIN+MAX_GUILDSKILL)
#define MC_SKILLRANGEMIN 800
-#define MC_SKILLRANGEMAX MC_SKILLRANGEMIN+MAX_MERCSKILL
+#define MC_SKILLRANGEMAX (MC_SKILLRANGEMIN+MAX_MERCSKILL)
#define HM_SKILLRANGEMIN 700
-#define HM_SKILLRANGEMAX HM_SKILLRANGEMIN+MAX_HOMUNSKILL
+#define HM_SKILLRANGEMAX (HM_SKILLRANGEMIN+MAX_HOMUNSKILL)
static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex]
static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex]
@@ -1820,11 +1820,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
&& (!sc || !sc->data[SC_PRESERVE])
&& damage < tsd->battle_status.hp)
{ //Updated to not be able to copy skills if the blow will kill you. [Skotlex]
- if ((!tsd->status.skill[skillid].id || tsd->status.skill[skillid].flag >= 13) &&
+ if ((tsd->status.skill[skillid].id == 0 || tsd->status.skill[skillid].flag == SKILL_FLAG_PLAGIARIZED) &&
can_copy(tsd,skillid,bl)) // Split all the check into their own function [Aru]
{
int lv = skilllv;
- if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == 13){
+ if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED){
tsd->status.skill[tsd->cloneskill_id].id = 0;
tsd->status.skill[tsd->cloneskill_id].lv = 0;
tsd->status.skill[tsd->cloneskill_id].flag = 0;
@@ -1840,7 +1840,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
tsd->status.skill[skillid].id = skillid;
tsd->status.skill[skillid].lv = lv;
- tsd->status.skill[skillid].flag = 13;//cloneskill flag
+ tsd->status.skill[skillid].flag = SKILL_FLAG_PLAGIARIZED;
clif_addskill(tsd,skillid);
}
}
@@ -2277,7 +2277,7 @@ int skill_area_sub_count (struct block_list *src, struct block_list *target, int
/*==========================================
*
*------------------------------------------*/
-static int skill_timerskill(int tid, unsigned int tick, int id, intptr data)
+static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *src = map_id2bl(id),*target;
struct unit_data *ud = unit_bl2ud(src);
@@ -3958,51 +3958,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case KN_BRANDISHSPEAR:
case ML_BRANDISH:
- {
- int c,n=4;
- int dir = map_calc_dir(src,bl->x,bl->y);
- struct square tc;
- int x=bl->x,y=bl->y;
- skill_brandishspear_first(&tc,dir,x,y);
- skill_brandishspear_dir(&tc,dir,4);
- skill_area_temp[1] = bl->id;
-
- if(skilllv > 9){
- for(c=1;c<4;c++){
- map_foreachincell(skill_area_sub,
- bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
- skill_castend_damage_id);
- }
- }
- if(skilllv > 6){
- skill_brandishspear_dir(&tc,dir,-1);
- n--;
- }else{
- skill_brandishspear_dir(&tc,dir,-2);
- n-=2;
- }
-
- if(skilllv > 3){
- for(c=0;c<5;c++){
- map_foreachincell(skill_area_sub,
- bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
- skill_castend_damage_id);
- if(skilllv > 6 && n==3 && c==4){
- skill_brandishspear_dir(&tc,dir,-1);
- n--;c=-1;
- }
- }
- }
- for(c=0;c<10;c++){
- if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1);
- map_foreachincell(skill_area_sub,
- bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
- skill_castend_damage_id);
- }
- }
+ skill_brandishspear(src, bl, skillid, skilllv, tick, flag);
break;
case WZ_SIGHTRASHER:
@@ -5531,7 +5487,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
//AuronX reported you CAN memorize the same map as all three. [Skotlex]
if (sd) {
if(!sd->feel_map[skilllv-1].index)
- clif_parse_ReqFeel(sd->fd,sd, skilllv);
+ clif_feel_req(sd->fd,sd, skilllv);
else
clif_feel_info(sd, skilllv-1, 1);
}
@@ -5726,7 +5682,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
/*==========================================
*
*------------------------------------------*/
-int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
+int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *target, *src;
struct map_session_data *sd;
@@ -6016,7 +5972,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
/*==========================================
*
*------------------------------------------*/
-int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
+int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list* src = map_id2bl(id);
int maxcount;
@@ -9149,7 +9105,12 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
/*=========================================
*
*-----------------------------------------*/
-void skill_brandishspear_first (struct square *tc, int dir, int x, int y)
+struct square {
+ int val1[5];
+ int val2[5];
+};
+
+static void skill_brandishspear_first (struct square *tc, int dir, int x, int y)
{
nullpo_retv(tc);
@@ -9252,10 +9213,7 @@ void skill_brandishspear_first (struct square *tc, int dir, int x, int y)
}
-/*=========================================
- *
- *-----------------------------------------*/
-void skill_brandishspear_dir (struct square* tc, int dir, int are)
+static void skill_brandishspear_dir (struct square* tc, int dir, int are)
{
int c;
nullpo_retv(tc);
@@ -9276,6 +9234,53 @@ void skill_brandishspear_dir (struct square* tc, int dir, int are)
}
}
+void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag)
+{
+ int c,n=4;
+ int dir = map_calc_dir(src,bl->x,bl->y);
+ struct square tc;
+ int x=bl->x,y=bl->y;
+ skill_brandishspear_first(&tc,dir,x,y);
+ skill_brandishspear_dir(&tc,dir,4);
+ skill_area_temp[1] = bl->id;
+
+ if(skilllv > 9){
+ for(c=1;c<4;c++){
+ map_foreachincell(skill_area_sub,
+ bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
+ skill_castend_damage_id);
+ }
+ }
+ if(skilllv > 6){
+ skill_brandishspear_dir(&tc,dir,-1);
+ n--;
+ }else{
+ skill_brandishspear_dir(&tc,dir,-2);
+ n-=2;
+ }
+
+ if(skilllv > 3){
+ for(c=0;c<5;c++){
+ map_foreachincell(skill_area_sub,
+ bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|n,
+ skill_castend_damage_id);
+ if(skilllv > 6 && n==3 && c==4){
+ skill_brandishspear_dir(&tc,dir,-1);
+ n--;c=-1;
+ }
+ }
+ }
+ for(c=0;c<10;c++){
+ if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1);
+ map_foreachincell(skill_area_sub,
+ bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ }
+}
+
/*==========================================
* Weapon Repair [Celest/DracoRPG]
*------------------------------------------*/
@@ -10485,7 +10490,7 @@ static int skill_unit_timer_sub (DBKey key, void* data, va_list ap)
/*==========================================
* Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds.
*------------------------------------------*/
-int skill_unit_timer(int tid, unsigned int tick, int id, intptr data)
+int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data)
{
map_freeblock_lock();
@@ -11181,7 +11186,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid)
/*==========================================
*
*------------------------------------------*/
-int skill_blockpc_end(int tid, unsigned int tick, int id, intptr data)
+int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data)
{
struct map_session_data *sd = map_id2sd(id);
if (data <= 0 || data >= MAX_SKILL)
@@ -11212,7 +11217,7 @@ int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick)
return 0;
}
-int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr data) //[orn]
+int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn]
{
struct homun_data *hd = (TBL_HOM*) map_id2bl(id);
if (data <= 0 || data >= MAX_SKILL)
@@ -11238,7 +11243,7 @@ int skill_blockhomun_start(struct homun_data *hd, int skillid, int tick) //[orn]
return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skillid);
}
-int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr data) //[orn]
+int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[orn]
{
struct mercenary_data *md = (TBL_MER*)map_id2bl(id);
if( data <= 0 || data >= MAX_SKILL )
diff --git a/src/map/skill.h b/src/map/skill.h
index 6f55af7ec..1ad6ea25a 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -22,51 +22,61 @@ struct status_change_entry;
#define MAX_SKILL_LEVEL 100
//Constants to identify the skill's inf value:
-#define INF_ATTACK_SKILL 1
-#define INF_GROUND_SKILL 2
-// Skills casted on self where target is automatically chosen:
-#define INF_SELF_SKILL 4
-#define INF_SUPPORT_SKILL 16
-#define INF_TARGET_TRAP 32
+enum e_skill_inf
+{
+ INF_ATTACK_SKILL = 0x01,
+ INF_GROUND_SKILL = 0x02,
+ INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen
+ // 0x08 not assigned
+ INF_SUPPORT_SKILL = 0x10,
+ INF_TARGET_TRAP = 0x20,
+};
//Constants to identify a skill's nk value (damage properties)
//The NK value applies only to non INF_GROUND_SKILL skills
//when determining skill castend function to invoke.
-#define NK_NO_DAMAGE 0x01
-#define NK_SPLASH (0x02|0x04) // 0x4 = splash & split
-#define NK_SPLASHSPLIT 0x04
-#define NK_NO_CARDFIX_ATK 0x08
-#define NK_NO_ELEFIX 0x10
-#define NK_IGNORE_DEF 0x20
-#define NK_IGNORE_FLEE 0x40
-#define NK_NO_CARDFIX_DEF 0x80
+enum e_skill_nk
+{
+ NK_NO_DAMAGE = 0x01,
+ NK_SPLASH = 0x02|0x04, // 0x4 = splash & split
+ NK_SPLASHSPLIT = 0x04,
+ NK_NO_CARDFIX_ATK = 0x08,
+ NK_NO_ELEFIX = 0x10,
+ NK_IGNORE_DEF = 0x20,
+ NK_IGNORE_FLEE = 0x40,
+ NK_NO_CARDFIX_DEF = 0x80,
+};
//A skill with 3 would be no damage + splash: area of effect.
//Constants to identify a skill's inf2 value.
-#define INF2_QUEST_SKILL 1
-//NPC skills are those that players can't have in their skill tree.
-#define INF2_NPC_SKILL 0x2
-#define INF2_WEDDING_SKILL 0x4
-#define INF2_SPIRIT_SKILL 0x8
-#define INF2_GUILD_SKILL 0x10
-#define INF2_SONG_DANCE 0x20
-#define INF2_ENSEMBLE_SKILL 0x40
-#define INF2_TRAP 0x80
-//Refers to ground placed skills that will target the caster as well (like Grandcross)
-#define INF2_TARGET_SELF 0x100
-#define INF2_NO_TARGET_SELF 0x200
-#define INF2_PARTY_ONLY 0x400
-#define INF2_GUILD_ONLY 0x800
-#define INF2_NO_ENEMY 0x1000
+enum e_skill_inf2
+{
+ INF2_QUEST_SKILL = 0x0001,
+ INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree.
+ INF2_WEDDING_SKILL = 0x0004,
+ INF2_SPIRIT_SKILL = 0x0008,
+ INF2_GUILD_SKILL = 0x0010,
+ INF2_SONG_DANCE = 0x0020,
+ INF2_ENSEMBLE_SKILL = 0x0040,
+ INF2_TRAP = 0x0080,
+ INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross)
+ INF2_NO_TARGET_SELF = 0x0200,
+ INF2_PARTY_ONLY = 0x0400,
+ INF2_GUILD_ONLY = 0x0800,
+ INF2_NO_ENEMY = 0x1000,
+};
//Walk intervals at which chase-skills are attempted to be triggered.
#define WALK_SKILL_INTERVAL 5
// Flags passed to skill_attack/skill_area_sub
-#define SD_LEVEL 0x1000 // skill_attack will send -1 instead of skill level (affects display of some skills)
-#define SD_ANIMATION 0x2000 // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation)
-#define SD_SPLASH 0x4000 // skill_area_sub will count targets in skill_area_temp[2]
-#define SD_PREAMBLE 0x8000 // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected
+enum e_skill_display
+{
+ SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills)
+ SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation)
+ SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2]
+ SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected
+};
#define MAX_SKILL_ITEM_REQUIRE 10
struct skill_condition {
@@ -253,8 +263,8 @@ const char* skill_get_desc( int id ); // [Skotlex]
int skill_name2id(const char* name);
int skill_isammotype(struct map_session_data *sd, int skill);
-int skill_castend_id(int tid, unsigned int tick, int id, intptr data);
-int skill_castend_pos(int tid, unsigned int tick, int id, intptr data);
+int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data);
+int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data);
int skill_castend_map( struct map_session_data *sd,short skill_num, const char *map);
int skill_cleartimerskill(struct block_list *src);
@@ -305,8 +315,7 @@ int skill_guildaura_sub (struct block_list *bl,va_list ap);
int skill_castcancel(struct block_list *bl,int type);
int skill_sit (struct map_session_data *sd, int type);
-void skill_brandishspear_first(struct square *tc,int dir,int x,int y);
-void skill_brandishspear_dir(struct square *tc,int dir,int are);
+void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag);
void skill_repairweapon(struct map_session_data *sd, int idx);
void skill_identify(struct map_session_data *sd,int idx);
void skill_weaponrefine(struct map_session_data *sd,int idx); // [Celest]
diff --git a/src/map/sql/CMakeLists.txt b/src/map/sql/CMakeLists.txt
new file mode 100644
index 000000000..74598423a
--- /dev/null
+++ b/src/map/sql/CMakeLists.txt
@@ -0,0 +1,110 @@
+
+#
+# map sql
+#
+if( HAVE_common_sql )
+message( STATUS "Creating target map-server_sql" )
+set( SQL_MAP_HEADERS
+ "${MAP_SOURCE_DIR}/atcommand.h"
+ "${MAP_SOURCE_DIR}/battle.h"
+ "${MAP_SOURCE_DIR}/battleground.h"
+ "${MAP_SOURCE_DIR}/buyingstore.h"
+ "${MAP_SOURCE_DIR}/chat.h"
+ "${MAP_SOURCE_DIR}/chrif.h"
+ "${MAP_SOURCE_DIR}/clif.h"
+ "${MAP_SOURCE_DIR}/date.h"
+ "${MAP_SOURCE_DIR}/duel.h"
+ "${MAP_SOURCE_DIR}/guild.h"
+ "${MAP_SOURCE_DIR}/homunculus.h"
+ "${MAP_SOURCE_DIR}/instance.h"
+ "${MAP_SOURCE_DIR}/intif.h"
+ "${MAP_SOURCE_DIR}/itemdb.h"
+ "${MAP_SOURCE_DIR}/log.h"
+ "${MAP_SOURCE_DIR}/mail.h"
+ "${MAP_SOURCE_DIR}/map.h"
+ "${MAP_SOURCE_DIR}/mapreg.h"
+ "${MAP_SOURCE_DIR}/mercenary.h"
+ "${MAP_SOURCE_DIR}/mob.h"
+ "${MAP_SOURCE_DIR}/npc.h"
+ "${MAP_SOURCE_DIR}/party.h"
+ "${MAP_SOURCE_DIR}/path.h"
+ "${MAP_SOURCE_DIR}/pc.h"
+ "${MAP_SOURCE_DIR}/pet.h"
+ "${MAP_SOURCE_DIR}/quest.h"
+ "${MAP_SOURCE_DIR}/script.h"
+ "${MAP_SOURCE_DIR}/searchstore.h"
+ "${MAP_SOURCE_DIR}/skill.h"
+ "${MAP_SOURCE_DIR}/status.h"
+ "${MAP_SOURCE_DIR}/storage.h"
+ "${MAP_SOURCE_DIR}/trade.h"
+ "${MAP_SOURCE_DIR}/unit.h"
+ "${MAP_SOURCE_DIR}/vending.h"
+ )
+set( SQL_MAP_SOURCES
+ "${MAP_SOURCE_DIR}/atcommand.c"
+ "${MAP_SOURCE_DIR}/battle.c"
+ "${MAP_SOURCE_DIR}/battleground.c"
+ "${MAP_SOURCE_DIR}/buyingstore.c"
+ "${MAP_SOURCE_DIR}/chat.c"
+ "${MAP_SOURCE_DIR}/chrif.c"
+ "${MAP_SOURCE_DIR}/clif.c"
+ "${MAP_SOURCE_DIR}/date.c"
+ "${MAP_SOURCE_DIR}/duel.c"
+ "${MAP_SOURCE_DIR}/guild.c"
+ "${MAP_SOURCE_DIR}/homunculus.c"
+ "${MAP_SOURCE_DIR}/instance.c"
+ "${MAP_SOURCE_DIR}/intif.c"
+ "${MAP_SOURCE_DIR}/itemdb.c"
+ "${MAP_SOURCE_DIR}/log.c"
+ "${MAP_SOURCE_DIR}/mail.c"
+ "${MAP_SOURCE_DIR}/map.c"
+ "${MAP_SOURCE_DIR}/mapreg_sql.c"
+ "${MAP_SOURCE_DIR}/mercenary.c"
+ "${MAP_SOURCE_DIR}/mob.c"
+ "${MAP_SOURCE_DIR}/npc.c"
+ "${MAP_SOURCE_DIR}/npc_chat.c"
+ "${MAP_SOURCE_DIR}/party.c"
+ "${MAP_SOURCE_DIR}/path.c"
+ "${MAP_SOURCE_DIR}/pc.c"
+ "${MAP_SOURCE_DIR}/pet.c"
+ "${MAP_SOURCE_DIR}/quest.c"
+ "${MAP_SOURCE_DIR}/script.c"
+ "${MAP_SOURCE_DIR}/searchstore.c"
+ "${MAP_SOURCE_DIR}/skill.c"
+ "${MAP_SOURCE_DIR}/status.c"
+ "${MAP_SOURCE_DIR}/storage.c"
+ "${MAP_SOURCE_DIR}/trade.c"
+ "${MAP_SOURCE_DIR}/unit.c"
+ "${MAP_SOURCE_DIR}/vending.c"
+ )
+set( DEPENDENCIES common_sql )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} )
+if( WITH_PCRE )
+ message( STATUS "Using PCRE" )
+ list( APPEND LIBRARIES ${PCRE_LIBRARIES} )
+ list( APPEND INCLUDE_DIRS ${PCRE_INCLUDE_DIRS} )
+ list( APPEND DEFINITIONS PCRE_SUPPORT )
+endif()
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} )
+source_group( map FILES ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( map-server_sql ${SOURCE_FILES} )
+add_dependencies( map-server_sql ${DEPENDENCIES} )
+target_link_libraries( map-server_sql ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( map-server_sql PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server_sql" GROUP Runtime )
+ install( TARGETS map-server_sql
+ DESTINATION "."
+ COMPONENT Runtime_mapserver_sql )
+endif()
+message( STATUS "Creating target map-server_sql - done" )
+set( HAVE_map-server_sql ON CACHE BOOL "map-server_sql target is available" )
+mark_as_advanced( HAVE_map-server_sql )
+else()
+message( STATUS "Skipping target map-server_sql (requires common_sql; optional PCRE)" )
+unset( HAVE_map-server_sql CACHE )
+endif()
diff --git a/src/map/status.c b/src/map/status.c
index e68ebd291..37dad30b9 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -38,10 +38,13 @@
//Regen related flags.
-#define RGN_HP 0x01
-#define RGN_SP 0x02
-#define RGN_SHP 0x04
-#define RGN_SSP 0x08
+enum e_regen
+{
+ RGN_HP = 0x01,
+ RGN_SP = 0x02,
+ RGN_SHP = 0x04,
+ RGN_SSP = 0x08,
+};
static int max_weight_base[CLASS_COUNT];
static int hp_coefficient[CLASS_COUNT];
@@ -6961,7 +6964,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
return 1;
}
-int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data)
+int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl;
struct status_change *sc;
@@ -6998,7 +7001,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data)
/*==========================================
* ステータス異常終了タイマー
*------------------------------------------*/
-int status_change_timer(int tid, unsigned int tick, int id, intptr data)
+int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
{
enum sc_type type = (sc_type)data;
struct block_list *bl;
@@ -7258,7 +7261,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data)
case SC_BERSERK:
// 5% every 10 seconds [DracoRPG]
- if(--(sce->val3)>0 && status_charge(bl, sce->val2, 0))
+ if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 )
{
sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
return 0;
@@ -7689,7 +7692,7 @@ static int status_natural_heal(struct block_list* bl, va_list args)
}
//Natural heal main timer.
-static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr data)
+static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
{
natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
map_foreachregen(status_natural_heal);
diff --git a/src/map/status.h b/src/map/status.h
index 45eaa5c8d..abaeff75e 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -915,13 +915,16 @@ enum si_type {
};
// JOINTBEAT stackable ailments
-#define BREAK_ANKLE 0x01 // MoveSpeed reduced by 50%
-#define BREAK_WRIST 0x02 // ASPD reduced by 25%
-#define BREAK_KNEE 0x04 // MoveSpeed reduced by 30%, ASPD reduced by 10%
-#define BREAK_SHOULDER 0x08 // DEF reduced by 50%
-#define BREAK_WAIST 0x10 // DEF reduced by 25%, ATK reduced by 25%
-#define BREAK_NECK 0x20 // current attack does 2x damage, inflicts 'bleeding' for 30 seconds
-#define BREAK_FLAGS ( BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK )
+enum e_joint_break
+{
+ BREAK_ANKLE = 0x01, // MoveSpeed reduced by 50%
+ BREAK_WRIST = 0x02, // ASPD reduced by 25%
+ BREAK_KNEE = 0x04, // MoveSpeed reduced by 30%, ASPD reduced by 10%
+ BREAK_SHOULDER = 0x08, // DEF reduced by 50%
+ BREAK_WAIST = 0x10, // DEF reduced by 25%, ATK reduced by 25%
+ BREAK_NECK = 0x20, // current attack does 2x damage, inflicts 'bleeding' for 30 seconds
+ BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
+};
extern int current_equip_item_index;
extern int current_equip_card_id;
@@ -929,22 +932,25 @@ extern int current_equip_card_id;
extern int percentrefinery[5][MAX_REFINE+1]; //The last slot always has a 0% success chance [Skotlex]
//Mode definitions to clear up code reading. [Skotlex]
-#define MD_CANMOVE 0x0001
-#define MD_LOOTER 0x0002
-#define MD_AGGRESSIVE 0x0004
-#define MD_ASSIST 0x0008
-#define MD_CASTSENSOR_IDLE 0x0010
-#define MD_BOSS 0x0020
-#define MD_PLANT 0x0040
-#define MD_CANATTACK 0x0080
-#define MD_DETECTOR 0x0100
-#define MD_CASTSENSOR_CHASE 0x0200
-#define MD_CHANGECHASE 0x0400
-#define MD_ANGRY 0x0800
-#define MD_CHANGETARGET_MELEE 0x1000
-#define MD_CHANGETARGET_CHASE 0x2000
-#define MD_TARGETWEAK 0x4000
-#define MD_MASK 0xFFFF
+enum e_mode
+{
+ MD_CANMOVE = 0x0001,
+ MD_LOOTER = 0x0002,
+ MD_AGGRESSIVE = 0x0004,
+ MD_ASSIST = 0x0008,
+ MD_CASTSENSOR_IDLE = 0x0010,
+ MD_BOSS = 0x0020,
+ MD_PLANT = 0x0040,
+ MD_CANATTACK = 0x0080,
+ MD_DETECTOR = 0x0100,
+ MD_CASTSENSOR_CHASE = 0x0200,
+ MD_CHANGECHASE = 0x0400,
+ MD_ANGRY = 0x0800,
+ MD_CHANGETARGET_MELEE = 0x1000,
+ MD_CHANGETARGET_CHASE = 0x2000,
+ MD_TARGETWEAK = 0x4000,
+ MD_MASK = 0xFFFF,
+};
//Status change option definitions (options are what makes status changes visible to chars
//who were not on your field of sight when it happened)
@@ -1026,19 +1032,21 @@ enum {
OPTION_DRAGON3 = 0x01000000,
OPTION_DRAGON4 = 0x02000000,
OPTION_DRAGON5 = 0x04000000,
+ // compound constants
+ OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5,
+ OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5,
+ OPTION_MASK = ~OPTION_INVISIBLE,
};
-#define OPTION_CART (OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5)
-#define OPTION_DRAGON (OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5)
-
-#define OPTION_MASK ~0x40
-
//Defines for the manner system [Skotlex]
-#define MANNER_NOCHAT 0x01
-#define MANNER_NOSKILL 0x02
-#define MANNER_NOCOMMAND 0x04
-#define MANNER_NOITEM 0x08
-#define MANNER_NOROOM 0x10
+enum manner_flags
+{
+ MANNER_NOCHAT = 0x01,
+ MANNER_NOSKILL = 0x02,
+ MANNER_NOCOMMAND = 0x04,
+ MANNER_NOITEM = 0x08,
+ MANNER_NOROOM = 0x10,
+};
//Define flags for the status_calc_bl function. [Skotlex]
enum scb_flag
@@ -1278,8 +1286,8 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag);
int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
#define status_change_end(bl,type,tid) status_change_end_(bl,type,tid,__FILE__,__LINE__)
-int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr data);
-int status_change_timer(int tid, unsigned int tick, int id, intptr data);
+int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data);
+int status_change_timer(int tid, unsigned int tick, int id, intptr_t data);
int status_change_timer_sub(struct block_list* bl, va_list ap);
int status_change_clear(struct block_list* bl, int type);
int status_change_clear_buffs(struct block_list* bl, int type);
diff --git a/src/map/txt/CMakeLists.txt b/src/map/txt/CMakeLists.txt
new file mode 100644
index 000000000..d58866f96
--- /dev/null
+++ b/src/map/txt/CMakeLists.txt
@@ -0,0 +1,110 @@
+
+#
+# map txt
+#
+if( HAVE_common_base )
+message( STATUS "Creating target map-server" )
+set( TXT_MAP_HEADERS
+ "${MAP_SOURCE_DIR}/atcommand.h"
+ "${MAP_SOURCE_DIR}/battle.h"
+ "${MAP_SOURCE_DIR}/battleground.h"
+ "${MAP_SOURCE_DIR}/buyingstore.h"
+ "${MAP_SOURCE_DIR}/chat.h"
+ "${MAP_SOURCE_DIR}/chrif.h"
+ "${MAP_SOURCE_DIR}/clif.h"
+ "${MAP_SOURCE_DIR}/date.h"
+ "${MAP_SOURCE_DIR}/duel.h"
+ "${MAP_SOURCE_DIR}/guild.h"
+ "${MAP_SOURCE_DIR}/homunculus.h"
+ "${MAP_SOURCE_DIR}/instance.h"
+ "${MAP_SOURCE_DIR}/intif.h"
+ "${MAP_SOURCE_DIR}/itemdb.h"
+ "${MAP_SOURCE_DIR}/log.h"
+ "${MAP_SOURCE_DIR}/mail.h"
+ "${MAP_SOURCE_DIR}/map.h"
+ "${MAP_SOURCE_DIR}/mapreg.h"
+ "${MAP_SOURCE_DIR}/mercenary.h"
+ "${MAP_SOURCE_DIR}/mob.h"
+ "${MAP_SOURCE_DIR}/npc.h"
+ "${MAP_SOURCE_DIR}/party.h"
+ "${MAP_SOURCE_DIR}/path.h"
+ "${MAP_SOURCE_DIR}/pc.h"
+ "${MAP_SOURCE_DIR}/pet.h"
+ "${MAP_SOURCE_DIR}/quest.h"
+ "${MAP_SOURCE_DIR}/script.h"
+ "${MAP_SOURCE_DIR}/searchstore.h"
+ "${MAP_SOURCE_DIR}/skill.h"
+ "${MAP_SOURCE_DIR}/status.h"
+ "${MAP_SOURCE_DIR}/storage.h"
+ "${MAP_SOURCE_DIR}/trade.h"
+ "${MAP_SOURCE_DIR}/unit.h"
+ "${MAP_SOURCE_DIR}/vending.h"
+ )
+set( TXT_MAP_SOURCES
+ "${MAP_SOURCE_DIR}/atcommand.c"
+ "${MAP_SOURCE_DIR}/battle.c"
+ "${MAP_SOURCE_DIR}/battleground.c"
+ "${MAP_SOURCE_DIR}/buyingstore.c"
+ "${MAP_SOURCE_DIR}/chat.c"
+ "${MAP_SOURCE_DIR}/chrif.c"
+ "${MAP_SOURCE_DIR}/clif.c"
+ "${MAP_SOURCE_DIR}/date.c"
+ "${MAP_SOURCE_DIR}/duel.c"
+ "${MAP_SOURCE_DIR}/guild.c"
+ "${MAP_SOURCE_DIR}/homunculus.c"
+ "${MAP_SOURCE_DIR}/instance.c"
+ "${MAP_SOURCE_DIR}/intif.c"
+ "${MAP_SOURCE_DIR}/itemdb.c"
+ "${MAP_SOURCE_DIR}/log.c"
+ "${MAP_SOURCE_DIR}/mail.c"
+ "${MAP_SOURCE_DIR}/map.c"
+ "${MAP_SOURCE_DIR}/mapreg_txt.c"
+ "${MAP_SOURCE_DIR}/mercenary.c"
+ "${MAP_SOURCE_DIR}/mob.c"
+ "${MAP_SOURCE_DIR}/npc.c"
+ "${MAP_SOURCE_DIR}/npc_chat.c"
+ "${MAP_SOURCE_DIR}/party.c"
+ "${MAP_SOURCE_DIR}/path.c"
+ "${MAP_SOURCE_DIR}/pc.c"
+ "${MAP_SOURCE_DIR}/pet.c"
+ "${MAP_SOURCE_DIR}/quest.c"
+ "${MAP_SOURCE_DIR}/script.c"
+ "${MAP_SOURCE_DIR}/searchstore.c"
+ "${MAP_SOURCE_DIR}/skill.c"
+ "${MAP_SOURCE_DIR}/status.c"
+ "${MAP_SOURCE_DIR}/storage.c"
+ "${MAP_SOURCE_DIR}/trade.c"
+ "${MAP_SOURCE_DIR}/unit.c"
+ "${MAP_SOURCE_DIR}/vending.c"
+ )
+set( DEPENDENCIES common_base )
+set( LIBRARIES ${GLOBAL_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} TXT_ONLY )
+if( WITH_PCRE )
+ message( STATUS "Using PCRE" )
+ list( APPEND LIBRARIES ${PCRE_LIBRARIES} )
+ list( APPEND INCLUDE_DIRS ${PCRE_INCLUDE_DIRS} )
+ list( APPEND DEFINITIONS PCRE_SUPPORT )
+endif()
+set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${TXT_MAP_HEADERS} ${TXT_MAP_SOURCES} )
+source_group( common FILES ${COMMON_BASE_HEADERS} )
+source_group( map FILES ${TXT_MAP_HEADERS} ${TXT_MAP_SOURCES} )
+include_directories( ${INCLUDE_DIRS} )
+add_executable( map-server ${SOURCE_FILES} )
+add_dependencies( map-server ${DEPENDENCIES} )
+target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} )
+set_target_properties( map-server PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_mapserver_txt DESCRIPTION "map-server (txt version)" DISPLAY_NAME "map-server" GROUP Runtime )
+ install( TARGETS map-server
+ DESTINATION "."
+ COMPONENT Runtime_mapserver_txt )
+endif()
+message( STATUS "Creating target map-server - done" )
+set( HAVE_map-server ON CACHE BOOL "map-server target is available" )
+mark_as_advanced( HAVE_map-server )
+else()
+message( STATUS "Skipping target map-server (requires common_base; optional PCRE)" )
+unset( HAVE_map-server CACHE )
+endif()
diff --git a/src/map/unit.c b/src/map/unit.c
index 3cec43f70..2165532b4 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -51,8 +51,8 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
return NULL;
}
-static int unit_attack_timer(int tid, unsigned int tick, int id, intptr data);
-static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data);
+static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
+static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
int unit_walktoxy_sub(struct block_list *bl)
{
@@ -106,7 +106,7 @@ int unit_walktoxy_sub(struct block_list *bl)
return 1;
}
-static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
+static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
int i;
int x,y,dx,dy;
@@ -263,7 +263,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
return 0;
}
-static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
+static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl = map_id2bl(id);
@@ -327,7 +327,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
if((bl)->type == BL_MOB && (flag)) \
((TBL_MOB*)(bl))->state.skillstate = ((TBL_MOB*)(bl))->state.aggressive?MSS_FOLLOW:MSS_RUSH;
-static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr data)
+static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl = map_id2bl(id);
struct unit_data *ud = bl?unit_bl2ud(bl):NULL;
@@ -847,7 +847,7 @@ int unit_can_move(struct block_list *bl)
* Resume running after a walk delay
*------------------------------------------*/
-int unit_resume_running(int tid, unsigned int tick, int id, intptr data)
+int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
{
struct unit_data *ud = (struct unit_data *)data;
@@ -891,7 +891,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
//Resume running after can move again [Kevin]
if(ud->state.running)
{
- add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr)ud);
+ add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr_t)ud);
}
else
{
@@ -1655,7 +1655,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
return 1;
}
-static int unit_attack_timer(int tid, unsigned int tick, int id, intptr data)
+static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
{
struct block_list *bl;
bl = map_id2bl(id);
@@ -1881,7 +1881,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
storage_guild_storage_quit(sd,0);
sd->state.storage_flag = 0; //Force close it when being warped.
if(sd->party_invite>0)
- party_reply_invite(sd,sd->party_invite_account,0);
+ party_reply_invite(sd,sd->party_invite,0);
if(sd->guild_invite>0)
guild_reply_invite(sd,sd->guild_invite,0);
if(sd->guild_alliance>0)
diff --git a/src/plugins/console.c b/src/plugins/console.c
index bf1a133ca..74c431d32 100644
--- a/src/plugins/console.c
+++ b/src/plugins/console.c
@@ -126,9 +126,9 @@ PLUGIN_EVENTS_TABLE = {
// Imported functions
-typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr data);
+typedef int (*TimerFunc)(int tid, unsigned int tick, int id, intptr_t data);
int (*add_timer_func_list)(TimerFunc func, char* name);
-int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr data, int interval);
+int (*add_timer_interval)(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval);
int (*delete_timer)(int tid, TimerFunc func);
unsigned int (*gettick)(void);
int (*parse_console)(const char* buf);
@@ -423,7 +423,7 @@ WORKER_FUNC_END(getinput)
/// Timer function that checks if there's assynchronous input data and feeds parse_console()
/// The input reads one line at a time and line terminators are removed.
-int console_getinputtimer(int tid, unsigned int tick, int id, intptr data)
+int console_getinputtimer(int tid, unsigned int tick, int id, intptr_t data)
{
char* cmd;
size_t len;
diff --git a/src/tool/CMakeLists.txt b/src/tool/CMakeLists.txt
new file mode 100644
index 000000000..e45586915
--- /dev/null
+++ b/src/tool/CMakeLists.txt
@@ -0,0 +1,42 @@
+
+#
+# mapcache
+#
+if( WITH_ZLIB )
+message( STATUS "Creating target mapcache" )
+set( COMMON_HEADERS
+ ${COMMON_MINI_HEADERS}
+ "${COMMON_SOURCE_DIR}/grfio.h"
+ "${COMMON_SOURCE_DIR}/utils.h"
+ )
+set( COMMON_SOURCES
+ ${COMMON_MINI_SOURCES}
+ "${COMMON_SOURCE_DIR}/grfio.c"
+ "${COMMON_SOURCE_DIR}/utils.c"
+ )
+set( MAPCACHE_SOURCES
+ "${CMAKE_CURRENT_SOURCE_DIR}/mapcache.c"
+ )
+set( LIBRARIES ${GLOBAL_LIBRARIES} ${ZLIB_LIBRARIES} )
+set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} )
+set( DEFINITIONS ${GLOBAL_DEFINITIONS} ${COMMON_MINI_DEFINITIONS} )
+set( SOURCE_FILES ${COMMON_HEADERS} ${COMMON_SOURCES} ${MAPCACHE_SOURCES} )
+source_group( common FILES ${COMMON_HEADERS} ${COMMON_SOURCES} )
+source_group( mapcache FILES ${MAPCACHE_SOURCES} )
+add_executable( mapcache ${SOURCE_FILES} )
+include_directories( ${INCLUDE_DIRS} )
+target_link_libraries( mapcache ${LIBRARIES} )
+set_target_properties( mapcache PROPERTIES COMPILE_DEFINITIONS "${DEFINITIONS}" )
+if( WITH_COMPONENT_RUNTIME )
+ cpack_add_component( Runtime_mapcache DESCRIPTION "mapcache generator" DISPLAY_NAME "mapcache" GROUP Runtime )
+ install( TARGETS mapcache
+ DESTINATION "."
+ COMPONENT Runtime_mapcache )
+endif()
+message( STATUS "Creating target mapcache - done" )
+set( HAVE_mapcache ON CACHE BOOL "mapcache target is available" )
+mark_as_advanced( HAVE_mapcache )
+else()
+message( STATUS "Skipping target mapcache (requires ZLIB)" )
+unset( HAVE_mapcache CACHE )
+endif()
diff --git a/src/tool/mapcache.c b/src/tool/mapcache.c
index deec27c4c..f1a7559f1 100644
--- a/src/tool/mapcache.c
+++ b/src/tool/mapcache.c
@@ -98,7 +98,7 @@ int32 GetLong(const unsigned char* buf)
float GetFloat(const unsigned char* buf)
{
uint32 val = GetULong(buf);
- return *((float*)&val);
+ return *((float*)(void*)&val);
}
@@ -171,7 +171,7 @@ void cache_map(char *name, struct map_data *m)
len = (unsigned long)m->xs*(unsigned long)m->ys*2;
write_buf = (unsigned char *)aMalloc(len);
// Compress the cells and get the compressed length
- compress(write_buf, &len, m->cells, m->xs*m->ys);
+ encode_zip(write_buf, &len, m->cells, m->xs*m->ys);
// Fill the map header
strncpy(info.name, name, MAP_NAME_LENGTH);