Browse Source

Initial support for 2021-11-03RagexeRE (#6431)

Fixes #6415
Lemongrass3110 3 years ago
parent
commit
4bc9e24b4e

+ 1 - 0
src/char/char-server.vcxproj

@@ -177,6 +177,7 @@
     <ClInclude Include="int_pet.hpp" />
     <ClInclude Include="int_pet.hpp" />
     <ClInclude Include="int_quest.hpp" />
     <ClInclude Include="int_quest.hpp" />
     <ClInclude Include="int_storage.hpp" />
     <ClInclude Include="int_storage.hpp" />
+    <ClInclude Include="packets.hpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="char.cpp" />
     <ClCompile Include="char.cpp" />

+ 3 - 0
src/char/char-server.vcxproj.filters

@@ -65,6 +65,9 @@
     <ClInclude Include="int_clan.hpp">
     <ClInclude Include="int_clan.hpp">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="packets.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="char.cpp">
     <ClCompile Include="char.cpp">

+ 63 - 84
src/char/char.cpp

@@ -35,6 +35,7 @@
 #include "int_mercenary.hpp"
 #include "int_mercenary.hpp"
 #include "int_party.hpp"
 #include "int_party.hpp"
 #include "int_storage.hpp"
 #include "int_storage.hpp"
+#include "packets.hpp"
 
 
 //definition of exported var declared in header
 //definition of exported var declared in header
 int login_fd=-1; //login file descriptor
 int login_fd=-1; //login file descriptor
@@ -1789,113 +1790,91 @@ int char_count_users(void)
 // Writes char data to the buffer in the format used by the client.
 // Writes char data to the buffer in the format used by the client.
 // Used in packets 0x6b (chars info) and 0x6d (new char info)
 // Used in packets 0x6b (chars info) and 0x6d (new char info)
 // Returns the size
 // Returns the size
-int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
-{
-	unsigned short offset = 0;
-	uint8* buf;
-
+int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p){
 	if( buffer == NULL || p == NULL )
 	if( buffer == NULL || p == NULL )
 		return 0;
 		return 0;
 
 
-	buf = WBUFP(buffer,0);
-	WBUFL(buf,0) = p->char_id;
+	struct CHARACTER_INFO* info = (struct CHARACTER_INFO*)buffer;
+
+	info->GID = p->char_id;
 #if PACKETVER >= 20170830
 #if PACKETVER >= 20170830
-	WBUFQ(buf,4) = u64min(p->base_exp, MAX_EXP);
-	offset += 4;
-	buf = WBUFP(buffer, offset);
+	info->exp = u64min( p->base_exp, MAX_EXP );
 #else
 #else
-	WBUFL(buf,4) = (int32)u64min(p->base_exp, MAX_EXP);
+	info->exp = (int32)u64min( p->base_exp, MAX_EXP );
 #endif
 #endif
-	WBUFL(buf,8) = p->zeny;
+	info->money = p->zeny;
 #if PACKETVER >= 20170830
 #if PACKETVER >= 20170830
-	WBUFQ(buf,12) = u64min(p->job_exp, MAX_EXP);
-	offset += 4;
-	buf = WBUFP(buffer, offset);
+	info->jobexp = u64min( p->job_exp, MAX_EXP );
 #else
 #else
-	WBUFL(buf,12) = (int32)u64min(p->job_exp, MAX_EXP);
+	info->jobexp = (int32)u64min( p->job_exp, MAX_EXP );
 #endif
 #endif
-	WBUFL(buf,16) = p->job_level;
-	WBUFL(buf,20) = 0; // probably opt1
-	WBUFL(buf,24) = 0; // probably opt2
-	WBUFL(buf,28) = p->option;
-	WBUFL(buf,32) = p->karma;
-	WBUFL(buf,36) = p->manner;
-	WBUFW(buf,40) = umin(p->status_point, INT16_MAX);
-	WBUFL(buf,42) = p->hp;
-	WBUFL(buf,46) = p->max_hp;
-	offset+=4;
-	buf = WBUFP(buffer,offset);
-	WBUFW(buf,46) = min(p->sp, INT16_MAX);
-	WBUFW(buf,48) = min(p->max_sp, INT16_MAX);
-	WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed;
-	WBUFW(buf,52) = p->class_;
-	WBUFW(buf,54) = p->hair;
-
+	info->joblevel = p->job_level;
+	info->bodystate = 0; // probably opt1
+	info->healthstate = 0; // probably opt2
+	info->effectstate = p->option;
+	info->virtue = p->karma;
+	info->honor = p->manner;
+	info->jobpoint = umin( p->status_point, INT16_MAX );
+	info->hp = p->hp;
+	info->maxhp = p->max_hp;
+	info->sp = min( p->sp, INT16_MAX );
+	info->maxsp = min( p->max_sp, INT16_MAX );
+	info->speed = DEFAULT_WALK_SPEED; // p->speed;
+	info->job = p->class_;
+	info->head = p->hair;
 #if PACKETVER >= 20141022
 #if PACKETVER >= 20141022
-	WBUFW(buf,56) = p->body;
-	offset+=2;
-	buf = WBUFP(buffer,offset);
+	info->body = p->body;
 #endif
 #endif
-
 	//When the weapon is sent and your option is riding, the client crashes on login!?
 	//When the weapon is sent and your option is riding, the client crashes on login!?
-	WBUFW(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon;
-
-	WBUFW(buf,58) = p->base_level;
-	WBUFW(buf,60) = umin(p->skill_point, INT16_MAX);
-	WBUFW(buf,62) = p->head_bottom;
-	WBUFW(buf,64) = p->shield;
-	WBUFW(buf,66) = p->head_top;
-	WBUFW(buf,68) = p->head_mid;
-	WBUFW(buf,70) = p->hair_color;
-	WBUFW(buf,72) = p->clothes_color;
-	memcpy(WBUFP(buf,74), p->name, NAME_LENGTH);
-	WBUFB(buf,98) = (unsigned char)u16min(p->str, UINT8_MAX);
-	WBUFB(buf,99) = (unsigned char)u16min(p->agi, UINT8_MAX);
-	WBUFB(buf,100) = (unsigned char)u16min(p->vit, UINT8_MAX);
-	WBUFB(buf,101) = (unsigned char)u16min(p->int_, UINT8_MAX);
-	WBUFB(buf,102) = (unsigned char)u16min(p->dex, UINT8_MAX);
-	WBUFB(buf,103) = (unsigned char)u16min(p->luk, UINT8_MAX);
-	WBUFW(buf,104) = p->slot;
-	WBUFW(buf,106) = ( p->rename > 0 ) ? 0 : 1;
-	offset += 2;
+	info->weapon = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon;
+	info->level = p->base_level;
+	info->sppoint = umin( p->skill_point, INT16_MAX );
+	info->accessory = p->head_bottom;
+	info->shield = p->shield;
+	info->accessory2 = p->head_top;
+	info->accessory3 = p->head_mid;
+	info->headpalette = p->hair_color;
+	info->bodypalette = p->clothes_color;
+	safestrncpy( info->name, p->name, NAME_LENGTH );
+	info->Str = (uint8)u16min( p->str, UINT8_MAX );
+	info->Agi = (uint8)u16min( p->agi, UINT8_MAX );
+	info->Vit = (uint8)u16min( p->vit, UINT8_MAX );
+	info->Int = (uint8)u16min( p->int_, UINT8_MAX );
+	info->Dex = (uint8)u16min( p->dex, UINT8_MAX );
+	info->Luk = (uint8)u16min( p->luk, UINT8_MAX );
+	info->CharNum = p->slot;
+	info->hairColor = (uint8)u16min( p->hair_color, UINT8_MAX );
+	info->bIsChangedCharName = ( p->rename > 0 ) ? 0 : 1;
 #if (PACKETVER >= 20100720 && PACKETVER <= 20100727) || PACKETVER >= 20100803
 #if (PACKETVER >= 20100720 && PACKETVER <= 20100727) || PACKETVER >= 20100803
-	mapindex_getmapname_ext(mapindex_id2name(p->last_point.map), WBUFCP(buf,108));
-	offset += MAP_NAME_LENGTH_EXT;
+	mapindex_getmapname_ext( mapindex_id2name( p->last_point.map ), info->mapName );
 #endif
 #endif
 #if PACKETVER >= 20100803
 #if PACKETVER >= 20100803
 #if PACKETVER_CHAR_DELETEDATE
 #if PACKETVER_CHAR_DELETEDATE
-	WBUFL(buf,124) = (p->delete_date?TOL(p->delete_date-time(NULL)):0);
+	info->DelRevDate = ( p->delete_date ? TOL( p->delete_date - time( NULL ) ) : 0 );
 #else
 #else
-	WBUFL(buf,124) = TOL(p->delete_date);
+	info->DelRevDate = TOL( p->delete_date );
 #endif
 #endif
-	offset += 4;
 #endif
 #endif
 #if PACKETVER >= 20110111
 #if PACKETVER >= 20110111
-	WBUFL(buf,128) = p->robe;
-	offset += 4;
+	info->robePalette = p->robe;
 #endif
 #endif
-#if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity.
-	#if PACKETVER >= 20110928
-		// change slot feature (0 = disabled, otherwise enabled)
-		if( (charserv_config.charmove_config.char_move_enabled)==0 )
-			WBUFL(buf,132) = 0;
-		else if( charserv_config.charmove_config.char_moves_unlimited )
-			WBUFL(buf,132) = 1;
-		else
-			WBUFL(buf,132) = max( 0, (int)p->character_moves );
-		offset += 4;
-	#endif
-	#if PACKETVER >= 20111025
-		WBUFL(buf,136) = ( p->rename > 0 ) ? 1 : 0;  // (0 = disabled, otherwise displays "Add-Ons" sidebar)
-		offset += 4;
-	#endif
-	#if PACKETVER >= 20141016
-		WBUFB(buf,140) = p->sex;// sex - (0 = female, 1 = male, 99 = logindefined)
-		offset += 1;
-	#endif
+#if PACKETVER >= 20110928
+	// change slot feature (0 = disabled, otherwise enabled)
+	if( charserv_config.charmove_config.char_move_enabled == 0 )
+		info->chr_slot_changeCnt = 0;
+	else if( charserv_config.charmove_config.char_moves_unlimited )
+		info->chr_slot_changeCnt = 1;
+	else
+		info->chr_slot_changeCnt = max( 0, (int)p->character_moves );
+#endif
+#if PACKETVER >= 20111025
+	info->chr_name_changeCnt = ( p->rename > 0 ) ? 1 : 0; // (0 = disabled, otherwise displays "Add-Ons" sidebar)
+#endif
+#if PACKETVER >= 20141016
+	info->sex = p->sex; // sex - (0 = female, 1 = male, 99 = logindefined)
 #endif
 #endif
 
 
-	return 106+offset;
+	return sizeof( struct CHARACTER_INFO );
 }
 }
 
 
 
 

+ 3 - 1
src/char/char.hpp

@@ -12,6 +12,8 @@
 #include "../common/timer.hpp"
 #include "../common/timer.hpp"
 #include "../config/core.hpp"
 #include "../config/core.hpp"
 
 
+#include "packets.hpp"
+
 extern int login_fd; //login file descriptor
 extern int login_fd; //login file descriptor
 extern int char_fd; //char file descriptor
 extern int char_fd; //char file descriptor
 
 
@@ -270,7 +272,7 @@ extern struct fame_list chemist_fame_list[MAX_FAME_LIST];
 extern struct fame_list taekwon_fame_list[MAX_FAME_LIST];
 extern struct fame_list taekwon_fame_list[MAX_FAME_LIST];
 
 
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000
-#define MAX_CHAR_BUF 150 //Max size (for WFIFOHEAD calls)
+#define MAX_CHAR_BUF sizeof( struct CHARACTER_INFO ) //Max size (for WFIFOHEAD calls)
 
 
 int char_search_mapserver(unsigned short map, uint32 ip, uint16 port);
 int char_search_mapserver(unsigned short map, uint32 ip, uint16 port);
 int char_lan_subnetcheck(uint32 ip);
 int char_lan_subnetcheck(uint32 ip);

+ 5 - 4
src/char/char_clif.cpp

@@ -21,6 +21,7 @@
 #include "char_logif.hpp"
 #include "char_logif.hpp"
 #include "char_mapif.hpp"
 #include "char_mapif.hpp"
 #include "inter.hpp"
 #include "inter.hpp"
+#include "packets.hpp"
 
 
 #if PACKETVER_SUPPORTS_PINCODE
 #if PACKETVER_SUPPORTS_PINCODE
 bool pincode_allowed( char* pincode );
 bool pincode_allowed( char* pincode );
@@ -34,7 +35,7 @@ bool pincode_allowed( char* pincode );
 // 1: failed
 // 1: failed
 void chclif_moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ){
 void chclif_moveCharSlotReply( int fd, struct char_session_data* sd, unsigned short index, short reason ){
 	WFIFOHEAD(fd,8);
 	WFIFOHEAD(fd,8);
-	WFIFOW(fd,0) = 0x8d5;
+	WFIFOW(fd,0) = HEADER_HC_ACK_CHANGE_CHARACTER_SLOT;
 	WFIFOW(fd,2) = 8;
 	WFIFOW(fd,2) = 8;
 	WFIFOW(fd,4) = reason;
 	WFIFOW(fd,4) = reason;
 	WFIFOW(fd,6) = sd->char_moves[index];
 	WFIFOW(fd,6) = sd->char_moves[index];
@@ -374,7 +375,7 @@ void chclif_mmo_send099d(int fd, struct char_session_data *sd) {
 	uint8 count = 0;
 	uint8 count = 0;
 
 
 	WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
 	WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
-	WFIFOW(fd,0) = 0x99d;
+	WFIFOW(fd,0) = HEADER_HC_ACK_CHARINFO_PER_PAGE;
 	WFIFOW(fd,2) = char_mmo_chars_fromsql(sd, WFIFOP(fd,4), &count) + 4;
 	WFIFOW(fd,2) = char_mmo_chars_fromsql(sd, WFIFOP(fd,4), &count) + 4;
 	WFIFOSET(fd,WFIFOW(fd,2));
 	WFIFOSET(fd,WFIFOW(fd,2));
 
 
@@ -382,7 +383,7 @@ void chclif_mmo_send099d(int fd, struct char_session_data *sd) {
 	// The client triggers some finalization code only if count is != 3.
 	// The client triggers some finalization code only if count is != 3.
 	if( count == 3 ){
 	if( count == 3 ){
 		WFIFOHEAD(fd,4);
 		WFIFOHEAD(fd,4);
-		WFIFOW(fd,0) = 0x99d;
+		WFIFOW(fd,0) = HEADER_HC_ACK_CHARINFO_PER_PAGE;
 		WFIFOW(fd,2) = 4;
 		WFIFOW(fd,2) = 4;
 		WFIFOSET(fd,4);
 		WFIFOSET(fd,4);
 	}
 	}
@@ -1050,7 +1051,7 @@ int chclif_parse_createnewchar(int fd, struct char_session_data* sd,int cmd){
 
 
 		// send to player
 		// send to player
 		WFIFOHEAD(fd,2+MAX_CHAR_BUF);
 		WFIFOHEAD(fd,2+MAX_CHAR_BUF);
-		WFIFOW(fd,0) = 0x6d;
+		WFIFOW(fd,0) = HEADER_HC_ACCEPT_MAKECHAR;
 		len = 2 + char_mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
 		len = 2 + char_mmo_char_tobuf(WFIFOP(fd,2), &char_dat);
 		WFIFOSET(fd,len);
 		WFIFOSET(fd,len);
 
 

+ 120 - 0
src/char/packets.hpp

@@ -0,0 +1,120 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef PACKETS_HPP
+#define PACKETS_HPP
+
+#include "../common/mmo.hpp"
+
+#pragma warning( push )
+#pragma warning( disable : 4200 )
+
+// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
+	#pragma pack( push, 1 )
+#endif
+
+struct CHARACTER_INFO{
+	uint32 GID;
+#if PACKETVER >= 20170830
+	int64 exp;
+#else
+	int32 exp;
+#endif
+	int32 money;
+#if PACKETVER >= 20170830
+	int64 jobexp;
+#else
+	int32 jobexp;
+#endif
+	int32 joblevel;
+	int32 bodystate;
+	int32 healthstate;
+	int32 effectstate;
+	int32 virtue;
+	int32 honor;
+	int16 jobpoint;
+#if PACKETVER_RE_NUM >= 20211103
+	int64 hp;
+	int64 maxhp;
+	int64 sp;
+	int64 maxsp;
+#else
+	int32 hp;
+	int32 maxhp;
+	int16 sp;
+	int16 maxsp;
+#endif
+	int16 speed;
+	int16 job;
+	int16 head;
+#if PACKETVER >= 20141022
+	int16 body;
+#endif
+	int16 weapon;
+	int16 level;
+	int16 sppoint;
+	int16 accessory;
+	int16 shield;
+	int16 accessory2;
+	int16 accessory3;
+	int16 headpalette;
+	int16 bodypalette;
+	char name[24];
+	uint8 Str;
+	uint8 Agi;
+	uint8 Vit;
+	uint8 Int;
+	uint8 Dex;
+	uint8 Luk;
+	uint8 CharNum;
+	uint8 hairColor;
+	int16 bIsChangedCharName;
+#if (PACKETVER >= 20100720 && PACKETVER <= 20100727) || PACKETVER >= 20100803
+	char mapName[16];
+#endif
+#if PACKETVER >= 20100803
+	int32 DelRevDate;
+#endif
+#if PACKETVER >= 20110111
+	int32 robePalette;
+#endif
+#if PACKETVER >= 20110928
+	int32 chr_slot_changeCnt;
+#endif
+#if PACKETVER >= 20111025
+	int32 chr_name_changeCnt;
+#endif
+#if PACKETVER >= 20141016
+	uint8 sex;
+#endif
+} __attribute__((packed));
+
+#define DEFINE_PACKET_HEADER(name, id) const int16 HEADER_##name = id;
+
+#if PACKETVER_MAIN_NUM >= 20201007 || PACKETVER_RE_NUM >= 20211103
+	DEFINE_PACKET_HEADER( HC_ACK_CHANGE_CHARACTER_SLOT, 0xb70 )
+#else
+	DEFINE_PACKET_HEADER( HC_ACK_CHANGE_CHARACTER_SLOT, 0x8d5 )
+#endif
+#if PACKETVER_MAIN_NUM >= 20201007 || PACKETVER_RE_NUM >= 20211103
+	DEFINE_PACKET_HEADER( HC_ACK_CHARINFO_PER_PAGE, 0xb72 )
+#else
+	DEFINE_PACKET_HEADER( HC_ACK_CHARINFO_PER_PAGE, 0x99d )
+#endif
+#if PACKETVER_MAIN_NUM >= 20201007 || PACKETVER_RE_NUM >= 20211103
+	DEFINE_PACKET_HEADER( HC_ACCEPT_MAKECHAR, 0xb6f )
+#else
+	DEFINE_PACKET_HEADER( HC_ACCEPT_MAKECHAR, 0x6d )
+#endif
+
+#undef DEFINE_PACKET_HEADER
+
+// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
+	#pragma pack( pop )
+#endif
+
+#pragma warning( pop )
+
+#endif /* PACKETS_HPP */

+ 1 - 1
src/config/packets.hpp

@@ -13,7 +13,7 @@
 	/// Do NOT edit this line! To set your client version, please do this instead:
 	/// Do NOT edit this line! To set your client version, please do this instead:
 	/// In Windows: Add this line in your src\custom\defines_pre.hpp file: #define PACKETVER YYYYMMDD
 	/// In Windows: Add this line in your src\custom\defines_pre.hpp file: #define PACKETVER YYYYMMDD
 	/// In Linux: The same as above or run the following command: ./configure --enable-packetver=YYYYMMDD
 	/// In Linux: The same as above or run the following command: ./configure --enable-packetver=YYYYMMDD
-	#define PACKETVER 20200902
+	#define PACKETVER 20211103
 #endif
 #endif
 
 
 #ifndef PACKETVER_RE
 #ifndef PACKETVER_RE

+ 62 - 2
src/map/clif.cpp

@@ -1799,8 +1799,13 @@ void clif_hominfo( struct map_session_data *sd, struct homun_data *hd, int flag
 		p.sp = status->sp;
 		p.sp = status->sp;
 		p.maxSp = status->max_sp;
 		p.maxSp = status->max_sp;
 	}
 	}
+#if PACKETVER_MAIN_NUM >= 20210303 || PACKETVER_RE_NUM >= 20211103
+	p.exp = hd->homunculus.exp;
+	p.expNext = hd->exp_next;
+#else
 	p.exp = (uint32)hd->homunculus.exp;
 	p.exp = (uint32)hd->homunculus.exp;
 	p.expNext = (uint32)hd->exp_next;
 	p.expNext = (uint32)hd->exp_next;
+#endif
 	switch( hom_class2type( hd->homunculus.class_ ) ){
 	switch( hom_class2type( hd->homunculus.class_ ) ){
 		case HT_REG:
 		case HT_REG:
 		case HT_EVO:
 		case HT_EVO:
@@ -2175,7 +2180,7 @@ void clif_buylist( struct map_session_data *sd, struct npc_data *nd ){
 	uint16 len = sizeof( struct PACKET_ZC_PC_PURCHASE_ITEMLIST ) + nd->u.shop.count * sizeof( struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub );
 	uint16 len = sizeof( struct PACKET_ZC_PC_PURCHASE_ITEMLIST ) + nd->u.shop.count * sizeof( struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub );
 	WFIFOHEAD( fd, len );
 	WFIFOHEAD( fd, len );
 	struct PACKET_ZC_PC_PURCHASE_ITEMLIST *p = (struct PACKET_ZC_PC_PURCHASE_ITEMLIST *)WFIFOP( fd, 0 );
 	struct PACKET_ZC_PC_PURCHASE_ITEMLIST *p = (struct PACKET_ZC_PC_PURCHASE_ITEMLIST *)WFIFOP( fd, 0 );
-	p->packetType = 0xc6;
+	p->packetType = HEADER_ZC_PC_PURCHASE_ITEMLIST;
 
 
 	int count = 0;
 	int count = 0;
 	for( int i = 0, discount = npc_shop_discount( nd ); i < nd->u.shop.count; i++ ){
 	for( int i = 0, discount = npc_shop_discount( nd ); i < nd->u.shop.count; i++ ){
@@ -2185,6 +2190,12 @@ void clif_buylist( struct map_session_data *sd, struct npc_data *nd ){
 		p->items[count].discountPrice = ( discount ) ? pc_modifybuyvalue( sd, val ) : val;
 		p->items[count].discountPrice = ( discount ) ? pc_modifybuyvalue( sd, val ) : val;
 		p->items[count].itemType = itemtype( nd->u.shop.shop_item[i].nameid );
 		p->items[count].itemType = itemtype( nd->u.shop.shop_item[i].nameid );
 		p->items[count].itemId = client_nameid( nd->u.shop.shop_item[i].nameid );
 		p->items[count].itemId = client_nameid( nd->u.shop.shop_item[i].nameid );
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
+		struct item_data* id = itemdb_exists( nd->u.shop.shop_item[i].nameid );
+
+		p->items[count].viewSprite = id->look;
+		p->items[count].location = pc_equippoint_sub( sd, id );
+#endif
 		count++;
 		count++;
 	}
 	}
 
 
@@ -2277,6 +2288,9 @@ void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
 		p->list[count].price = item->value;
 		p->list[count].price = item->value;
 		p->list[count].qty = item->qty;
 		p->list[count].qty = item->qty;
 		p->list[count].weight = id->weight;
 		p->list[count].weight = id->weight;
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
+		p->list[count].location = pc_equippoint_sub( sd, id );
+#endif
 		count++;
 		count++;
 	}
 	}
 
 
@@ -16352,15 +16366,22 @@ void clif_Mail_Receiver_Ack( struct map_session_data* sd, uint32 char_id, short
 /// Request information about the recipient
 /// Request information about the recipient
 /// 0a13 <name>.24B (CZ_CHECK_RECEIVE_CHARACTER_NAME)
 /// 0a13 <name>.24B (CZ_CHECK_RECEIVE_CHARACTER_NAME)
 void clif_parse_Mail_Receiver_Check(int fd, struct map_session_data *sd) {
 void clif_parse_Mail_Receiver_Check(int fd, struct map_session_data *sd) {
+#if PACKETVER >= 20140423
+#if PACKETVER_MAIN_NUM >= 20201104 || PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20201118
+	struct PACKET_CZ_CHECKNAME2* p = (struct PACKET_CZ_CHECKNAME2*)RFIFOP( fd, 0 );
+#else
+	struct PACKET_CZ_CHECKNAME1* p = (struct PACKET_CZ_CHECKNAME1*)RFIFOP( fd, 0 );
+#endif
 	static char name[NAME_LENGTH];
 	static char name[NAME_LENGTH];
 
 
 	if( mail_invalid_operation( sd ) ){
 	if( mail_invalid_operation( sd ) ){
 		return;
 		return;
 	}
 	}
 
 
-	safestrncpy(name, RFIFOCP(fd, 2), NAME_LENGTH);
+	safestrncpy(name, p->Name, NAME_LENGTH);
 
 
 	intif_mail_checkreceiver(sd, name);
 	intif_mail_checkreceiver(sd, name);
+#endif
 }
 }
 
 
 /// Request to receive mail's attachment.
 /// Request to receive mail's attachment.
@@ -16518,7 +16539,18 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd){
 /// Request to return a mail (CZ_REQ_MAIL_RETURN).
 /// Request to return a mail (CZ_REQ_MAIL_RETURN).
 /// 0273 <mail id>.L <receive name>.24B
 /// 0273 <mail id>.L <receive name>.24B
 void clif_parse_Mail_return(int fd, struct map_session_data *sd){
 void clif_parse_Mail_return(int fd, struct map_session_data *sd){
+#if PACKETVER_MAIN_NUM >= 20201104 || PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20201118
+	struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN* p = (struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN*)RFIFOP( fd, 0 );
+
+	//ShowDump( p, sizeof( p ) );
+
+	int mail_id = p->msgId;
+
+	// not supported for now
+	return;
+#else
 	int mail_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
 	int mail_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
+#endif
 	//char *rec_name = RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[1]);
 	//char *rec_name = RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[1]);
 	int i;
 	int i;
 
 
@@ -22304,6 +22336,34 @@ void clif_parse_refineui_refine( int fd, struct map_session_data* sd ){
 #endif
 #endif
 }
 }
 
 
+void clif_unequipall_reply( struct map_session_data* sd, bool failed ){
+#if PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103
+	struct PACKET_ZC_TAKEOFF_EQUIP_ALL_ACK p = {};
+
+	p.PacketType = HEADER_ZC_TAKEOFF_EQUIP_ALL_ACK;
+	p.result = failed;
+
+	clif_send( &p, sizeof( struct PACKET_ZC_TAKEOFF_EQUIP_ALL_ACK ), &sd->bl, SELF );
+#endif  // PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103
+}
+
+void clif_parse_unequipall( int fd, struct map_session_data* sd ){
+#if PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818
+	if( pc_cant_act( sd ) ){
+		clif_unequipall_reply( sd, true );
+		return;
+	}
+
+	for( int i = 0; i < EQI_COSTUME_HEAD_TOP; i++ ){
+		if( sd->equip_index[i] >= 0 ){
+			pc_unequipitem( sd, sd->equip_index[i], 1 );
+		}
+	}
+
+	clif_unequipall_reply( sd, false );
+#endif
+}
+
 /*==========================================
 /*==========================================
  * Main client packet processing function
  * Main client packet processing function
  *------------------------------------------*/
  *------------------------------------------*/

+ 7 - 0
src/map/clif_packetdb.hpp

@@ -2435,4 +2435,11 @@
 	parseable_packet( HEADER_CZ_UNCONFIRMED_TSTATUS_UP, sizeof( PACKET_CZ_UNCONFIRMED_TSTATUS_UP ), clif_parse_traitstatus_up, 0 );
 	parseable_packet( HEADER_CZ_UNCONFIRMED_TSTATUS_UP, sizeof( PACKET_CZ_UNCONFIRMED_TSTATUS_UP ), clif_parse_traitstatus_up, 0 );
 #endif
 #endif
 
 
+#if PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818
+	parseable_packet( HEADER_CZ_CHECKNAME2, sizeof( struct PACKET_CZ_CHECKNAME2 ), clif_parse_Mail_Receiver_Check, 0 );
+	parseable_packet( HEADER_CZ_UNCONFIRMED_RODEX_RETURN, sizeof( struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN ), clif_parse_Mail_return, 0 );
+	parseable_packet( HEADER_CZ_REQ_TAKEOFF_EQUIP_ALL, sizeof( struct PACKET_CZ_REQ_TAKEOFF_EQUIP_ALL ), clif_parse_unequipall, 0 );
+	parseable_packet( 0xb93, 12, clif_parse_dull, 0 );
+#endif
+
 #endif /* CLIF_PACKETDB_HPP */
 #endif /* CLIF_PACKETDB_HPP */

+ 5 - 1
src/map/clif_shuffle.hpp

@@ -4741,7 +4741,11 @@
 #endif
 #endif
 	parseable_packet(0x0368,6,clif_parse_GetCharNameRequest,2);
 	parseable_packet(0x0368,6,clif_parse_GetCharNameRequest,2);
 	parseable_packet(0x0369,6,clif_parse_SolveCharName,2);
 	parseable_packet(0x0369,6,clif_parse_SolveCharName,2);
-	parseable_packet(0x0436,19,clif_parse_WantToConnection,2,6,10,14,18);
+#if PACKETVER_RE_NUM >= 20211103
+	parseable_packet( 0x0436, 23, clif_parse_WantToConnection, 2, 6, 10, 14, 22 );
+#else
+	parseable_packet( 0x0436, 19, clif_parse_WantToConnection, 2, 6, 10, 14, 18 );
+#endif
 	parseable_packet(0x0437,7,clif_parse_ActionRequest,2,6);
 	parseable_packet(0x0437,7,clif_parse_ActionRequest,2,6);
 	parseable_packet(0x0438,10,clif_parse_UseSkillToId,2,4,6);
 	parseable_packet(0x0438,10,clif_parse_UseSkillToId,2,4,6);
 	parseable_packet(0x07E4,-1,clif_parse_ItemListWindowSelected,2,4,8,12);
 	parseable_packet(0x07E4,-1,clif_parse_ItemListWindowSelected,2,4,8,12);

+ 6 - 0
src/map/packets.hpp

@@ -217,6 +217,11 @@ struct PACKET_ZC_ENTRY_QUEUE_INIT {
 	int16 packetType;
 	int16 packetType;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
+struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN{
+	int16 packetType;
+	uint32 msgId;
+} __attribute__((packed));
+
 // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
 #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
 	#pragma pack( pop )
 	#pragma pack( pop )
@@ -274,6 +279,7 @@ DEFINE_PACKET_HEADER(ZC_REMOVE_EFFECT, 0x0b0d)
 DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
 DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
 DEFINE_PACKET_HEADER(CZ_GUILD_EMBLEM_CHANGE2, 0x0b46)
 DEFINE_PACKET_HEADER(CZ_GUILD_EMBLEM_CHANGE2, 0x0b46)
 DEFINE_PACKET_HEADER(ZC_UNCONFIRMED_SPIRITS3, 0xb73)
 DEFINE_PACKET_HEADER(ZC_UNCONFIRMED_SPIRITS3, 0xb73)
+DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_RODEX_RETURN, 0xb98)
 
 
 const int16 MAX_INVENTORY_ITEM_PACKET_NORMAL = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_normal ) - ( sizeof( struct NORMALITEM_INFO ) * MAX_ITEMLIST) ) ) / sizeof( struct NORMALITEM_INFO ) );
 const int16 MAX_INVENTORY_ITEM_PACKET_NORMAL = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_normal ) - ( sizeof( struct NORMALITEM_INFO ) * MAX_ITEMLIST) ) ) / sizeof( struct NORMALITEM_INFO ) );
 const int16 MAX_INVENTORY_ITEM_PACKET_EQUIP = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_equip ) - ( sizeof( struct EQUIPITEM_INFO ) * MAX_ITEMLIST ) ) ) / sizeof( struct EQUIPITEM_INFO ) );
 const int16 MAX_INVENTORY_ITEM_PACKET_EQUIP = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_equip ) - ( sizeof( struct EQUIPITEM_INFO ) * MAX_ITEMLIST ) ) ) / sizeof( struct EQUIPITEM_INFO ) );

+ 193 - 14
src/map/packets_struct.hpp

@@ -1389,7 +1389,26 @@ struct packet_npc_market_purchase {
 	struct packet_npc_market_purchase_sub list[];
 	struct packet_npc_market_purchase_sub list[];
 } __attribute__((packed));
 } __attribute__((packed));
 
 
-#if PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20131106 || defined(PACKETVER_ZERO)
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
+struct PACKET_ZC_NPC_MARKET_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 nameid;
+#else
+	uint16 nameid;
+#endif
+	uint8 type;
+	uint32 price;
+	uint32 qty;
+	uint16 weight;
+	uint32 location;
+} __attribute__((packed));
+struct PACKET_ZC_NPC_MARKET_OPEN {
+	int16 packetType;
+	int16 packetLength;
+	struct PACKET_ZC_NPC_MARKET_OPEN_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_MARKET_OPEN, 0x0b7a);
+#elif PACKETVER_MAIN_NUM >= 20131120 || PACKETVER_RE_NUM >= 20131106 || defined(PACKETVER_ZERO)
 /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
 /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
 struct PACKET_ZC_NPC_MARKET_OPEN_sub {
 struct PACKET_ZC_NPC_MARKET_OPEN_sub {
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
@@ -1402,13 +1421,11 @@ struct PACKET_ZC_NPC_MARKET_OPEN_sub {
 	uint32 qty;
 	uint32 qty;
 	uint16 weight;
 	uint16 weight;
 } __attribute__((packed));
 } __attribute__((packed));
-
 struct PACKET_ZC_NPC_MARKET_OPEN {
 struct PACKET_ZC_NPC_MARKET_OPEN {
 	int16 packetType;
 	int16 packetType;
 	int16 packetLength;
 	int16 packetLength;
 	struct PACKET_ZC_NPC_MARKET_OPEN_sub list[];
 	struct PACKET_ZC_NPC_MARKET_OPEN_sub list[];
 } __attribute__((packed));
 } __attribute__((packed));
-
 DEFINE_PACKET_HEADER(ZC_NPC_MARKET_OPEN, 0x09d5);
 DEFINE_PACKET_HEADER(ZC_NPC_MARKET_OPEN, 0x09d5);
 #endif
 #endif
 
 
@@ -1681,10 +1698,22 @@ struct PACKET_ZC_WRITE_MAIL_RESULT {
 	int8 result;
 	int8 result;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
-struct PACKET_CZ_CHECKNAME {
+#if PACKETVER >= 20140423
+struct PACKET_CZ_CHECKNAME1 {
 	int16 PacketType;
 	int16 PacketType;
 	char Name[24];
 	char Name[24];
 } __attribute__((packed));
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CHECKNAME1, 0x0a13)
+#endif  // PACKETVER >= 20140423
+
+#if PACKETVER_MAIN_NUM >= 20201104 || PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20201118
+struct PACKET_CZ_CHECKNAME2 {
+	int16 PacketType;
+	char Name[24];
+	char own_char;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_CHECKNAME2, 0x0b97)
+#endif  // PACKETVER_MAIN_NUM >= 20201104 || PACKETVER_ZERO_NUM >= 20201118
 
 
 struct PACKET_ZC_CHECKNAME {
 struct PACKET_ZC_CHECKNAME {
 	int16 PacketType;
 	int16 PacketType;
@@ -2375,7 +2404,63 @@ struct PACKET_ZC_ACK_WEAPONREFINE {
 #endif
 #endif
 } __attribute__((packed));
 } __attribute__((packed));
 
 
-#if PACKETVER_MAIN_NUM >= 20190619 || PACKETVER_RE_NUM >= 20190605 || PACKETVER_ZERO_NUM >= 20190626
+#if PACKETVER_MAIN_NUM >= 20210303 || PACKETVER_RE_NUM >= 20211103
+// PACKET_ZC_PROPERTY_HOMUN4
+struct PACKET_ZC_PROPERTY_HOMUN {
+	int16 packetType;
+	char name[NAME_LENGTH];
+	// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
+	uint8 flags;
+	uint16 level;
+	uint16 hunger;
+	uint16 intimacy;
+	uint16 atk2;
+	uint16 matk;
+	uint16 hit;
+	uint16 crit;
+	uint16 def;
+	uint16 mdef;
+	uint16 flee;
+	uint16 amotion;
+	uint32 hp;
+	uint32 maxHp;
+	uint32 sp;
+	uint32 maxSp;
+	int64 exp;
+	int64 expNext;
+	uint16 skillPoints;
+	uint16 range;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PROPERTY_HOMUN, 0x0ba4);
+#elif PACKETVER_MAIN_NUM >= 20200819 || PACKETVER_RE_NUM >= 20200723
+// PACKET_ZC_PROPERTY_HOMUN3
+struct PACKET_ZC_PROPERTY_HOMUN {
+	int16 packetType;
+	char name[NAME_LENGTH];
+	// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
+	uint8 flags;
+	uint16 level;
+	uint16 hunger;
+	uint16 intimacy;
+	uint16 atk2;
+	uint16 matk;
+	uint16 hit;
+	uint16 crit;
+	uint16 def;
+	uint16 mdef;
+	uint16 flee;
+	uint16 amotion;
+	uint32 hp;
+	uint32 maxHp;
+	uint32 sp;
+	uint32 maxSp;
+	uint32 exp;
+	uint32 expNext;
+	uint16 skillPoints;
+	uint16 range;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PROPERTY_HOMUN, 0x0b76);
+#elif PACKETVER_MAIN_NUM >= 20190619 || PACKETVER_RE_NUM >= 20190605 || PACKETVER_ZERO_NUM >= 20190626
 // PACKET_ZC_PROPERTY_HOMUN3
 // PACKET_ZC_PROPERTY_HOMUN3
 struct PACKET_ZC_PROPERTY_HOMUN {
 struct PACKET_ZC_PROPERTY_HOMUN {
 	int16 packetType;
 	int16 packetType;
@@ -2573,6 +2658,26 @@ struct PACKET_ZC_PC_PURCHASE_MYITEMLIST {
 	struct PACKET_ZC_PC_PURCHASE_MYITEMLIST_sub items[];
 	struct PACKET_ZC_PC_PURCHASE_MYITEMLIST_sub items[];
 } __attribute__((packed));
 } __attribute__((packed));
 
 
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 itemId;
+#else
+	uint16 itemId;
+#endif
+	uint32 price;
+	uint32 discountPrice;
+	uint8 itemType;
+	uint16 viewSprite;
+	uint32 location;
+} __attribute__((packed));
+struct PACKET_ZC_PC_PURCHASE_ITEMLIST {
+	int16 packetType;
+	int16 packetLength;
+	struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PC_PURCHASE_ITEMLIST, 0x0b77)
+#else  // PACKETVER_MAIN_NUM >= 20210203
 struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub {
 struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub {
 	uint32 price;
 	uint32 price;
 	uint32 discountPrice;
 	uint32 discountPrice;
@@ -2583,12 +2688,13 @@ struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub {
 	uint16 itemId;
 	uint16 itemId;
 #endif
 #endif
 } __attribute__((packed));
 } __attribute__((packed));
-
 struct PACKET_ZC_PC_PURCHASE_ITEMLIST {
 struct PACKET_ZC_PC_PURCHASE_ITEMLIST {
 	int16 packetType;
 	int16 packetType;
 	int16 packetLength;
 	int16 packetLength;
 	struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub items[];
 	struct PACKET_ZC_PC_PURCHASE_ITEMLIST_sub items[];
 } __attribute__((packed));
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PC_PURCHASE_ITEMLIST, 0x00c6)
+#endif
 
 
 struct PACKET_CZ_PC_PURCHASE_ITEMLIST_sub {
 struct PACKET_CZ_PC_PURCHASE_ITEMLIST_sub {
 	uint16 amount;
 	uint16 amount;
@@ -3245,7 +3351,33 @@ struct PACKET_CZ_PARTY_CONFIG {
 } __attribute__((packed));
 } __attribute__((packed));
 DEFINE_PACKET_HEADER(CZ_PARTY_CONFIG, 0x02c8);
 DEFINE_PACKET_HEADER(CZ_PARTY_CONFIG, 0x02c8);
 
 
-#if PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
+struct PACKET_ZC_NPC_BARTER_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 nameid;
+#else
+	uint16 nameid;
+#endif
+	uint8 type;
+	uint32 amount;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 currencyNameid;
+#else
+	uint16 currencyNameid;
+#endif
+	uint32 currencyAmount;
+	uint32 weight;
+	uint32 index;
+	uint16 viewSprite;
+	uint32 location;
+} __attribute__((packed));
+struct PACKET_ZC_NPC_BARTER_OPEN {
+	int16 packetType;
+	int16 packetLength;
+	struct PACKET_ZC_NPC_BARTER_OPEN_sub list[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_BARTER_OPEN, 0x0b78);
+#elif PACKETVER_MAIN_NUM >= 20190116 || PACKETVER_RE_NUM >= 20190116 || PACKETVER_ZERO_NUM >= 20181226
 struct PACKET_ZC_NPC_BARTER_OPEN_sub {
 struct PACKET_ZC_NPC_BARTER_OPEN_sub {
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
 	uint32 nameid;
 	uint32 nameid;
@@ -3263,13 +3395,11 @@ struct PACKET_ZC_NPC_BARTER_OPEN_sub {
 	uint32 weight;
 	uint32 weight;
 	uint32 index;
 	uint32 index;
 } __attribute__((packed));
 } __attribute__((packed));
-
 struct PACKET_ZC_NPC_BARTER_OPEN {
 struct PACKET_ZC_NPC_BARTER_OPEN {
 	int16 packetType;
 	int16 packetType;
 	int16 packetLength;
 	int16 packetLength;
 	struct PACKET_ZC_NPC_BARTER_OPEN_sub list[];
 	struct PACKET_ZC_NPC_BARTER_OPEN_sub list[];
 } __attribute__((packed));
 } __attribute__((packed));
-
 DEFINE_PACKET_HEADER(ZC_NPC_BARTER_OPEN, 0x0b0e);
 DEFINE_PACKET_HEADER(ZC_NPC_BARTER_OPEN, 0x0b0e);
 #endif
 #endif
 
 
@@ -3883,7 +4013,7 @@ struct PACKET_CZ_NPC_EXPANDED_BARTER_CLOSE {
 DEFINE_PACKET_HEADER(CZ_NPC_EXPANDED_BARTER_CLOSE, 0x0b58);
 DEFINE_PACKET_HEADER(CZ_NPC_EXPANDED_BARTER_CLOSE, 0x0b58);
 #endif
 #endif
 
 
-#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
+#if PACKETVER_MAIN_NUM >= 20210203 || PACKETVER_RE_NUM >= 20211103
 struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 {
 struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 {
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
 	uint32 nameid;
 	uint32 nameid;
@@ -3906,13 +4036,47 @@ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub {
 	uint32 weight;
 	uint32 weight;
 	uint32 index;
 	uint32 index;
 	uint32 zeny;
 	uint32 zeny;
+	uint16 viewSprite;
+	uint32 location;
 	uint32 currency_count;
 	uint32 currency_count;
-#if defined(_MSC_VER)
-	// Workaround for fix Visual Studio bug (error C2233). Here should be currencies[]
+	// Workaround: this should be currencies[], but compilers do not support multiple layers of incomplete types. See error C2233
 	struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[1];
 	struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[1];
+} __attribute__((packed));
+
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
+	int16 packetType;
+	int16 packetLength;
+	int32 items_count;
+	struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub items[];
+} __attribute__((packed));
+
+DEFINE_PACKET_HEADER(ZC_NPC_EXPANDED_BARTER_OPEN, 0x0b79);
+#elif PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 nameid;
+#else
+	uint16 nameid;
+#endif
+	uint16 refine_level;
+	uint32 amount;
+	uint16 type;
+} __attribute__((packed));
+
+struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub {
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+	uint32 nameid;
 #else
 #else
-	struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[];
+	uint16 nameid;
 #endif
 #endif
+	uint16 type;
+	uint32 amount;
+	uint32 weight;
+	uint32 index;
+	uint32 zeny;
+	uint32 currency_count;
+	// Workaround: this should be currencies[], but compilers do not support multiple layers of incomplete types. See error C2233
+	struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[1];
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
 struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
@@ -3923,7 +4087,7 @@ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
 } __attribute__((packed));
 } __attribute__((packed));
 
 
 DEFINE_PACKET_HEADER(ZC_NPC_EXPANDED_BARTER_OPEN, 0x0b56);
 DEFINE_PACKET_HEADER(ZC_NPC_EXPANDED_BARTER_OPEN, 0x0b56);
-#endif
+#endif  // PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
 
 
 #if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
 #if PACKETVER_MAIN_NUM >= 20190904 || PACKETVER_RE_NUM >= 20190904 || PACKETVER_ZERO_NUM >= 20190828
 struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE_sub {
 struct PACKET_CZ_NPC_EXPANDED_BARTER_PURCHASE_sub {
@@ -4130,6 +4294,21 @@ struct PACKET_ZC_NOTIFY_SKILL_POSITION {
 };
 };
 DEFINE_PACKET_HEADER(ZC_NOTIFY_SKILL_POSITION, 0x0115);
 DEFINE_PACKET_HEADER(ZC_NOTIFY_SKILL_POSITION, 0x0115);
 
 
+#if PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818
+struct PACKET_CZ_REQ_TAKEOFF_EQUIP_ALL {
+	int16 PacketType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_TAKEOFF_EQUIP_ALL, 0x0bad);
+#endif  // PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818
+
+#if PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103
+struct PACKET_ZC_TAKEOFF_EQUIP_ALL_ACK {
+	int16 PacketType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_TAKEOFF_EQUIP_ALL_ACK, 0x0bae);
+#endif  // PACKETVER_MAIN_NUM >= 20210818 || PACKETVER_RE_NUM >= 20211103
+
 #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #pragma pack(pop)
 #pragma pack(pop)
 #endif // not NetBSD < 6 / Solaris
 #endif // not NetBSD < 6 / Solaris