Explorar o código

VIP System Additions
* GM's (or group IDs > VIP group ID) will not be able to become VIP.
* Adjusted @whodrops and @mobinfo to account for VIP rates.

aleos89 %!s(int64=11) %!d(string=hai) anos
pai
achega
f9165044ca
Modificáronse 5 ficheiros con 89 adicións e 60 borrados
  1. 5 2
      conf/msg_conf/map_msg.conf
  2. 28 26
      src/char/char.c
  3. 18 13
      src/login/login.c
  4. 15 0
      src/map/atcommand.c
  5. 23 19
      src/map/chrif.c

+ 5 - 2
conf/msg_conf/map_msg.conf

@@ -443,9 +443,9 @@
 420: Your account has not more authorised.
 421: Your account has been totally erased.
 423: Your %s has been banished until %s 
-424: login-serv has been asked to %s the player '%.*s'.
+424: Login-serv has been asked to %s the player '%.*s'.
 425: The player '%.*s' doesn't exist.
-426: Your GM level don't authorise you to %s the player '%.*s'.
+426: Your GM level doesn't authorise you to %s the player '%.*s'.
 427: Login-server is offline. Impossible to %s the player '%.*s'.
 428: block
 429: ban
@@ -455,6 +455,9 @@
 433: This character has been banned until 
 434: Char-server has been asked to %s the character '%.*s'.
 435: Please enter a player name (usage: @charunblock <char name>).
+436: VIP
+437: GM's cannot become a VIP.
+438: You are no longer VIP.
 
 // Homunculus messages
 450: You already have a homunculus

+ 28 - 26
src/char/char.c

@@ -184,8 +184,8 @@ void pincode_notifyLoginPinError( int account_id );
 void pincode_decrypt( uint32 userSeed, char* pin );
 int pincode_compare( int fd, struct char_session_data* sd, char* pin );
 
-int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint32 groupid);
-int loginif_reqviddata(uint32 aid, uint8 type, int add_vip_time, int mapfd);
+int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid);
+int loginif_reqvipdata(uint32 aid, uint8 type, int add_vip_time, int mapfd);
 int loginif_parse_vipack(int fd);
 
 // Addon system
@@ -2290,15 +2290,16 @@ int mapif_BankingAck(int32 account_id, int32 bank_vault){
  * HZ 0x2b2b
  * Transmist vip data to mapserv
  */
-int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint32 groupid) {
+int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint8 isgm, uint32 groupid) {
 #ifdef VIP_ENABLE
 	uint8 buf[16];
 	WBUFW(buf,0) = 0x2b2b;
 	WBUFL(buf,2) = aid;
 	WBUFL(buf,6) = vip_time;
 	WBUFB(buf,10) = isvip;
-	WBUFL(buf,11) = groupid;
-	mapif_send(mapfd,buf,15);  // inform the mapserv back
+	WBUFB(buf,11) = isgm;
+	WBUFL(buf,12) = groupid;
+	mapif_send(mapfd,buf,16);  // inform the mapserv back
 #endif
 	return 0;
 }
@@ -2310,17 +2311,17 @@ int mapif_vipack(int mapfd, uint32 aid, uint32 vip_time, uint8 isvip, uint32 gro
  * @param type : &2 define new duration, &1 load info
  * @param add_vip_time : tick to add to vip timestamp
  * @param mapfd: link to mapserv for ack
- * @return 0 if succes
+ * @return 0 if success
  */
-int loginif_reqviddata(uint32 aid, uint8 type, int32 timediff, int mapfd) {
+int loginif_reqvipdata(uint32 aid, uint8 type, int32 timediff, int mapfd) {
 	loginif_check(-1);
 #ifdef VIP_ENABLE
 	WFIFOHEAD(login_fd,15);
 	WFIFOW(login_fd,0) = 0x2742;
-	WFIFOL(login_fd,2) =  aid; //aid
+	WFIFOL(login_fd,2) = aid; //aid
 	WFIFOB(login_fd,6) = type; //type
-	WFIFOL(login_fd,7) =  timediff; //req_inc_duration
-	WFIFOL(login_fd,11) =  mapfd; //req_inc_duration
+	WFIFOL(login_fd,7) = timediff; //req_inc_duration
+	WFIFOL(login_fd,11) = mapfd; //req_inc_duration
 	WFIFOSET(login_fd,15);
 #endif
 	return 0;
@@ -2332,16 +2333,17 @@ int loginif_reqviddata(uint32 aid, uint8 type, int32 timediff, int mapfd) {
  */
 int loginif_parse_vipack(int fd) {
 #ifdef VIP_ENABLE
-	if (RFIFOREST(fd) < 19)
+	if (RFIFOREST(fd) < 20)
 		return 0;
 	else {
 		uint32 aid = RFIFOL(fd,2); //aid
 		uint32 vip_time = RFIFOL(fd,6); //vip_time
 		uint8 isvip = RFIFOB(fd,10); //isvip
 		uint32 groupid = RFIFOL(fd,11); //new group id
-		int mapfd = RFIFOL(fd,15); //link to mapserv for ack
-		RFIFOSKIP(fd,19);
-		mapif_vipack(mapfd,aid,vip_time,isvip,groupid);
+		uint8 isgm = RFIFOB(fd,15); //isgm
+		int mapfd = RFIFOL(fd,16); //link to mapserv for ack
+		RFIFOSKIP(fd,20);
+		mapif_vipack(mapfd,aid,vip_time,isvip,isgm,groupid);
 	}
 #endif
 	return 1;
@@ -3084,17 +3086,17 @@ int mapif_parse_reqcharunban(int fd){
  * ZH 2b0e <aid>L <charname>24B <opetype>W <timediff>L
  * @param fd: link to mapserv
  */
-int mapif_parse_req_alter_acc(int fd){
+int mapif_parse_req_alter_acc(int fd) {
 	if (RFIFOREST(fd) < 44)
 		return 0;
 	else {
-		int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline
+		int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline, 4-current group level > VIP group level
 		char esc_name[NAME_LENGTH*2+1];
-		char anwser=true;
+		char answer = true;
 
 		int aid = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request)
 		const char* name = (char*)RFIFOP(fd,6); // name of the target character
-		int operation = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban,  5 changesex, 6 vip, 7 bank
+		int operation = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex, 6-vip, 7-bank
 		int32 timediff = RFIFOL(fd,32);
 		int val1 = RFIFOL(fd,36);
 		int val2 = RFIFOL(fd,40);
@@ -3103,10 +3105,10 @@ int mapif_parse_req_alter_acc(int fd){
 		Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
 		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`char_id`,`unban_time` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
 			Sql_ShowDebug(sql_handle);
-		else if( Sql_NumRows(sql_handle) == 0 ){
+		else if( Sql_NumRows(sql_handle) == 0 ) {
 			result = 1; // 1-player not found
 		}
-		else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ){
+		else if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) {
 			Sql_ShowDebug(sql_handle);
 			result = 1;
 		} else {
@@ -3153,26 +3155,26 @@ int mapif_parse_req_alter_acc(int fd){
 					WFIFOSET(login_fd,6);
 				break;
 				case 5: // changesex
-					anwser=false;
+					answer = false;
 					WFIFOHEAD(login_fd,6);
 					WFIFOW(login_fd,0) = 0x2727;
 					WFIFOL(login_fd,2) = account_id;
 					WFIFOSET(login_fd,6);
 				break;
 				case 6:
-					anwser=(val1&4); // vip_req val1=type, &1 login send return, &2 upd timestamp &4 map send awnser
-					loginif_reqviddata(account_id, val1, timediff, fd);
+					answer = (val1&4); // vip_req val1=type, &1 login send return, &2 update timestamp, &4 map send answer
+					loginif_reqvipdata(account_id, val1, timediff, fd);
 					break;
 				case 7:
-					anwser=(val1&1); //val&1 request anwser, val1&2 save data
+					answer = (val1&1); //val&1 request answer, val1&2 save data
 					loginif_BankingReq(aid, val1, val2);
 					break;
 				} //end switch operation
 			} //login is connected
 		}
 
-		// send answer if a player ask, not if the server ask
-		if( aid != -1 && anwser) { // Don't send answer for changesex
+		// send answer if a player asks, not if the server asks
+		if( aid != -1 && answer) { // Don't send answer for changesex
 			WFIFOHEAD(fd,34);
 			WFIFOW(fd, 0) = 0x2b0f;
 			WFIFOL(fd, 2) = aid;

+ 18 - 13
src/login/login.c

@@ -463,7 +463,7 @@ int chrif_send_accdata(int fd, uint32 aid) {
 #ifdef VIP_ENABLE
 		char_vip = login_config.vip_sys.char_increase;
 		if( acc.vip_time > time(NULL) ) {
-			isvip=true;
+			isvip = true;
 			char_slots = login_config.char_per_account + char_vip;
 		} else
 			char_slots = login_config.char_per_account;
@@ -501,7 +501,7 @@ int chrif_parse_reqaccdata(int fd, int cid, char *ip) {
 }
 
 
-int chrif_sendvipdata(int fd, struct mmo_account acc, char isvip, int mapfd) {
+int chrif_sendvipdata(int fd, struct mmo_account acc, char isvip, char isgm, int mapfd) {
 #ifdef VIP_ENABLE
 	WFIFOHEAD(fd,19);
 	WFIFOW(fd,0) = 0x2743;
@@ -509,8 +509,9 @@ int chrif_sendvipdata(int fd, struct mmo_account acc, char isvip, int mapfd) {
 	WFIFOL(fd,6) = (int)acc.vip_time;
 	WFIFOB(fd,10) = isvip;
 	WFIFOL(fd,11) = acc.group_id; //new group id
-	WFIFOL(fd,15) = mapfd; //link to mapserv
-	WFIFOSET(fd,19);
+	WFIFOL(fd,15) = isgm;
+	WFIFOL(fd,16) = mapfd; //link to mapserv
+	WFIFOSET(fd,20);
 	chrif_send_accdata(fd,acc.account_id); //refresh char with new setting
 #endif
 	return 1;
@@ -522,7 +523,7 @@ int chrif_sendvipdata(int fd, struct mmo_account acc, char isvip, int mapfd) {
  *  &1 : Select info and update old_groupid
  *  &2 : Update vip time
  * @param fd link to charserv
- * @return 0 missing data, 1 succeed
+ * @return 0 missing data, 1 succeeded
  */
 int chrif_parse_reqvipdata(int fd) {
 #ifdef VIP_ENABLE
@@ -533,19 +534,23 @@ int chrif_parse_reqvipdata(int fd) {
 		int aid = RFIFOL(fd,2);
 		int8 type = RFIFOB(fd,6);
 		int32 timediff = RFIFOL(fd,7);
-		int mapfd =  RFIFOL(fd,11);
+		int mapfd = RFIFOL(fd,11);
 		RFIFOSKIP(fd,15);
 		
-		if( accounts->load_num(accounts, &acc, aid ) ){
+		if( accounts->load_num(accounts, &acc, aid ) ) {
 			time_t now = time(NULL);
 			time_t vip_time = acc.vip_time;
 			bool isvip = false;
 
-			if( type&2 ){
+			if( acc.group_id > login_config.vip_sys.group ) { //Don't change group if it's higher.
+				chrif_sendvipdata(fd,acc,false,true,mapfd);
+				return 1;
+			}
+			if( type&2 ) {
 				if(!vip_time) vip_time = now; //new entry
-				vip_time +=  timediff; // set new duration
-			} 
-			if( now < vip_time) { //isvip
+				vip_time += timediff; // set new duration
+			}
+			if( now < vip_time ) { //isvip
 				if(acc.group_id != login_config.vip_sys.group) //only upd this if we're not vip already
 					acc.old_group = acc.group_id;
 				acc.group_id = login_config.vip_sys.group;
@@ -553,14 +558,14 @@ int chrif_parse_reqvipdata(int fd) {
 				isvip = true;
 			} else { //expired or @vip -xx
 				vip_time = 0;
-				if(acc.group_id == login_config.vip_sys.group) //prevent alteration in case we wasn't registered vip yet
+				if(acc.group_id == login_config.vip_sys.group) //prevent alteration in case account wasn't registered as vip yet
 					acc.group_id = acc.old_group;
 				acc.old_group = 0;
 				acc.char_slots = login_config.char_per_account;
 			}
 			acc.vip_time = vip_time;
 			accounts->save(accounts,&acc);
-			if( type&1 ) chrif_sendvipdata(fd,acc,isvip,mapfd);
+			if( type&1 ) chrif_sendvipdata(fd,acc,isvip,false,mapfd);
 		}
 	}
 #endif

+ 15 - 0
src/map/atcommand.c

@@ -6960,6 +6960,14 @@ ACMD_FUNC(mobinfo)
 			base_exp = base_exp * pc_level_penalty_mod(sd, mob->lv, mob->status.class_, 1) / 100;
 			job_exp = job_exp * pc_level_penalty_mod(sd, mob->lv, mob->status.class_, 1) / 100;
 		}
+#endif
+#ifdef VIP_ENABLE
+	// Display EXP and item rate increase for VIP.
+	if (pc_isvip(sd) && (battle_config.vip_base_exp_increase || battle_config.vip_job_exp_increase || battle_config.vip_drop_increase)) {
+		base_exp += battle_config.vip_base_exp_increase;
+		job_exp += battle_config.vip_job_exp_increase;
+		droprate += battle_config.vip_drop_increase;
+	}
 #endif
 		// stats
 		if (mob->mexp)
@@ -7520,6 +7528,11 @@ ACMD_FUNC(whodrops)
 #ifdef RENEWAL_DROP
 				if( battle_config.atcommand_mobinfo_type )
 					dropchance = dropchance * pc_level_penalty_mod(sd, mob_db(item_data->mob[j].id)->lv, mob_db(item_data->mob[j].id)->status.class_,  2) / 100;
+#endif
+#ifdef VIP_ENABLE
+				// Display item rate increase for VIP.
+				if (pc_isvip(sd) && battle_config.vip_drop_increase)
+					dropchance += battle_config.vip_drop_increase;
 #endif
 				sprintf(atcmd_output, "- %s (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, dropchance/100.);
 				clif_displaymessage(fd, atcmd_output);
@@ -7635,12 +7648,14 @@ ACMD_FUNC(rates)
 	nullpo_ret(sd);
 	memset(buf, '\0', sizeof(buf));
 
+#ifdef VIP_ENABLE
 	// Display EXP and item rate increase for VIP.
 	if (pc_isvip(sd) && (battle_config.vip_base_exp_increase || battle_config.vip_job_exp_increase || battle_config.vip_drop_increase)) {
 		base_exp_rate += battle_config.vip_base_exp_increase;
 		job_exp_rate += battle_config.vip_job_exp_increase;
 		item_rate += battle_config.vip_drop_increase;
 	}
+#endif
 	snprintf(buf, CHAT_SIZE_MAX, msg_txt(sd,1298), // Experience rates: Base %.2fx / Job %.2fx
 		(battle_config.base_exp_rate+base_exp_rate)/100., (battle_config.job_exp_rate+job_exp_rate)/100.);
 	clif_displaymessage(fd, buf);

+ 23 - 19
src/map/chrif.c

@@ -876,15 +876,15 @@ int chrif_changesex(struct map_session_data *sd) {
 /**
  * R 2b0f <accid>.l <name>.24B <type>.w <answer>.w
  * Processing a reply to chrif_req_login_operation() (request to modify an account).
- * NB: That ack is received just after the char as sent the request to login and therefore didn't have login reply yet
+ * NB: That ack is received just after the char has sent the request to login and therefore didn't have login reply yet
  * @param aid : player account id the request was concerning
  * @param player_name : name the request was concerning
  * @param type : code of operation done:
  *   1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: vip, 7: bank
- * @param awnser : type of anwser \n
- *   0: login-server request done \n
- *   1: player not found \n
- *   2: gm level too low \n
+ * @param answer : type of answer
+ *   0: login-server request done
+ *   1: player not found
+ *   2: gm level too low
  *   3: login-server offline
  */
 static void chrif_ack_login_req(int aid, const char* player_name, uint16 type, uint16 answer) {
@@ -901,21 +901,20 @@ static void chrif_ack_login_req(int aid, const char* player_name, uint16 type, u
 	
 	if( type > 0 && type <= 5 )
 		snprintf(action,25,"%s",msg_txt(sd,427+type)); //block|ban|unblock|unban|change the sex of
-	else if(type==6) snprintf(action,25,"%s","vip"); //TODO make some place for those type in msg_conf
-	else if(type==7){
+	else if(type == 6) snprintf(action,25,"%s",msg_txt(sd,436)); //VIP
+	else if(type == 7) {
 		if (!battle_config.disp_serverbank_msg)
 			return;
 		snprintf(action,25,"%s","bank");
-	}
-	else
+	} else
 		snprintf(action,25,"???");
 
 	switch( answer ) {
-		case 0 : sprintf(output, msg_txt(sd,424), action, NAME_LENGTH, player_name); break; //login-serv has been asked to %s the player '%.*s'.
-		case 1 : sprintf(output, msg_txt(sd,425), NAME_LENGTH, player_name); break;
-		case 2 : sprintf(output, msg_txt(sd,426), action, NAME_LENGTH, player_name); break;
-		case 3 : sprintf(output, msg_txt(sd,427), action, NAME_LENGTH, player_name); break;
-		case 4 : sprintf(output, msg_txt(sd,424), action, NAME_LENGTH, player_name); break;
+		case 0: sprintf(output, msg_txt(sd,424), action, NAME_LENGTH, player_name); break; //Login-serv has been asked to %s '%.*s'.
+		case 1: sprintf(output, msg_txt(sd,425), NAME_LENGTH, player_name); break;
+		case 2: sprintf(output, msg_txt(sd,426), action, NAME_LENGTH, player_name); break;
+		case 3: sprintf(output, msg_txt(sd,427), action, NAME_LENGTH, player_name); break;
+		case 4: sprintf(output, msg_txt(sd,424), action, NAME_LENGTH, player_name); break;
 		default: output[0] = '\0'; break;
 	}
 	clif_displaymessage(sd->fd, output);
@@ -1551,13 +1550,19 @@ void chrif_parse_ack_vipActive(int fd) {
 	int aid = RFIFOL(fd,2);
 	uint32 vip_time = RFIFOL(fd,6);
 	bool isvip = RFIFOB(fd,10);
-	uint32 groupid = RFIFOL(fd,11);
+	bool isgm = RFIFOB(fd,11);
+	uint32 groupid = RFIFOL(fd,12);
 	TBL_PC *sd = map_id2sd(aid);
 
-	if(sd == NULL) return ;
+	if(sd == NULL) return;
 
 	sd->group_id = groupid;
 	pc_group_pc_load(sd);
+
+	if(isgm) {
+		clif_displaymessage(sd->fd,msg_txt(sd,437));
+		return;
+	}
 	if(isvip) {
 		sd->vip.enabled = 1;
 		sd->vip.time = vip_time;
@@ -1570,13 +1575,12 @@ void chrif_parse_ack_vipActive(int fd) {
 		// Magic Stone requirement avoidance for VIP.
 		if (battle_config.vip_gemstone)
 			sd->special_state.no_gemstone = 2; // need to be done after status_calc_bl(bl,first);
-	}
-	else if (sd->vip.enabled){
+	} else if (sd->vip.enabled) {
 		sd->vip.enabled = 0;
 		sd->vip.time = 0;
 		sd->storage_size = MIN_STORAGE;
 		sd->special_state.no_gemstone = 0;
-		clif_displaymessage(sd->fd,"You're no longer a VIP_Member");
+		clif_displaymessage(sd->fd,msg_txt(sd,438));
 	}
 #endif
 }