Sfoglia il codice sorgente

* Some preparations for the guild script update
- cleaned up npc event execution code
- cleaned up guild data loading/saving code; to be improved later
- removed dummy 'account name' expulsion list management code
- removed columns 'rsv1' and 'rsv2' from guild member data
- removed columns 'rsv1' 'rsv2' 'rsv3' and 'acc' from guild expulsion data
- added upgrade_svn11895.sql for SQL

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@11895 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 anni fa
parent
commit
8be1c4d48c

+ 7 - 0
Changelog-Trunk.txt

@@ -3,6 +3,13 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2007/12/12
+	* Some preparations for the guild script update [ultramage]
+	- cleaned up npc event execution code
+	- cleaned up guild data loading/saving code; to be improved later
+	- removed dummy 'account name' expulsion list management code
+	- removed columns 'rsv1' and 'rsv2' from guild member data
+	- removed columns 'rsv1' 'rsv2' 'rsv3' and 'acc' from guild expulsion data
 2007/12/11
 	* Added query_logsql script command to perform sql commands using the log
 	  db connection.

+ 1 - 7
sql-files/main.sql

@@ -231,13 +231,9 @@ CREATE TABLE `guild_castle` (
 DROP TABLE IF EXISTS `guild_expulsion`;
 CREATE TABLE `guild_expulsion` (
   `guild_id` int(11) unsigned NOT NULL default '0',
+  `account_id` int(11) unsigned NOT NULL default '0',
   `name` varchar(24) NOT NULL default '',
   `mes` varchar(40) NOT NULL default '',
-  `acc` varchar(40) NOT NULL default '',
-  `account_id` int(11) unsigned NOT NULL default '0',
-  `rsv1` int(11) unsigned NOT NULL default '0',
-  `rsv2` int(11) unsigned NOT NULL default '0',
-  `rsv3` int(11) unsigned NOT NULL default '0',
   PRIMARY KEY  (`guild_id`,`name`)
 ) TYPE=MyISAM;
 
@@ -259,8 +255,6 @@ CREATE TABLE `guild_member` (
   `exp_payper` tinyint(11) unsigned NOT NULL default '0',
   `online` tinyint(4) unsigned NOT NULL default '0',
   `position` tinyint(6) unsigned NOT NULL default '0',
-  `rsv1` int(11) unsigned NOT NULL default '0',
-  `rsv2` int(11) unsigned NOT NULL default '0',
   `name` varchar(24) NOT NULL default '',
   PRIMARY KEY  (`guild_id`,`char_id`),
   KEY `char_id` (`char_id`)

+ 1 - 1
sql-files/upgrade_svn11721_log.sql

@@ -1 +1 @@
-ALTER TABLE `picklog` CHANGE `type` `type` ENUM( 'M', 'P', 'L', 'T', 'V', 'S', 'N', 'C', 'A', 'R', 'G', 'E' ) NOT NULL DEFAULT 'P';
+ALTER TABLE `picklog` CHANGE `type` `type` ENUM( 'M', 'P', 'L', 'T', 'V', 'S', 'N', 'C', 'A', 'R', 'G', 'E' ) NOT NULL DEFAULT 'P';

+ 12 - 0
sql-files/upgrade_svn11895.sql

@@ -0,0 +1,12 @@
+ALTER TABLE `guild_expulsion`
+  DROP `acc`,
+  DROP `rsv1`,
+  DROP `rsv2`,
+  DROP `rsv3`;
+
+ALTER TABLE `guild_expulsion`
+  MODIFY `account_id` int(11) unsigned NOT NULL default '0' AFTER `guild_id`;
+
+ALTER TABLE `guild_member`
+  DROP `rsv1`,
+  DROP `rsv2`;

+ 256 - 195
src/char/int_guild.c

@@ -31,23 +31,24 @@ static unsigned int guild_exp[100];
 
 int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes);
 int mapif_guild_broken(int guild_id, int flag);
-int guild_check_empty(struct guild *g);
+bool guild_check_empty(struct guild *g);
 int guild_calcinfo(struct guild *g);
 int mapif_guild_basicinfochanged(int guild_id, int type, const void *data, int len);
 int mapif_guild_info(int fd, struct guild *g);
 int guild_break_sub(DBKey key, void *data, va_list ap);
 
-// ギルドデータの文字列への変換
-int inter_guild_tostr(char *str, struct guild *g) {
+/// serializes the guild data structure into the provided string
+int inter_guild_tostr(char* str, struct guild* g)
+{
 	int i, c, len;
 
-	// 基本データ
+	// save guild base info
 	len = sprintf(str, "%d\t%s\t%s\t%d,%d,%u,%d,%d\t%s#\t%s#\t",
-	              g->guild_id, g->name, g->master,
-	              g->guild_lv, g->max_member, g->exp, g->skill_point, g->castle_id,
-	              g->mes1, g->mes2);
-	// メンバー
-	for(i = 0; i < g->max_member; i++) {
+		g->guild_id, g->name, g->master, g->guild_lv, g->max_member, g->exp, g->skill_point, 0, g->mes1, g->mes2);
+
+	// save guild member info
+	for(i = 0; i < g->max_member; i++)
+	{
 		struct guild_member *m = &g->member[i];
 		len += sprintf(str + len, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%s\t",
 		               m->account_id, m->char_id,
@@ -55,18 +56,21 @@ int inter_guild_tostr(char *str, struct guild *g) {
 		               m->class_, m->lv, m->exp, m->exp_payper, m->position,
 		               ((m->account_id > 0) ? m->name : "-"));
 	}
-	// 役職
+
+	// save guild position info
 	for(i = 0; i < MAX_GUILDPOSITION; i++) {
 		struct guild_position *p = &g->position[i];
 		len += sprintf(str + len, "%d,%d\t%s#\t", p->mode, p->exp_mode, p->name);
 	}
-	// エンブレム
+
+	// save guild emblem
 	len += sprintf(str + len, "%d,%d,", g->emblem_len, g->emblem_id);
 	for(i = 0; i < g->emblem_len; i++) {
 		len += sprintf(str + len, "%02x", (unsigned char)(g->emblem_data[i]));
 	}
 	len += sprintf(str + len, "$\t");
-	// 同盟リスト
+
+	// save guild alliance info
 	c = 0;
 	for(i = 0; i < MAX_GUILDALLIANCE; i++)
 		if (g->alliance[i].guild_id > 0)
@@ -77,7 +81,8 @@ int inter_guild_tostr(char *str, struct guild *g) {
 		if (a->guild_id > 0)
 			len += sprintf(str + len, "%d,%d\t%s\t", a->guild_id, a->opposition, a->name);
 	}
-	// 追放リスト
+
+	// save guild expulsion info
 	c = 0;
 	for(i = 0; i < MAX_GUILDEXPULSION; i++)
 		if (g->expulsion[i].account_id > 0)
@@ -87,10 +92,10 @@ int inter_guild_tostr(char *str, struct guild *g) {
 		struct guild_expulsion *e = &g->expulsion[i];
 		if (e->account_id > 0)
 			len += sprintf(str + len, "%d,%d,%d,%d\t%s\t%s\t%s#\t",
-			               e->account_id, e->rsv1, e->rsv2, e->rsv3,
-			               e->name, e->acc, e->mes );
+			               e->account_id, 0, 0, 0, e->name, "#", e->mes );
 	}
-	// ギルドスキル
+
+	// save guild skill info
 	for(i = 0; i < MAX_GUILDSKILL; i++) {
 		len += sprintf(str + len, "%d,%d ", g->skill[i].id, g->skill[i].lv);
 	}
@@ -99,154 +104,206 @@ int inter_guild_tostr(char *str, struct guild *g) {
 	return 0;
 }
 #endif //TXT_SQL_CONVERT
-// ギルドデータの文字列からの変換
-int inter_guild_fromstr(char *str, struct guild *g) {
-	int i, j, c;
-	unsigned int exp;
-	int tmp_int[16];
-	char tmp_str[4][256];
-	char tmp_str2[4096];
+
+/// parses the guild data string into a guild data structure
+int inter_guild_fromstr(char* str, struct guild* g)
+{
+	int i, c;
 	char *pstr;
 
-	// 基本データ
 	memset(g, 0, sizeof(struct guild));
-	if (sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%u,%d,%d\t%[^\t]\t%[^\t]\t", &tmp_int[0],
-	           tmp_str[0], tmp_str[1],
-	           &tmp_int[1], &tmp_int[2], &exp, &tmp_int[4], &tmp_int[5],
-	           tmp_str[2], tmp_str[3]) < 8)
-		return 1;
 
-	g->guild_id = tmp_int[0];
-	g->guild_lv = tmp_int[1];
-	g->max_member = tmp_int[2];
-	g->exp = exp;
-	g->skill_point = tmp_int[4];
-#ifndef TXT_SQL_CONVERT
-	g->castle_id = tmp_int[5];
-#endif
-	memcpy(g->name, tmp_str[0], NAME_LENGTH);
-	memcpy(g->master, tmp_str[1], NAME_LENGTH);
-	memcpy(g->mes1, tmp_str[2], 60);
-	memcpy(g->mes2, tmp_str[3], 120);
-	g->mes1[strlen(g->mes1)-1] = 0;
-	g->mes2[strlen(g->mes2)-1] = 0;
-
-	for(j = 0; j < 6 && str != NULL; j++)	// 位置スキップ
-		str = strchr(str + 1, '\t');
-//	printf("GuildBaseInfo OK\n");
-
-	// メンバー
-	for(i = 0; i < g->max_member; i++) {
-		struct guild_member *m = &g->member[i];
-		if (sscanf(str + 1, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%[^\t]\t",
-		           &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4],
-		           &tmp_int[5], &tmp_int[6], &exp, &tmp_int[8], &tmp_int[9],
-		           tmp_str[0]) < 11)
+	{// load guild base info
+		int guildid;
+		char name[256]; // only 24 used
+		char master[256]; // only 24 used
+		int guildlv;
+		int max_member;
+		unsigned int exp;
+		int skpoint;
+		char mes1[256]; // only 60 used
+		char mes2[256]; // only 120 used
+		int len;
+
+		if( sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%u,%d,%*d\t%[^\t]\t%[^\t]\t%n",
+				   &guildid, name, master, &guildlv, &max_member, &exp, &skpoint, mes1, mes2, &len) < 9 )
 			return 1;
-		m->account_id = tmp_int[0];
-		m->char_id = tmp_int[1];
-		m->hair = tmp_int[2];
-		m->hair_color = tmp_int[3];
-		m->gender = tmp_int[4];
-		m->class_ = tmp_int[5];
-		m->lv = tmp_int[6];
-		m->exp = exp;
-		m->exp_payper = tmp_int[8];
-		m->position = tmp_int[9];
-		memcpy(m->name, tmp_str[0], NAME_LENGTH);
-
-		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
-			str = strchr(str + 1, '\t');
+
+		// remove '#'
+		mes1[strlen(mes1)-1] = '\0';
+		mes2[strlen(mes2)-1] = '\0';
+
+		g->guild_id = guildid;
+		g->guild_lv = guildlv;
+		g->max_member = max_member;
+		g->exp = exp;
+		g->skill_point = skpoint;
+		safestrncpy(g->name, name, sizeof(g->name));
+		safestrncpy(g->master, master, sizeof(g->master));
+		safestrncpy(g->mes1, mes1, sizeof(g->mes1));
+		safestrncpy(g->mes2, mes2, sizeof(g->mes2));
+
+		str+= len;
 	}
-//	printf("GuildMemberInfo OK\n");
-	// 役職
-	i = 0;
-	while (sscanf(str+1, "%d,%d%n", &tmp_int[0], &tmp_int[1], &j) == 2 && str[1+j] == '\t') {
-		struct guild_position *p = &g->position[i];
-		if (sscanf(str+1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str[0]) < 3)
-			return 1;
-		p->mode = tmp_int[0];
-		p->exp_mode = tmp_int[1];
-		tmp_str[0][strlen(tmp_str[0])-1] = 0;
-		memcpy(p->name, tmp_str[0], NAME_LENGTH);
 
-		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
-			str = strchr(str+1, '\t');
-		i++;
+	{// load guild member info
+		int accountid;
+		int charid;
+		int hair, hair_color, gender;
+		int class_, lv;
+		unsigned int exp;
+		int exp_payper;
+		int position;
+		char name[256]; // only 24 used
+		int len;
+		int i;
+
+		for( i = 0; i < g->max_member; i++ )
+		{
+			struct guild_member* m = &g->member[i];
+			if (sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%u,%d,%d\t%[^\t]\t%n",
+					   &accountid, &charid, &hair, &hair_color, &gender,
+					   &class_, &lv, &exp, &exp_payper, &position,
+					   name, &len) < 11)
+				return 1;
+
+			m->account_id = accountid;
+			m->char_id = charid;
+			m->hair = hair;
+			m->hair_color = hair_color;
+			m->gender = gender;
+			m->class_ = class_;
+			m->lv = lv;
+			m->exp = exp;
+			m->exp_payper = exp_payper;
+			m->position = position;
+			safestrncpy(m->name, name, NAME_LENGTH);
+
+			str+= len;
+		}
 	}
-//	printf("GuildPositionInfo OK\n");
-	// エンブレム
-	tmp_int[1] = 0;
-	if (sscanf(str + 1, "%d,%d,%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str2)< 3 &&
-		sscanf(str + 1, "%d,%[^\t]\t", &tmp_int[0], tmp_str2) < 2)
-		return 1;
-	g->emblem_len = tmp_int[0];
-	g->emblem_id = tmp_int[1];
-	for(i = 0, pstr = tmp_str2; i < g->emblem_len; i++, pstr += 2) {
-		int c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0;
-		if (c1 >= '0' && c1 <= '9') x1 = c1 - '0';
-		if (c1 >= 'a' && c1 <= 'f') x1 = c1 - 'a' + 10;
-		if (c1 >= 'A' && c1 <= 'F') x1 = c1 - 'A' + 10;
-		if (c2 >= '0' && c2 <= '9') x2 = c2 - '0';
-		if (c2 >= 'a' && c2 <= 'f') x2 = c2 - 'a' + 10;
-		if (c2 >= 'A' && c2 <= 'F') x2 = c2 - 'A' + 10;
-		g->emblem_data[i] = (x1<<4) | x2;
+
+	{// load guild position info
+		int mode, exp_mode;
+		char name[256]; // only 24 used
+		int len;
+		int i = 0;
+		int j;
+
+		while (sscanf(str, "%d,%d%n", &mode, &exp_mode, &j) == 2 && str[j] == '\t')
+		{
+			struct guild_position *p = &g->position[i];
+			if (sscanf(str, "%d,%d\t%[^\t]\t%n", &mode, &exp_mode, name, &len) < 3)
+				return 1;
+
+			p->mode = mode;
+			p->exp_mode = exp_mode;
+			name[strlen(name)-1] = 0;
+			safestrncpy(p->name, name, NAME_LENGTH);
+
+			i++;
+			str+= len;
+		}
 	}
-//	printf("GuildEmblemInfo OK\n");
-	str=strchr(str + 1, '\t');	// 位置スキップ
 
-	// 同盟リスト
-	if (sscanf(str + 1, "%d\t", &c) < 1)
-		return 1;
-	str = strchr(str + 1, '\t');	// 位置スキップ
-	for(i = 0; i < c; i++) {
-		struct guild_alliance *a = &g->alliance[i];
-		if (sscanf(str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str[0]) < 3)
+	{// load guild emblem
+		int emblemlen;
+		int emblemid;
+		char emblem[4096];
+		int len;
+
+		emblemid = 0;
+		if( sscanf(str, "%d,%d,%[^\t]\t%n", &emblemlen, &emblemid, emblem, &len) < 3 )
+		if( sscanf(str, "%d,%[^\t]\t%n", &emblemlen, emblem, &len) < 2 ) //! pre-svn format
 			return 1;
-		a->guild_id = tmp_int[0];
-		a->opposition = tmp_int[1];
-		memcpy(a->name, tmp_str[0], NAME_LENGTH);
 
-		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
-			str = strchr(str + 1, '\t');
+		g->emblem_len = emblemlen;
+		g->emblem_id = emblemid;
+		for(i = 0, pstr = emblem; i < g->emblem_len; i++, pstr += 2) {
+			int c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0;
+			if (c1 >= '0' && c1 <= '9') x1 = c1 - '0';
+			if (c1 >= 'a' && c1 <= 'f') x1 = c1 - 'a' + 10;
+			if (c1 >= 'A' && c1 <= 'F') x1 = c1 - 'A' + 10;
+			if (c2 >= '0' && c2 <= '9') x2 = c2 - '0';
+			if (c2 >= 'a' && c2 <= 'f') x2 = c2 - 'a' + 10;
+			if (c2 >= 'A' && c2 <= 'F') x2 = c2 - 'A' + 10;
+			g->emblem_data[i] = (x1<<4) | x2;
+		}
+
+		str+= len;
 	}
-//	printf("GuildAllianceInfo OK\n");
-	// 追放リスト
-	if (sscanf(str+1, "%d\t", &c) < 1)
-		return 1;
-	str = strchr(str + 1, '\t');	// 位置スキップ
-	for(i = 0; i < c; i++) {
-		struct guild_expulsion *e = &g->expulsion[i];
-		if (sscanf(str + 1, "%d,%d,%d,%d\t%[^\t]\t%[^\t]\t%[^\t]\t",
-		           &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-		           tmp_str[0], tmp_str[1], tmp_str[2]) < 6)
+
+	{// load guild alliance info
+		int guildid;
+		int opposition;
+		char name[256]; // only 24 used
+		int len;
+
+		if (sscanf(str, "%d\t%n", &c, &len) < 1)
 			return 1;
-		e->account_id = tmp_int[0];
-		e->rsv1 = tmp_int[1];
-		e->rsv2 = tmp_int[2];
-		e->rsv3 = tmp_int[3];
-		memcpy(e->name, tmp_str[0], NAME_LENGTH);
-		memcpy(e->acc, tmp_str[1], 24);
-		tmp_str[2][strlen(tmp_str[2])-1] = 0;
-		memcpy(e->mes, tmp_str[2], 40);
-
-		for(j = 0; j < 4 && str != NULL; j++)	// 位置スキップ
-			str = strchr(str + 1, '\t');
+		str+= len;
+
+		for(i = 0; i < c; i++)
+		{
+			struct guild_alliance* a = &g->alliance[i];
+			if (sscanf(str, "%d,%d\t%[^\t]\t%n", &guildid, &opposition, name, &len) < 3)
+				return 1;
+
+			a->guild_id = guildid;
+			a->opposition = opposition;
+			safestrncpy(a->name, name, NAME_LENGTH);
+
+			str+= len;
+		}
 	}
-//	printf("GuildExpulsionInfo OK\n");
-	// ギルドスキル
-	for(i = 0; i < MAX_GUILDSKILL; i++) {
-		if (sscanf(str+1,"%d,%d ", &tmp_int[0], &tmp_int[1]) < 2)
-			break;
-		g->skill[i].id = tmp_int[0];
-		g->skill[i].lv = tmp_int[1];
-		str = strchr(str + 1, ' ');
+
+	{// load guild expulsion info
+		int accountid;
+		char name[256]; // only 24 used
+		char message[256]; // only 40 used
+		int len;
+		int i;
+
+		if (sscanf(str, "%d\t%n", &c, &len) < 1)
+			return 1;
+		str+= len;
+
+		for(i = 0; i < c; i++)
+		{
+			struct guild_expulsion *e = &g->expulsion[i];
+			if (sscanf(str, "%d,%*d,%*d,%*d\t%[^\t]\t%*[^\t]\t%[^\t]\t%n", &accountid, name, message, &len) < 3)
+				return 1;
+
+			e->account_id = accountid;
+			safestrncpy(e->name, name, sizeof(e->name));
+			message[strlen(message)-1] = 0; // remove '#'
+			safestrncpy(e->mes, message, sizeof(e->mes));
+
+			str+= len;
+		}
+	}
+
+	{// load guild skill info
+		int skillid;
+		int skilllv;
+		int len;
+		int i;
+
+		for(i = 0; i < MAX_GUILDSKILL; i++)
+		{
+			if (sscanf(str, "%d,%d %n", &skillid, &skilllv, &len) < 2)
+				break;
+			g->skill[i].id = skillid;
+			g->skill[i].lv = skilllv;
+
+			str+= len;
+		}
+		str = strchr(str, '\t');
 	}
-	str = strchr(str + 1, '\t');
-//	printf("GuildSkillInfo OK\n");
 
 	return 0;
 }
+
 #ifndef TXT_SQL_CONVERT
 // ギルド城データの文字列への変換
 int inter_guildcastle_tostr(char *str, struct guild_castle *gc) {
@@ -500,7 +557,6 @@ int inter_guild_save() {
 	guild_db->foreach(guild_db, inter_guild_save_sub, fp);
 //	fprintf(fp, "%d\t%%newid%%\n", guild_newid);
 	lock_fclose(fp, guild_txt, &lock);
-//	printf("int_guild: %s saved.\n", guild_txt);
 
 	if ((fp = lock_fopen(castle_txt,&lock)) == NULL) {
 		ShowError("int_guild: can't write [%s] !!! data is lost !!!\n", castle_txt);
@@ -532,20 +588,19 @@ struct guild* search_guildname(char *str) {
 }
 
 // ギルドが空かどうかチェック
-int guild_check_empty(struct guild *g) {
+static bool guild_check_empty(struct guild *g)
+{
 	int i;
+	ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 );
+	if( i < g->max_member)
+		return false; // not empty
 
-	for(i = 0; i < g->max_member; i++) {
-		if (g->member[i].account_id > 0) {
-			return 0;
-		}
-	}
-		// 誰もいないので解散
+	// 誰もいないので解散
 	guild_db->foreach(guild_db, guild_break_sub, g->guild_id);
 	inter_guild_storage_delete(g->guild_id);
 	mapif_guild_broken(g->guild_id, 0);
 	idb_remove(guild_db, g->guild_id);
-	return 1;
+	return true;
 }
 
 unsigned int guild_nextexp (int level)
@@ -1023,46 +1078,48 @@ int mapif_parse_GuildAddMember(int fd, int guild_id, struct guild_member *m) {
 	return 0;
 }
 
-// ギルド脱退/追放要求
-int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) {
-	struct guild *g = NULL;
+// Delete member from guild
+int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
+{
 	int i, j;
 
-	g = idb_get(guild_db, guild_id);
-	if (g != NULL) {
-		for(i = 0; i < MAX_GUILD; i++) {
-			if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) {
-//				printf("%d %d\n", i, (int)(&g->member[i]));
-//				printf("%d %s\n", i, g->member[i].name);
-
-				if (flag) {	// 追放の場合追放リストに入れる
-					for(j = 0; j < MAX_GUILDEXPULSION; j++) {
-						if (g->expulsion[j].account_id == 0)
-							break;
-					}
-					if (j == MAX_GUILDEXPULSION) {	// 一杯なので古いのを消す
-						for(j = 0; j < MAX_GUILDEXPULSION - 1; j++)
-							g->expulsion[j] = g->expulsion[j+1];
-						j = MAX_GUILDEXPULSION - 1;
-					}
-					g->expulsion[j].account_id = account_id;
-					strncpy(g->expulsion[j].acc, "dummy", NAME_LENGTH);
-					memcpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
-					memcpy(g->expulsion[j].mes, mes, 40);
-				}
-
-				mapif_guild_leaved(guild_id, account_id, char_id, flag, g->member[i].name, mes);
-//				printf("%d %d\n", i, (int)(&g->member[i]));
-//				printf("%d %s\n", i, (&g->member[i])->name);
-				memset(&g->member[i], 0, sizeof(struct guild_member));
+	struct guild* g = idb_get(guild_db, guild_id);
+	if( g == NULL )
+	{
+		//TODO
+		return 0;
+	}
 
-				if (guild_check_empty(g) == 0)
-					mapif_guild_info(-1,g);// まだ人がいるのでデータ送信
+	// Find the member
+	ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
+	if( i == g->max_member )
+	{
+		//TODO
+		return 0;
+	}
 
-				return 0;
-			}
+	if( flag )
+	{	// 追放の場合追放リストに入れる
+		ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 );
+		if (j == MAX_GUILDEXPULSION)
+		{	// 一杯なので古いのを消す
+			for(j = 0; j < MAX_GUILDEXPULSION - 1; j++)
+				g->expulsion[j] = g->expulsion[j+1];
+			j = MAX_GUILDEXPULSION - 1;
 		}
+		// Save the expulsion entry
+		g->expulsion[j].account_id = account_id;
+		safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
+		safestrncpy(g->expulsion[j].mes, mes, 40);
 	}
+
+	mapif_guild_leaved(guild_id, account_id, char_id, flag, g->member[i].name, mes);
+
+	memset(&g->member[i], 0, sizeof(struct guild_member));
+
+	if (guild_check_empty(g) == 0)
+		mapif_guild_info(-1,g);// まだ人がいるのでデータ送信
+
 	return 0;
 }
 
@@ -1408,12 +1465,13 @@ int mapif_parse_GuildCastleDataLoad(int fd, int castle_id, int index) {
 	return 0;
 }
 
-int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value) {
+int mapif_parse_GuildCastleDataSave(int fd, int castle_id, int index, int value)
+{
 	struct guild_castle *gc= idb_get(castle_db, castle_id);
 
-	if (gc == NULL) {
+	if (gc == NULL)
 		return mapif_guild_castle_datasave(castle_id, index, value);
-	}
+
 	switch(index) {
 	case 1:
 		if (gc->guild_id != value) {
@@ -1494,7 +1552,8 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
 // ・パケット長データはinter.cにセットしておくこと
 // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
 // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
-int inter_guild_parse_frommap(int fd) {
+int inter_guild_parse_frommap(int fd)
+{
 	RFIFOHEAD(fd);
 	switch(RFIFOW(fd,0)) {
 	case 0x3030: mapif_parse_CreateGuild(fd, RFIFOL(fd,4), (char*)RFIFOP(fd,8), (struct guild_member *)RFIFOP(fd,32)); break;
@@ -1522,13 +1581,15 @@ int inter_guild_parse_frommap(int fd) {
 	return 1;
 }
 
-// マップサーバーの接続時処理
-int inter_guild_mapif_init(int fd) {
+// processes a mapserver connection event
+int inter_guild_mapif_init(int fd)
+{
 	return mapif_guild_castle_alldataload(fd);
 }
 
 // サーバーから脱退要求(キャラ削除用)
-int inter_guild_leave(int guild_id, int account_id, int char_id) {
+int inter_guild_leave(int guild_id, int account_id, int char_id)
+{
 	return mapif_parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **");
 }
 #endif //TXT_SQL_CONVERT

+ 96 - 114
src/char_sql/int_guild.c

@@ -1,13 +1,13 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
-#include "../common/mmo.h"
 #include "../common/cbasetypes.h"
-#include "../common/strlib.h"
-#include "../common/showmsg.h"
-#include "../common/db.h"
+#include "../common/mmo.h"
 #include "../common/malloc.h"
 #include "../common/socket.h"
+#include "../common/db.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
 #include "../common/timer.h"
 #include "char.h"
 #include "inter.h"
@@ -40,7 +40,7 @@ static unsigned int guild_exp[100];
 
 int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes);
 int mapif_guild_broken(int guild_id,int flag);
-int guild_check_empty(struct guild *g);
+bool guild_check_empty(struct guild *g);
 int guild_calcinfo(struct guild *g);
 int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len);
 int mapif_guild_info(int fd,struct guild *g);
@@ -105,10 +105,10 @@ int inter_guild_tosql(struct guild *g,int flag)
 	// GS_LEVEL `guild_lv`,`max_member`,`exp`,`next_exp`,`skill_point`
 	// GS_BASIC `name`,`master`,`char_id`
 
-	// GS_MEMBER `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name`)
+	// GS_MEMBER `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`)
 	// GS_POSITION `guild_position` (`guild_id`,`position`,`name`,`mode`,`exp_mode`)
 	// GS_ALLIANCE `guild_alliance` (`guild_id`,`opposition`,`alliance_id`,`name`)
-	// GS_EXPULSION `guild_expulsion` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`)
+	// GS_EXPULSION `guild_expulsion` (`guild_id`,`account_id`,`name`,`mes`)
 	// GS_SKILL `guild_skill` (`guild_id`,`id`,`lv`) 
 
 	// temporary storage for str convertion. They must be twice the size of the
@@ -327,15 +327,11 @@ int inter_guild_tosql(struct guild *g,int flag)
 			struct guild_expulsion *e=&g->expulsion[i];
 			if(e->account_id>0){
 				char esc_mes[sizeof(e->mes)*2+1];
-				char esc_acc[sizeof(e->acc)*2+1];
 
 				Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH));
 				Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes)));
-				Sql_EscapeStringLen(sql_handle, esc_acc, e->acc, strnlen(e->acc, sizeof(e->acc)));
-				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) "
-					"VALUES ('%d','%s','%s','%s','%d','%d','%d','%d')",
-					guild_expulsion_db, g->guild_id,
-					esc_name, esc_mes, esc_acc, e->account_id, e->rsv1, e->rsv2 ,e->rsv3) )
+				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) "
+					"VALUES ('%d','%d','%s','%s')", guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) )
 					Sql_ShowDebug(sql_handle);
 			}
 		}
@@ -392,11 +388,11 @@ struct guild * inter_guild_fromsql(int guild_id)
 	CREATE(g, struct guild, 1);
 
 	g->guild_id = guild_id;
-	Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH));
-	Sql_GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH));
-	Sql_GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data);
-	Sql_GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data);
-	Sql_GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data);
+	Sql_GetData(sql_handle,  0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH));
+	Sql_GetData(sql_handle,  1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH));
+	Sql_GetData(sql_handle,  2, &data, NULL); g->guild_lv = atoi(data);
+	Sql_GetData(sql_handle,  3, &data, NULL); g->connect_member = atoi(data);
+	Sql_GetData(sql_handle,  4, &data, NULL); g->max_member = atoi(data);
 	if( g->max_member > MAX_GUILD )
 	{	// Fix reduction of MAX_GUILD [PoW]
 		ShowWarning("Guild %d:%s specifies higher capacity (%d) than MAX_GUILD (%d)\n", guild_id, g->name, g->max_member, MAX_GUILD);
@@ -433,9 +429,9 @@ struct guild * inter_guild_fromsql(int guild_id)
 		++data;
 	}
 
-	//printf("- Read guild_member %d from sql \n",guild_id);
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name` "
-		"FROM `%s` WHERE `guild_id`='%d'  ORDER BY `position`", guild_member_db, guild_id) )
+	// load guild member info
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` "
+		"FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
 		aFree(g);
@@ -445,29 +441,25 @@ struct guild * inter_guild_fromsql(int guild_id)
 	{
 		struct guild_member* m = &g->member[i];
 
-		Sql_GetData(sql_handle,  1, &data, NULL); m->account_id = atoi(data);
-		Sql_GetData(sql_handle,  2, &data, NULL); m->char_id = atoi(data);
-		Sql_GetData(sql_handle,  3, &data, NULL); m->hair = atoi(data);
-		Sql_GetData(sql_handle,  4, &data, NULL); m->hair_color = atoi(data);
-		Sql_GetData(sql_handle,  5, &data, NULL); m->gender = atoi(data);
-		Sql_GetData(sql_handle,  6, &data, NULL); m->class_ = atoi(data);
-		Sql_GetData(sql_handle,  7, &data, NULL); m->lv = atoi(data);
-		Sql_GetData(sql_handle,  8, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10);
-		Sql_GetData(sql_handle,  9, &data, NULL); m->exp_payper = (unsigned int)atoi(data);
-		Sql_GetData(sql_handle, 10, &data, NULL); m->online = atoi(data);
-		Sql_GetData(sql_handle, 11, &data, NULL); m->position = atoi(data);
+		Sql_GetData(sql_handle,  0, &data, NULL); m->account_id = atoi(data);
+		Sql_GetData(sql_handle,  1, &data, NULL); m->char_id = atoi(data);
+		Sql_GetData(sql_handle,  2, &data, NULL); m->hair = atoi(data);
+		Sql_GetData(sql_handle,  3, &data, NULL); m->hair_color = atoi(data);
+		Sql_GetData(sql_handle,  4, &data, NULL); m->gender = atoi(data);
+		Sql_GetData(sql_handle,  5, &data, NULL); m->class_ = atoi(data);
+		Sql_GetData(sql_handle,  6, &data, NULL); m->lv = atoi(data);
+		Sql_GetData(sql_handle,  7, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10);
+		Sql_GetData(sql_handle,  8, &data, NULL); m->exp_payper = (unsigned int)atoi(data);
+		Sql_GetData(sql_handle,  9, &data, NULL); m->online = atoi(data);
+		Sql_GetData(sql_handle, 10, &data, NULL); m->position = atoi(data);
 		if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW]
 			m->position = MAX_GUILDPOSITION - 1;
-		//## TODO what about the rsv fields?
-		// rsv1 (12)
-		// rsv2 (13)
-		// name
-		Sql_GetData(sql_handle, 14, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
+		Sql_GetData(sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
 		m->modified = GS_MEMBER_UNMODIFIED;
 	}
 
 	//printf("- Read guild_position %d from sql \n",guild_id);
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) )
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
 		aFree(g);
@@ -478,18 +470,18 @@ struct guild * inter_guild_fromsql(int guild_id)
 		int position;
 		struct guild_position* p;
 
-		Sql_GetData(sql_handle, 1, &data, NULL); position = atoi(data);
+		Sql_GetData(sql_handle, 0, &data, NULL); position = atoi(data);
 		if( position < 0 || position >= MAX_GUILDPOSITION )
 			continue;// invalid position
 		p = &g->position[position];
-		Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH));
-		Sql_GetData(sql_handle, 3, &data, NULL); p->mode = atoi(data);
-		Sql_GetData(sql_handle, 4, &data, NULL); p->exp_mode = atoi(data);
+		Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH));
+		Sql_GetData(sql_handle, 2, &data, NULL); p->mode = atoi(data);
+		Sql_GetData(sql_handle, 3, &data, NULL); p->exp_mode = atoi(data);
 		p->modified = GS_POSITION_UNMODIFIED;
 	}
 
 	//printf("- Read guild_alliance %d from sql \n",guild_id);
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) )
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
 		aFree(g);
@@ -499,13 +491,13 @@ struct guild * inter_guild_fromsql(int guild_id)
 	{
 		struct guild_alliance* a = &g->alliance[i];
 
-		Sql_GetData(sql_handle, 1, &data, NULL); a->opposition = atoi(data);
-		Sql_GetData(sql_handle, 2, &data, NULL); a->guild_id = atoi(data);
-		Sql_GetData(sql_handle, 3, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH));
+		Sql_GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data);
+		Sql_GetData(sql_handle, 1, &data, NULL); a->guild_id = atoi(data);
+		Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH));
 	}
 
 	//printf("- Read guild_expulsion %d from sql \n",guild_id);
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) )
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
 		aFree(g);
@@ -515,17 +507,13 @@ struct guild * inter_guild_fromsql(int guild_id)
 	{
 		struct guild_expulsion *e = &g->expulsion[i];
 
+		Sql_GetData(sql_handle, 0, &data, NULL); e->account_id = atoi(data);
 		Sql_GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH));
 		Sql_GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes)));
-		Sql_GetData(sql_handle, 3, &data, &len); memcpy(e->acc, data, min(len, sizeof(e->acc)));
-		Sql_GetData(sql_handle, 4, &data, NULL); e->account_id = atoi(data);
-		Sql_GetData(sql_handle, 5, &data, NULL); e->rsv1 = atoi(data);
-		Sql_GetData(sql_handle, 6, &data, NULL); e->rsv2 = atoi(data);
-		Sql_GetData(sql_handle, 7, &data, NULL); e->rsv3 = atoi(data);
 	}
 
 	//printf("- Read guild_skill %d from sql \n",guild_id);
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) )
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
 		aFree(g);
@@ -540,14 +528,10 @@ struct guild * inter_guild_fromsql(int guild_id)
 	while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
 	{
 		int id;
-		// id
-		Sql_GetData(sql_handle, 1, &data, NULL);
-		id = atoi(data) - GD_SKILLBASE;
+		Sql_GetData(sql_handle, 0, &data, NULL); id = atoi(data) - GD_SKILLBASE;
 		if( id < 0 && id >= MAX_GUILDSKILL )
 			continue;// invalid guild skill
-		// lv
-		Sql_GetData(sql_handle, 2, &data, NULL);
-		g->skill[id].lv = atoi(data);
+		Sql_GetData(sql_handle, 1, &data, NULL); g->skill[id].lv = atoi(data);
 	}
 	Sql_FreeResult(sql_handle);
 
@@ -853,17 +837,16 @@ int search_guildname(char *str)
 }
 
 // Check if guild is empty
-int guild_check_empty(struct guild *g)
+static bool guild_check_empty(struct guild *g)
 {
 	int i;
-	for(i=0;i<g->max_member;i++){
-		if(g->member[i].account_id>0){
-			return 0;
-		}
-	}
+	ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 );
+	if( i < g->max_member)
+		return false; // not empty
+
 	//Let the calling function handle the guild removal in case they need
 	//to do something else with it before freeing the data. [Skotlex]
-	return 1;
+	return true;
 }
 
 unsigned int guild_nextexp(int level)
@@ -1385,60 +1368,57 @@ int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m)
 }
 
 // Delete member from guild
-int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes)
+int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
 {
-	struct guild * g = inter_guild_fromsql(guild_id);
-
-	if(g){
-		int i;
-		// Find the member
-		for(i=0;i<g->max_member;i++){
-			if( g->member[i].account_id==account_id && g->member[i].char_id==char_id)
-			{
-				if(flag)
-				{	
-					// Write expulsion reason
-					int j;
-					// Find an empty slot
-					for(j=0;j<MAX_GUILDEXPULSION;j++){
-						if(g->expulsion[j].account_id==0)
-							break;
-					}
-					// Expulsion list is full, flush the oldest one
-					if(j==MAX_GUILDEXPULSION){
-						for(j=0;j<MAX_GUILDEXPULSION-1;j++)
-							g->expulsion[j]=g->expulsion[j+1];
-						j=MAX_GUILDEXPULSION-1;
-					}
-					// Save the expulsion
-					g->expulsion[j].account_id=account_id;
-					strncpy(g->expulsion[j].acc,"dummy",NAME_LENGTH);
-					memcpy(g->expulsion[j].name,g->member[i].name,NAME_LENGTH);
-					memcpy(g->expulsion[j].mes,mes,40);
-				}
+	int i, j;
 
-				mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);
-				inter_guild_removemember_tosql(g->member[i].account_id,g->member[i].char_id);
+	struct guild* g = inter_guild_fromsql(guild_id);
+	if( g == NULL )
+	{
+		// Unknown guild, just update the player
+		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) )
+			Sql_ShowDebug(sql_handle);
+		// mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);
+		return 0;
+	}
 
-				memset(&g->member[i],0,sizeof(struct guild_member));
+	// Find the member
+	ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
+	if( i == g->max_member )
+	{
+		//TODO
+		return 0;
+	}
 
-				if(!guild_check_empty(g)) {
-					break;
-				}
-				//Guild empty? break it.	
-				mapif_parse_BreakGuild(-1,guild_id); //Break the guild.
-				return 0;
-			}
+	if( flag )
+	{	// Write expulsion reason
+		// Find an empty slot
+		ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 );
+		if( j == MAX_GUILDEXPULSION )
+		{
+			// Expulsion list is full, flush the oldest one
+			for( j = 0; j < MAX_GUILDEXPULSION - 1; j++ )
+				g->expulsion[j] = g->expulsion[j+1];
+			j = MAX_GUILDEXPULSION-1;
 		}
+		// Save the expulsion entry
+		g->expulsion[j].account_id = account_id;
+		safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
+		safestrncpy(g->expulsion[j].mes, mes, 40);
+	}
+
+	mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);
+	inter_guild_removemember_tosql(g->member[i].account_id,g->member[i].char_id);
+
+	memset(&g->member[i],0,sizeof(struct guild_member));
+
+	if( guild_check_empty(g) )
+		mapif_parse_BreakGuild(-1,guild_id); //Break the guild.
+	else {
 		//Update member info.
 		if (!guild_calcinfo(g))
 			mapif_guild_info(fd,g);
 		g->save_flag |= GS_EXPULSION;
-	}else{
-		// Unknown guild, just update the player
-		if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) )
-			Sql_ShowDebug(sql_handle);
-		/* mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);	*/
 	}
 
 	return 0;
@@ -1994,7 +1974,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
 int inter_guild_parse_frommap(int fd)
 {
 	RFIFOHEAD(fd);
-	switch(RFIFOW(fd,0)){
+	switch(RFIFOW(fd,0)) {
 	case 0x3030: mapif_parse_CreateGuild(fd,RFIFOL(fd,4),(char*)RFIFOP(fd,8),(struct guild_member *)RFIFOP(fd,32)); break;
 	case 0x3031: mapif_parse_GuildInfo(fd,RFIFOL(fd,2)); break;
 	case 0x3032: mapif_parse_GuildAddMember(fd,RFIFOL(fd,4),(struct guild_member *)RFIFOP(fd,8)); break;
@@ -2016,18 +1996,20 @@ int inter_guild_parse_frommap(int fd)
 	default:
 		return 0;
 	}
+
 	return 1;
 }
 
+// processes a mapserver connection event
 int inter_guild_mapif_init(int fd)
 {
 	return mapif_guild_castle_alldataload(fd);
 }
 
 // サーバーから脱退要求(キャラ削除用)
-int inter_guild_leave(int guild_id,int account_id,int char_id)
+int inter_guild_leave(int guild_id, int account_id, int char_id)
 {
-	return mapif_parse_GuildLeave(-1,guild_id,account_id,char_id,0,"** Character Deleted **");
+	return mapif_parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **");
 }
 
 int inter_guild_broken(int guild_id)

+ 9 - 9
src/char_sql/int_homun.c

@@ -27,12 +27,12 @@ void inter_homunculus_sql_final(void){
 	return;
 }
 
-int mapif_saved_homunculus(int fd, int account_id, unsigned char flag)
+static int mapif_saved_homunculus(int fd, int account_id, bool flag)
 {
 	WFIFOHEAD(fd, 7);
 	WFIFOW(fd,0) = 0x3892;
 	WFIFOL(fd,2) = account_id;
-	WFIFOB(fd,6) = flag;
+	WFIFOB(fd,6) = flag; // 1:success, 0:failure
 	WFIFOSET(fd, 7);
 	return 0;
 }
@@ -71,7 +71,7 @@ int mapif_homunculus_created(int fd, int account_id, struct s_homunculus *sh, un
 }
 
 // Save/Update Homunculus Skills
-int mapif_save_homunculus_skills(struct s_homunculus *hd)
+static bool mapif_save_homunculus_skills(struct s_homunculus *hd)
 {
 	SqlStmt* stmt;
 	int i;
@@ -89,18 +89,18 @@ int mapif_save_homunculus_skills(struct s_homunculus *hd)
 			{
 				SqlStmt_ShowDebug(stmt);
 				SqlStmt_Free(stmt);
-				return 0;
+				return false;
 			}
 		}
 	}
 	SqlStmt_Free(stmt);
 
-	return 1;
+	return true;
 }
 
-int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd)
+static bool mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd)
 {
-	int flag = 1;
+	bool flag = true;
 	char esc_name[NAME_LENGTH*2+1];
 
 	Sql_EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH));
@@ -114,7 +114,7 @@ int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd)
 			hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) )
 		{
 			Sql_ShowDebug(sql_handle);
-			flag = 0;
+			flag = false;
 		}
 		else
 		{
@@ -128,7 +128,7 @@ int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd)
 			hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) )
 		{
 			Sql_ShowDebug(sql_handle);
-			flag = 0;
+			flag = false;
 		}
 		else
 		{

+ 0 - 7
src/common/mmo.h

@@ -328,7 +328,6 @@ struct guild_member {
 	unsigned int exp;
 	int exp_payper;
 	short online,position;
-	int rsv1,rsv2;
 	char name[NAME_LENGTH];
 	struct map_session_data *sd;
 	unsigned char modified;
@@ -350,9 +349,7 @@ struct guild_alliance {
 struct guild_expulsion {
 	char name[NAME_LENGTH];
 	char mes[40];
-	char acc[40];
 	int account_id;
-	int rsv1,rsv2,rsv3;
 };
 
 struct guild_skill {
@@ -364,10 +361,6 @@ struct guild {
 	short guild_lv, connect_member, max_member, average_lv;
 	unsigned int exp,next_exp;
 	int skill_point;
-#ifdef TXT_ONLY
-	//FIXME: Gotta remove this variable completely, but doing so screws up the format of the txt save file...
-	int castle_id;
-#endif
 	char name[NAME_LENGTH],master[NAME_LENGTH];
 	struct guild_member member[MAX_GUILD];
 	struct guild_position position[MAX_GUILDPOSITION];

+ 1 - 1
src/common/showmsg.c

@@ -76,7 +76,7 @@ int msg_silent = 0; //Specifies how silent the console is.
 		buf.d_ = StringBuf_Malloc();					\
 		buf.l_ = StringBuf_Vprintf(buf.d_, fmt, args);	\
 		buf.v_ = StringBuf_Value(buf.d_);				\
-		ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.", buf.l_+1);\
+		ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.\n", buf.l_+1);\
 	}													\
 //define BUFVPRINTF
 

+ 2 - 2
src/map/battle.c

@@ -3232,7 +3232,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 			int t_guild = status_get_guild_id(t_bl);
 			if (
 				!(map[m].flag.pvp && map[m].flag.pvp_noguild) &&
-				s_guild && t_guild && (s_guild == t_guild || guild_idisallied(s_guild, t_guild))
+				s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))
 			)
 				state |= BCT_GUILD;
 			else
@@ -3260,7 +3260,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 		if (flag&BCT_GUILD || state&BCT_ENEMY) {
 			int s_guild = status_get_guild_id(s_bl);
 			int t_guild = status_get_guild_id(t_bl);
-			if(s_guild && t_guild && (s_guild == t_guild || guild_idisallied(s_guild, t_guild)))
+			if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)))
 				state |= BCT_GUILD;
 		}
 	}

+ 6 - 4
src/map/chrif.c

@@ -92,7 +92,6 @@ static uint32 char_ip = 0;
 static uint16 char_port = 6121;
 static char userid[NAME_LENGTH], passwd[NAME_LENGTH];
 static int chrif_state = 0;
-static int char_init_done = 0;
 int other_mapserver_count=0; //Holds count of how many other map servers are online (apart of this instance) [Skotlex]
 
 //Interval at which map server updates online listing. [Valaris]
@@ -342,20 +341,23 @@ int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int c
  *------------------------------------------*/
 int chrif_connectack(int fd)
 {
+	static bool char_init_done = false;
+
 	if (RFIFOB(fd,2)) {
 		ShowFatalError("Connection to char-server failed %d.\n", RFIFOB(fd,2));
 		exit(EXIT_FAILURE);
 	}
+
 	ShowStatus("Successfully logged on to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd);
 	chrif_state = 1;
-	chrif_connected=1;
+	chrif_connected = 1;
 
 	chrif_sendmap(fd);
 
 	ShowStatus("Event '"CL_WHITE"OnCharIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnCharIfInit"));
 	ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
-	if(!char_init_done) {
-		char_init_done = 1;
+	if( !char_init_done ) {
+		char_init_done = true;
 		ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce"));
 	}
 

+ 19 - 13
src/map/clif.c

@@ -6472,6 +6472,7 @@ int clif_guild_inviteack(struct map_session_data *sd,int flag)
 	WFIFOSET(fd,packet_len(0x169));
 	return 0;
 }
+
 /*==========================================
  * ギルドメンバ脱退通知
  *------------------------------------------*/
@@ -6487,23 +6488,24 @@ int clif_guild_leave(struct map_session_data *sd,const char *name,const char *me
 	clif_send(buf,packet_len(0x15a),&sd->bl,GUILD);
 	return 0;
 }
+
 /*==========================================
  * ギルドメンバ追放通知
  *------------------------------------------*/
-int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char *mes,
-	int account_id)
+int clif_guild_expulsion(struct map_session_data *sd,const char *name,const char *mes,int account_id)
 {
 	unsigned char buf[128];
 
 	nullpo_retr(0, sd);
 
 	WBUFW(buf, 0)=0x15c;
-	memcpy(WBUFP(buf, 2),name,NAME_LENGTH);
-	memcpy(WBUFP(buf,26),mes,40);
-	memcpy(WBUFP(buf,66),"dummy",NAME_LENGTH);
+	safestrncpy(WBUFP(buf, 2),name,NAME_LENGTH);
+	safestrncpy(WBUFP(buf,26),mes,40);
+	safestrncpy(WBUFP(buf,66),"",NAME_LENGTH); // account name (not used for security reasons)
 	clif_send(buf,packet_len(0x15c),&sd->bl,GUILD);
 	return 0;
 }
+
 /*==========================================
  * ギルド追放メンバリスト
  *------------------------------------------*/
@@ -6519,18 +6521,18 @@ int clif_guild_expulsionlist(struct map_session_data *sd)
 	g=guild_search(sd->status.guild_id);
 	if(g==NULL)
 		return 0;
-	WFIFOHEAD(fd,MAX_GUILDEXPULSION * 88 + 4);
+	WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * 88);
 	WFIFOW(fd,0)=0x163;
 	for(i=c=0;i<MAX_GUILDEXPULSION;i++){
 		struct guild_expulsion *e=&g->expulsion[i];
 		if(e->account_id>0){
-			memcpy(WFIFOP(fd,c*88+ 4),e->name,NAME_LENGTH);
-			memcpy(WFIFOP(fd,c*88+28),e->acc,24);
-			memcpy(WFIFOP(fd,c*88+52),e->mes,44);
+			safestrncpy(WFIFOP(fd,4 + c*88),e->name,NAME_LENGTH);
+			safestrncpy(WFIFOP(fd,4 + c*88+24),"",24); // account name (not used for security reasons)
+			safestrncpy(WFIFOP(fd,4 + c*88+48),e->mes,40);
 			c++;
 		}
 	}
-	WFIFOW(fd,2)=c*88+4;
+	WFIFOW(fd,2) = 4 + c*88;
 	WFIFOSET(fd,WFIFOW(fd,2));
 	return 0;
 }
@@ -8542,7 +8544,9 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd)
  *------------------------------------------*/
 void clif_parse_DropItem(int fd, struct map_session_data *sd)
 {
-	int item_index, item_amount;
+	int item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
+	int item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]);
+
 	item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
 	item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]);
 	do {
@@ -8564,7 +8568,8 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd)
 
 		return;
 	} while (0);
-	//Because the client does not likes being ignored.
+
+	//Because the client does not like being ignored.
 	clif_delitem(sd, item_index,0);
 }
 
@@ -9991,7 +9996,8 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd)
 }
 
 /*==========================================
- * ギルド追放
+ * Request to expel a member of a guild
+ * S 015b <guild_id>.L <account_id>.L <char_id>.L <reason>.39B 00
  *------------------------------------------*/
 void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd)
 {

+ 40 - 93
src/map/guild.c

@@ -655,9 +655,7 @@ int guild_invite(struct map_session_data *sd,struct map_session_data *tsd)
 	}
 
 	// 定員確認
-	for(i=0;i<g->max_member;i++)
-		if(g->member[i].account_id==0)
-			break;
+	ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
 	if(i==g->max_member){
 		clif_guild_inviteack(sd,3);
 		return 0;
@@ -669,60 +667,52 @@ int guild_invite(struct map_session_data *sd,struct map_session_data *tsd)
 	clif_guild_invite(tsd,g);
 	return 0;
 }
-// ギルド勧誘への返答
-int guild_reply_invite(struct map_session_data *sd,int guild_id,int flag)
+
+/// Guild invitation reply.
+/// flag: 0:rejected, 1:accepted
+int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag)
 {
-	struct map_session_data *tsd;
+	struct map_session_data* tsd;
 
 	nullpo_retr(0, sd);
-	
-	//nullpo_retr(0, tsd= map_id2sd( sd->guild_invite_account ));
-	//I checked the code, and there's no "check" for the case where the guy
-	//that invites another to a guild quits the map-server before being replied.
-	//Hence that's a valid null pointer scenario. :) [Skotlex]
-	if ((tsd= map_id2sd( sd->guild_invite_account )) == NULL)
-	{	//Do we send a "invitation failed" msg or something to the player?
-		//Or should we accept the invitation and add it to the guild anyway?
-		//afterall, guild_invite holds the guild id that the player was invited to.
-		sd->guild_invite=0;
-		sd->guild_invite_account=0;
-		return 0;
-	}
 
-	if(sd->guild_invite!=guild_id)	// 勧誘とギルドIDが違う
-		return 0;
+	// subsequent requests may override the value
+	if( sd->guild_invite != guild_id )
+		return 0; // mismatch
 
-	if(flag==1){	// 承諾
+	// look up the person who sent the invite
+	//NOTE: this can be NULL because the person might have logged off in the meantime
+	tsd = map_id2sd(sd->guild_invite_account);
+
+	// zero out the status data
+	sd->guild_invite = 0;
+	sd->guild_invite_account = 0;
+
+	if( flag == 0 )
+	{// rejected
+		if( tsd ) clif_guild_inviteack(tsd,1);
+	}
+	else
+	{// accepted
 		struct guild_member m;
-		struct guild *g;
+		struct guild* g;
 		int i;
 
-		// 定員確認
-		if( (g=guild_search(tsd->status.guild_id))==NULL ){
-			sd->guild_invite=0;
-			sd->guild_invite_account=0;
+		if( (g=guild_search(guild_id)) == NULL )
 			return 0;
-		}
-		for(i=0;i<g->max_member;i++)
-			if(g->member[i].account_id==0)
-				break;
-		if(i==g->max_member){
-			sd->guild_invite=0;
-			sd->guild_invite_account=0;
-			clif_guild_inviteack(tsd,3);
+
+		ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
+		if( i == g->max_member )
+		{
+			if( tsd ) clif_guild_inviteack(tsd,3);
 			return 0;
 		}
 
-		//inter鯖へ追加要求
 		guild_makemember(&m,sd);
-		intif_guild_addmember( sd->guild_invite, &m );
+		intif_guild_addmember(guild_id, &m);
 		//TODO: send a minimap update to this player
-		return 0;
-	}else{		// 拒否
-		sd->guild_invite=0;
-		sd->guild_invite_account=0;
-		clif_guild_inviteack(tsd,1);
 	}
+
 	return 0;
 }
 // ギルドメンバが追加された
@@ -1821,7 +1811,9 @@ int guild_castlealldataload(int len,struct guild_castle *gc)
 	for( i = n-1; i >= 0 && !(gc[i].guild_id); --i );
 	ev = i; // offset of castle or -1
 
-	// load received castles into memory, one by one
+	if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is.
+		npc_event_doall("OnAgitInit");
+	else // load received castles into memory, one by one
 	for( i = 0; i < n; i++, gc++ )
 	{
 		struct guild_castle *c = guild_castle_search(gc->castle_id);
@@ -1842,9 +1834,6 @@ int guild_castlealldataload(int len,struct guild_castle *gc)
 		}
 	}
 
-	if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is.
-		npc_event_doall("OnAgitInit");
-
 	return 0;
 }
 
@@ -1906,57 +1895,15 @@ int guild_checkcastles(struct guild *g)
 	return nb_cas;
 }
 
-// [MouseJstr]
-//    is this guild allied with this castle?
-int guild_isallied(struct guild *g, struct guild_castle *gc)
-{
-	int i;
-
-	nullpo_retr(0, g);
-
-	if(g->guild_id == gc->guild_id)
-		return 1;
-
-	if (gc->guild_id == 0)
-		return 0;
-
-
-	for(i=0;i<MAX_GUILDALLIANCE;i++)
-		if(g->alliance[i].guild_id == gc->guild_id) {
-			if(g->alliance[i].opposition == 0)
-				return 1;
-			else
-				return 0;
-		}
-
-	return 0;
-}
-
-int guild_idisallied(int guild_id, int guild_id2)
+// Are these two guilds allied?
+bool guild_isallied(int guild_id, int guild_id2)
 {
 	int i;
-	struct guild *g;
-
-	if (guild_id <= 0 || guild_id2 <= 0)
-		return 0;
-	
-	if(guild_id == guild_id2)
-		return 1;
-
-	g = guild_search(guild_id);
-
+	struct guild* g = guild_search(guild_id);
 	nullpo_retr(0, g);
 
-
-	for(i=0;i<MAX_GUILDALLIANCE;i++)
-		if(g->alliance[i].guild_id == guild_id2) {
-			if(g->alliance[i].opposition == 0)
-				return 1;
-			else
-				return 0;
-		}
-
-	return 0;
+	ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 );
+	return( i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0 );
 }
 
 static int guild_infoevent_db_final(DBKey key,void *data,va_list ap)

+ 1 - 2
src/map/guild.h

@@ -18,8 +18,7 @@ int guild_skill_get_max(int id);
 int guild_checkskill(struct guild *g,int id);
 int guild_check_skill_require(struct guild *g,int id); // [Komurka]
 int guild_checkcastles(struct guild *g); // [MouseJstr]
-int guild_isallied(struct guild *g, struct guild_castle *gc);
-int guild_idisallied(int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex]
+bool guild_isallied(int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex]
 
 void do_init_guild(void);
 struct guild *guild_search(int guild_id);

+ 2 - 3
src/map/intif.c

@@ -587,13 +587,12 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha
 	WFIFOL(inter_fd, 6) = account_id;
 	WFIFOL(inter_fd,10) = char_id;
 	WFIFOB(inter_fd,14) = flag;
-	memcpy(WFIFOP(inter_fd,15),mes,40);
+	safestrncpy(WFIFOP(inter_fd,15),mes,40);
 	WFIFOSET(inter_fd,55);
 	return 0;
 }
 // ギルドメンバのオンライン状況/Lv更新要求
-int intif_guild_memberinfoshort(int guild_id,
-	int account_id,int char_id,int online,int lv,int class_)
+int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
 {
 	if (CheckForCharServer())
 		return 0;

+ 1 - 1
src/map/irc.c

@@ -52,7 +52,7 @@ int irc_connect_timer(int tid, unsigned int tick, int id, int data)
 		return 0;
 	//Ok, this ShowInfo and printf are a little ugly, but they are meant to 
 	//debug just how long the code freezes here. [Skotlex]
-	ShowInfo("(IRC) Connecting to %s... ", irc_ip_str);
+	ShowInfo("(IRC) Connecting to %s...\n", irc_ip_str);
 	irc_fd = make_connection(irc_ip,irc_port);
 	if(irc_fd > 0){
 		printf("ok\n");

+ 51 - 54
src/map/npc.c

@@ -59,7 +59,6 @@ struct event_data {
 	struct npc_data *nd;
 	int pos;
 };
-static struct tm ev_tm_b;	// 時計イベント用
 
 static struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
 
@@ -227,17 +226,20 @@ int npc_event_doall_sub(DBKey key, void* data, va_list ap)
 	const char* p = key.str;
 	struct event_data* ev;
 	int* c;
+	const char* name;
 	int rid;
-	char* name;
 
-	ev = (struct event_data *)data;
-	c = va_arg(ap, int *);
-	name = va_arg(ap,char *);
+	nullpo_retr(0, ev = (struct event_data *)data);
+	nullpo_retr(0, ap);
+	nullpo_retr(0, c = va_arg(ap, int *));
+	nullpo_retr(0, name = va_arg(ap, const char *));
 	rid = va_arg(ap, int);
 
-	if( (p=strchr(p, ':')) && p && strcmpi(name, p)==0 ) {
-		if(rid)
-			npc_event_sub(((struct map_session_data *)map_id2bl(rid)),ev,key.str);
+	p = strchr(p, ':'); // match only the event name
+	if( p && strcmpi(name, p) == 0 )
+	{
+		if(rid) // a player may only have 1 script running at the same time
+			npc_event_sub(map_id2sd(rid),ev,key.str);
 		else
 			run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id);
 		(*c)++;
@@ -245,26 +247,8 @@ int npc_event_doall_sub(DBKey key, void* data, va_list ap)
 
 	return 0;
 }
-int npc_event_doall(const char* name)
-{
-	int c = 0;
-	char buf[64] = "::";
 
-	strncpy(buf+2, name, 62);
-	ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,0);
-	return c;
-}
-int npc_event_doall_id(const char* name, int rid)
-{
-	int c = 0;
-	char buf[64] = "::";
-
-	strncpy(buf+2, name, 62);
-	ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid);
-	return c;
-}
-
-int npc_event_do_sub(DBKey key, void* data, va_list ap)
+static int npc_event_do_sub(DBKey key, void* data, va_list ap)
 {
 	const char* p = key.str;
 	struct event_data* ev;
@@ -274,43 +258,61 @@ int npc_event_do_sub(DBKey key, void* data, va_list ap)
 	nullpo_retr(0, ev = (struct event_data *)data);
 	nullpo_retr(0, ap);
 	nullpo_retr(0, c = va_arg(ap, int *));
+	nullpo_retr(0, name = va_arg(ap, const char *));
 
-	name = va_arg(ap, const char *);
-
-	if (p && strcmpi(name, p)==0) {
+	if( p && strcmpi(name, p) == 0 )
+	{
 		run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
 		(*c)++;
 	}
 
 	return 0;
 }
+
+// runs the specified event (supports both single-npc and global events)
 int npc_event_do(const char* name)
 {
 	int c = 0;
 
-	if (*name == ':' && name[1] == ':') {
-		return npc_event_doall(name+2);
-	}
+	if( name[0] == ':' && name[1] == ':' )
+		ev_db->foreach(ev_db,npc_event_doall_sub,&c,name,0);
+	else
+		ev_db->foreach(ev_db,npc_event_do_sub,&c,name);
 
-	ev_db->foreach(ev_db,npc_event_do_sub,&c,name);
 	return c;
 }
+// runs the specified event (global only)
+int npc_event_doall(const char* name)
+{
+	return npc_event_doall_id(name, 0);
+}
+// runs the specified event, with a RID attached (global only)
+int npc_event_doall_id(const char* name, int rid)
+{
+	int c = 0;
+	char buf[64];
+	safesnprintf(buf, sizeof(buf), "::%s", name);
+	ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid);
+	return c;
+}
+
 
 /*==========================================
  * 時計イベント実行
  *------------------------------------------*/
 int npc_event_do_clock(int tid, unsigned int tick, int id, int data)
 {
+	static struct tm ev_tm_b; // tracks previous execution time
 	time_t timer;
-	struct tm *t;
+	struct tm* t;
 	char buf[64];
-        char *day="";
-	int c=0;
+	char* day;
+	int c = 0;
 
-	time(&timer);
-	t=localtime(&timer);
+	timer = time(NULL);
+	t = localtime(&timer);
 
-        switch (t->tm_wday) {
+	switch (t->tm_wday) {
 	case 0: day = "Sun"; break;
 	case 1: day = "Mon"; break;
 	case 2: day = "Tue"; break;
@@ -318,6 +320,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data)
 	case 4: day = "Thu"; break;
 	case 5: day = "Fri"; break;
 	case 6: day = "Sat"; break;
+	default:day = ""; break;
 	}
 
 	if (t->tm_min != ev_tm_b.tm_min ) {
@@ -336,6 +339,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data)
 		sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday);
 		c+=npc_event_doall(buf);
 	}
+
 	memcpy(&ev_tm_b,t,sizeof(ev_tm_b));
 	return c;
 }
@@ -345,8 +349,7 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, int data)
  *------------------------------------------*/
 void npc_event_do_oninit(void)
 {
-	int count = npc_event_doall("OnInit");
-	ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", count);
+	ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc_event_doall("OnInit"));
 
 	add_timer_interval(gettick()+100,npc_event_do_clock,0,0,1000);
 }
@@ -361,7 +364,8 @@ int npc_timerevent_import(char* lname, void* data, va_list ap)
 	struct npc_data *nd=va_arg(ap,struct npc_data *);
 	int t=0,i=0;
 
-	if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':') {
+	if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':')
+	{
 		// タイマーイベント
 		struct npc_timerevent_list *te=nd->u.scr.timer_event;
 		int j,i=nd->u.scr.timeramount;
@@ -371,12 +375,9 @@ int npc_timerevent_import(char* lname, void* data, va_list ap)
 			ShowFatalError("npc_timerevent_import: out of memory !\n");
 			exit(EXIT_FAILURE);
 		}
-		for(j=0;j<i;j++){
-			if(te[j].timer>t){
-				memmove(te+j+1,te+j,sizeof(struct npc_timerevent_list)*(i-j));
-				break;
-			}
-		}
+		ARR_FIND( 0, i, j, te[j].timer > t );
+		if( j < i )
+			memmove(te+j+1,te+j,sizeof(struct npc_timerevent_list)*(i-j));
 		te[j].timer=t;
 		te[j].pos=pos;
 		nd->u.scr.timer_event=te;
@@ -465,10 +466,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
 	if( n==0 )
 		return 0;
 
-	for(j=0;j<n;j++){
-		if( nd->u.scr.timer_event[j].timer > nd->u.scr.timer )
-			break;
-	}
+	ARR_FIND( 0, n, j, nd->u.scr.timer_event[j].timer > nd->u.scr.timer );
 	if(j>=n) // check if there is a timer to use !!BEFORE!! you write stuff to the structures [Shinomori]
 		return 0;
 	if (nd->u.scr.rid > 0) {
@@ -2931,7 +2929,6 @@ int do_init_npc(void)
 	ev_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1);
 	npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
 
-	memset(&ev_tm_b, -1, sizeof(ev_tm_b));
 	timer_event_ers = ers_new(sizeof(struct timer_event_data));
 
 	// process all npc files

+ 2 - 2
src/map/npc.h

@@ -74,9 +74,9 @@ int do_init_npc(void);
 void npc_event_do_oninit(void);
 int npc_do_ontimer(int npc_id, int option);
 
-int npc_event_doall(const char* name);
 int npc_event_do(const char* name);
-int npc_event_doall_id(const char* name, int id);
+int npc_event_doall(const char* name);
+int npc_event_doall_id(const char* name, int rid);
 
 int npc_timerevent_start(struct npc_data* nd, int rid);
 int npc_timerevent_stop(struct npc_data* nd);

+ 1 - 1
src/map/status.c

@@ -4065,7 +4065,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl)
 struct status_data *status_get_status_data(struct block_list *bl)
 {
 	nullpo_retr(&dummy_status, bl);
-		
+
 	switch (bl->type) {
 		case BL_PC:  return &((TBL_PC*)bl)->battle_status;
 		case BL_MOB: return &((TBL_MOB*)bl)->status;

+ 1 - 1
src/map/status.h

@@ -20,8 +20,8 @@ extern unsigned long StatusChangeFlagTable[];
 // Status changes listing. These code are for use by the server. 
 enum sc_type {
 	//First we enumerate common status ailments which are often used around.
-	SC_COMMON_MIN = 0, // begin
 	SC_STONE = 0,
+	SC_COMMON_MIN = 0, // begin
 	SC_FREEZE,
 	SC_STUN,
 	SC_SLEEP,