Przeglądaj źródła

Added some checks to guild leader change

Introduces two new configurations:
1) Allow guild leader changes in WoE (yes/no)
	Default: no
2) Delay between the changes (in minutes)
	Default: 1440 minutes = 1 day

Follow up to b51617c
Lemongrass3110 7 lat temu
rodzic
commit
a3c0590508

+ 10 - 0
conf/battle/guild.conf

@@ -61,3 +61,13 @@ guild_notice_changemap: 2
 // Should maprespawnguildid kill clones too?
 // Default: no
 guild_maprespawn_clones: no
+
+// How long (in minutes) should a guild have to wait between guild master changes?
+// Default: 1440 (1 day)
+// Use 0 minutes to disable the delay.
+//guild_leaderchange_delay: 1440
+guild_leaderchange_delay: 0
+
+// Is changing the guild leader allowed during WoE?
+// Default: no
+guild_leaderchange_woe: no

+ 4 - 3
doc/packet_interserv.txt

@@ -1967,14 +1967,15 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
 
 0x3843
 	Type: IZ
-	Structure: <cmd>.W <guild_id>.L <aid>.L <cid>.L
-	index: 0,2,6,10
-	len: 14
+	Structure: <cmd>.W <guild_id>.L <aid>.L <cid>.L <time>.L
+	index: 0,2,6,10,14
+	len: 18
 	parameter:
 		- cmd : packet identification (0x3843)
 		- guild_id
 		- aid
 		- cid
+		- time of change
 	desc:
 		- mapif_guild_master_changed
 

+ 1 - 0
sql-files/main.sql

@@ -412,6 +412,7 @@ CREATE TABLE IF NOT EXISTS `guild` (
   `emblem_len` int(11) unsigned NOT NULL default '0',
   `emblem_id` int(11) unsigned NOT NULL default '0',
   `emblem_data` blob,
+  `last_master_change` datetime,
   PRIMARY KEY  (`guild_id`,`char_id`),
   UNIQUE KEY `guild_id` (`guild_id`),
   KEY `char_id` (`char_id`)

+ 2 - 0
sql-files/upgrades/upgrade_20170702.sql

@@ -0,0 +1,2 @@
+alter table `guild`
+	add column `last_master_change` datetime;

+ 14 - 6
src/char/int_guild.c

@@ -183,6 +183,9 @@ int inter_guild_tosql(struct guild *g,int flag)
 			else
 				add_comma = true;
 			StringBuf_Printf(&buf, "`name`='%s', `master`='%s', `char_id`=%d", esc_name, esc_master, g->member[0].char_id);
+
+			if (g->last_leader_change)
+				StringBuf_Printf(&buf, ", `last_master_change`=FROM_UNIXTIME(%d)", g->last_leader_change);
 		}
 		if (flag & GS_CONNECT)
 		{
@@ -348,7 +351,7 @@ struct guild * inter_guild_fromsql(int guild_id)
 	ShowInfo("Guild load request (%d)...\n", guild_id);
 #endif
 
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT g.`name`,c.`name`,g.`guild_lv`,g.`connect_member`,g.`max_member`,g.`average_lv`,g.`exp`,g.`next_exp`,g.`skill_point`,g.`mes1`,g.`mes2`,g.`emblem_len`,g.`emblem_id`,g.`emblem_data` "
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT g.`name`,c.`name`,g.`guild_lv`,g.`connect_member`,g.`max_member`,g.`average_lv`,g.`exp`,g.`next_exp`,g.`skill_point`,g.`mes1`,g.`mes2`,g.`emblem_len`,g.`emblem_id`,COALESCE(UNIX_TIMESTAMP(g.`last_master_change`),0), g.`emblem_data` "
 		"FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d'", schema_config.guild_db, schema_config.char_db, guild_id) )
 	{
 		Sql_ShowDebug(sql_handle);
@@ -379,7 +382,8 @@ struct guild * inter_guild_fromsql(int guild_id)
 	Sql_GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, zmin(len, sizeof(g->mes2)));
 	Sql_GetData(sql_handle, 11, &data, &len); g->emblem_len = atoi(data);
 	Sql_GetData(sql_handle, 12, &data, &len); g->emblem_id = atoi(data);
-	Sql_GetData(sql_handle, 13, &data, &len);
+	Sql_GetData(sql_handle, 13, &data, NULL); g->last_leader_change = atoi(data);
+	Sql_GetData(sql_handle, 14, &data, &len);
 	// convert emblem data from hexadecimal to binary
 	//TODO: why not store it in the db as binary directly? [ultramage]
 	for( i = 0, p = g->emblem_data; i < g->emblem_len; ++i, ++p )
@@ -1085,14 +1089,15 @@ int mapif_guild_emblem(struct guild *g)
 	return 0;
 }
 
-int mapif_guild_master_changed(struct guild *g, int aid, int cid)
+int mapif_guild_master_changed(struct guild *g, int aid, int cid, time_t time)
 {
-	unsigned char buf[14];
+	unsigned char buf[18];
 	WBUFW(buf,0)=0x3843;
 	WBUFL(buf,2)=g->guild_id;
 	WBUFL(buf,6)=aid;
 	WBUFL(buf,10)=cid;
-	chmapif_sendall(buf,14);
+	WBUFL(buf,14)=time;
+	chmapif_sendall(buf,18);
 	return 0;
 }
 
@@ -1825,13 +1830,16 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le
 	g->member[0].position = 0; //Position 0: guild Master.
 	g->member[0].modified = GS_MEMBER_MODIFIED;
 
+	// Store changing time
+	g->last_leader_change = time(NULL);
+
 	safestrncpy(g->master, name, len);
 	if (len < NAME_LENGTH)
 		g->master[len] = '\0';
 
 	ShowInfo("int_guild: Guildmaster Changed to %s (Guild %d - %s)\n",g->master, guild_id, g->name);
 	g->save_flag |= (GS_BASIC|GS_MEMBER); //Save main data and member data.
-	return mapif_guild_master_changed(g, g->member[0].account_id, g->member[0].char_id);
+	return mapif_guild_master_changed(g, g->member[0].account_id, g->member[0].char_id, g->last_leader_change);
 }
 
 // Communication from the map server

+ 1 - 0
src/common/mmo.h

@@ -637,6 +637,7 @@ struct guild {
 	struct guild_skill skill[MAX_GUILDSKILL];
 	struct Channel *channel;
 	unsigned short instance_id;
+	time_t last_leader_change;
 
 	/* Used by char-server to save events for guilds */
 	unsigned short save_flag;

+ 2 - 0
src/map/battle.c

@@ -8412,6 +8412,8 @@ static const struct _battle_data {
 	{ "mail_attachment_price",				&battle_config.mail_attachment_price,			2500,	0,		INT32_MAX,		},
 	{ "mail_attachment_weight",				&battle_config.mail_attachment_weight,			2000,	0,		INT32_MAX,		},
 	{ "banana_bomb_duration",				&battle_config.banana_bomb_duration,			0,		0,		UINT16_MAX,		},
+	{ "guild_leaderchange_delay",			&battle_config.guild_leaderchange_delay,		1440,	0,		INT32_MAX,		},
+	{ "guild_leaderchange_woe",				&battle_config.guild_leaderchange_woe,			0,		0,		1,				},
 
 #include "../custom/battle_config_init.inc"
 };

+ 2 - 0
src/map/battle.h

@@ -627,6 +627,8 @@ extern struct Battle_Config
 	int mail_attachment_price;
 	int mail_attachment_weight;
 	int banana_bomb_duration;
+	int guild_leaderchange_delay;
+	int guild_leaderchange_woe;
 
 #include "../custom/battle_config_struct.inc"
 } battle_config;

+ 10 - 0
src/map/clif.c

@@ -13368,6 +13368,16 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd)
 
 	// Guild leadership change
 	if( len == 16 && RFIFOL(fd,12) == 0 ){
+		if( !battle_config.guild_leaderchange_woe && is_agit_start() ){
+			clif_msg(sd, GUILD_MASTER_WOE);
+			return;
+		}
+
+		if( battle_config.guild_leaderchange_delay && DIFF_TICK(time(NULL),sd->guild->last_leader_change) < battle_config.guild_leaderchange_delay ){
+			clif_msg(sd, GUILD_MASTER_DELAY);
+			return;
+		}
+
 		guild_gm_change(sd->status.guild_id, RFIFOL(fd, 8));
 		return;
 	}

+ 3 - 1
src/map/clif.h

@@ -486,7 +486,7 @@ enum clif_messages {
 	ITEM_PARTY_NO_MEMBER_IN_MAP = 0x4c6, ///< "There is no party member to summon in the current map."
 	MERC_MSG_BASE = 0x4f2,
 	SKILL_CANT_USE_AREA = 0x536,
-	ITEM_CANT_USE_AREA =  0x537,
+	ITEM_CANT_USE_AREA = 0x537,
 	VIEW_EQUIP_FAIL = 0x54d,
 	RUNE_CANT_CREATE = 0x61b,
 	ITEM_CANT_COMBINE = 0x623,
@@ -499,6 +499,8 @@ enum clif_messages {
 	NEED_REINS_OF_MOUNT = 0x78c,
 	PARTY_MASTER_CHANGE_SAME_MAP = 0x82e, ///< "It is only possible to change the party leader while on the same map."
 	MERGE_ITEM_NOT_AVAILABLE = 0x887,
+	GUILD_MASTER_WOE = 0xb93, /// <"Currently in WoE hours, unable to delegate Guild leader"
+	GUILD_MASTER_DELAY = 0xb94, /// <"You have to wait for one day before delegating a new Guild leader"
 };
 
 enum e_personalinfo {

+ 4 - 1
src/map/guild.c

@@ -1791,7 +1791,7 @@ int guild_gm_change(int guild_id, uint32 char_id) {
 * @param account_id
 * @param char_id
 */
-int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id) {
+int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id, time_t time) {
 	struct guild *g;
 	struct guild_member gm;
 	int pos, i;
@@ -1840,6 +1840,9 @@ int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id) {
 		}
 	}
 
+	// Store changing time
+	g->last_leader_change = time;
+
 	return 1;
 }
 

+ 1 - 1
src/map/guild.h

@@ -91,7 +91,7 @@ int guild_skillupack(int guild_id,uint16 skill_id,uint32 account_id);
 int guild_break(struct map_session_data *sd,char *name);
 int guild_broken(int guild_id,int flag);
 int guild_gm_change(int guild_id, uint32 char_id);
-int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id);
+int guild_gm_changed(int guild_id, uint32 account_id, uint32 char_id, time_t time);
 
 void guild_castle_map_init(void);
 int guild_castledatasave(int castle_id,int index,int value);

+ 2 - 2
src/map/intif.c

@@ -32,7 +32,7 @@ static const int packet_len_table[] = {
 	 0, 0, 0, 0,  0, 0, 0, 0, -1,11, 0, 0,  0, 0,  0, 0, //0x3810
 	39,-1,15,15, 15+NAME_LENGTH,19, 7,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3820
 	10,-1,15, 0, 79,19, 7,-1,  0,-1,-1,-1, 14,67,186,-1, //0x3830
-	-1, 0, 0,14,  0, 0, 0, 0, -1,75,-1,11, 11,-1, 38, 0, //0x3840
+	-1, 0, 0,18,  0, 0, 0, 0, -1,75,-1,11, 11,-1, 38, 0, //0x3840
 	-1,-1, 7, 7,  7,11, 8,-1,  0, 0, 0, 0,  0, 0,  0, 0, //0x3850  Auctions [Zephyrus] itembound[Akinari]
 	-1, 7, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3860  Quests [Kevin] [Inkfish]
 	-1, 3, 3, 0,  0, 0, 0, 0,  0, 0, 0, 0, -1, 3,  3, 0, //0x3870  Mercenaries [Zephyrus] / Elemental [pakpil]
@@ -1811,7 +1811,7 @@ int intif_parse_GuildCastleDataLoad(int fd)
  */
 int intif_parse_GuildMasterChanged(int fd)
 {
-	return guild_gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
+	return guild_gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14));
 }
 
 /**