浏览代码

I'm still here!
Rewrote fame ranking lists

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

DracoRPG 19 年之前
父节点
当前提交
d94ebfdd53
共有 9 个文件被更改,包括 335 次插入129 次删除
  1. 6 0
      Changelog-Trunk.txt
  2. 118 47
      src/char/char.c
  3. 128 30
      src/char_sql/char.c
  4. 44 13
      src/map/chrif.c
  5. 2 1
      src/map/chrif.h
  6. 31 32
      src/map/pc.c
  7. 1 1
      src/map/pc.h
  8. 2 2
      src/map/skill.c
  9. 3 3
      src/map/status.c

+ 6 - 0
Changelog-Trunk.txt

@@ -3,6 +3,12 @@ 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.
 
+2006/05/26
+	* Rewrote fame rank lists system to reduce char-server load, as requested by
+	  Skotlex: now it has a copy of those lists, and updates only the proper one
+	  when needed instead of rebuilding all from saves everytime (which required
+	  to always save the character before rebuilding the lists) [DracoRPG]
+	  - Note it hasn't been compiled nor tested with SQL, please do it for me
 2006/05/25
 	* Simplified ASC_BREAKER by making it a BF_WEAPON attack with an additional
 	  int-based damage component (which is added right before elemental

+ 118 - 47
src/char/char.c

@@ -133,6 +133,11 @@ int fame_list_size_chemist = MAX_FAME_LIST;
 int fame_list_size_smith = MAX_FAME_LIST;
 int fame_list_size_taekwon = MAX_FAME_LIST;
 
+// Char-server-side stored fame lists [DracoRPG]
+struct fame_list smith_fame_list[MAX_FAME_LIST];
+struct fame_list chemist_fame_list[MAX_FAME_LIST];
+struct fame_list taekwon_fame_list[MAX_FAME_LIST];
+
 // Initial position (it's possible to set it in conf file)
 struct point start_point = { 0, 53, 111};
 
@@ -1771,14 +1776,14 @@ int e_mail_check(char *email) {
 //----------------------------------------------------------------------
 // Force disconnection of an online player (with account value) by [Yor]
 //----------------------------------------------------------------------
-int disconnect_player(int accound_id) {
+int disconnect_player(int account_id) {
 	int i;
 	struct char_session_data *sd;
 
 	// disconnect player if online on char-server
 	for(i = 0; i < fd_max; i++) {
 		if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) {
-			if (sd->account_id == accound_id) {
+			if (sd->account_id == account_id) {
 				session[i]->eof = 1;
 				return 1;
 			}
@@ -2403,8 +2408,43 @@ int char_account_reg_reply(int fd,int account_id,int char_id) {
 	return 0;
 }
 
+// Send map-servers the fame ranking lists
+int char_send_fame_list(int fd) {
+	int i, len = 8;
+	unsigned char buf[32000];
+	
+	WBUFW(buf,0) = 0x2b1b;
+
+	for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add blacksmith's block length
+	WBUFW(buf, 6) = len;
+
+	for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add alchemist's block length
+	WBUFW(buf, 4) = len;
+
+	for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add total packet length
+	WBUFW(buf, 2) = len;
+
+	// send to all map-servers
+	mapif_sendall(buf, len);
+
+	return 0;
+}
+
 int search_mapserver(unsigned short map, long ip, short port);
 
+
 int parse_frommap(int fd) {
 	int i, j;
 	int id;
@@ -2440,7 +2480,7 @@ int parse_frommap(int fd) {
 	}
 
 	while(RFIFOREST(fd) >= 2 && !session[fd]->eof) {
-//		printf("parse_frommap: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
+		//ShowDebug("Received packet 0x%4x (%d bytes) from map-server (connection %d)\n", RFIFOW(fd, 0), RFIFOREST(fd), fd);
 
 		switch(RFIFOW(fd,0)) {
 
@@ -2457,7 +2497,6 @@ int parse_frommap(int fd) {
 				WFIFOHEAD(login_fd, 2);
 				WFIFOW(login_fd,0) = 0x2709;
 				WFIFOSET(login_fd, 2);
-//				printf("char : request from map-server to reload GM accounts -> login-server.\n");
 			}
 			RFIFOSKIP(fd,2);
 			break;
@@ -2708,7 +2747,6 @@ int parse_frommap(int fd) {
 			else
 				memcpy(WFIFOP(fd,6), unknown_char_name, NAME_LENGTH);
 			WFIFOSET(fd,6+NAME_LENGTH);
-			//WFIFOSET(fd,30);
 			RFIFOSKIP(fd,6);
 			break;
 
@@ -2847,10 +2885,60 @@ int parse_frommap(int fd) {
 			break;
 		  }
 
-//		case 0x2b0f: not more used (available for futur usage)
+//		case 0x2b0f: Not used anymore, available for future use
 
-		//Packet 0x2b10 deprecated in favor of packet 0x3004 for registry saving. [Skotlex]
-		//case 0x2b10:
+		// Update and send fame ranking list [DracoRPG]
+		case 0x2b10:
+			if (RFIFOREST(fd) < 10)
+				return 0;
+			{
+				int i, j;
+				int id = RFIFOL(fd, 2);
+				int fame = RFIFOL(fd, 6);
+				char type = RFIFOB(fd, 10);
+				char pos = RFIFOB(fd, 11);
+				int size;
+				struct fame_list *list;
+
+				switch(type) {
+					case 1:
+						size = fame_list_size_smith;
+						list = smith_fame_list;
+						break;
+					case 2:
+						size = fame_list_size_chemist;
+						list = chemist_fame_list;
+						break;
+					case 3:
+						size = fame_list_size_taekwon;
+						list = taekwon_fame_list;
+						break;
+					default:
+						return 0;
+				}
+
+				if(pos) // If the player's already in the list, remove the entry and shift the following ones 1 step up
+					memmove(list + pos - 1, list + pos, (size - pos) * sizeof(struct fame_list));
+					list[size].fame = 0; // At worst, the guy'll end up last (shouldn't happen if fame only goes up)
+
+				for(i = 0; i < size; i++) // Find the position where the player has to be inserted
+					if(fame >= list[i].fame) { // When found someone with less or as much fame, insert just above
+						memmove(list + i + 1, list + i, (size - i - 1) * sizeof(struct fame_list));
+						list[i].id = id;
+						list[i].fame = fame;
+						for(j = 0; j < char_num; j++) // Look for the player's name
+							if(char_dat[j].status.char_id == id) {
+								strncpy(list[j].name, char_dat[j].status.name, NAME_LENGTH);
+								break;
+							}
+						break;
+					}
+
+				char_send_fame_list(fd);
+			}
+
+			RFIFOSKIP(fd,12);
+			break;
 
 		// Recieve rates [Wizputer]
 		case 0x2b16:
@@ -2864,7 +2952,6 @@ int parse_frommap(int fd) {
 		case 0x2b17:
 			if (RFIFOREST(fd) < 6)
 				return 0;
-			//printf("Setting %d char offline\n",RFIFOL(fd,2));
 			set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6));
 			RFIFOSKIP(fd,10);
 			break;
@@ -2880,28 +2967,18 @@ int parse_frommap(int fd) {
 		case 0x2b19:
 			if (RFIFOREST(fd) < 6)
 				return 0;
-			//printf("Setting %d char online\n",RFIFOL(fd,2));
 			set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6));
 			RFIFOSKIP(fd,10);
 			break;
 
-		// Request sending of fame list
+		// Build and send fame ranking lists [DracoRPG]
 		case 0x2b1a:
 			if (RFIFOREST(fd) < 2)
 				return 0;
 		{
-			int i, j, k, len = 8;
-			unsigned char buf[32000];
+			int i, j, k;
 			struct fame_list fame_item;
-			//struct mmo_charstatus *dat;
-			//dat = (struct mmo_charstatus *)aCalloc(char_num, sizeof(struct mmo_charstatus *));
 			CREATE_BUFFER(id, int, char_num);
-			
-			// copy character list into buffer
-			//for (i = 0; i < char_num; i++)
-			//	dat[i] = char_dat[i];
-			// sort according to fame
-			// qsort(dat, char_num, sizeof(struct mmo_charstatus *), sort_fame);
 
 			for(i = 0; i < char_num; i++) {
 				id[i] = i;
@@ -2915,9 +2992,11 @@ int parse_frommap(int fd) {
 				}
 			}
 
-			// starting to send to map
-			WBUFW(buf,0) = 0x2b1b;
-			// add list for blacksmiths
+			// Empty ranking lists
+			memset(smith_fame_list, 0, sizeof(smith_fame_list));
+			memset(chemist_fame_list, 0, sizeof(chemist_fame_list));
+			memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list));
+			// Build Blacksmith ranking list
 			for (i = 0, j = 0; i < char_num && j < fame_list_size_smith; i++) {
 				if (char_dat[id[i]].status.fame && (char_dat[id[i]].status.class_ == 10 ||
 					char_dat[id[i]].status.class_ == 4011 ||
@@ -2926,16 +3005,13 @@ int parse_frommap(int fd) {
 					fame_item.id = char_dat[id[i]].status.char_id;
 					fame_item.fame = char_dat[id[i]].status.fame;
 					strncpy(fame_item.name, char_dat[id[i]].status.name, NAME_LENGTH);
-					
-					memcpy(WBUFP(buf, len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
+
+					smith_fame_list[j] = fame_item;
+
 					j++;
 				}
 			}
-			// add blacksmith's block length
-			WBUFW(buf, 6) = len;
-			
-			// add list for alchemists
+			// Build Alchemist ranking list
 			for (i = 0, j = 0; i < char_num && j < fame_list_size_chemist; i++) {
 				if (char_dat[id[i]].status.fame && (char_dat[id[i]].status.class_ == 18 ||
 					char_dat[id[i]].status.class_ == 4019 ||
@@ -2944,39 +3020,34 @@ int parse_frommap(int fd) {
 					fame_item.id = char_dat[id[i]].status.char_id;
 					fame_item.fame = char_dat[id[i]].status.fame;
 					strncpy(fame_item.name, char_dat[id[i]].status.name, NAME_LENGTH);
-					
-					memcpy(WBUFP(buf, len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
+
+					chemist_fame_list[j] = fame_item;
+
 					j++;
 				}
 			}
-			// add alchemist's block length
-			WBUFW(buf, 4) = len;
-
-			// adding list for taekwons
+			// Build Taekwon ranking list
 			for (i = 0, j = 0; i < char_num && j < fame_list_size_taekwon; i++) {
 				if (char_dat[id[i]].status.fame && char_dat[id[i]].status.class_ == 4046)
 				{
 					fame_item.id = char_dat[id[i]].status.char_id;
 					fame_item.fame = char_dat[id[i]].status.fame;
 					strncpy(fame_item.name, char_dat[id[i]].status.name, NAME_LENGTH);
-					
-					memcpy(WBUFP(buf, len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
+
+					taekwon_fame_list[j] = fame_item;
+
 					j++;
 				}
 			}
-			// add total packet length
-			WBUFW(buf, 2) = len;
 
-			// sending to all maps
-			mapif_sendall(buf, len);
-			// done!
-			//aFree(dat);
 			DELETE_BUFFER(id);
+
+			char_send_fame_list(fd);
+
 			RFIFOSKIP(fd,2);
 			break;
 		}
+
 		//Request to save status change data. [Skotlex]
 		case 0x2b1c:
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))

+ 128 - 30
src/char_sql/char.c

@@ -152,6 +152,11 @@ int fame_list_size_chemist = MAX_FAME_LIST;
 int fame_list_size_smith = MAX_FAME_LIST;
 int fame_list_size_taekwon = MAX_FAME_LIST;
 
+// Char-server-side stored fame lists [DracoRPG]
+struct fame_list smith_fame_list[MAX_FAME_LIST];
+struct fame_list chemist_fame_list[MAX_FAME_LIST];
+struct fame_list taekwon_fame_list[MAX_FAME_LIST];
+
 // check for exit signal
 // 0 is saving complete
 // other is char_id
@@ -2201,8 +2206,44 @@ int save_accreg2(unsigned char* buf, int len) {
 	}
 	return 0;
 }
+
+// Send map-servers the fame ranking lists
+int char_send_fame_list(int fd) {
+	int i, len = 8;
+	unsigned char buf[32000];
+	
+	WBUFW(buf,0) = 0x2b1b;
+
+	for(i = 0; i < fame_list_size_smith && smith_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &smith_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add blacksmith's block length
+	WBUFW(buf, 6) = len;
+
+	for(i = 0; i < fame_list_size_chemist && chemist_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &chemist_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add alchemist's block length
+	WBUFW(buf, 4) = len;
+
+	for(i = 0; i < fame_list_size_taekwon && taekwon_fame_list[i].id; i++) {
+		memcpy(WBUFP(buf, len), &taekwon_fame_list[i], sizeof(struct fame_list));
+		len += sizeof(struct fame_list);
+	}
+	// add total packet length
+	WBUFW(buf, 2) = len;
+
+	// send to all map-servers
+	mapif_sendall(buf, len);
+
+	return 0;
+}
+
 int search_mapserver(unsigned short map, long ip, short port);
 
+
 int parse_frommap(int fd) {
 	int i = 0, j = 0;
 	int id;
@@ -2249,7 +2290,7 @@ int parse_frommap(int fd) {
 	}
 
 	while(RFIFOREST(fd) >= 2 && !session[fd]->eof) {
-//		printf("parse_frommap : %d %d %x\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
+	//ShowDebug("Received packet 0x%4x (%d bytes) from map-server (connection %d)\n", RFIFOW(fd, 0), RFIFOREST(fd), fd);
 
 		switch(RFIFOW(fd, 0)) {
 
@@ -2575,9 +2616,6 @@ int parse_frommap(int fd) {
 			RFIFOSKIP(fd, RFIFOW(fd, 2));
 			break;
 
-		//Packet 0x2b10 deprecated in favor of packet 0x3004 for registry saving. [Skotlex]
-		//case 0x2b10:
-
 		// Map server send information to change an email of an account -> login-server
 		case 0x2b0c:
 			if (RFIFOREST(fd) < 86)
@@ -2704,6 +2742,61 @@ int parse_frommap(int fd) {
 			RFIFOSKIP(fd, 44);
 			break;
 
+//		case 0x2b0f: Not used anymore, available for future use
+
+		// Update and send fame ranking list [DracoRPG]
+		case 0x2b10:
+			if (RFIFOREST(fd) < 10)
+				return 0;
+			{
+				int i, j;
+				int id = RFIFOL(fd, 2);
+				int fame = RFIFOL(fd, 6);
+				char type = RFIFOB(fd, 10);
+				char pos = RFIFOB(fd, 11);
+				int size;
+				struct fame_list *list;
+
+				switch(type) {
+					case 1:
+						size = fame_list_size_smith;
+						list = smith_fame_list;
+						break;
+					case 2:
+						size = fame_list_size_chemist;
+						list = chemist_fame_list;
+						break;
+					case 3:
+						size = fame_list_size_taekwon;
+						list = taekwon_fame_list;
+						break;
+					default:
+						return 0;
+				}
+
+				if(pos) // If the player's already in the list, remove the entry and shift the following ones 1 step up
+					memmove(list + pos - 1, list + pos, (size - pos) * sizeof(struct fame_list));
+					list[size].fame = 0; // At worst, the guy'll end up last (shouldn't happen if fame only goes up)
+
+				for(i = 0; i < size; i++) // Find the position where the player has to be inserted
+					if(fame >= list[i].fame) { // When found someone with less or as much fame, insert just above
+						memmove(list + i + 1, list + i, (size - i - 1) * sizeof(struct fame_list));
+						list[i].id = id;
+						list[i].fame = fame;
+						for(j = 0; j < char_num; j++) // Look for the player's name
+							if(char_dat[j].status.char_id == id) {
+								strncpy(list[j].name, char_dat[j].status.name, NAME_LENGTH);
+								break;
+							}
+						break;
+					}
+
+				char_send_fame_list(fd);
+			}
+
+			RFIFOSKIP(fd,12);
+			break;
+
 		// Recieve rates [Wizputer]
 		case 0x2b16:
 			if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,8))
@@ -2746,83 +2839,88 @@ int parse_frommap(int fd) {
 			RFIFOSKIP(fd,10);
 			break;
 
-		// Request sending of fame list
+		// Build and send fame ranking lists [DracoRPG]
 		case 0x2b1a:
 			if (RFIFOREST(fd) < 2)
 				return 0;
 		{
-			int len = 8, num = 0;
-			unsigned char buf[32000];
+			int i;
 			struct fame_list fame_item;
 
-			WBUFW(buf,0) = 0x2b1b;
-			sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='10' OR `class`='4011'OR `class`='4033') ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_smith);
+			// Empty ranking lists
+			memset(smith_fame_list, 0, sizeof(smith_fame_list));
+			memset(chemist_fame_list, 0, sizeof(chemist_fame_list));
+			memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list));
+			// Build Blacksmith ranking list
+			sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='10' OR `class`='4011' OR `class`='4033') ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_smith);
 			if (mysql_query(&mysql_handle, tmp_sql)) {
 				ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
 				ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
 			}
 			sql_res = mysql_store_result(&mysql_handle);
 			if (sql_res) {
+				i = 0;
 				while((sql_row = mysql_fetch_row(sql_res))) {
 					fame_item.id = atoi(sql_row[0]);
 					fame_item.fame = atoi(sql_row[1]);
 					strncpy(fame_item.name, sql_row[2], NAME_LENGTH);
 
-					memcpy(WBUFP(buf,len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
-					if (++num == fame_list_size_smith)
+					smith_fame_list[i] = fame_item;
+
+					if (++i == fame_list_size_smith)
 						break;
 				}
    			mysql_free_result(sql_res);
 			}
-			WBUFW(buf, 6) = len; //Blacksmith block size
-
-			num = 0;
-			sprintf(tmp_sql, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='18' OR `class`='4019' OR `class`='4041') ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_chemist);
+			// Build Alchemist ranking list
+			sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='18' OR `class`='4019' OR `class`='4041') ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_chemist);
 			if (mysql_query(&mysql_handle, tmp_sql)) {
 				ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
 				ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
 			}
 			sql_res = mysql_store_result(&mysql_handle);
 			if (sql_res) {
+				i = 0;
 				while((sql_row = mysql_fetch_row(sql_res))) {
 					fame_item.id = atoi(sql_row[0]);
 					fame_item.fame = atoi(sql_row[1]);
 					strncpy(fame_item.name, sql_row[2], NAME_LENGTH);
-					memcpy(WBUFP(buf,len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
-					if (++num == fame_list_size_chemist)
+
+					chemist_fame_list[i] = fame_item;
+
+					if (++i == fame_list_size_chemist)
 						break;
 				}
-				mysql_free_result(sql_res);
+   			mysql_free_result(sql_res);
 			}
-			WBUFW(buf, 4) = len; //Alchemist block size
-
-			num = 0;
-			sprintf(tmp_sql, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND `class`='4046' ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_taekwon);
+			// Build Taekwon ranking list
+			sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='4048') ORDER BY `fame` DESC LIMIT 0,%d", char_db, fame_list_size_taekwon);
 			if (mysql_query(&mysql_handle, tmp_sql)) {
 				ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
 				ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
 			}
 			sql_res = mysql_store_result(&mysql_handle);
 			if (sql_res) {
+				i = 0;
 				while((sql_row = mysql_fetch_row(sql_res))) {
 					fame_item.id = atoi(sql_row[0]);
 					fame_item.fame = atoi(sql_row[1]);
 					strncpy(fame_item.name, sql_row[2], NAME_LENGTH);
-					memcpy(WBUFP(buf,len), &fame_item, sizeof(struct fame_list));
-					len += sizeof(struct fame_list);
-					if (++num == fame_list_size_taekwon)
+
+					taekwon_fame_list[i] = fame_item;
+
+					if (++i == fame_list_size_taekwon)
 						break;
 				}
-				mysql_free_result(sql_res);
+   			mysql_free_result(sql_res);
 			}
-			WBUFW(buf, 2) = len; //Total packet length
 
-			mapif_sendall(buf, len);
+			char_send_fame_list(fd);
+
 			RFIFOSKIP(fd,2);
 			break;
 		}
+
 		//Request saving sc_data of a player. [Skotlex]
 		case 0x2b1c:
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))

+ 44 - 13
src/map/chrif.c

@@ -73,18 +73,18 @@ static const int packet_len_table[0x3d] = {
 //2b0d: Incomming, chrif_changedsex -> 'Change sex of acc XY'
 //2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)'
 //2b0f: Incomming, chrif_char_ask_name_answer -> 'answer of the 2b0e'
-//2b10: FREE
+//2b10: Outgoing, chrif_updatefamelist -> 'Update the fame ranking lists and send them'
 //2b11: Outgoing, chrif_changesex -> 'change sex of acc X'
 //2b12: Incomming, chrif_divorce -> 'divorce a wedding of charid X and partner id X'
 //2b13: Incomming, chrif_accountdeletion -> 'Delete acc XX, if the player is on, kick ....'
 //2b14: Incomming, chrif_accountban -> 'not sure: kick the player with message XY'
-//2b15: Incomming, chrif_recvgmaccounts -> 'recive gm accs from charserver (seems to be incomplete !)'
+//2b15: Incomming, chrif_recvgmaccounts -> 'recieve gm accs from charserver (seems to be incomplete !)'
 //2b16: Outgoing, chrif_ragsrvinfo -> 'sends motd / rates ....'
 //2b17: Outgoing, chrif_char_offline -> 'tell the charserver that the char is now offline'
 //2b18: Outgoing, chrif_char_reset_offline -> 'set all players OFF!'
 //2b19: Outgoing, chrif_char_online -> 'tell the charserver that the char .. is online'
-//2b1a: Outgoing, chrif_reqfamelist -> 'Request the fame list (top10)'
-//2b1b: Incomming, chrif_recvfamelist -> 'answer of 2b1a ..... the famelist top10^^'
+//2b1a: Outgoing, chrif_buildfamelist -> 'Build the fame ranking lists and send them'
+//2b1b: Incomming, chrif_recvfamelist -> 'Receive fame ranking lists'
 //2b1c: Outgoing, chrif_save_scdata -> 'Send sc_data of player for saving.'
 //2b1d: Incomming, chrif_load_scdata -> 'received sc_data of player for loading.'
 //2b1e: FREE
@@ -1107,19 +1107,50 @@ int chrif_recvgmaccounts(int fd)
  * Request/Receive top 10 Fame character list
  *------------------------------------------
  */
-int chrif_reqfamelist(void)
+
+int chrif_updatefamelist(struct map_session_data *sd)
 {
+	char type;
 	chrif_check(-1);
 
-        WFIFOHEAD(char_fd, 2);
-	WFIFOW(char_fd,0) = 0x2b1a;
+	switch(sd->class_&MAPID_UPPERMASK) {
+		case MAPID_BLACKSMITH:
+			type = 1;
+			break;
+		case MAPID_ALCHEMIST:
+			type = 2;
+			break;
+		case MAPID_TAEKWON:
+			type = 3;
+			break;
+		default:
+			return 0;
+	}
+
+    WFIFOHEAD(char_fd, 12);
+	WFIFOW(char_fd, 0) = 0x2b10;
+	WFIFOL(char_fd, 2) = sd->char_id;
+	WFIFOL(char_fd, 6) = sd->status.fame;
+	WFIFOB(char_fd, 10) = type;
+	WFIFOB(char_fd, 11) = pc_famerank(sd->char_id, sd->class_&MAPID_UPPERMASK);
+	WFIFOSET(char_fd, 12);
+
+	return 0;
+}
+
+int chrif_buildfamelist(void)
+{
+	chrif_check(-1);
+
+    WFIFOHEAD(char_fd, 2);
+	WFIFOW(char_fd, 0) = 0x2b1a;
 	WFIFOSET(char_fd, 2);
 
 	return 0;
 }
 
 int chrif_recvfamelist(int fd)
-{	// response from 0x2b1b
+{
 	int num, size;
 	int total = 0, len = 8;
 	RFIFOHEAD(fd);
@@ -1128,21 +1159,21 @@ int chrif_recvfamelist(int fd)
 	memset (chemist_fame_list, 0, sizeof(chemist_fame_list));
 	memset (taekwon_fame_list, 0, sizeof(taekwon_fame_list));
 
-	size = RFIFOW(fd,6); //Blacksmith block size
+	size = RFIFOW(fd, 6); //Blacksmith block size
 	for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
 		memcpy(&smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
  		len += sizeof(struct fame_list);
 	}
 	total += num;
 
-	size = RFIFOW(fd,4); //Alchemist block size
+	size = RFIFOW(fd, 4); //Alchemist block size
 	for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
 		memcpy(&chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
  		len += sizeof(struct fame_list);
 	}
 	total += num;
 
-	size = RFIFOW(fd,2); //Total packet length
+	size = RFIFOW(fd, 2); //Total packet length
 	for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
 		memcpy(&taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
  		len += sizeof(struct fame_list);
@@ -1254,7 +1285,7 @@ int chrif_load_scdata(int fd)
 
 	chrif_check(-1);
 
-        WFIFOHEAD(char_fd, sizeof(buf) + 10);
+	WFIFOHEAD(char_fd, sizeof(buf) + 10);
 	WFIFOW(char_fd,0) = 0x2b16;
 	WFIFOW(char_fd,2) = base_rate;
 	WFIFOW(char_fd,4) = job_rate;
@@ -1426,7 +1457,7 @@ int chrif_parse(int fd)
 
 		switch(cmd) {
 		case 0x2af9: chrif_connectack(fd); break;
-		case 0x2afb: chrif_sendmapack(fd); chrif_reqfamelist(); break;
+		case 0x2afb: chrif_sendmapack(fd); chrif_buildfamelist(); break;
 		case 0x2afd: chrif_authok(fd); break;
 		case 0x2b00: map_setusers(fd); break;
 		case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break;

+ 2 - 1
src/map/chrif.h

@@ -34,7 +34,8 @@ int chrif_changegm(int id,const char *pass,int len);
 int chrif_changeemail(int id, const char *actual_email, const char *new_email);
 int chrif_char_ask_name(int id, char * character_name, short operation_type, int year, int month, int day, int hour, int minute, int second);
 int chrif_reloadGMdb(void);
-int chrif_reqfamelist(void);
+int chrif_updatefamelist(struct map_session_data *sd);
+int chrif_buildfamelist(void);
 int chrif_save_scdata(struct map_session_data *sd);
 int chrif_ragsrvinfo(int base_rate,int job_rate, int drop_rate);
 int chrif_char_offline(struct map_session_data *sd);

+ 31 - 32
src/map/pc.c

@@ -242,7 +242,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type) {
 	return 0;
 }
 
-// Increases a player's  and displays a notice to him
+// Increases a player's fame points and displays a notice to him
 void pc_addfame(struct map_session_data *sd,int count) {
     nullpo_retv(sd);
 	sd->status.fame += count;
@@ -251,41 +251,40 @@ void pc_addfame(struct map_session_data *sd,int count) {
 	switch(sd->class_&MAPID_UPPERMASK){
 		case MAPID_BLACKSMITH: // Blacksmith
             clif_fame_blacksmith(sd,count);
-            break;
+			break;
 		case MAPID_ALCHEMIST: // Alchemist
             clif_fame_alchemist(sd,count);
-            break;
+			break;
 		case MAPID_TAEKWON: // Taekwon
             clif_fame_taekwon(sd,count);
-            break;	
+			break;	
 	}
-	//FIXME: Is this needed? It places unnecessary stress on the char server.... >.< [Skotlex]
-	chrif_save(sd,0); // Save to allow up-to-date fame list refresh
-	chrif_reqfamelist(); // Refresh the fame list
+	chrif_updatefamelist(sd);
 }
 
-// Check whether a player ID is in the Top 10 fame list of its job
-int pc_istop10fame(int char_id,int job) {
+// Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else
+unsigned char pc_famerank(int char_id,int job) {
     int i;
+
 	switch(job){
-	case MAPID_BLACKSMITH: // Blacksmith
-	    for(i=0;i<MAX_FAME_LIST;i++){
-			if(smith_fame_list[i].id==char_id)
-			    return smith_fame_list[i].fame;
-		}
-		break;
-	case MAPID_ALCHEMIST: // Alchemist
-	    for(i=0;i<MAX_FAME_LIST;i++){
-	        if(chemist_fame_list[i].id==char_id)
-	            return chemist_fame_list[i].fame;
-		}
-		break;
-	case MAPID_TAEKWON: // Taekwon
-	    for(i=0;i<MAX_FAME_LIST;i++){
-	        if(taekwon_fame_list[i].id==char_id)
-	            return taekwon_fame_list[i].fame;
-		}
-		break;
+		case MAPID_BLACKSMITH: // Blacksmith
+		    for(i = 0; i < MAX_FAME_LIST; i++){
+				if(smith_fame_list[i].id == char_id)
+				    return i + 1;
+			}
+			break;
+		case MAPID_ALCHEMIST: // Alchemist
+			for(i = 0; i < MAX_FAME_LIST; i++){
+				if(chemist_fame_list[i].id == char_id)
+					return i + 1;
+			}
+			break;
+		case MAPID_TAEKWON: // Taekwon
+			for(i = 0; i < MAX_FAME_LIST; i++){
+				if(taekwon_fame_list[i].id == char_id)
+					return i + 1;
+			}
+			break;
 	}
 
 	return 0;
@@ -991,7 +990,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
 			}
 		}
 	} while(flag);
-	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_istop10fame(sd->char_id, MAPID_TAEKWON)) {
+	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->char_id, MAPID_TAEKWON)) {
 		//Grant all Taekwon Tree, but only as bonus skills in case they drop from ranking. [Skotlex]
 		for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0;i++){
 			if ((skill_get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)))
@@ -2701,7 +2700,7 @@ int pc_useitem(struct map_session_data *sd,int n)
 		pc_delitem(sd,n,1,1);
 	}
 	if(sd->status.inventory[n].card[0]==0x00fe &&
-		pc_istop10fame(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
+		pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
 	{
 	    potion_flag = 2; // Famous player's potions have 50% more efficiency
 		 if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_ROGUE)
@@ -5271,7 +5270,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 
 	sd->status.class_ = job;
 	status_set_viewdata(&sd->bl, job);
-	fame_flag = pc_istop10fame(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
+	fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
 	sd->class_ = (unsigned short)b_class;
 	sd->status.job_level=1;
 	sd->status.job_exp=0;
@@ -5305,7 +5304,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 	//if you were previously famous, not anymore.
 	if (fame_flag) {
 		chrif_save(sd,0);
-		chrif_reqfamelist();
+		chrif_buildfamelist();
 	} else if (sd->status.fame > 0) {
 		//It may be that now they are famous?
  		switch (sd->class_&MAPID_UPPERMASK) {
@@ -5313,7 +5312,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 			case MAPID_ALCHEMIST:
 			case MAPID_TAEKWON:
 				chrif_save(sd,0);
-				chrif_reqfamelist();
+				chrif_buildfamelist();
 			break;
 		}
 	}

+ 1 - 1
src/map/pc.h

@@ -234,7 +234,7 @@ int pc_delinvincibletimer(struct map_session_data *sd);
 int pc_addspiritball(struct map_session_data *sd,int,int);
 int pc_delspiritball(struct map_session_data *sd,int,int);
 void pc_addfame(struct map_session_data *sd,int count);
-int pc_istop10fame(int char_id, int job);
+unsigned char pc_famerank(int char_id, int job);
 int pc_eventtimer(int tid,unsigned int tick,int id,int data); // for npc_dequeue
 
 extern struct fame_list smith_fame_list[MAX_FAME_LIST];

+ 2 - 2
src/map/skill.c

@@ -1825,7 +1825,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
 				//set this skill as previous one.
 				sd->skillid_old = skillid;
 				sd->skilllv_old = skilllv;
-				if (pc_istop10fame(sd->char_id,MAPID_TAEKWON))
+				if (pc_famerank(sd->char_id,MAPID_TAEKWON))
 					break; //Do not end combo state.
 			default:
 				status_change_end(src,SC_COMBO,-1);
@@ -7784,7 +7784,7 @@ int skill_check_condition(struct map_session_data *sd,int skill, int lv, int typ
 	case TK_COUNTER:
 		if(sd->sc.data[SC_COMBO].timer == -1)
 			return 0; //Combo needs to be ready
-		if (pc_istop10fame(sd->char_id,MAPID_TAEKWON))
+		if (pc_famerank(sd->char_id,MAPID_TAEKWON))
 		{	//Unlimited Combo
 			if (skill == sd->skillid_old) {
 				status_change_end(&sd->bl, SC_COMBO, -1);

+ 3 - 3
src/map/status.c

@@ -919,7 +919,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 			{	// Forged weapon
 				wd->star += (sd->status.inventory[index].card[1]>>8);
 				if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
-				if(pc_istop10fame( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
+				if(pc_famerank( MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
 					wd->star += 10;
 				
 				if (!wd->atk_ele) //Do not overwrite element from previous bonuses.
@@ -1420,7 +1420,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		index += index * 30/100;
 	else if (sd->class_&JOBL_BABY)
 		index -= index * 30/100;
-	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_istop10fame(sd->char_id, MAPID_TAEKWON))
+	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->char_id, MAPID_TAEKWON))
 		index *= 3; //Triple max HP for top ranking Taekwons over level 90.
 	
 	sd->status.max_hp += index;
@@ -1482,7 +1482,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		index += index * 30/100;
 	else if (sd->class_&JOBL_BABY)
 		index -= index * 30/100;
-	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_istop10fame(sd->char_id, MAPID_TAEKWON))
+	if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->char_id, MAPID_TAEKWON))
 		index *= 3; //Triple max SP for top ranking Taekwons over level 90.
 	
 	sd->status.max_sp += index;