Added support for clients up to 2018-03-07bRagexeRE (#2975)

Thanks to @4144 as always
Credits to @dastgir and the leaked 2015 dump for the quest packets
Thanks to @idamonli for testing and feedback
This commit is contained in:
Lemongrass3110 2018-03-14 23:05:01 +01:00 committed by GitHub
parent c1b9ee8694
commit f338d53c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 227 additions and 31 deletions

View File

@ -2064,10 +2064,14 @@ int char_loadName(uint32 char_id, char* name){
safestrncpy(name, data, NAME_LENGTH);
return 1;
}
#if PACKETVER < 20180221
else
{
safestrncpy(name, charserv_config.char_config.unknown_char_name, NAME_LENGTH);
}
#else
name[0] = '\0';
#endif
return 0;
}

View File

@ -6509,13 +6509,23 @@ void clif_wis_end(int fd, int result)
/// Returns character name requested by char_id (ZC_ACK_REQNAME_BYGID).
/// 0194 <char id>.L <name>.24B
/// 0af7 <flag>.W <char id>.L <name>.24B
void clif_solved_charname(int fd, int charid, const char* name)
{
#if PACKETVER >= 20180221
WFIFOHEAD(fd,packet_len(0xaf7));
WFIFOW(fd,0) = 0xaf7;
WFIFOW(fd,2) = name[0] ? 3 : 2;
WFIFOL(fd,4) = charid;
safestrncpy(WFIFOCP(fd, 8), name, NAME_LENGTH);
WFIFOSET(fd,packet_len(0x0af7));
#else
WFIFOHEAD(fd,packet_len(0x194));
WFIFOW(fd,0)=0x194;
WFIFOL(fd,2)=charid;
safestrncpy(WFIFOCP(fd,6), name, NAME_LENGTH);
WFIFOSET(fd,packet_len(0x194));
#endif
}
@ -12278,6 +12288,7 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
/// Request to use a ground skill.
/// 0116 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND)
/// 0366 <skill lv>.W <skill id>.W <x>.W <y>.W (CZ_USE_SKILL_TOGROUND2)
/// 0AF4 <skill lv>.W <skill id>.W <x>.W <y>.W <unknown>.B (CZ_USE_SKILL_TOGROUND3)
/// There are various variants of this packet, some of them have padding between fields.
void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
{
@ -12292,6 +12303,8 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
RFIFOW(fd,info->pos[1]), //skill num
RFIFOW(fd,info->pos[2]), //pos x
RFIFOW(fd,info->pos[3]), //pos y
// TODO: find out what this is intended to do
//RFIFOB(fd, info->pos[4])
-1 //Skill more info.
);
}
@ -14303,6 +14316,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
/// Toggles a single friend online/offline [Skotlex] (ZC_FRIENDS_STATE).
/// 0206 <account id>.L <char id>.L <state>.B
/// 0206 <account id>.L <char id>.L <state>.B <name>.24B >= 20180221
/// state:
/// 0 = online
/// 1 = offline
@ -14322,6 +14336,9 @@ void clif_friendslist_toggle(struct map_session_data *sd,uint32 account_id, uint
WFIFOL(fd, 2) = sd->status.friends[i].account_id;
WFIFOL(fd, 6) = sd->status.friends[i].char_id;
WFIFOB(fd,10) = !online; //Yeah, a 1 here means "logged off", go figure...
#if PACKETVER >= 20180221
safestrncpy(WFIFOCP(fd, 11), sd->status.friends[i].name, NAME_LENGTH);
#endif
WFIFOSET(fd, packet_len(0x206));
}
@ -14340,21 +14357,29 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap)
/// Sends the whole friends list (ZC_FRIENDS_LIST).
/// 0201 <packet len>.W { <account id>.L <char id>.L <name>.24B }*
/// 0201 <packet len>.W { <account id>.L <char id>.L }* >= 20180221
void clif_friendslist_send(struct map_session_data *sd)
{
int i = 0, n, fd = sd->fd;
#if PACKETVER >= 20180221
const int size = 8;
#else
const int size = 8 + NAME_LENGTH;
#endif
// Send friends list
WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4);
WFIFOHEAD(fd, MAX_FRIENDS * size + 4);
WFIFOW(fd, 0) = 0x201;
for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) {
WFIFOL(fd, 4 + 32 * i + 0) = sd->status.friends[i].account_id;
WFIFOL(fd, 4 + 32 * i + 4) = sd->status.friends[i].char_id;
safestrncpy(WFIFOCP(fd, 4 + 32 * i + 8), sd->status.friends[i].name, NAME_LENGTH);
WFIFOL(fd, 4 + size * i + 0) = sd->status.friends[i].account_id;
WFIFOL(fd, 4 + size * i + 4) = sd->status.friends[i].char_id;
#if PACKETVER < 20180221
safestrncpy(WFIFOCP(fd, 4 + size * i + 8), sd->status.friends[i].name, NAME_LENGTH);
#endif
}
if (i) {
WFIFOW(fd,2) = 4 + 32 * i;
WFIFOW(fd,2) = 4 + size * i;
WFIFOSET(fd, WFIFOW(fd,2));
}
@ -16561,10 +16586,10 @@ static void clif_quest_len(int def_len, int info_len, int avail_quests, int *lim
(*len_out) = ((*limit_out) * info_len) + def_len;
}
/// Sends list of all quest states (ZC_ALL_QUEST_LIST).
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num
/// Sends list of all quest states
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num (ZC_ALL_QUEST_LIST)
/// 097a <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <mob_id>.L <killed>.W <total>.W <mob name>.24B }*count }*num (ZC_ALL_QUEST_LIST2)
/// 09f8 <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <mob_id>.L <killed>.W <total>.W <mob name>.24B }*count }*num (ZC_ALL_QUEST_LIST3) // TODO!
/// 09f8 <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <hunt identification>.L <mob type>.L <mob_id>.L <min level>.W <max level>.W <killed>.W <total>.W <mob name>.24B }*count }*num (ZC_ALL_QUEST_LIST3)
void clif_quest_send_list(struct map_session_data *sd)
{
int fd = sd->fd;
@ -16573,9 +16598,19 @@ void clif_quest_send_list(struct map_session_data *sd)
int limit = 0;
#if PACKETVER >= 20141022
clif_quest_len(offset, 15 + ((10 + NAME_LENGTH) * MAX_QUEST_OBJECTIVES), sd->avail_quests, &limit, &i);
#if PACKETVER >= 20150513
int size = 22 + NAME_LENGTH;
#else
int size = 10 + NAME_LENGTH;
#endif
clif_quest_len(offset, 15 + ( size * MAX_QUEST_OBJECTIVES), sd->avail_quests, &limit, &i);
WFIFOHEAD(fd,i);
#if PACKETVER >= 20150513
WFIFOW(fd, 0) = 0x9f8;
#else
WFIFOW(fd, 0) = 0x97a;
#endif
WFIFOL(fd, 4) = limit;
for (i = 0; i < limit; i++) {
@ -16599,8 +16634,20 @@ void clif_quest_send_list(struct map_session_data *sd)
for( j = 0; j < qi->objectives_count; j++ ){
mob = mob_db(qi->objectives[j].mob);
#if PACKETVER >= 20150513
WFIFOL(fd, offset) = sd->quest_log[i].quest_id * 1000 + j;
offset += 4;
WFIFOL(fd, offset) = 0; // TODO: Find info - mobType
offset += 4;
#endif
WFIFOL(fd, offset) = qi->objectives[j].mob;
offset += 4;
#if PACKETVER >= 20150513
WFIFOW(fd, offset) = 0; // TODO: Find info - levelMin
offset += 2;
WFIFOW(fd, offset) = 0; // TODO: Find info - levelMax
offset += 2;
#endif
WFIFOW(fd, offset) = sd->quest_log[i].count[j];
offset += 2;
WFIFOW(fd, offset) = qi->objectives[j].count;
@ -16666,31 +16713,71 @@ void clif_quest_send_mission(struct map_session_data *sd)
}
/// Notification about a new quest (ZC_ADD_QUEST).
/// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3
/// Notification about a new quest
/// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3 (ZC_ADD_QUEST)
/// 08fe <packet len>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3 (ZC_HUNTING_QUEST_INFO)
/// 09f9 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <hunt identification>.L <mob type>.L <mob id>.L <min level>.W <max level>.W <mob count>.W <mob name>.24B }*3 (ZC_ADD_QUEST_EX)
void clif_quest_add(struct map_session_data *sd, struct quest *qd)
{
int fd = sd->fd;
int i;
int i, offset;
struct quest_db *qi = quest_search(qd->quest_id);
#if PACKETVER >= 20150513
int cmd = 0x9f9;
#else
int cmd = 0x2b3;
#endif
WFIFOHEAD(fd, packet_len(0x2b3));
WFIFOW(fd, 0) = 0x2b3;
WFIFOHEAD(fd, packet_len(cmd));
WFIFOW(fd, 0) = cmd;
WFIFOL(fd, 2) = qd->quest_id;
WFIFOB(fd, 6) = qd->state;
WFIFOB(fd, 7) = qd->time - qi->time;
WFIFOL(fd, 11) = qd->time;
WFIFOW(fd, 15) = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
for (i = 0, offset = 17; i < qi->objectives_count; i++) {
struct mob_db *mob;
WFIFOL(fd, i*30+17) = qi->objectives[i].mob;
WFIFOW(fd, i*30+21) = qd->count[i];
#if PACKETVER >= 20150513
WFIFOL(fd, offset) = qd->quest_id * 1000 + i;
offset += 4;
WFIFOL(fd, offset) = 0; // TODO: Find info - mobType
offset += 4;
#endif
WFIFOL(fd, offset) = qi->objectives[i].mob;
offset += 4;
#if PACKETVER >= 20150513
WFIFOW(fd, offset) = 0; // TODO: Find info - levelMin
offset += 2;
WFIFOW(fd, offset) = 0; // TODO: Find info - levelMax
offset += 2;
#endif
WFIFOW(fd, offset) = qd->count[i];
offset += 2;
mob = mob_db(qi->objectives[i].mob);
safestrncpy(WFIFOCP(fd, i*30+23), mob->jname, NAME_LENGTH);
safestrncpy(WFIFOCP(fd, offset), mob->jname, NAME_LENGTH);
offset += NAME_LENGTH;
}
WFIFOSET(fd, packet_len(0x2b3));
WFIFOSET(fd, packet_len(cmd));
#if PACKETVER >= 20150513
int len = 4 + qi->objectives_count * 12;
WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x8fe;
WFIFOW(fd, 2) = len;
for( i = 0, offset = 4; i < qi->objectives_count; i++, offset += 12 ){
WFIFOL(fd, offset) = qd->quest_id * 1000 + i;
WFIFOL(fd, offset+4) = qi->objectives[i].mob;
WFIFOW(fd, offset + 10) = qi->objectives[i].count;
WFIFOW(fd, offset + 12) = qd->count[i];
}
WFIFOSET(fd, len);
#endif
}
@ -16707,30 +16794,45 @@ void clif_quest_delete(struct map_session_data *sd, int quest_id)
}
/// Notification of an update to the hunting mission counter (ZC_UPDATE_MISSION_HUNT).
/// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
/// Notification of an update to the hunting mission counter
/// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3 (ZC_UPDATE_MISSION_HUNT)
/// 09fa <packet len>.W <mobs>.W { <quest id>.L <hunt identification>.L <total count>.W <current count>.W }*3 (ZC_UPDATE_MISSION_HUNT_EX)
void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd, int mobid)
{
int fd = sd->fd;
int i;
int i, offset;
struct quest_db *qi = quest_search(qd->quest_id);
int len = qi->objectives_count * 12 + 6;
#if PACKETVER >= 20150513
int cmd = 0x9fa;
#else
int cmd = 0x2b5;
#endif
WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x2b5;
WFIFOW(fd, 2) = len;
WFIFOW(fd, 0) = cmd;
WFIFOW(fd, 4) = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
for (i = 0, offset = 6; i < qi->objectives_count; i++) {
if (mobid == 0 || mobid == qi->objectives[i].mob) {
WFIFOL(fd, i * 12 + 6) = qd->quest_id;
WFIFOL(fd, i * 12 + 10) = qi->objectives[i].mob;
WFIFOW(fd, i * 12 + 14) = qi->objectives[i].count;
WFIFOW(fd, i * 12 + 16) = qd->count[i];
WFIFOL(fd, offset) = qd->quest_id;
offset += 4;
#if PACKETVER >= 20150513
WFIFOL(fd, offset) = qd->quest_id * 1000 + i;
offset += 4;
#else
WFIFOL(fd, offset) = qi->objectives[i].mob;
offset += 4;
#endif
WFIFOW(fd, offset) = qi->objectives[i].count;
offset += 2;
WFIFOW(fd, offset) = qd->count[i];
offset += 2;
}
}
WFIFOSET(fd, len);
WFIFOW(fd, 2) = offset;
WFIFOSET(fd, offset);
}

View File

@ -414,6 +414,10 @@
packet_keys(0x45AA1B44,0x20E716B7,0x5388105C);
#elif PACKETVER == 20180213 // 2018-02-13aRagexeRE
packet_keys(0x189D69B2,0x43B85EAD,0x2B7A687E);
#elif PACKETVER == 20180221 // 2018-02-21aRagexeRE or 2018-02-21bRagexeRE
packet_keys(0x6E2F6233,0x193B0A66,0x0D1D2CA5);
#elif PACKETVER == 20180307 // 2018-03-07bRagexeRE
packet_keys(0x47DA10EB,0x4B922CCF,0x765C5055);
#elif PACKETVER > 20110817
#error Unsupported packet version.
#endif

View File

@ -2222,7 +2222,6 @@
packet(0x09FD,-1); // ZC_NOTIFY_MOVEENTRY11
packet(0x09FE,-1); // ZC_NOTIFY_NEWENTRY11
packet(0x09FF,-1); // ZC_NOTIFY_STANDENTRY11
//packet(0x09F8,-1); // ZC_ALL_QUEST_LIST3
#endif
// 2015-02-25aRagexeRE
@ -2282,6 +2281,12 @@
// Pet Evolution System
parseable_packet(0x09FB,-1,clif_parse_dull,0); // CZ_PET_EVOLUTION
packet(0x09FC,6); // ZC_PET_EVOLUTION_RESULT
// Quest UI
packet(0x08FE,-1); // ZC_HUNTING_QUEST_INFO
packet(0x09F8,-1); // ZC_ALL_QUEST_LIST3
packet(0x09F9,143); // ZC_ADD_QUEST_EX
packet(0x09FA,-1); // ZC_UPDATE_MISSION_HUNT_EX
#endif
// 2015-05-20aRagexe
@ -2353,4 +2358,23 @@
packet(0x0ACC,18);
#endif
// 2018-02-07bRagexeRE
#if PACKETVER >= 20180207
parseable_packet(0x0AF4,11,clif_parse_UseSkillToPos,2,4,6,8,10);
#endif
// 2018-02-21aRagexeRE or 2018-02-21bRagexeRE
#if PACKETVER >= 20180221
packet(0x0206,35); // ZC_FRIENDS_STATE
packet(0x0af7,32);
#endif
// 2018-03-07bRagexeRE
#if PACKETVER >= 20180307
parseable_packet(0x0A68,3,clif_parse_dull,0);
packet(0x0AE2,7);
parseable_packet(0x0AEF,2,clif_parse_dull,0);
packet(0x0AF0,10);
#endif
#endif /* _CLIF_PACKETDB_HPP_ */

View File

@ -4656,6 +4656,68 @@
parseable_packet(0x0955,8,clif_parse_MoveToKafra,2,4);
parseable_packet(0x095A,-1,clif_parse_ItemListWindowSelected,2,4,8,12);
parseable_packet(0x0962,5,clif_parse_HomMenu,2,4);
// 2018-02-21aRagexeRE or 2018-02-21bRagexeRE
#elif PACKETVER == 20180221
parseable_packet(0x0202,90,clif_parse_UseSkillToPosMoreInfo,2,4,6,8,10);
//parseable_packet(0x0366,8,NULL,0); // CZ_JOIN_BATTLE_FIELD
parseable_packet(0x0436,26,clif_parse_FriendsListAdd,2);
parseable_packet(0x0838,5,clif_parse_ChangeDir,2,4);
parseable_packet(0x0867,-1,clif_parse_SearchStoreInfo,2,4,5,9,13,14,15);
parseable_packet(0x086C,6,clif_parse_ReqClickBuyingStore,2);
parseable_packet(0x086F,-1,clif_parse_ReqOpenBuyingStore,2,4,8,9,89);
parseable_packet(0x0871,6,clif_parse_DropItem,2,4);
parseable_packet(0x0876,5,clif_parse_HomMenu,2,4);
parseable_packet(0x0879,8,clif_parse_MoveToKafra,2,4);
parseable_packet(0x087D,5,clif_parse_WalkToXY,2);
parseable_packet(0x0880,-1,clif_parse_ItemListWindowSelected,2,4,8,12);
parseable_packet(0x0881,18,clif_parse_PartyBookingRegisterReq,2,4);
parseable_packet(0x0883,-1,clif_parse_ReqTradeBuyingStore,2,4,8,12);
parseable_packet(0x088F,6,clif_parse_SolveCharName,2);
//parseable_packet(0x0891,4,NULL,0); // CZ_GANGSI_RANK
parseable_packet(0x0897,19,clif_parse_WantToConnection,2,6,10,14,18);
parseable_packet(0x0899,2,clif_parse_SearchStoreInfoNextPage,0);
parseable_packet(0x089D,6,clif_parse_TickSend,2);
parseable_packet(0x0917,36,clif_parse_StoragePassword,0);
parseable_packet(0x091E,8,clif_parse_MoveFromKafra,2,4);
parseable_packet(0x0929,2,clif_parse_ReqCloseBuyingStore,0);
parseable_packet(0x093D,26,clif_parse_PartyInvite2,2);
parseable_packet(0x094B,10,clif_parse_UseSkillToId,2,4,6);
parseable_packet(0x094D,10,clif_parse_UseSkillToPos,2,4,6,8);
parseable_packet(0x094E,6,clif_parse_TakeItem,2);
parseable_packet(0x0957,6,clif_parse_GetCharNameRequest,2);
parseable_packet(0x0964,12,clif_parse_SearchStoreInfoListItemClick,2,6,10);
parseable_packet(0x096A,7,clif_parse_ActionRequest,2,6);
// 2018-03-07bRagexeRE
#elif PACKETVER == 20180307
parseable_packet(0x035F,-1,clif_parse_ReqOpenBuyingStore,2,4,8,9,89);
parseable_packet(0x0437,6,clif_parse_DropItem,2,4);
parseable_packet(0x07E4,19,clif_parse_WantToConnection,2,6,10,14,18);
parseable_packet(0x0861,90,clif_parse_UseSkillToPosMoreInfo,2,4,6,8,10);
parseable_packet(0x0862,6,clif_parse_ReqClickBuyingStore,2);
parseable_packet(0x0864,-1,clif_parse_SearchStoreInfo,2,4,5,9,13,14,15);
parseable_packet(0x086C,6,clif_parse_TickSend,2);
parseable_packet(0x0870,-1,clif_parse_ItemListWindowSelected,2,4,8,12);
parseable_packet(0x0872,18,clif_parse_PartyBookingRegisterReq,2,4);
parseable_packet(0x0877,5,clif_parse_WalkToXY,2);
parseable_packet(0x088D,8,clif_parse_MoveFromKafra,2,4);
parseable_packet(0x0893,10,clif_parse_UseSkillToId,2,4,6);
parseable_packet(0x089B,12,clif_parse_SearchStoreInfoListItemClick,2,6,10);
parseable_packet(0x08A6,2,clif_parse_SearchStoreInfoNextPage,0);
parseable_packet(0x08AA,26,clif_parse_FriendsListAdd,2);
parseable_packet(0x08AB,5,clif_parse_ChangeDir,2,4);
parseable_packet(0x0917,10,clif_parse_UseSkillToPos,2,4,6,8);
parseable_packet(0x0920,8,clif_parse_MoveToKafra,2,4);
parseable_packet(0x0937,-1,clif_parse_ReqTradeBuyingStore,2,4,8,12);
parseable_packet(0x0939,36,clif_parse_StoragePassword,0);
parseable_packet(0x093D,2,clif_parse_ReqCloseBuyingStore,0);
parseable_packet(0x0941,6,clif_parse_GetCharNameRequest,2);
parseable_packet(0x0944,5,clif_parse_HomMenu,2,4);
parseable_packet(0x0948,26,clif_parse_PartyInvite2,2);
//parseable_packet(0x0951,8,NULL,0); // CZ_JOIN_BATTLE_FIELD
parseable_packet(0x0954,6,clif_parse_TakeItem,2);
parseable_packet(0x0957,6,clif_parse_SolveCharName,2);
parseable_packet(0x0969,7,clif_parse_ActionRequest,2,6);
//parseable_packet(0x0281,4,NULL,0); // CZ_GANGSI_RANK
#endif
#endif /* _CLIF_SHUFFLE_HPP_ */