Browse Source

DB Import

Add folder import/ into db/ to load all customs
This folder is meant to hold all the customs file you wish override rA
one.
(In short it work like conf import)
related to tid:90199
lighta 11 years ago
parent
commit
28ecab5712

+ 0 - 0
db/item_cash_db2.txt → db/import/item_cash_db.txt


+ 0 - 0
db/import/item_combo_db.txt


+ 0 - 0
db/item_db2.txt → db/import/item_db.txt


+ 0 - 0
db/import/mob_branch.txt


+ 0 - 0
db/mob_db2.txt → db/import/mob_db.txt


+ 0 - 0
db/mob_skill_db2.txt → db/import/mob_skill_db.txt


+ 0 - 0
db/pet_db2.txt → db/import/pet_db.txt


+ 1 - 5
src/char/char.c

@@ -72,11 +72,7 @@ char bonus_script_db[256] = "bonus_script";
 
 
 // show loading/saving messages
 // show loading/saving messages
 int save_log = 1;
 int save_log = 1;
-
 static DBMap* char_db_; /// int char_id -> struct mmo_charstatus*
 static DBMap* char_db_; /// int char_id -> struct mmo_charstatus*
-
-char db_path[1024] = "db";
-
 int db_use_sqldbs;
 int db_use_sqldbs;
 
 
 struct mmo_map_server {
 struct mmo_map_server {
@@ -5614,7 +5610,7 @@ int char_config_read(const char* cfgName)
 		} else if (strcmpi(w1, "char_del_option") == 0) {
 		} else if (strcmpi(w1, "char_del_option") == 0) {
 			char_del_option = atoi(w2);
 			char_del_option = atoi(w2);
 		} else if(strcmpi(w1,"db_path")==0) {
 		} else if(strcmpi(w1,"db_path")==0) {
-			safestrncpy(db_path, w2, sizeof(db_path));
+			safestrncpy(db_path, w2, ARRAYLENGTH(db_path));
 		} else if (strcmpi(w1, "console") == 0) {
 		} else if (strcmpi(w1, "console") == 0) {
 			console = config_switch(w2);
 			console = config_switch(w2);
 		} else if (strcmpi(w1, "fame_list_alchemist") == 0) {
 		} else if (strcmpi(w1, "fame_list_alchemist") == 0) {

+ 1 - 1
src/char/int_guild.c

@@ -725,7 +725,7 @@ int inter_guild_sql_init(void)
 	castle_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	castle_db = idb_alloc(DB_OPT_RELEASE_DATA);
 
 
 	//Read exp file
 	//Read exp file
-	sv_readdb("db", DBPATH"exp_guild.txt", ',', 1, 1, 100, exp_guild_parse_row);
+	sv_readdb("db", DBPATH"exp_guild.txt", ',', 1, 1, 100, exp_guild_parse_row, 0);
 
 
 	add_timer_func_list(guild_save_timer, "guild_save_timer");
 	add_timer_func_list(guild_save_timer, "guild_save_timer");
 	add_timer(gettick() + 10000, guild_save_timer, 0, 0);
 	add_timer(gettick() + 10000, guild_save_timer, 0, 0);

+ 2 - 1
src/common/core.c

@@ -25,7 +25,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #else
 #else
 #include "../common/winapi.h" // Console close event handling
 #include "../common/winapi.h" // Console close event handling
-#include <direct.h>
+#include <direct.h> // _chdir
 #endif
 #endif
 
 
 
 
@@ -39,6 +39,7 @@ void (*shutdown_callback)(void) = NULL;
 int runflag = CORE_ST_RUN;
 int runflag = CORE_ST_RUN;
 int arg_c = 0;
 int arg_c = 0;
 char **arg_v = NULL;
 char **arg_v = NULL;
+char db_path[12] = "db"; /// relative path for db from server
 
 
 char *SERVER_NAME = NULL;
 char *SERVER_NAME = NULL;
 char SERVER_TYPE = ATHENA_SERVER_NONE;
 char SERVER_TYPE = ATHENA_SERVER_NONE;

+ 1 - 0
src/common/core.h

@@ -21,6 +21,7 @@ extern char **arg_v;
 /// @see E_CORE_ST
 /// @see E_CORE_ST
 extern int runflag;
 extern int runflag;
 extern char *SERVER_NAME;
 extern char *SERVER_NAME;
+extern char db_path[12]; /// relative path for db from servers
 
 
 enum {
 enum {
 	ATHENA_SERVER_NONE = 0,	// not defined
 	ATHENA_SERVER_NONE = 0,	// not defined

+ 16 - 13
src/common/strlib.c

@@ -968,18 +968,21 @@ const char* skip_escaped_c(const char* p)
 }
 }
 
 
 
 
-/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
-/// Tracks the progress of the operation (current line number, number of successfully processed rows).
-/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
-///
-/// @param directory Directory
-/// @param filename File to process
-/// @param delim Field delimiter
-/// @param mincols Minimum number of columns of a valid row
-/// @param maxcols Maximum number of columns of a valid row
-/// @param parseproc User-supplied row processing function
-/// @return true on success, false if file could not be opened
-bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current))
+/**
+ * Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
+ * Tracks the progress of the operation (current line number, number of successfully processed rows).
+ * Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
+ * @param directory : Directory
+ * @param filename : filename File to process
+ * @param delim : delim Field delimiter
+ * @param mincols : mincols Minimum number of columns of a valid row
+ * @param maxcols : maxcols Maximum number of columns of a valid row
+ * @param maxrows : maxcols Maximum number of columns of a valid row
+ * @param parseproc : parseproc User-supplied row processing function
+ * @param silent : should we display error if file not found ?
+ * @return true on success, false if file could not be opened
+ */
+bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current), bool silent)
 {
 {
 	FILE* fp;
 	FILE* fp;
 	int lines = 0;
 	int lines = 0;
@@ -995,7 +998,7 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc
 	fp = fopen(path, "r");
 	fp = fopen(path, "r");
 	if( fp == NULL )
 	if( fp == NULL )
 	{
 	{
-		ShowError("sv_readdb: can't read %s\n", path);
+		if(silent == 0) ShowError("sv_readdb: can't read %s\n", path);
 		return false;
 		return false;
 	}
 	}
 
 

+ 1 - 1
src/common/strlib.h

@@ -128,7 +128,7 @@ const char* skip_escaped_c(const char* p);
 /// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
 /// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row.
 /// Tracks the progress of the operation (current line number, number of successfully processed rows).
 /// Tracks the progress of the operation (current line number, number of successfully processed rows).
 /// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
 /// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read.
-bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current));
+bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current), bool silent);
 
 
 
 
 /// StringBuf - dynamic string
 /// StringBuf - dynamic string

+ 3 - 9
src/login/login.c

@@ -1778,6 +1778,8 @@ int login_config_read(const char* cfgName)
 
 
 		if(!strcmpi(w1,"timestamp_format"))
 		if(!strcmpi(w1,"timestamp_format"))
 			safestrncpy(timestamp_format, w2, 20);
 			safestrncpy(timestamp_format, w2, 20);
+		else if(strcmpi(w1,"db_path")==0)
+			safestrncpy(db_path, w2, ARRAYLENGTH(db_path));
 		else if(!strcmpi(w1,"stdout_with_ansisequence"))
 		else if(!strcmpi(w1,"stdout_with_ansisequence"))
 			stdout_with_ansisequence = config_switch(w2);
 			stdout_with_ansisequence = config_switch(w2);
 		else if(!strcmpi(w1,"console_silent")) {
 		else if(!strcmpi(w1,"console_silent")) {
@@ -1794,10 +1796,8 @@ int login_config_read(const char* cfgName)
 		}
 		}
 		else if( !strcmpi(w1, "login_port") ) {
 		else if( !strcmpi(w1, "login_port") ) {
 			login_config.login_port = (uint16)atoi(w2);
 			login_config.login_port = (uint16)atoi(w2);
-		}
-		else if(!strcmpi(w1, "log_login"))
+		} else if(!strcmpi(w1, "log_login"))
 			login_config.log_login = (bool)config_switch(w2);
 			login_config.log_login = (bool)config_switch(w2);
-
 		else if(!strcmpi(w1, "new_account"))
 		else if(!strcmpi(w1, "new_account"))
 			login_config.new_account_flag = (bool)config_switch(w2);
 			login_config.new_account_flag = (bool)config_switch(w2);
 		else if(!strcmpi(w1, "new_acc_length_limit"))
 		else if(!strcmpi(w1, "new_acc_length_limit"))
@@ -1835,26 +1835,20 @@ int login_config_read(const char* cfgName)
 		else if(!strcmpi(w1, "client_hash")) {
 		else if(!strcmpi(w1, "client_hash")) {
 			int group = 0;
 			int group = 0;
 			char md5[33];
 			char md5[33];
-
 			if (sscanf(w2, "%d, %32s", &group, md5) == 2) {
 			if (sscanf(w2, "%d, %32s", &group, md5) == 2) {
 				struct client_hash_node *nnode;
 				struct client_hash_node *nnode;
 				int i;
 				int i;
 				CREATE(nnode, struct client_hash_node, 1);
 				CREATE(nnode, struct client_hash_node, 1);
-
 				for (i = 0; i < 32; i += 2) {
 				for (i = 0; i < 32; i += 2) {
 					char buf[3];
 					char buf[3];
 					unsigned int byte;
 					unsigned int byte;
-
 					memcpy(buf, &md5[i], 2);
 					memcpy(buf, &md5[i], 2);
 					buf[2] = 0;
 					buf[2] = 0;
-
 					sscanf(buf, "%x", &byte);
 					sscanf(buf, "%x", &byte);
 					nnode->hash[i / 2] = (uint8)(byte & 0xFF);
 					nnode->hash[i / 2] = (uint8)(byte & 0xFF);
 				}
 				}
-
 				nnode->group_id = group;
 				nnode->group_id = group;
 				nnode->next = login_config.client_hash_nodes;
 				nnode->next = login_config.client_hash_nodes;
-
 				login_config.client_hash_nodes = nnode;
 				login_config.client_hash_nodes = nnode;
 			}
 			}
 		} else if(strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius]
 		} else if(strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius]

+ 1 - 1
src/map/cashshop.c

@@ -69,7 +69,7 @@ static int cashshop_parse_dbrow( char** str, const char* source, int line ){
  * parses lines and sends them to parse_dbrow.
  * parses lines and sends them to parse_dbrow.
  */
  */
 static void cashshop_read_db_txt( void ){
 static void cashshop_read_db_txt( void ){
-	const char* filename[] = { DBPATH"item_cash_db.txt", "item_cash_db2.txt" };
+	const char* filename[] = { DBPATH"item_cash_db.txt", "import/item_cash_db.txt" };
 	int fi;
 	int fi;
 
 
 	for( fi = 0; fi < ARRAYLENGTH( filename ); ++fi ){
 	for( fi = 0; fi < ARRAYLENGTH( filename ); ++fi ){

+ 131 - 124
src/map/clif.c

@@ -17821,157 +17821,164 @@ void packetdb_readdb(void)
 		{ "ZC_PERSONAL_INFOMATION_CHN", ZC_PERSONAL_INFOMATION_CHN},
 		{ "ZC_PERSONAL_INFOMATION_CHN", ZC_PERSONAL_INFOMATION_CHN},
 		{ "ZC_CLEAR_DIALOG", ZC_CLEAR_DIALOG},
 		{ "ZC_CLEAR_DIALOG", ZC_CLEAR_DIALOG},
 	};
 	};
+	const char *filename[] = { "packet_db.txt", "import/packet_db.txt"};
+	int f;
 
 
 	// initialize packet_db[SERVER] from hardcoded packet_len_table[] values
 	// initialize packet_db[SERVER] from hardcoded packet_len_table[] values
 	memset(packet_db,0,sizeof(packet_db));
 	memset(packet_db,0,sizeof(packet_db));
 	for( i = 0; i < ARRAYLENGTH(packet_len_table); ++i )
 	for( i = 0; i < ARRAYLENGTH(packet_len_table); ++i )
 		packet_len(i) = packet_len_table[i];
 		packet_len(i) = packet_len_table[i];
 
 
-	sprintf(line, "%s/packet_db.txt", db_path);
-	if( (fp=fopen(line,"r"))==NULL ){
-		ShowFatalError("can't read %s\n", line);
-		exit(EXIT_FAILURE);
-	}
+	for(f = 0; f<ARRAYLENGTH(filename); f++){
+		sprintf(line, "%s/%s", db_path,filename[f]);
+		if( (fp=fopen(line,"r"))==NULL ){
+			if(f==0) {
+				ShowFatalError("can't read %s\n", line);
+				exit(EXIT_FAILURE);
+			}
+			return;
+		}
 
 
-	clif_config.packet_db_ver = MAX_PACKET_VER;
-	packet_ver = MAX_PACKET_VER;	// read into packet_db's version by default
-	while( fgets(line, sizeof(line), fp) )
-	{
-		ln++;
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-		if (sscanf(line,"%256[^:]: %256[^\r\n]",w1,w2) == 2)
+		clif_config.packet_db_ver = MAX_PACKET_VER;
+		packet_ver = MAX_PACKET_VER;	// read into packet_db's version by default
+		while( fgets(line, sizeof(line), fp) )
 		{
 		{
-			if(strcmpi(w1,"packet_ver")==0) {
-				int prev_ver = packet_ver;
-				skip_ver = 0;
-				packet_ver = atoi(w2);
-				if ( packet_ver > MAX_PACKET_VER )
-				{	//Check to avoid overflowing. [Skotlex]
-					if( (warned&1) == 0 )
-						ShowWarning("The packet_db table only has support up to version %d.\n", MAX_PACKET_VER);
-					warned &= 1;
-					skip_ver = 1;
-				}
-				else if( packet_ver < 0 )
-				{
-					if( (warned&2) == 0 )
-						ShowWarning("Negative packet versions are not supported.\n");
-					warned &= 2;
-					skip_ver = 1;
-				}
-				else if( packet_ver == SERVER )
-				{
-					if( (warned&4) == 0 )
-						ShowWarning("Packet version %d is reserved for server use only.\n", SERVER);
-					warned &= 4;
-					skip_ver = 1;
-				}
+			ln++;
+			if(line[0]=='/' && line[1]=='/')
+				continue;
+			if (sscanf(line,"%256[^:]: %256[^\r\n]",w1,w2) == 2)
+			{
+				if(strcmpi(w1,"packet_ver")==0) {
+					int prev_ver = packet_ver;
+					skip_ver = 0;
+					packet_ver = atoi(w2);
+					if ( packet_ver > MAX_PACKET_VER )
+					{	//Check to avoid overflowing. [Skotlex]
+						if( (warned&1) == 0 )
+							ShowWarning("The packet_db table only has support up to version %d.\n", MAX_PACKET_VER);
+						warned &= 1;
+						skip_ver = 1;
+					}
+					else if( packet_ver < 0 )
+					{
+						if( (warned&2) == 0 )
+							ShowWarning("Negative packet versions are not supported.\n");
+						warned &= 2;
+						skip_ver = 1;
+					}
+					else if( packet_ver == SERVER )
+					{
+						if( (warned&4) == 0 )
+							ShowWarning("Packet version %d is reserved for server use only.\n", SERVER);
+						warned &= 4;
+						skip_ver = 1;
+					}
+
+					if( skip_ver )
+					{
+						ShowWarning("Skipping packet version %d.\n", packet_ver);
+						packet_ver = prev_ver;
+						continue;
+					}
+					// copy from previous version into new version and continue
+					// - indicating all following packets should be read into the newer version
+					memcpy(&packet_db[packet_ver], &packet_db[prev_ver], sizeof(packet_db[0]));
+					memcpy(&packet_db_ack[packet_ver], &packet_db_ack[prev_ver], sizeof(packet_db_ack[0]));
+					continue;
+				} else if(strcmpi(w1,"packet_db_ver")==0) {
+					if(strcmpi(w2,"default")==0) //This is the preferred version.
+						clif_config.packet_db_ver = MAX_PACKET_VER;
+					else // to manually set the packet DB version
+						clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER);
 
 
-				if( skip_ver )
-				{
-					ShowWarning("Skipping packet version %d.\n", packet_ver);
-					packet_ver = prev_ver;
 					continue;
 					continue;
 				}
 				}
-				// copy from previous version into new version and continue
-				// - indicating all following packets should be read into the newer version
-				memcpy(&packet_db[packet_ver], &packet_db[prev_ver], sizeof(packet_db[0]));
-				memcpy(&packet_db_ack[packet_ver], &packet_db_ack[prev_ver], sizeof(packet_db_ack[0]));
+			}
+
+			if( skip_ver != 0 )
+				continue; // Skipping current packet version
+
+			memset(str,0,sizeof(str));
+			for(j=0,p=line;j<4 && p; ++j)
+			{
+				str[j]=p;
+				p=strchr(p,',');
+				if(p) *p++=0;
+			}
+			if(str[0]==NULL)
 				continue;
 				continue;
-			} else if(strcmpi(w1,"packet_db_ver")==0) {
-				if(strcmpi(w2,"default")==0) //This is the preferred version.
-					clif_config.packet_db_ver = MAX_PACKET_VER;
-				else // to manually set the packet DB version
-					clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER);
+			cmd=strtol(str[0],(char **)NULL,0);
 
 
+			if(max_cmd < cmd)
+				max_cmd = cmd;
+			if(cmd <= 0 || cmd > MAX_PACKET_DB)
+				continue;
+			if(str[1]==NULL){
+				ShowError("packet_db: packet len error\n");
 				continue;
 				continue;
 			}
 			}
-		}
 
 
-		if( skip_ver != 0 )
-			continue; // Skipping current packet version
+			packet_db[packet_ver][cmd].len = (short)atoi(str[1]);
 
 
-		memset(str,0,sizeof(str));
-		for(j=0,p=line;j<4 && p; ++j)
-		{
-			str[j]=p;
-			p=strchr(p,',');
-			if(p) *p++=0;
-		}
-		if(str[0]==NULL)
-			continue;
-		cmd=strtol(str[0],(char **)NULL,0);
+			if(str[2]==NULL){
+				packet_db[packet_ver][cmd].func = NULL;
+				ln++;
+				continue;
+			}
 
 
-		if(max_cmd < cmd)
-			max_cmd = cmd;
-		if(cmd <= 0 || cmd > MAX_PACKET_DB)
-			continue;
-		if(str[1]==NULL){
-			ShowError("packet_db: packet len error\n");
-			continue;
-		}
+			// look up processing function by name
+			ARR_FIND( 0, ARRAYLENGTH(clif_parse_func), j, clif_parse_func[j].name != NULL && strcmp(str[2],clif_parse_func[j].name)==0 );
+			if( j < ARRAYLENGTH(clif_parse_func) )
+				packet_db[packet_ver][cmd].func = clif_parse_func[j].func;
+			else { //search if it's a mapped ack func
+				ARR_FIND( 0, ARRAYLENGTH(clif_ack_func), j, clif_ack_func[j].name != NULL && strcmp(str[2],clif_ack_func[j].name)==0 );
+				if( j < ARRAYLENGTH(clif_ack_func)) {
+					int fidx = clif_ack_func[j].funcidx;
+					packet_db_ack[packet_ver][fidx] = cmd;
+					//ShowInfo("Added %s, <=> %X i=%d for v=%d\n",clif_ack_func[j].name,cmd,fidx,packet_ver);
+				}
+			}
 
 
-		packet_db[packet_ver][cmd].len = (short)atoi(str[1]);
+			// set the identifying cmd for the packet_db version
+			if (strcmp(str[2],"wanttoconnection")==0)
+				clif_config.connect_cmd[packet_ver] = cmd;
 
 
-		if(str[2]==NULL){
-			packet_db[packet_ver][cmd].func = NULL;
-			ln++;
-			continue;
-		}
+			if(str[3]==NULL){
+				ShowError("packet_db: packet error\n");
+				exit(EXIT_FAILURE);
+			}
+			for(j=0,p2=str[3];p2;j++){
+				short k;
+				str2[j]=p2;
+				p2=strchr(p2,':');
+				if(p2) *p2++=0;
+				k = atoi(str2[j]);
+				// if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db)	// not used for now
+
+				if( j >= MAX_PACKET_POS )
+				{
+					ShowError("Too many positions found for packet 0x%04x (max=%d).\n", cmd, MAX_PACKET_POS);
+					break;
+				}
 
 
-		// look up processing function by name
-		ARR_FIND( 0, ARRAYLENGTH(clif_parse_func), j, clif_parse_func[j].name != NULL && strcmp(str[2],clif_parse_func[j].name)==0 );
-		if( j < ARRAYLENGTH(clif_parse_func) )
-			packet_db[packet_ver][cmd].func = clif_parse_func[j].func;
-		else { //search if it's a mapped ack func
-			ARR_FIND( 0, ARRAYLENGTH(clif_ack_func), j, clif_ack_func[j].name != NULL && strcmp(str[2],clif_ack_func[j].name)==0 );
-			if( j < ARRAYLENGTH(clif_ack_func)) {
-				int fidx = clif_ack_func[j].funcidx;
-				packet_db_ack[packet_ver][fidx] = cmd;
-				//ShowInfo("Added %s, <=> %X i=%d for v=%d\n",clif_ack_func[j].name,cmd,fidx,packet_ver);
+				packet_db[packet_ver][cmd].pos[j] = k;
 			}
 			}
+			entries++;
 		}
 		}
-
-		// set the identifying cmd for the packet_db version
-		if (strcmp(str[2],"wanttoconnection")==0)
-			clif_config.connect_cmd[packet_ver] = cmd;
-
-		if(str[3]==NULL){
-			ShowError("packet_db: packet error\n");
-			exit(EXIT_FAILURE);
+		fclose(fp);
+		if(max_cmd > MAX_PACKET_DB)
+		{
+			ShowWarning("Found packets up to 0x%X, ignored 0x%X and above.\n", max_cmd, MAX_PACKET_DB);
+			ShowWarning("Please increase MAX_PACKET_DB and recompile.\n");
 		}
 		}
-		for(j=0,p2=str[3];p2;j++){
-			short k;
-			str2[j]=p2;
-			p2=strchr(p2,':');
-			if(p2) *p2++=0;
-			k = atoi(str2[j]);
-			// if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db)	// not used for now
-
-			if( j >= MAX_PACKET_POS )
-			{
-				ShowError("Too many positions found for packet 0x%04x (max=%d).\n", cmd, MAX_PACKET_POS);
-				break;
-			}
+		if (!clif_config.connect_cmd[clif_config.packet_db_ver])
+		{	//Locate the nearest version that we still support. [Skotlex]
+			for(j = clif_config.packet_db_ver; j >= 0 && !clif_config.connect_cmd[j]; j--);
 
 
-			packet_db[packet_ver][cmd].pos[j] = k;
+			clif_config.packet_db_ver = j?j:MAX_PACKET_VER;
 		}
 		}
-		entries++;
-	}
-	fclose(fp);
-	if(max_cmd > MAX_PACKET_DB)
-	{
-		ShowWarning("Found packets up to 0x%X, ignored 0x%X and above.\n", max_cmd, MAX_PACKET_DB);
-		ShowWarning("Please increase MAX_PACKET_DB and recompile.\n");
-	}
-	if (!clif_config.connect_cmd[clif_config.packet_db_ver])
-	{	//Locate the nearest version that we still support. [Skotlex]
-		for(j = clif_config.packet_db_ver; j >= 0 && !clif_config.connect_cmd[j]; j--);
-
-		clif_config.packet_db_ver = j?j:MAX_PACKET_VER;
+		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, "packet_db.txt");
 	}
 	}
-	ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, "packet_db.txt");
 	ShowStatus("Using default packet version: "CL_WHITE"%d"CL_RESET".\n", clif_config.packet_db_ver);
 	ShowStatus("Using default packet version: "CL_WHITE"%d"CL_RESET".\n", clif_config.packet_db_ver);
 }
 }
 
 

+ 2 - 2
src/map/guild.c

@@ -2189,10 +2189,10 @@ void do_init_guild(void) {
 
 
 	guild_flags_count = 0;
 	guild_flags_count = 0;
 
 
-	sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb);
+	sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb, 0);
 
 
 	memset(guild_skill_tree,0,sizeof(guild_skill_tree));
 	memset(guild_skill_tree,0,sizeof(guild_skill_tree));
-	sv_readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka]
+	sv_readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db, 0); //guild skill tree [Komurka]
 
 
 	add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
 	add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
 	add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");
 	add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");

+ 2 - 2
src/map/homunculus.c

@@ -1236,7 +1236,7 @@ int read_homunculusdb(void)
 			}
 			}
 		}
 		}
 
 
-		sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub);
+		sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub, 0);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -1287,7 +1287,7 @@ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current)
 int read_homunculus_skilldb(void)
 int read_homunculus_skilldb(void)
 {
 {
 	memset(hskill_tree,0,sizeof(hskill_tree));
 	memset(hskill_tree,0,sizeof(hskill_tree));
-	sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, &read_homunculus_skilldb_sub);
+	sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, &read_homunculus_skilldb_sub, 0);
 
 
 	return 0;
 	return 0;
 }
 }

+ 5 - 3
src/map/instance.c

@@ -639,10 +639,12 @@ static bool instance_readdb_sub(char* str[], int columns, int current)
 
 
 void instance_readdb(void)
 void instance_readdb(void)
 {
 {
-
+	const char* filename[] = { DBPATH"instance_db.txt", "import/instance_db.txt"};
+	int f;
 	memset(&instance_db, 0, sizeof(instance_db));
 	memset(&instance_db, 0, sizeof(instance_db));
-	sv_readdb(db_path, DBPATH"instance_db.txt", ',', 7, 7+MAX_MAP_PER_INSTANCE, MAX_INSTANCE_DB, &instance_readdb_sub);
-
+	for (f=0; f<ARRAYLENGTH(filename); f++){
+		sv_readdb(db_path, filename[f], ',', 7, 7+MAX_MAP_PER_INSTANCE, MAX_INSTANCE_DB, &instance_readdb_sub, f);
+	}
 }
 }
 
 
 /*==========================================
 /*==========================================

+ 34 - 31
src/map/itemdb.c

@@ -976,17 +976,17 @@ static int itemdb_combo_split_atoi (char *str, int *val) {
 /**
 /**
  * <combo{:combo{:combo:{..}}}>,<{ script }>
  * <combo{:combo{:combo:{..}}}>,<{ script }>
  **/
  **/
-static void itemdb_read_combos() {
+static void itemdb_read_combos(const char* basedir, bool silent) {
 	uint32 lines = 0, count = 0;
 	uint32 lines = 0, count = 0;
 	char line[1024];
 	char line[1024];
 
 
 	char path[256];
 	char path[256];
 	FILE* fp;
 	FILE* fp;
 
 
-	sprintf(path, "%s/%s", db_path, DBPATH"item_combo_db.txt");
+	sprintf(path, "%s/%s", basedir, "item_combo_db.txt");
 
 
 	if ((fp = fopen(path, "r")) == NULL) {
 	if ((fp = fopen(path, "r")) == NULL) {
-		ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
+		if(silent==0) ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
 		return;
 		return;
 	}
 	}
 
 
@@ -1028,7 +1028,6 @@ static void itemdb_read_combos() {
 			ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
 			ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
 			continue;
 			continue;
 		}
 		}
-
 		/* no ending key anywhere (missing \}\) */
 		/* no ending key anywhere (missing \}\) */
 		if ( str[1][strlen(str[1])-1] != '}' ) {
 		if ( str[1][strlen(str[1])-1] != '}' ) {
 			ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
 			ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
@@ -1038,12 +1037,10 @@ static void itemdb_read_combos() {
 			int v = 0, retcount = 0;
 			int v = 0, retcount = 0;
 			struct item_data * id = NULL;
 			struct item_data * id = NULL;
 			int idx = 0;
 			int idx = 0;
-
 			if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
 			if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
 				ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
 				ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
 				continue;
 				continue;
 			}
 			}
-
 			/* validate */
 			/* validate */
 			for(v = 0; v < retcount; v++) {
 			for(v = 0; v < retcount; v++) {
 				if( !itemdb_exists(items[v]) ) {
 				if( !itemdb_exists(items[v]) ) {
@@ -1054,11 +1051,8 @@ static void itemdb_read_combos() {
 			/* failed at some item */
 			/* failed at some item */
 			if( v < retcount )
 			if( v < retcount )
 				continue;
 				continue;
-
 			id = itemdb_exists(items[0]);
 			id = itemdb_exists(items[0]);
-
 			idx = id->combos_count;
 			idx = id->combos_count;
-
 			/* first entry, create */
 			/* first entry, create */
 			if( id->combos == NULL ) {
 			if( id->combos == NULL ) {
 				CREATE(id->combos, struct item_combo*, 1);
 				CREATE(id->combos, struct item_combo*, 1);
@@ -1066,9 +1060,7 @@ static void itemdb_read_combos() {
 			} else {
 			} else {
 				RECREATE(id->combos, struct item_combo*, ++id->combos_count);
 				RECREATE(id->combos, struct item_combo*, ++id->combos_count);
 			}
 			}
-
 			CREATE(id->combos[idx],struct item_combo,1);
 			CREATE(id->combos[idx],struct item_combo,1);
-
 			id->combos[idx]->nameid = aMalloc( retcount * sizeof(unsigned short) );
 			id->combos[idx]->nameid = aMalloc( retcount * sizeof(unsigned short) );
 			id->combos[idx]->count = retcount;
 			id->combos[idx]->count = retcount;
 			id->combos[idx]->script = parse_script(str[1], path, lines, 0);
 			id->combos[idx]->script = parse_script(str[1], path, lines, 0);
@@ -1083,20 +1075,15 @@ static void itemdb_read_combos() {
 			for( v = 1; v < retcount; v++ ) {
 			for( v = 1; v < retcount; v++ ) {
 				struct item_data * it;
 				struct item_data * it;
 				int index;
 				int index;
-
 				it = itemdb_exists(items[v]);
 				it = itemdb_exists(items[v]);
-
 				index = it->combos_count;
 				index = it->combos_count;
-
 				if( it->combos == NULL ) {
 				if( it->combos == NULL ) {
 					CREATE(it->combos, struct item_combo*, 1);
 					CREATE(it->combos, struct item_combo*, 1);
 					it->combos_count = 1;
 					it->combos_count = 1;
 				} else {
 				} else {
 					RECREATE(it->combos, struct item_combo*, ++it->combos_count);
 					RECREATE(it->combos, struct item_combo*, ++it->combos_count);
 				}
 				}
-
 				CREATE(it->combos[index],struct item_combo,1);
 				CREATE(it->combos[index],struct item_combo,1);
-
 				/* we copy previously alloc'd pointers and just set it to reference */
 				/* we copy previously alloc'd pointers and just set it to reference */
 				memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo));
 				memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo));
 				/* we flag this way to ensure we don't double-dealloc same data */
 				/* we flag this way to ensure we don't double-dealloc same data */
@@ -1106,10 +1093,9 @@ static void itemdb_read_combos() {
 		}
 		}
 		count++;
 		count++;
 	}
 	}
-
 	fclose(fp);
 	fclose(fp);
 
 
-	ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
+	ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,path);
 
 
 	return;
 	return;
 }
 }
@@ -1300,11 +1286,11 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
  * Reading item from item db
  * Reading item from item db
  * item_db2 overwriting item_db
  * item_db2 overwriting item_db
  *------------------------------------------*/
  *------------------------------------------*/
-static int itemdb_readdb(void)
-{
+static int itemdb_readdb(void){
 	const char* filename[] = {
 	const char* filename[] = {
 		DBPATH"item_db.txt",
 		DBPATH"item_db.txt",
-		"item_db2.txt" };
+		"import/item_db.txt" 
+	};
 
 
 	int fi;
 	int fi;
 
 
@@ -1540,22 +1526,39 @@ bool itemdb_isNoEquip(struct item_data *id, uint16 m) {
  * read all item-related databases
  * read all item-related databases
  *------------------------------------*/
  *------------------------------------*/
 static void itemdb_read(void) {
 static void itemdb_read(void) {
-
+	int i;
+	const char* dbsubpath[] = {
+		"",
+		"/import",
+	};
+	
 	if (db_use_sqldbs)
 	if (db_use_sqldbs)
 		itemdb_read_sqldb();
 		itemdb_read_sqldb();
 	else
 	else
 		itemdb_readdb();
 		itemdb_readdb();
 
 
-	itemdb_read_combos();
+	
 	itemdb_read_itemgroup();
 	itemdb_read_itemgroup();
-	sv_readdb(db_path, "item_avail.txt",         ',', 2, 2, -1, &itemdb_read_itemavail);
-	sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip);
-	sv_readdb(db_path, DBPATH"item_trade.txt",   ',', 3, 3, -1, &itemdb_read_itemtrade);
-	sv_readdb(db_path, DBPATH"item_delay.txt",   ',', 2, 2, -1, &itemdb_read_itemdelay);
-	sv_readdb(db_path, "item_stack.txt",         ',', 3, 3, -1, &itemdb_read_stack);
-	sv_readdb(db_path, DBPATH"item_buyingstore.txt",   ',', 1, 1, -1, &itemdb_read_buyingstore);
-	sv_readdb(db_path, "item_nouse.txt",		 ',', 3, 3, -1, &itemdb_read_nouse);
-
+	
+	for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
+		int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
+		int n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
+		char* dbsubpath2 = aMalloc(n2+1);
+		safesnprintf(dbsubpath2,n1,"%s%s",db_path,dbsubpath[i]);
+		
+		sv_readdb(dbsubpath2, "item_avail.txt",         ',', 2, 2, -1, &itemdb_read_itemavail, i);
+		sv_readdb(dbsubpath2, "item_stack.txt",         ',', 3, 3, -1, &itemdb_read_stack, i);
+		sv_readdb(dbsubpath2, "item_nouse.txt",         ',', 3, 3, -1, &itemdb_read_nouse, i);
+		
+		if(i==0) 
+			safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
+		itemdb_read_combos(dbsubpath2,i); //TODO change this to sv_read ? id#script ?
+		sv_readdb(dbsubpath2, "item_noequip.txt",       ',', 2, 2, -1, &itemdb_read_noequip, i);
+		sv_readdb(dbsubpath2, "item_trade.txt",         ',', 3, 3, -1, &itemdb_read_itemtrade, i);
+		sv_readdb(dbsubpath2, "item_delay.txt",         ',', 2, 2, -1, &itemdb_read_itemdelay, i);
+		sv_readdb(dbsubpath2, "item_buyingstore.txt",   ',', 1, 1, -1, &itemdb_read_buyingstore, i);
+		aFree(dbsubpath2);
+	}
 	itemdb_uid_load();
 	itemdb_uid_load();
 }
 }
 
 

+ 1 - 2
src/map/map.c

@@ -148,7 +148,6 @@ struct map_cache_map_info {
 	int32 len;
 	int32 len;
 };
 };
 
 
-char db_path[256] = "db";
 char motd_txt[256] = "conf/motd.txt";
 char motd_txt[256] = "conf/motd.txt";
 char help_txt[256] = "conf/help.txt";
 char help_txt[256] = "conf/help.txt";
 char help2_txt[256] = "conf/help2.txt";
 char help2_txt[256] = "conf/help2.txt";
@@ -3442,7 +3441,7 @@ int map_config_read(char *cfgName)
 		else if (strcmpi(w1, "charhelp_txt") == 0)
 		else if (strcmpi(w1, "charhelp_txt") == 0)
 			strcpy(charhelp_txt, w2);
 			strcpy(charhelp_txt, w2);
 		else if(strcmpi(w1,"db_path") == 0)
 		else if(strcmpi(w1,"db_path") == 0)
-			safestrncpy(db_path,w2,255);
+			safestrncpy(db_path,w2,ARRAYLENGTH(db_path));
 		else if (strcmpi(w1, "console") == 0) {
 		else if (strcmpi(w1, "console") == 0) {
 			console = config_switch(w2);
 			console = config_switch(w2);
 			if (console)
 			if (console)

+ 0 - 1
src/map/map.h

@@ -694,7 +694,6 @@ extern int agit_flag;
 extern int agit2_flag;
 extern int agit2_flag;
 extern int night_flag; // 0=day, 1=night [Yor]
 extern int night_flag; // 0=day, 1=night [Yor]
 extern int enable_spy; //Determines if @spy commands are active.
 extern int enable_spy; //Determines if @spy commands are active.
-extern char db_path[256];
 
 
 extern char motd_txt[];
 extern char motd_txt[];
 extern char help_txt[];
 extern char help_txt[];

+ 2 - 2
src/map/mercenary.c

@@ -463,7 +463,7 @@ static bool read_mercenarydb_sub(char* str[], int columns, int current)
 int read_mercenarydb(void)
 int read_mercenarydb(void)
 {
 {
 	memset(mercenary_db,0,sizeof(mercenary_db));
 	memset(mercenary_db,0,sizeof(mercenary_db));
-	sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub);
+	sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub, 0);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -501,7 +501,7 @@ static bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
 
 
 int read_mercenary_skilldb(void)
 int read_mercenary_skilldb(void)
 {
 {
-	sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub);
+	sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub, 0);
 
 
 	return 0;
 	return 0;
 }
 }

+ 42 - 62
src/map/mob.c

@@ -3923,29 +3923,6 @@ static bool mob_readdb_sub(char* fields[], int columns, int current)
 	return mob_parse_dbrow(fields);
 	return mob_parse_dbrow(fields);
 }
 }
 
 
-static void mob_readdb(void)
-{
-	const char* filename[] = {
-		DBPATH"mob_db.txt",
-		"mob_db2.txt" };
-	int fi;
-
-	for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
-	{
-		if(fi > 0)
-		{
-			char path[256];
-			sprintf(path, "%s/%s", db_path, filename[fi]);
-			if(!exists(path))
-			{
-				continue;
-			}
-		}
-
-		sv_readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub);
-	}
-}
-
 /*==========================================
 /*==========================================
  * mob_db table reading
  * mob_db table reading
  *------------------------------------------*/
  *------------------------------------------*/
@@ -4058,18 +4035,24 @@ static int mob_read_randommonster(void)
 		DBPATH"mob_poring.txt",
 		DBPATH"mob_poring.txt",
 		DBPATH"mob_boss.txt",
 		DBPATH"mob_boss.txt",
 		"mob_pouch.txt",
 		"mob_pouch.txt",
-		"mob_classchange.txt"};
+		"mob_classchange.txt",
+		"import/mob_branch.txt",
+		"import/mob_poring.txt",
+		"import/mob_boss.txt",
+		"import/mob_pouch.txt",
+		"import/mob_classchange.txt"
+	};
 
 
 	memset(&summon, 0, sizeof(summon));
 	memset(&summon, 0, sizeof(summon));
 
 
-	for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ )
+	for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER*2; i++ )
 	{ // MobID,DummyName,Rate
 	{ // MobID,DummyName,Rate
 		entries=0;
 		entries=0;
 		mob_db_data[0]->summonper[i] = MOBID_PORING;	// Default fallback value, in case the database does not provide one
 		mob_db_data[0]->summonper[i] = MOBID_PORING;	// Default fallback value, in case the database does not provide one
 		sprintf(line, "%s/%s", db_path, mobfile[i]);
 		sprintf(line, "%s/%s", db_path, mobfile[i]);
 		fp=fopen(line,"r");
 		fp=fopen(line,"r");
 		if(fp==NULL){
 		if(fp==NULL){
-			ShowError("can't read %s\n",line);
+			if(i>=ARRAYLENGTH(mobfile)/2-1) ShowError("mob_read_randommonster: can't read %s\n",line);
 			return -1;
 			return -1;
 		}
 		}
 		while(fgets(line, sizeof(line), fp))
 		while(fgets(line, sizeof(line), fp))
@@ -4425,32 +4408,12 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
 /*==========================================
 /*==========================================
  * mob_skill_db.txt reading
  * mob_skill_db.txt reading
  *------------------------------------------*/
  *------------------------------------------*/
-static void mob_readskilldb(void) {
-	const char* filename[] = {
-		DBPATH"mob_skill_db.txt",
-		"mob_skill_db2.txt" };
-	int fi;
-
-	if( battle_config.mob_skill_rate == 0 )
-	{
+static void mob_readskilldb(const char* basedir, bool silent) {
+	if( battle_config.mob_skill_rate == 0 ) {
 		ShowStatus("Mob skill use disabled. Not reading mob skills.\n");
 		ShowStatus("Mob skill use disabled. Not reading mob skills.\n");
 		return;
 		return;
 	}
 	}
-
-	for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
-	{
-		if(fi > 0)
-		{
-			char path[256];
-			sprintf(path, "%s/%s", db_path, filename[fi]);
-			if(!exists(path))
-			{
-				continue;
-			}
-		}
-
-		sv_readdb(db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb);
-	}
+	sv_readdb(basedir, "mob_skill_db.txt", ',', 19, 19, -1, &mob_parse_row_mobskilldb, silent);
 }
 }
 
 
 /**
 /**
@@ -4570,21 +4533,38 @@ static bool mob_readdb_itemratio(char* str[], int columns, int current)
  */
  */
 static void mob_load(void)
 static void mob_load(void)
 {
 {
-	sv_readdb(db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb
-	sv_readdb(db_path, "mob_chat_db.txt", '#', 3, 3, MAX_MOB_CHAT, &mob_parse_row_chatdb);
-	if (db_use_sqldbs)
-	{
-		mob_read_sqldb();
-		mob_read_sqlskilldb();
-	}
-	else
-	{
-		mob_readdb();
-		mob_readskilldb();
+	int i;
+	const char* dbsubpath[] = {
+		"",
+		"import",
+	};
+	
+	for(i=0; i<ARRAYLENGTH(dbsubpath); i++){	
+		int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
+		int n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
+		char* dbsubpath1 = aMalloc(n1+1);
+		char* dbsubpath2 = aMalloc(n2+1);
+		safesnprintf(dbsubpath1,n1+1,"%s/%s",db_path,dbsubpath[i]);
+		if(i==0) safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
+		else safesnprintf(dbsubpath2,n2,"%s/%s",db_path,dbsubpath[i]);
+		
+		sv_readdb(dbsubpath1, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio, i); // must be read before mobdb
+		sv_readdb(dbsubpath1, "mob_chat_db.txt", '#', 3, 3, MAX_MOB_CHAT, &mob_parse_row_chatdb, i);
+		if (db_use_sqldbs && i==0) //only read once for sql
+		{
+			mob_read_sqldb();
+			mob_read_sqlskilldb();
+		} else {
+			sv_readdb(dbsubpath2, "mob_db.txt", ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub, i);
+			mob_readskilldb(dbsubpath2,i);
+		}
+		sv_readdb(dbsubpath1, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail, i);
+		sv_readdb(dbsubpath2, "mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2, i);
+		
+		aFree(dbsubpath1);
+		aFree(dbsubpath2);
 	}
 	}
-	sv_readdb(db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail);
 	mob_read_randommonster();
 	mob_read_randommonster();
-	sv_readdb(db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2);
 }
 }
 
 
 void mob_reload(void) {
 void mob_reload(void) {

+ 68 - 44
src/map/pc.c

@@ -10120,6 +10120,37 @@ static bool pc_readdb_job_param(char* fields[], int columns, int current)
 	return true;
 	return true;
 }
 }
 
 
+int pc_read_statsdb(const char *basedir, bool silent){
+	int i=1;
+	char line[24000]; //FIXME this seem too big
+	FILE *fp;
+	
+	sprintf(line, "%s/statpoint.txt", basedir);
+	fp=fopen(line,"r");
+	if(fp == NULL){
+		if(silent==0) ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line);
+		return -1;
+	} else {
+		int entries=0;
+		while(fgets(line, sizeof(line), fp))
+		{
+			int stat;
+			if(line[0]=='/' && line[1]=='/')
+				continue;
+			if ((stat=strtoul(line,NULL,10))<0)
+				stat=0;
+			if (i > MAX_LEVEL)
+				break;
+			statp[i]=stat;
+			i++;
+			entries++;
+		}
+		fclose(fp);
+		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, DBPATH"statpoint.txt");
+	}
+	return i;
+}
+
 /*==========================================
 /*==========================================
  * pc DB reading.
  * pc DB reading.
  * job_exp.txt		- required experience values
  * job_exp.txt		- required experience values
@@ -10131,19 +10162,24 @@ static bool pc_readdb_job_param(char* fields[], int columns, int current)
  *------------------------------------------*/
  *------------------------------------------*/
 int pc_readdb(void)
 int pc_readdb(void)
 {
 {
-	int i, k;
-	FILE *fp;
-	char line[24000];
-
+	int i, k, s;
+	const char* dbsubpath[] = {
+		"",
+		"import"
+		//add other path here
+	};
+		
 	//reset
 	//reset
 	memset(job_info,0,sizeof(job_info)); // job_info table
 	memset(job_info,0,sizeof(job_info)); // job_info table
 
 
 	// Reset and read skilltree
 	// Reset and read skilltree
 	memset(skill_tree,0,sizeof(skill_tree));
 	memset(skill_tree,0,sizeof(skill_tree));
-	sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree);
+	sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree, 0);
+	sv_readdb(db_path, "import/skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree, 1);
 
 
 #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
 #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
-	sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty);
+	sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 0);
+	sv_readdb(db_path, "import/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 1);
 	for( k=1; k < 3; k++ ){ // fill in the blanks
 	for( k=1; k < 3; k++ ){ // fill in the blanks
 		int j;
 		int j;
 		for( j = 0; j < CLASS_ALL; j++ ){
 		for( j = 0; j < CLASS_ALL; j++ ){
@@ -10162,50 +10198,38 @@ int pc_readdb(void)
 
 
 	 // reset then read statspoint
 	 // reset then read statspoint
 	memset(statp,0,sizeof(statp));
 	memset(statp,0,sizeof(statp));
-	i=1;
-
-	sprintf(line, "%s/"DBPATH"statpoint.txt", db_path);
-	fp=fopen(line,"r");
-	if(fp == NULL){
-		ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line);
-		//return 1;
-	} else {
-		int entries=0;
-		while(fgets(line, sizeof(line), fp))
-		{
-			int stat;
-			if(line[0]=='/' && line[1]=='/')
-				continue;
-			if ((stat=strtoul(line,NULL,10))<0)
-				stat=0;
-			if (i > MAX_LEVEL)
-				break;
-			statp[i]=stat;
-			i++;
-			entries++;
-		}
-		fclose(fp);
-		ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, DBPATH"statpoint.txt");
+	for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
+		int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
+		int n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
+		char* dbsubpath1 = aMalloc(n1+1);
+		char* dbsubpath2 = aMalloc(n2+1);
+		safesnprintf(dbsubpath1,n1+1,"%s/%s",db_path,dbsubpath[i]);
+		if(i==0) safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
+		else safesnprintf(dbsubpath2,n2,"%s/%s",db_path,dbsubpath[i]);
+
+		s = pc_read_statsdb(dbsubpath2,i);
+#ifdef RENEWAL_ASPD
+		sv_readdb(dbsubpath1, "re/job_db1.txt",',',6+MAX_WEAPON_TYPE,6+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1, i);
+#else
+		sv_readdb(dbsubpath1, "pre-re/job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1, i);
+#endif
+		sv_readdb(dbsubpath1, "job_db2.txt",',',1,1+MAX_LEVEL,CLASS_COUNT,&pc_readdb_job2, i);
+		sv_readdb(dbsubpath2, "job_exp.txt",',',4,1000+3,CLASS_COUNT*2,&pc_readdb_job_exp, i); //support till 1000lvl
+#ifdef HP_SP_TABLES
+		sv_readdb(dbsubpath2, "job_basehpsp_db.txt", ',', 4, 4+500, CLASS_COUNT*2, &pc_readdb_job_basehpsp, i); //Make it support until lvl 500!
+#endif
+		sv_readdb(dbsubpath2, "job_param_db.txt", ',', 2, PARAM_MAX+1, CLASS_COUNT, &pc_readdb_job_param, i);
+		aFree(dbsubpath1);
+		aFree(dbsubpath2);
 	}
 	}
+	
 	// generate the remaining parts of the db if necessary
 	// generate the remaining parts of the db if necessary
 	k = battle_config.use_statpoint_table; //save setting
 	k = battle_config.use_statpoint_table; //save setting
 	battle_config.use_statpoint_table = 0; //temporarily disable to force pc_gets_status_point use default values
 	battle_config.use_statpoint_table = 0; //temporarily disable to force pc_gets_status_point use default values
 	statp[0] = 45; // seed value
 	statp[0] = 45; // seed value
-	for (; i <= MAX_LEVEL; i++)
-		statp[i] = statp[i-1] + pc_gets_status_point(i-1);
+	for (; s <= MAX_LEVEL; s++)
+		statp[s] = statp[s-1] + pc_gets_status_point(s-1);
 	battle_config.use_statpoint_table = k; //restore setting
 	battle_config.use_statpoint_table = k; //restore setting
-
-#ifdef RENEWAL_ASPD
-	sv_readdb(db_path, "re/job_db1.txt",',',6+MAX_WEAPON_TYPE,6+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1);
-#else
-	sv_readdb(db_path, "pre-re/job_db1.txt",',',5+MAX_WEAPON_TYPE,5+MAX_WEAPON_TYPE,CLASS_COUNT,&pc_readdb_job1);
-#endif
-	sv_readdb(db_path, "job_db2.txt",',',1,1+MAX_LEVEL,CLASS_COUNT,&pc_readdb_job2);
-	sv_readdb(db_path, DBPATH"job_exp.txt",',',4,1000+3,CLASS_COUNT*2,&pc_readdb_job_exp); //support till 1000lvl
-#ifdef HP_SP_TABLES
-	sv_readdb(db_path, DBPATH"job_basehpsp_db.txt", ',', 4, 4+500, CLASS_COUNT*2, &pc_readdb_job_basehpsp); //Make it support until lvl 500!
-#endif
-	sv_readdb(db_path, DBPATH"job_param_db.txt", ',', 2, PARAM_MAX+1, CLASS_COUNT, &pc_readdb_job_param);
 	
 	
 	//Checking if all class have their data
 	//Checking if all class have their data
 	for (i = 0; i < JOB_MAX; i++) {
 	for (i = 0; i < JOB_MAX; i++) {

+ 42 - 25
src/map/skill.c

@@ -18971,8 +18971,14 @@ static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
  * create_arrow_db.txt
  * create_arrow_db.txt
  * abra_db.txt
  * abra_db.txt
  *------------------------------*/
  *------------------------------*/
-static void skill_readdb(void)
-{
+static void skill_readdb(void) {
+	int i;
+	const char* dbsubpath[] = {
+		"",
+		"import"
+		//add other path here
+	};
+	
 	// init skill db structures
 	// init skill db structures
 	db_clear(skilldb_name2id);
 	db_clear(skilldb_name2id);
 	memset(skill_db,0,sizeof(skill_db));
 	memset(skill_db,0,sizeof(skill_db));
@@ -18982,38 +18988,49 @@ static void skill_readdb(void)
 	memset(skill_spellbook_db,0,sizeof(skill_spellbook_db));
 	memset(skill_spellbook_db,0,sizeof(skill_spellbook_db));
 	memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db));
 	memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db));
 	memset(skill_changematerial_db,0,sizeof(skill_changematerial_db));
 	memset(skill_changematerial_db,0,sizeof(skill_changematerial_db));
-
 	// load skill databases
 	// load skill databases
 	safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name));
 	safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name));
 	safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
 	safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
 
 
-	sv_readdb(db_path, DBPATH"skill_db.txt"          , ',',  18, 18, MAX_SKILL_DB, skill_parse_row_skilldb);
-	sv_readdb(db_path, DBPATH"skill_require_db.txt"  , ',',  34, 34, MAX_SKILL_DB, skill_parse_row_requiredb);
+	for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
+		int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
+		int n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
+		char* dbsubpath1 = aMalloc(n1+1);
+		char* dbsubpath2 = aMalloc(n2+1);
+		safesnprintf(dbsubpath1,n1+1,"%s/%s",db_path,dbsubpath[i]);
+		if(i==0) safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
+		else safesnprintf(dbsubpath2,n2,"%s/%s",db_path,dbsubpath[i]);
+		
+		sv_readdb(dbsubpath2, "skill_db.txt"          , ',',  18, 18, MAX_SKILL_DB, skill_parse_row_skilldb, i);
+		sv_readdb(dbsubpath2, "skill_require_db.txt"  , ',',  34, 34, MAX_SKILL_DB, skill_parse_row_requiredb, i);
 #ifdef RENEWAL_CAST
 #ifdef RENEWAL_CAST
-	sv_readdb(db_path, "re/skill_cast_db.txt"        , ',',   8,  8, MAX_SKILL_DB, skill_parse_row_castdb);
+		sv_readdb(dbsubpath1, "re/skill_cast_db.txt"        , ',',   8,  8, MAX_SKILL_DB, skill_parse_row_castdb, i);
 #else
 #else
-	sv_readdb(db_path, "pre-re/skill_cast_db.txt"    , ',',   7,  7, MAX_SKILL_DB, skill_parse_row_castdb);
+		sv_readdb(dbsubpath1, "pre-re/skill_cast_db.txt"    , ',',   7,  7, MAX_SKILL_DB, skill_parse_row_castdb, i);
 #endif
 #endif
-	sv_readdb(db_path, DBPATH"skill_castnodex_db.txt", ',',   2,  3, MAX_SKILL_DB, skill_parse_row_castnodexdb);
-	sv_readdb(db_path, DBPATH"skill_unit_db.txt"     , ',',   8,  8, MAX_SKILL_DB, skill_parse_row_unitdb);
-
-	sv_readdb(db_path, DBPATH"skill_nocast_db.txt"   , ',',   2,  2, MAX_SKILL_DB, skill_parse_row_nocastdb);
-
-	skill_init_unit_layout();
-	sv_readdb(db_path, "produce_db.txt"              , ',',   4,  4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb);
-	sv_readdb(db_path, "create_arrow_db.txt"         , ',', 1+2,  1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb);
-	sv_readdb(db_path, "abra_db.txt"                 , ',',   3,  3, MAX_SKILL_ABRA_DB, skill_parse_row_abradb);
-	//Warlock
-	sv_readdb(db_path, "spellbook_db.txt"            , ',',   3,  3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb);
-	//Guillotine Cross
-	sv_readdb(db_path, "magicmushroom_db.txt"        , ',',   1,  1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb);
-	sv_readdb(db_path, "skill_copyable_db.txt"       , ',',    2,  4, MAX_SKILL_DB, skill_parse_row_copyabledb);
-	sv_readdb(db_path, "skill_improvise_db.txt"      , ',',   2,  2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb);
-	sv_readdb(db_path, "skill_changematerial_db.txt" , ',',   4,  4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb);
-	sv_readdb(db_path, "skill_nonearnpc_db.txt"      , ',',   2,  3, MAX_SKILL_DB, skill_parse_row_nonearnpcrangedb);
+		sv_readdb(dbsubpath2, "skill_castnodex_db.txt", ',',   2,  3, MAX_SKILL_DB, skill_parse_row_castnodexdb, i);
+		sv_readdb(dbsubpath2, "skill_unit_db.txt"     , ',',   8,  8, MAX_SKILL_DB, skill_parse_row_unitdb, i);
+		sv_readdb(dbsubpath2, "skill_nocast_db.txt"   , ',',   2,  2, MAX_SKILL_DB, skill_parse_row_nocastdb, i);
+
+		sv_readdb(dbsubpath1, "produce_db.txt"              , ',',   4,  4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb, i);
+		sv_readdb(dbsubpath1, "create_arrow_db.txt"         , ',', 1+2,  1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb, i);
+		sv_readdb(dbsubpath1, "abra_db.txt"                 , ',',   3,  3, MAX_SKILL_ABRA_DB, skill_parse_row_abradb, i);
+		//Warlock
+		sv_readdb(dbsubpath1, "spellbook_db.txt"            , ',',   3,  3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb, i);
+		//Guillotine Cross
+		sv_readdb(dbsubpath1, "magicmushroom_db.txt"        , ',',   1,  1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb, i);
+		sv_readdb(dbsubpath1, "skill_copyable_db.txt"       , ',',    2,  4, MAX_SKILL_DB, skill_parse_row_copyabledb, i);
+		sv_readdb(dbsubpath1, "skill_improvise_db.txt"      , ',',   2,  2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb, i);
+		sv_readdb(dbsubpath1, "skill_changematerial_db.txt" , ',',   4,  4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb, i);
+		sv_readdb(dbsubpath1, "skill_nonearnpc_db.txt"      , ',',   2,  3, MAX_SKILL_DB, skill_parse_row_nonearnpcrangedb, i);
 #ifdef ADJUST_SKILL_DAMAGE
 #ifdef ADJUST_SKILL_DAMAGE
-	sv_readdb(db_path, "skill_damage_db.txt"         , ',',   4,  7, MAX_SKILL_DB, skill_parse_row_skilldamage);
+		sv_readdb(dbsubpath1, "skill_damage_db.txt"         , ',',   4,  7, MAX_SKILL_DB, skill_parse_row_skilldamage, i);
 #endif
 #endif
+		aFree(dbsubpath1);
+		aFree(dbsubpath2);
+	}
+	
+	skill_init_unit_layout();
 }
 }
 
 
 void skill_reload (void) {
 void skill_reload (void) {

+ 23 - 7
src/map/status.c

@@ -12169,17 +12169,17 @@ static bool status_readdb_refine(char* fields[], int columns, int current)
 * Function stores information in the attr_fix_table
 * Function stores information in the attr_fix_table
 * @return True
 * @return True
 **/
 **/
-static bool status_readdb_attrfix()
+static bool status_readdb_attrfix(const char *basedir,bool silent)
 {
 {
 	FILE *fp;
 	FILE *fp;
 	char line[512], path[512],*p;
 	char line[512], path[512],*p;
 	int entries=0;
 	int entries=0;
 
 
 
 
-	sprintf(path, "%s/"DBPATH"attr_fix.txt", db_path);
+	sprintf(path, "%s/attr_fix.txt", basedir);
 	fp=fopen(path,"r");
 	fp=fopen(path,"r");
 	if(fp==NULL) {
 	if(fp==NULL) {
-		ShowError("can't read %s\n", path);
+		if(silent==0) ShowError("can't read %s\n", path);
 		return 1;
 		return 1;
 	}
 	}
 	while(fgets(line, sizeof(line), fp))
 	while(fgets(line, sizeof(line), fp))
@@ -12237,6 +12237,11 @@ static bool status_readdb_attrfix()
 int status_readdb(void)
 int status_readdb(void)
 {
 {
 	int i, j, k;
 	int i, j, k;
+	const char* dbsubpath[] = {
+		"",
+		"import"
+		//add other path here
+	};
 	// Initialize databases to default
 	// Initialize databases to default
 	// size_fix.txt
 	// size_fix.txt
 	for(i=0;i<ARRAYLENGTH(atkmods);i++)
 	for(i=0;i<ARRAYLENGTH(atkmods);i++)
@@ -12260,10 +12265,21 @@ int status_readdb(void)
 
 
 	// read databases
 	// read databases
 	// path,filename,separator,mincol,maxcol,maxrow,func_parsor
 	// path,filename,separator,mincol,maxcol,maxrow,func_parsor
-	status_readdb_attrfix(); // !TODO use sv_readdb ?
-	sv_readdb(db_path, "size_fix.txt",',',MAX_WEAPON_TYPE,MAX_WEAPON_TYPE,ARRAYLENGTH(atkmods),&status_readdb_sizefix);
-	sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine);
-
+	for(i=0; i<ARRAYLENGTH(dbsubpath); i++){
+		int n1 = strlen(db_path)+strlen(dbsubpath[i])+1;
+		int n2 = strlen(db_path)+strlen(DBPATH)+strlen(dbsubpath[i])+1;
+		char* dbsubpath1 = aMalloc(n1+1);
+		char* dbsubpath2 = aMalloc(n2+1);
+		safesnprintf(dbsubpath1,n1+1,"%s/%s",db_path,dbsubpath[i]);
+		if(i==0) safesnprintf(dbsubpath2,n2,"%s/%s%s",db_path,DBPATH,dbsubpath[i]);
+		else safesnprintf(dbsubpath2,n2,"%s/%s",db_path,dbsubpath[i]);
+		
+		status_readdb_attrfix(dbsubpath2,i); // !TODO use sv_readdb ?
+		sv_readdb(dbsubpath1, "size_fix.txt",',',MAX_WEAPON_TYPE,MAX_WEAPON_TYPE,ARRAYLENGTH(atkmods),&status_readdb_sizefix, i);
+		sv_readdb(dbsubpath2, "refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine, i);
+		aFree(dbsubpath1);
+		aFree(dbsubpath2);
+	}
 	return 0;
 	return 0;
 }
 }