diff options
Diffstat (limited to 'src/map/clif.c')
-rw-r--r-- | src/map/clif.c | 2649 |
1 files changed, 1537 insertions, 1112 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 3b2f255ef..524378439 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -190,7 +190,7 @@ static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, s #endif // 0 //To identify disguised characters. -static inline bool disguised(struct block_list* bl) +bool clif_isdisguised(struct block_list* bl) { struct map_session_data *sd = BL_CAST(BL_PC, bl); if (sd == NULL || sd->disguise == -1) @@ -198,22 +198,6 @@ static inline bool disguised(struct block_list* bl) return true; } -//Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex] -static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned int max) { - nullpo_retr(0, mes); - if (len <= 0) - { - mes[0] = '\0'; - Assert_retr(0, len > 0); - } - if( len > max ) - len = max; - - mes[len-1] = '\0'; - - return len; -} - /*========================================== * Ip setting of map-server *------------------------------------------*/ @@ -281,24 +265,50 @@ uint32 clif_refresh_ip(void) return 0; } +unsigned char clif_bl_type(struct block_list *bl) +{ #if PACKETVER >= 20071106 -static inline unsigned char clif_bl_type(struct block_list *bl) { - nullpo_retr(0x1, bl); + struct view_data *vd; + nullpo_retr(CLUT_NPC, bl); + switch (bl->type) { - case BL_PC: return (disguised(bl) && !pc->db_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE - case BL_ITEM: return 0x2; //ITEM_TYPE - case BL_SKILL: return 0x3; //SKILL_TYPE - case BL_CHAT: return 0x4; //UNKNOWN_TYPE - case BL_MOB: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE - case BL_NPC: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE - case BL_PET: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE - case BL_HOM: return 0x8; //NPC_HOM_TYPE - case BL_MER: return 0x9; //NPC_MERSOL_TYPE - case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE - default: return 0x1; //NPC_TYPE + case BL_PC: + vd = status->get_viewdata(bl); + nullpo_retr(CLUT_NPC, vd); + + if (clif->isdisguised(bl) && !pc->db_checkid(vd->class)) + return CLUT_NPC; + return CLUT_PC; + case BL_ITEM: + return CLUT_ITEM; + case BL_SKILL: + return CLUT_SKILL; + case BL_CHAT: + return CLUT_UNKNOWN; + case BL_MOB: + vd = status->get_viewdata(bl); + nullpo_retr(CLUT_NPC, vd); + return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_MOB; + case BL_NPC: + vd = status->get_viewdata(bl); + nullpo_retr(CLUT_NPC, vd); + return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_EVENT; + case BL_PET: + vd = status->get_viewdata(bl); + nullpo_retr(CLUT_NPC, vd); + return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_PET; + case BL_HOM: + return CLUT_HOMNUCLUS; + case BL_MER: + return CLUT_MERCNARY; + case BL_ELEM: + return CLUT_ELEMENTAL; + default: + return CLUT_NPC; } -} #endif + return CLUT_UNKNOWN; +} /*========================================== * sub process of clif_send @@ -335,17 +345,17 @@ int clif_send_sub(struct block_list *bl, va_list ap) { return 0; break; case AREA_WOC: - if (sd->chatID || bl == src_bl) + if (sd->chat_id != 0 || bl == src_bl) return 0; break; case AREA_WOSC: { if (src_bl->type == BL_PC) { const struct map_session_data *ssd = BL_UCCAST(BL_PC, src_bl); - if (ssd != NULL && sd->chatID != 0 && (sd->chatID == ssd->chatID)) + if (ssd != NULL && sd->chat_id != 0 && (sd->chat_id == ssd->chat_id)) return 0; } else if (src_bl->type == BL_NPC) { const struct npc_data *nd = BL_UCCAST(BL_NPC, src_bl); - if (nd != NULL && sd->chatID != 0 && (sd->chatID == nd->chat_id)) + if (nd != NULL && sd->chat_id != 0 && (sd->chat_id == nd->chat_id)) return 0; } } @@ -441,8 +451,8 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target break; case AREA_CHAT_WOC: nullpo_retr(true, bl); - map->foreachinarea(clif->send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5), - bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC); + map->foreachinarea(clif->send_sub, bl->m, bl->x-CHAT_AREA_SIZE, bl->y-CHAT_AREA_SIZE, + bl->x+CHAT_AREA_SIZE, bl->y+CHAT_AREA_SIZE, BL_PC, buf, len, bl, AREA_WOC); break; case CHAT: @@ -451,7 +461,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target { const struct chat_data *cd = NULL; if (sd != NULL) { - cd = map->id2cd(sd->chatID); + cd = map->id2cd(sd->chat_id); } else { cd = BL_CCAST(BL_CHAT, bl); } @@ -645,7 +655,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target break; default: - ShowError("clif_send: Unrecognized type %d\n",type); + ShowError("clif_send: Unrecognized type %u\n", type); return false; } @@ -667,7 +677,8 @@ void clif_authok(struct map_session_data *sd) #if PACKETVER >= 20080102 p.font = sd->status.font; #endif -#if PACKETVER >= 20141016 +// Some clients smaller than 20160330 cant be tested [4144] +#if PACKETVER >= 20141016 && PACKETVER < 20160330 p.sex = sd->status.sex; #endif clif->send(&p,sizeof(p),&sd->bl,SELF); @@ -839,7 +850,7 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) clif->send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS); - if(disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; clif->send(buf, packet_len(0x80), bl, SELF); } @@ -944,21 +955,22 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en p.PacketType = idle_unit2Type; #if PACKETVER >= 20071106 - p.objecttype = clif_bl_type(bl); + p.objecttype = clif->bl_type(bl); #endif p.GID = bl->id; p.speed = status->get_speed(bl); p.bodyState = (sc) ? sc->opt1 : 0; p.healthState = (sc) ? sc->opt2 : 0; p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); - p.job = vd->class_; + p.job = vd->class; p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; p.shield = vd->shield; p.accessory2 = vd->head_top; p.accessory3 = vd->head_mid; - if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + if (bl->type == BL_NPC && vd->class == FLAG_CLASS) { + // The hell, why flags work like this? p.shield = status->get_emblem_id(bl); p.accessory2 = GetWord(g_id, 1); p.accessory3 = GetWord(g_id, 0); @@ -995,7 +1007,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu nullpo_retv(bl); #if PACKETVER < 20091103 - if( !pc->db_checkid(vd->class_) ) { + if (!pc->db_checkid(vd->class)) { clif->set_unit_idle2(bl,tsd,target); return; } @@ -1006,7 +1018,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu p.PacketType = idle_unitType; #if PACKETVER >= 20091103 p.PacketLength = sizeof(p); - p.objecttype = clif_bl_type(bl); + p.objecttype = clif->bl_type(bl); #endif #if PACKETVER >= 20131223 p.AID = bl->id; @@ -1018,7 +1030,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu p.bodyState = (sc) ? sc->opt1 : 0; p.healthState = (sc) ? sc->opt2 : 0; p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); - p.job = vd->class_; + p.job = vd->class; p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; @@ -1027,7 +1039,8 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu #endif p.accessory2 = vd->head_top; p.accessory3 = vd->head_mid; - if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + if (bl->type == BL_NPC && vd->class == FLAG_CLASS) { + // The hell, why flags work like this? p.accessory = status->get_emblem_id(bl); p.accessory2 = GetWord(g_id, 1); p.accessory3 = GetWord(g_id, 0); @@ -1066,13 +1079,20 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu #if PACKETVER >= 20150513 p.body = vd->body_style; #endif - +/* Might be earlier, this is when the named item bug began */ +#if PACKETVER >= 20131223 + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); +#endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); - if( disguised(bl) ) { + if (clif->isdisguised(bl)) { #if PACKETVER >= 20091103 - p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE +#if PACKETVER >= 20131223 + p.AID = -bl->id; +#else p.GID = -bl->id; +#endif #else p.GID = -bl->id; #endif @@ -1094,7 +1114,7 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) { p.PacketType = spawn_unit2Type; #if PACKETVER >= 20071106 - p.objecttype = clif_bl_type(bl); + p.objecttype = clif->bl_type(bl); #endif p.GID = bl->id; p.speed = status->get_speed(bl); @@ -1104,11 +1124,12 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) { p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; - p.job = vd->class_; + p.job = vd->class; p.shield = vd->shield; p.accessory2 = vd->head_top; p.accessory3 = vd->head_mid; - if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + if (bl->type == BL_NPC && vd->class == FLAG_CLASS) { + // The hell, why flags work like this? p.shield = status->get_emblem_id(bl); p.accessory2 = GetWord(g_id, 1); p.accessory3 = GetWord(g_id, 0); @@ -1136,7 +1157,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { nullpo_retv(bl); #if PACKETVER < 20091103 - if( !pc->db_checkid(vd->class_) ) { + if (!pc->db_checkid(vd->class)) { clif->spawn_unit2(bl,target); return; } @@ -1147,7 +1168,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { p.PacketType = spawn_unitType; #if PACKETVER >= 20091103 p.PacketLength = sizeof(p); - p.objecttype = clif_bl_type(bl); + p.objecttype = clif->bl_type(bl); #endif #if PACKETVER >= 20131223 p.AID = bl->id; @@ -1159,7 +1180,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { p.bodyState = (sc) ? sc->opt1 : 0; p.healthState = (sc) ? sc->opt2 : 0; p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); - p.job = vd->class_; + p.job = vd->class; p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; @@ -1168,7 +1189,8 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { #endif p.accessory2 = vd->head_top; p.accessory3 = vd->head_mid; - if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + if (bl->type == BL_NPC && vd->class == FLAG_CLASS) { + // The hell, why flags work like this? p.accessory = status->get_emblem_id(bl); p.accessory2 = GetWord(g_id, 1); p.accessory3 = GetWord(g_id, 0); @@ -1206,13 +1228,21 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { #if PACKETVER >= 20150513 p.body = vd->body_style; #endif - if( disguised(bl) ) { +/* Might be earlier, this is when the named item bug began */ +#if PACKETVER >= 20131223 + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); +#endif + if (clif->isdisguised(bl)) { nullpo_retv(sd); - if( sd->status.class_ != sd->disguise ) + if (sd->status.class != sd->disguise) clif->send(&p,sizeof(p),bl,target); #if PACKETVER >= 20091103 - p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE +#if PACKETVER >= 20131223 + p.AID = -bl->id; +#else p.GID = -bl->id; +#endif #else p.GID = -bl->id; #endif @@ -1242,11 +1272,11 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.PacketLength = sizeof(p); #endif #if PACKETVER >= 20071106 - p.objecttype = clif_bl_type(bl); + p.objecttype = clif->bl_type(bl); #endif #if PACKETVER >= 20131223 p.AID = bl->id; - p.GID = (tsd) ? tsd->status.char_id : 0; // CCODE + p.GID = (sd) ? sd->status.char_id : 0; // CCODE #else p.GID = bl->id; #endif @@ -1254,7 +1284,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, p.bodyState = (sc) ? sc->opt1 : 0; p.healthState = (sc) ? sc->opt2 : 0; p.effectState = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); - p.job = vd->class_; + p.job = vd->class; p.head = vd->hair_style; p.weapon = vd->weapon; p.accessory = vd->head_bottom; @@ -1297,13 +1327,21 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, #if PACKETVER >= 20150513 p.body = vd->body_style; #endif +/* Might be earlier, this is when the named item bug began */ +#if PACKETVER >= 20131223 + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); +#endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); - if( disguised(bl) ) { + if (clif->isdisguised(bl)) { #if PACKETVER >= 20091103 - p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE +#if PACKETVER >= 20131223 + p.AID = -bl->id; +#else p.GID = -bl->id; +#endif #else p.GID = -bl->id; #endif @@ -1315,7 +1353,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, /// 01b0 <id>.L <type>.B <value>.L /// type: /// unused -void clif_class_change(struct block_list *bl, int class_, int type) +void clif_class_change(struct block_list *bl, int class_, int type, struct map_session_data *sd) { nullpo_retv(bl); @@ -1326,7 +1364,11 @@ void clif_class_change(struct block_list *bl, int class_, int type) WBUFL(buf,2)=bl->id; WBUFB(buf,6)=type; WBUFL(buf,7)=class_; - clif->send(buf,packet_len(0x1b0),bl,AREA); + + if (sd == NULL) + clif->send(buf, packet_len(0x1b0), bl, AREA); + else + clif->send(buf, packet_len(0x1b0), &sd->bl, SELF); } } @@ -1347,6 +1389,7 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) { *------------------------------------------*/ void clif_charm_single(int fd, struct map_session_data *sd) { +#if PACKETVER >= 20110809 nullpo_retv(sd); WFIFOHEAD(fd, packet_len(0x08cf)); WFIFOW(fd,0) = 0x08cf; @@ -1354,6 +1397,7 @@ void clif_charm_single(int fd, struct map_session_data *sd) WFIFOW(fd,6) = sd->charm_type; WFIFOW(fd,8) = sd->charm_count; WFIFOSET(fd, packet_len(0x08cf)); +#endif } /*========================================== @@ -1412,7 +1456,7 @@ bool clif_spawn(struct block_list *bl) if( !vd ) return false; - if (vd->class_ == INVISIBLE_CLASS) + if (vd->class == INVISIBLE_CLASS) return true; // Doesn't need to be spawned, so everything is alright if (bl->type == BL_NPC) { @@ -1442,7 +1486,7 @@ bool clif_spawn(struct block_list *bl) if (sd->bg_id != 0 && map->list[sd->bl.m].flag.battleground) clif->sendbgemblem_area(sd); for (i = 0; i < sd->sc_display_count; i++) { - clif->sc_load(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); + clif->sc_continue(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) clif->spiritcharm(sd); @@ -1482,6 +1526,15 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) struct status_data *hstatus; unsigned char buf[128]; enum homun_type htype; + int offset = 0; + +// probably can works also for < 20141223, but in 3CeaM packet size defined only for 20150513 +#if PACKETVER < 20150513 + int cmd = 0x22e; +#else + int cmd = 0x9f7; +#endif + int len = packet_len(cmd); nullpo_retv(sd); nullpo_retv(hd); @@ -1489,65 +1542,75 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) hstatus = &hd->battle_status; htype = homun->class2type(hd->homunculus.class_); - memset(buf,0,packet_len(0x22e)); - WBUFW(buf,0)=0x22e; - memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH); + memset(buf, 0, len); + WBUFW(buf, 0) = cmd; + memcpy(WBUFP(buf, 2), hd->homunculus.name, NAME_LENGTH); // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true) - WBUFB(buf,26)=(battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0); - WBUFW(buf,27)=hd->homunculus.level; - WBUFW(buf,29)=hd->homunculus.hunger; - WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ; - WBUFW(buf,33)=0; // equip id + WBUFB(buf, 26) = (!battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0); + WBUFW(buf, 27) = hd->homunculus.level; + WBUFW(buf, 29) = hd->homunculus.hunger; + WBUFW(buf, 31) = (unsigned short) (hd->homunculus.intimacy / 100) ; + WBUFW(buf, 33) = 0; // equip id #ifdef RENEWAL WBUFW(buf, 35) = cap_value(hstatus->rhw.atk2, 0, INT16_MAX); #else - WBUFW(buf,35)=cap_value(hstatus->rhw.atk2+hstatus->batk, 0, INT16_MAX); + WBUFW(buf,35) = cap_value(hstatus->rhw.atk2 + hstatus->batk, 0, INT16_MAX); #endif - WBUFW(buf,37)=cap_value(hstatus->matk_max, 0, INT16_MAX); - WBUFW(buf,39)=hstatus->hit; + WBUFW(buf,37) = cap_value(hstatus->matk_max, 0, INT16_MAX); + WBUFW(buf,39) = hstatus->hit; if (battle_config.hom_setting&0x10) - WBUFW(buf,41)=hstatus->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious] + WBUFW(buf, 41) = hstatus->luk / 3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious] else - WBUFW(buf,41)=hstatus->cri/10; + WBUFW(buf, 41) = hstatus->cri / 10; #ifdef RENEWAL WBUFW(buf, 43) = hstatus->def + hstatus->def2; WBUFW(buf, 45) = hstatus->mdef + hstatus->mdef2; #else - WBUFW(buf,43)=hstatus->def + hstatus->vit ; + WBUFW(buf, 43) =hstatus->def + hstatus->vit ; WBUFW(buf, 45) = hstatus->mdef; #endif - WBUFW(buf,47)=hstatus->flee; - WBUFW(buf,49)=(flag)?0:hstatus->amotion; + WBUFW(buf, 47) = hstatus->flee; + WBUFW(buf, 49) = (flag) ? 0 : hstatus->amotion; + +// probably can works also for < 20141223, but in 3CeaM packet size defined only for 20150513 +#if PACKETVER < 20150513 if (hstatus->max_hp > INT16_MAX) { - WBUFW(buf,51) = hstatus->hp/(hstatus->max_hp/100); - WBUFW(buf,53) = 100; + WBUFW(buf, 51) = hstatus->hp / (hstatus->max_hp / 100); + WBUFW(buf, 53) = 100; } else { - WBUFW(buf,51)=hstatus->hp; - WBUFW(buf,53)=hstatus->max_hp; + WBUFW(buf, 51) = hstatus->hp; + WBUFW(buf, 53) = hstatus->max_hp; } +#else + WBUFL(buf, 51) = hstatus->hp; + WBUFL(buf, 55) = hstatus->max_hp; + offset = 4; +#endif + if (hstatus->max_sp > INT16_MAX) { - WBUFW(buf,55) = hstatus->sp/(hstatus->max_sp/100); - WBUFW(buf,57) = 100; + WBUFW(buf, 55 + offset) = hstatus->sp / (hstatus->max_sp / 100); + WBUFW(buf, 57 + offset) = 100; } else { - WBUFW(buf,55)=hstatus->sp; - WBUFW(buf,57)=hstatus->max_sp; + WBUFW(buf, 55 + offset) = hstatus->sp; + WBUFW(buf, 57 + offset) = hstatus->max_sp; } - WBUFL(buf,59)=hd->homunculus.exp; - WBUFL(buf,63)=hd->exp_next; - switch( htype ) { + WBUFL(buf, 59 + offset) = hd->homunculus.exp; + WBUFL(buf, 63 + offset) = hd->exp_next; + switch (htype) { case HT_REG: case HT_EVO: - if( hd->homunculus.level >= battle_config.hom_max_level ) - WBUFL(buf,63)=0; + if (hd->homunculus.level >= battle_config.hom_max_level) + WBUFL(buf, 63 + offset) = 0; break; case HT_S: - if( hd->homunculus.level >= battle_config.hom_S_max_level ) - WBUFL(buf,63)=0; + if (hd->homunculus.level >= battle_config.hom_S_max_level) + WBUFL(buf, 63 + offset) = 0; break; } - WBUFW(buf,67)=hd->homunculus.skillpts; - WBUFW(buf,69)=status_get_range(&hd->bl); - clif->send(buf,packet_len(0x22e),&sd->bl,SELF); + WBUFW(buf, 67 + offset) = hd->homunculus.skillpts; + WBUFW(buf, 69 + offset) = status_get_range(&hd->bl); + + clif->send(buf, len, &sd->bl, SELF); } /// Notification about a change in homunuculus' state (ZC_CHANGESTATE_MER). @@ -1612,7 +1675,7 @@ void clif_homskillinfoblock(struct map_session_data *sd) { WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10) = 0; } - safestrncpy((char*)WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd, len + 36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_)) ? 1 : 0; len += 37; } @@ -1740,7 +1803,7 @@ void clif_move(struct unit_data *ud) bl = ud->bl; nullpo_retv(bl); vd = status->get_viewdata(bl); - if (!vd || vd->class_ == INVISIBLE_CLASS) + if (vd == NULL || vd->class == INVISIBLE_CLASS) return; //This performance check is needed to keep GM-hidden objects from being notified to bots. if (bl->type == BL_NPC) { @@ -1769,7 +1832,7 @@ void clif_move(struct unit_data *ud) clif->send(buf, packet_len(0x86), bl, AREA_WOS); - if (disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf,2)=-bl->id; clif->send(buf, packet_len(0x86), bl, SELF); } @@ -1816,7 +1879,7 @@ void clif_changemap(struct map_session_data *sd, short m, int x, int y) { WFIFOHEAD(fd,packet_len(0x91)); WFIFOW(fd,0) = 0x91; - mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, (char*)WFIFOP(fd,2)); + mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, WFIFOP(fd,2)); WFIFOW(fd,18) = x; WFIFOW(fd,20) = y; WFIFOSET(fd,packet_len(0x91)); @@ -1831,7 +1894,7 @@ void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, WFIFOHEAD(fd,packet_len(0x92)); WFIFOW(fd,0) = 0x92; - mapindex->getmapname_ext(mapindex_id2name(map_index), (char*)WFIFOP(fd,2)); + mapindex->getmapname_ext(mapindex_id2name(map_index), WFIFOP(fd,2)); WFIFOW(fd,18) = x; WFIFOW(fd,20) = y; WFIFOL(fd,22) = htonl(ip); @@ -1862,7 +1925,7 @@ void clif_fixpos(struct block_list *bl) { WBUFW(buf,8) = bl->y; clif->send(buf, packet_len(0x88), bl, AREA); - if( disguised(bl) ) { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; clif->send(buf, packet_len(0x88), bl, SELF); } @@ -1970,21 +2033,38 @@ void clif_selllist(struct map_session_data *sd) /// - set npcid of dialog window (0 by default) /// - if set to clear on next mes, clear contents /// - append this text -void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) { - int fd = sd->fd; - size_t slen; +void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) +{ + int fd, slen; +#ifdef SCRIPT_MES_STRIP_LINEBREAK + char *stripmes = NULL; + int i; +#endif nullpo_retv(sd); nullpo_retv(mes); - slen = strlen(mes) + 9; + + fd = sd->fd; + slen = (int)strlen(mes) + 9; + Assert_retv(slen <= INT16_MAX); sd->state.dialog = 1; WFIFOHEAD(fd, slen); - WFIFOW(fd,0)=0xb4; - WFIFOW(fd,2)=slen; - WFIFOL(fd,4)=npcid; - memcpy((char*)WFIFOP(fd,8), mes, slen-8); + WFIFOW(fd,0) = 0xb4; + WFIFOW(fd,2) = slen; + WFIFOL(fd,4) = npcid; +#ifdef SCRIPT_MES_STRIP_LINEBREAK + stripmes = aStrdup(mes); + for (i = 0; stripmes[i] != '\0'; ++i) { + if (stripmes[i] == '\r') + stripmes[i] = ' '; + } + memcpy(WFIFOP(fd,8), stripmes, slen-8); + aFree(stripmes); +#else // ! SCRIPT_MES_STRIP_LINEBREAK + memcpy(WFIFOP(fd,8), mes, slen-8); +#endif // SCRIPT_MES_STRIP_LINEBREAK WFIFOSET(fd,WFIFOW(fd,2)); } @@ -2085,25 +2165,28 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) { /// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window. /// Which suggests their have intertwined behavior. (probably the mouse targeting) /// TODO investigate behavior of other windows [FlavioJS] -void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) { - int fd; - size_t slen; +void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes) +{ + int fd, slen; struct block_list *bl = NULL; nullpo_retv(sd); nullpo_retv(mes); + fd = sd->fd; - slen = strlen(mes) + 9; + slen = (int)strlen(mes) + 9; + Assert_retv(slen <= INT16_MAX); + if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (bl->m!=sd->bl.m || bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) clif->sendfakenpc(sd, npcid); WFIFOHEAD(fd, slen); - WFIFOW(fd,0)=0xb7; - WFIFOW(fd,2)=slen; - WFIFOL(fd,4)=npcid; - memcpy((char*)WFIFOP(fd,8), mes, slen-8); + WFIFOW(fd,0) = 0xb7; + WFIFOW(fd,2) = slen; + WFIFOL(fd,4) = npcid; + memcpy(WFIFOP(fd,8), mes, slen-8); WFIFOSET(fd,WFIFOW(fd,2)); } @@ -2211,7 +2294,7 @@ void clif_cutin(struct map_session_data* sd, const char* image, int type) fd=sd->fd; WFIFOHEAD(fd, packet_len(0x1b3)); WFIFOW(fd,0)=0x1b3; - strncpy((char*)WFIFOP(fd,2),image,64); + strncpy(WFIFOP(fd,2),image,64); WFIFOB(fd,66)=type; WFIFOSET(fd,packet_len(0x1b3)); } @@ -2320,23 +2403,37 @@ void clif_addcards2(unsigned short *cards, struct item* item) { } /** - * Fills in RandomOptions(Bonuses) of items into the buffer + * Fills in ItemOptions(Bonuses) of items into the buffer * - * Dummy datais used since this feature isn't supported yet (ITEM_RDM_OPT). - * A maximum of 5 random options can be supported. + * A maximum of 5 item options can be supported. * * @param buf[in,out] The buffer to write to. The pointer must be valid and initialized. * @param item[in] The source item. */ -void clif_add_random_options(unsigned char* buf, struct item* item) + int clif_add_item_options(struct ItemOptions *buf, const struct item *it) { - int i; - nullpo_retv(buf); - for (i = 0; i < 5; i++){ - WBUFW(buf,i*5+0) = 0; // OptIndex - WBUFW(buf,i*5+2) = 0; // Value - WBUFB(buf,i*5+4) = 0; // Param1 + int i = 0, j = 0, total_options = 0; + + nullpo_ret(buf); + + // Append the buffer with existing options first. + for (i = 0; i < MAX_ITEM_OPTIONS; i++) { + if (it->option[i].index) { + WBUFW(buf, j * 5 + 0) = it->option[i].index; // OptIndex + WBUFW(buf, j * 5 + 2) = it->option[i].value; // Value + WBUFB(buf, j * 5 + 4) = it->option[i].param; // Param1 + total_options++; + j++; + } } + // Append the remaining buffer with no values; + for (; j < MAX_ITEM_OPTIONS || j < 5; j++) { + WBUFW(buf, j * 5 + 0) = 0; + WBUFW(buf, j * 5 + 2) = 0; + WBUFB(buf, j * 5 + 4) = 0; + } + + return total_options; } /// Notifies the client, about a received inventory item or the result of a pick-up request. @@ -2360,9 +2457,6 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { p.count = amount; if( !fail ) { -#if PACKETVER >= 20150226 - int i; -#endif if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; @@ -2372,7 +2466,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { p.nameid = sd->status.inventory[n].nameid; p.IsIdentified = sd->status.inventory[n].identify ? 1 : 0; - p.IsDamaged = sd->status.inventory[n].attribute ? 1 : 0; + p.IsDamaged = (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ? 1 : 0; p.refiningLevel =sd->status.inventory[n].refine; clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]); p.location = pc->equippoint(sd,n); @@ -2387,11 +2481,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { p.bindOnEquipType = sd->status.inventory[n].bound && !itemdb->isstackable2(sd->inventory_data[n]) ? 2 : sd->inventory_data[n]->flag.bindonequip ? 1 : 0; #endif #if PACKETVER >= 20150226 - for (i=0; i<5; i++){ - p.option_data[i].index = 0; - p.option_data[i].value = 0; - p.option_data[i].param = 0; - } + clif->add_item_options(&p.option_data[0], &sd->status.inventory[n]); #endif } p.result = (unsigned char)fail; @@ -2464,41 +2554,39 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data * } -void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) { -#if PACKETVER >= 20150226 - int j; -#endif +void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *it, struct item_data *id, int eqp_pos) +{ nullpo_retv(p); - nullpo_retv(i); + nullpo_retv(it); nullpo_retv(id); p->index = idx; if (id->view_id > 0) p->ITID = id->view_id; else - p->ITID = i->nameid; + p->ITID = it->nameid; p->type = itemtype(id->type); #if PACKETVER < 20120925 - p->IsIdentified = i->identify ? 1 : 0; + p->IsIdentified = it->identify ? 1 : 0; #endif p->location = eqp_pos; - p->WearState = i->equip; + p->WearState = it->equip; #if PACKETVER < 20120925 - p->IsDamaged = i->attribute ? 1 : 0; + p->IsDamaged = (it->attribute & ATTR_BROKEN) != 0 ? 1 : 0; #endif - p->RefiningLevel = i->refine; + p->RefiningLevel = it->refine; - clif->addcards2(&p->slot.card[0], i); + clif->addcards2(&p->slot.card[0], it); #if PACKETVER >= 20071002 - p->HireExpireDate = i->expire_time; + p->HireExpireDate = it->expire_time; #endif #if PACKETVER >= 20080102 - p->bindOnEquipType = i->bound ? 2 : id->flag.bindonequip ? 1 : 0; + p->bindOnEquipType = it->bound ? 2 : id->flag.bindonequip ? 1 : 0; #endif #if PACKETVER >= 20100629 @@ -2506,19 +2594,14 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct #endif #if PACKETVER >= 20120925 - p->Flag.IsIdentified = i->identify ? 1 : 0; - p->Flag.IsDamaged = i->attribute ? 1 : 0; - p->Flag.PlaceETCTab = i->favorite ? 1 : 0; + p->Flag.IsIdentified = it->identify ? 1 : 0; + p->Flag.IsDamaged = (it->attribute & ATTR_BROKEN) != 0 ? 1 : 0; + p->Flag.PlaceETCTab = it->favorite ? 1 : 0; p->Flag.SpareBits = 0; #endif #if PACKETVER >= 20150226 - p->option_count = 0; - for (j=0; j<5; j++){ - p->option_data[j].index = 0; - p->option_data[j].value = 0; - p->option_data[j].param = 0; - } + p->option_count = clif->add_item_options(p->option_data, it); #endif } @@ -3111,31 +3194,31 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->shield = val; break; case LOOK_BASE: - if( !sd ) break; + if (sd == NULL) + break; - if ( val == INVISIBLE_CLASS ) /* nothing to change look */ + if (val == INVISIBLE_CLASS) /* nothing to change look */ return; - if( sd->sc.option&OPTION_COSTUME ) + if (sd->sc.option & OPTION_COSTUME) vd->weapon = vd->shield = 0; - if( !vd->cloth_color ) + if (!vd->cloth_color) break; - if (sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette) + if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true) vd->cloth_color = 0; - if (sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette) + if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true) vd->cloth_color = 0; - if (sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette) + if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true) vd->cloth_color = 0; - if (sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette) + if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true) vd->cloth_color = 0; - if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */) + if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true) vd->cloth_color = 0; - if (vd->body_style && ( - sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS || - sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK || - sd->sc.option&OPTION_OKTOBERFEST)) + if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true) + vd->cloth_color = 0; + if (vd->body_style != 0 && (sd->sc.option & OPTION_COSTUME) != 0) vd->body_style = 0; break; case LOOK_HAIR: @@ -3154,16 +3237,18 @@ void clif_changelook(struct block_list *bl,int type,int val) vd->hair_color = val; break; case LOOK_CLOTHES_COLOR: - if( val && sd ) { - if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette ) + if (val && sd != NULL) { + if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true) + val = 0; + if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true) val = 0; - if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette ) + if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true) val = 0; - if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette ) + if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true) val = 0; - if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) + if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true) val = 0; - if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ ) + if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true) val = 0; } vd->cloth_color = val; @@ -3195,17 +3280,14 @@ void clif_changelook(struct block_list *bl,int type,int val) #endif break; case LOOK_BODY2: - if (val && ( - sd->sc.option&OPTION_WEDDING || sd->sc.option&OPTION_XMAS || - sd->sc.option&OPTION_SUMMER || sd->sc.option&OPTION_HANBOK || - sd->sc.option&OPTION_OKTOBERFEST)) + if (sd != NULL && (sd->sc.option&OPTION_COSTUME) != OPTION_NOTHING) val = 0; vd->body_style = val; break; } // prevent leaking the presence of GM-hidden objects - if( sc && sc->option&OPTION_INVISIBLE && !disguised(bl) ) + if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl)) target = SELF; #if PACKETVER < 4 clif->sendlook(bl, bl->id, type, val, 0, target); @@ -3216,11 +3298,12 @@ void clif_changelook(struct block_list *bl,int type,int val) val = vd->weapon; val2 = vd->shield; } - if( disguised(bl) ) { + if (clif->isdisguised(bl)) { clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS); clif->sendlook(bl, -bl->id, type, val, val2, SELF); - } else + } else { clif->sendlook(bl, bl->id, type, val, val2, target); + } #endif } @@ -3501,15 +3584,16 @@ void clif_changeoption(struct block_list* bl) WBUFW(buf,8) = (sc) ? sc->opt2 : 0; WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); WBUFB(buf,14) = (sd)? sd->status.karma : 0; - if(disguised(bl)) { + if (clif->isdisguised(bl)) { clif->send(buf,packet_len(0x229),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; clif->send(buf,packet_len(0x229),bl,SELF); WBUFL(buf,2) = bl->id; WBUFL(buf,10) = OPTION_INVISIBLE; clif->send(buf,packet_len(0x229),bl,SELF); - } else + } else { clif->send(buf,packet_len(0x229),bl,AREA); + } #else WBUFW(buf,0) = 0x119; WBUFL(buf,2) = bl->id; @@ -3517,15 +3601,16 @@ void clif_changeoption(struct block_list* bl) WBUFW(buf,8) = (sc) ? sc->opt2 : 0; WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); WBUFB(buf,12) = (sd)? sd->status.karma : 0; - if(disguised(bl)) { + if (clif->isdisguised(bl)) { clif->send(buf,packet_len(0x119),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; clif->send(buf,packet_len(0x119),bl,SELF); WBUFL(buf,2) = bl->id; WBUFW(buf,10) = OPTION_INVISIBLE; clif->send(buf,packet_len(0x119),bl,SELF); - } else + } else { clif->send(buf,packet_len(0x119),bl,AREA); + } #endif } @@ -3543,15 +3628,16 @@ void clif_changeoption2(struct block_list* bl) { WBUFL(buf,6) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0); WBUFL(buf,10) = clif_setlevel(bl); WBUFL(buf,14) = (sc) ? sc->opt3 : 0; - if(disguised(bl)) { + if (clif->isdisguised(bl)) { clif->send(buf,packet_len(0x28a),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; clif->send(buf,packet_len(0x28a),bl,SELF); WBUFL(buf,2) = bl->id; WBUFL(buf,6) = OPTION_INVISIBLE; clif->send(buf,packet_len(0x28a),bl,SELF); - } else + } else { clif->send(buf,packet_len(0x28a),bl,AREA); + } } /// Notifies the client about the result of an item use request. @@ -3623,26 +3709,29 @@ void clif_createchat(struct map_session_data* sd, int flag) /// 1 = public /// 2 = arena (npc waiting room) /// 3 = PK zone (non-clickable) -void clif_dispchat(struct chat_data* cd, int fd) +void clif_dispchat(struct chat_data *cd, int fd) { unsigned char buf[128]; uint8 type; + int len; - if( cd == NULL || cd->owner == NULL ) + if (cd == NULL || cd->owner == NULL) return; type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0 : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 : 1; + len = (int)strlen(cd->title); + Assert_retv(len <= INT16_MAX - 17); WBUFW(buf, 0) = 0xd7; - WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFW(buf, 2) = 17 + len; WBUFL(buf, 4) = cd->owner->id; WBUFL(buf, 8) = cd->bl.id; WBUFW(buf,12) = cd->limit; WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; WBUFB(buf,16) = type; - memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated if( fd ) { WFIFOHEAD(fd,WBUFW(buf,2)); @@ -3660,10 +3749,11 @@ void clif_dispchat(struct chat_data* cd, int fd) /// 1 = public /// 2 = arena (npc waiting room) /// 3 = PK zone (non-clickable) -void clif_changechatstatus(struct chat_data* cd) +void clif_changechatstatus(struct chat_data *cd) { unsigned char buf[128]; uint8 type; + int len; if( cd == NULL || cd->usersd[0] == NULL ) return; @@ -3671,15 +3761,17 @@ void clif_changechatstatus(struct chat_data* cd) type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0 : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 : 1; + len = (int)strlen(cd->title); + Assert_retv(len <= INT16_MAX - 17); WBUFW(buf, 0) = 0xdf; - WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFW(buf, 2) = 17 + len; WBUFL(buf, 4) = cd->owner->id; WBUFL(buf, 8) = cd->bl.id; WBUFW(buf,12) = cd->limit; WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; WBUFB(buf,16) = type; - memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated clif->send(buf,WBUFW(buf,2),cd->owner,CHAT); } @@ -3841,7 +3933,7 @@ void clif_traderequest(struct map_session_data *sd, const char *name) #if PACKETVER < 6 WFIFOHEAD(fd,packet_len(0xe5)); WFIFOW(fd,0) = 0xe5; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0xe5)); #else // PACKETVER >= 6 tsd = map->id2sd(sd->trade_partner); @@ -3850,7 +3942,7 @@ void clif_traderequest(struct map_session_data *sd, const char *name) WFIFOHEAD(fd,packet_len(0x1f4)); WFIFOW(fd,0) = 0x1f4; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOL(fd,26) = tsd->status.char_id; WFIFOW(fd,30) = tsd->status.base_level; WFIFOSET(fd,packet_len(0x1f4)); @@ -3927,7 +4019,7 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFW(buf,15)= 0; //card (4w) WBUFW(buf,17)= 0; //card (4w) #if PACKETVER >= 20150226 - clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); + clif->add_item_options(WBUFP(buf, 19), &sd->status.inventory[index]); #endif } else @@ -3953,7 +4045,7 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFB(buf,10)= sd->status.inventory[index].refine; //refine clif->addcards(WBUFP(buf, 11), &sd->status.inventory[index]); #if PACKETVER >= 20150226 - clif->add_random_options(WBUFP(buf, 19), &sd->status.inventory[index]); + clif->add_item_options(WBUFP(buf, 19), &sd->status.inventory[index]); #endif } WFIFOSET(fd,packet_len(tradeaddType)); @@ -4084,7 +4176,7 @@ void clif_storageitemadded(struct map_session_data* sd, struct item* i, int inde WFIFOB(fd,12+offset) = i->refine; //refine clif->addcards(WFIFOP(fd,13+offset), i); #if PACKETVER >= 20150226 - clif->add_random_options(WFIFOP(fd,21+offset), i); + clif->add_item_options(WFIFOP(fd, 21 + offset), i); #endif WFIFOSET(fd,packet_len(storageaddType)); } @@ -4097,12 +4189,13 @@ void clif_storageitemremoved(struct map_session_data* sd, int index, int amount) nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xf6)); - WFIFOW(fd,0)=0xf6; // Storage item removed - WFIFOW(fd,2)=index+1; - WFIFOL(fd,4)=amount; - WFIFOSET(fd,packet_len(0xf6)); + fd = sd->fd; + + WFIFOHEAD(fd, packet_len(0xf6)); + WFIFOW(fd, 0) = 0xf6; // Storage item removed + WFIFOW(fd, 2) = index + 1; + WFIFOL(fd, 4) = amount; + WFIFOSET(fd, packet_len(0xf6)); } /// Closes storage (ZC_CLOSE_STORE). @@ -4128,8 +4221,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds nullpo_retv(sd); nullpo_retv(dstsd); - if( dstsd->chatID ) { - struct chat_data *cd = map->id2cd(dstsd->chatID); + if (dstsd->chat_id != 0) { + struct chat_data *cd = map->id2cd(dstsd->chat_id); if (cd != NULL && cd->usersd[0] == dstsd) clif->dispchat(cd,sd->fd); } else if( dstsd->state.vending ) @@ -4143,7 +4236,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds clif->charm_single(sd->fd, dstsd); for( i = 0; i < dstsd->sc_display_count; i++ ) { - clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); + clif->sc_continue(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround @@ -4170,7 +4263,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { nullpo_retv(bl); vd = status->get_viewdata(bl); - if (!vd || vd->class_ == INVISIBLE_CLASS) + if (vd == NULL || vd->class == INVISIBLE_CLASS) return; if (bl->type == BL_NPC) { @@ -4333,16 +4426,17 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int p.is_sp_damaged = 0; // TODO: IsSPDamage - Displays blue digits. #endif - if(disguised(dst)) { + if (clif->isdisguised(dst)) { clif->send(&p,sizeof(p),dst,AREA_WOS); p.targetGID = -dst->id; clif->send(&p,sizeof(p),dst,SELF); - } else + } else { clif->send(&p,sizeof(p),dst,AREA); + } - if(disguised(src)) { + if (clif->isdisguised(src)) { p.GID = -src->id; - if (disguised(dst)) + if (clif->isdisguised(dst)) p.targetGID = dst->id; if(damage > 0) p.damage = -1; @@ -4391,7 +4485,7 @@ void clif_sitting(struct block_list* bl) WBUFB(buf,26) = 2; clif->send(buf, packet_len(0x8a), bl, AREA); - if(disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf, 2) = - bl->id; clif->send(buf, packet_len(0x8a), bl, SELF); } @@ -4410,7 +4504,7 @@ void clif_standing(struct block_list* bl) WBUFB(buf,26) = 3; clif->send(buf, packet_len(0x8a), bl, AREA); - if(disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf, 2) = - bl->id; clif->send(buf, packet_len(0x8a), bl, SELF); } @@ -4425,7 +4519,7 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe WBUFW(buf,2) = x; WBUFW(buf,4) = y; WBUFW(buf,6) = type; - mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name,(char*)WBUFP(buf,8)); + mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, WBUFP(buf,8)); if( fd ) { WFIFOHEAD(fd,packet_len(0x192)); @@ -4629,11 +4723,11 @@ int clif_outsight(struct block_list *bl,va_list ap) nullpo_ret(bl); switch(bl->type){ case BL_PC: - if (sd->vd.class_ != INVISIBLE_CLASS) + if (sd->vd.class != INVISIBLE_CLASS) clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - if (sd->chatID) { - struct chat_data *cd = map->id2cd(sd->chatID); - if(cd->usersd[0]==sd) + if (sd->chat_id != 0) { + struct chat_data *cd = map->id2cd(sd->chat_id); + if (cd != NULL && cd->usersd[0] == sd) clif->dispchat(cd,tsd->fd); } if( sd->state.vending ) @@ -4652,7 +4746,7 @@ int clif_outsight(struct block_list *bl,va_list ap) clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); break; default: - if ((vd=status->get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS) + if ((vd=status->get_viewdata(bl)) && vd->class != INVISIBLE_CLASS) clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); break; } @@ -4661,7 +4755,7 @@ int clif_outsight(struct block_list *bl,va_list ap) nullpo_ret(tbl); if (tbl->type == BL_SKILL) //Trap knocked out of sight clif->clearchar_skillunit(BL_UCAST(BL_SKILL, tbl), sd->fd); - else if ((vd = status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS + else if ((vd = status->get_viewdata(tbl)) != NULL && vd->class != INVISIBLE_CLASS && !(tbl->type == BL_NPC && (BL_UCAST(BL_NPC, tbl)->option&OPTION_INVISIBLE))) clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); } @@ -4735,9 +4829,9 @@ void clif_skillinfoblock(struct map_session_data *sd) WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10)= 0; } - safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; + WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class))? 1:0; else WFIFOB(fd,len+36) = 0; len += 37; @@ -4786,9 +4880,9 @@ void clif_addskill(struct map_session_data *sd, int id) WFIFOW(fd,10) = 0; WFIFOW(fd,12) = 0; } - safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0; + WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class))? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len(0x111)); @@ -4833,7 +4927,7 @@ void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, in WFIFOW(fd, 6) = skill->get_sp(skill_id, skill_lv); WFIFOW(fd, 8) = (flag)?skill->get_range2(&sd->bl, skill_id, skill_lv) : skill->get_range(skill_id, skill_lv); if( flag ) - WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_)) ? 1 : 0; + WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class)) ? 1 : 0; else WFIFOB(fd,10) = 1; @@ -4866,7 +4960,7 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf) WFIFOW(fd,12) = 0; } if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; + WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class))? 1:0; else WFIFOB(fd,14) = 0; WFIFOSET(fd,packet_len(0x7e1)); @@ -4887,7 +4981,7 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf) /// is disposable: /// 0 = yellow chat text "[src name] will use skill [skill name]." /// 1 = no text -void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime) +void clif_useskill(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int casttime) { #if PACKETVER < 20091124 const int cmd = 0x13e; @@ -4895,6 +4989,7 @@ void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, const int cmd = 0x7fb; #endif unsigned char buf[32]; + int property = skill->get_ele(skill_id, skill_lv); WBUFW(buf,0) = cmd; WBUFL(buf,2) = src_id; @@ -4908,12 +5003,13 @@ void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, WBUFB(buf,24) = 0; // isDisposable #endif - if (disguised(bl)) { + if (clif->isdisguised(bl)) { clif->send(buf,packet_len(cmd), bl, AREA_WOS); WBUFL(buf,2) = -src_id; clif->send(buf,packet_len(cmd), bl, SELF); - } else + } else { clif->send(buf,packet_len(cmd), bl, AREA); + } } /// Notifies clients in area, that an object canceled casting (ZC_DISPEL). @@ -5043,16 +5139,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick WBUFW(buf, 26) = skill_lv; WBUFW(buf, 28) = div; WBUFB(buf, 30) = type; - if (disguised(dst)) { + if (clif->isdisguised(dst)) { clif->send(buf, packet_len(0x114), dst, AREA_WOS); WBUFL(buf, 8) = -dst->id; clif->send(buf, packet_len(0x114), dst, SELF); - } else + } else { clif->send(buf, packet_len(0x114), dst, AREA); + } - if (disguised(src)) { + if (clif->isdisguised(src)) { WBUFL(buf, 4) = -src->id; - if (disguised(dst)) + if (clif->isdisguised(dst)) WBUFL(buf, 8) = dst->id; if (damage > 0) WBUFW(buf, 24) = -1; @@ -5082,16 +5179,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick #else WBUFB(buf, 32) = (type == BDT_SKILL) ? BDT_MULTIHIT : type; #endif - if (disguised(dst)) { + if (clif->isdisguised(dst)) { clif->send(buf, packet_len(0x1de), dst, AREA_WOS); WBUFL(buf,8)=-dst->id; clif->send(buf, packet_len(0x1de), dst, SELF); - } else + } else { clif->send(buf, packet_len(0x1de), dst, AREA); + } - if (disguised(src)) { + if (clif->isdisguised(src)) { WBUFL(buf, 4) = -src->id; - if (disguised(dst)) + if (clif->isdisguised(dst)) WBUFL(buf, 8) = dst->id; if (damage > 0) WBUFL(buf, 24) = -1; @@ -5140,15 +5238,15 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic WBUFW(buf,32)=div; WBUFB(buf,34)=type; clif->send(buf,packet_len(0x115),src,AREA); - if(disguised(src)) { + if (clif->isdisguised(src)) { WBUFL(buf,4)=-src->id; if(damage > 0) WBUFW(buf,28)=-1; clif->send(buf,packet_len(0x115),src,SELF); } - if (disguised(dst)) { + if (clif->isdisguised(dst)) { WBUFL(buf,8)=-dst->id; - if (disguised(src)) + if (clif->isdisguised(src)) WBUFL(buf,4)=src->id; else if(damage > 0) WBUFW(buf,28)=-1; @@ -5160,33 +5258,46 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic } #endif // 0 -/// Non-damaging skill effect (ZC_USE_SKILL). -/// 011a <skill id>.W <skill lv>.W <dst id>.L <src id>.L <result>.B -int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail) +/// Non-damaging skill effect. +/// 011a <skill id>.W <skill lv>.W <dst id>.L <src id>.L <result>.B (ZC_USE_SKILL) +/// 09cb <skill id>.W <skill lv>.L <dst id>.L <src id>.L <result>.B (ZC_USE_SKILL2) +int clif_skill_nodamage(struct block_list *src, struct block_list *dst, uint16 skill_id, int heal, int fail) { unsigned char buf[32]; + short offset = 0; +#if PACKETVER < 20131223 + short cmd = 0x11a; +#else + short cmd = 0x9cb; +#endif + int len = packet_len(cmd); nullpo_ret(dst); - WBUFW(buf,0)=0x11a; - WBUFW(buf,2)=skill_id; - WBUFW(buf,4)=min(heal, INT16_MAX); - WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=src?src->id:0; - WBUFB(buf,14)=fail; - - if (disguised(dst)) { - clif->send(buf,packet_len(0x11a),dst,AREA_WOS); - WBUFL(buf,6)=-dst->id; - clif->send(buf,packet_len(0x11a),dst,SELF); + WBUFW(buf, 0) = cmd; + WBUFW(buf, 2) = skill_id; +#if PACKETVER < 20131223 + WBUFW(buf, 4) = min(heal, INT16_MAX); +#else + WBUFL(buf, 4) = min(heal, INT_MAX); + offset += 2; +#endif + WBUFL(buf, 6 + offset) = dst->id; + WBUFL(buf, 10 + offset) = src ? src->id : 0; + WBUFB(buf, 14 + offset) = fail; + + if (clif->isdisguised(dst)) { + clif->send(buf, len, dst, AREA_WOS); + WBUFL(buf, 6 + offset) = -dst->id; + clif->send(buf, len, dst, SELF); } else - clif->send(buf,packet_len(0x11a),dst,AREA); + clif->send(buf, len, dst, AREA); - if(src && disguised(src)) { - WBUFL(buf,10)=-src->id; - if (disguised(dst)) - WBUFL(buf,6)=dst->id; - clif->send(buf,packet_len(0x11a),src,SELF); + if (src && clif->isdisguised(src)) { + WBUFL(buf, 10 + offset) = -src->id; + if (clif->isdisguised(dst)) + WBUFL(buf, 6 + offset) = dst->id; + clif->send(buf, len, src, SELF); } return fail; @@ -5206,12 +5317,13 @@ void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int WBUFW(buf,10)=x; WBUFW(buf,12)=y; WBUFL(buf,14)=(uint32)tick; - if(disguised(src)) { + if (clif->isdisguised(src)) { clif->send(buf,packet_len(0x117),src,AREA_WOS); WBUFL(buf,4)=-src->id; clif->send(buf,packet_len(0x117),src,SELF); - } else + } else { clif->send(buf,packet_len(0x117),src,AREA); + } } /// Presents a list of available warp destinations (ZC_WARPLIST). @@ -5227,12 +5339,12 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s WFIFOW(fd,0) = 0x11c; WFIFOW(fd,2) = skill_id; memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT); - if (map1 == (unsigned short)-1) strcpy((char*)WFIFOP(fd,4), "Random"); + if (map1 == (unsigned short)-1) strcpy(WFIFOP(fd,4), "Random"); else // normal map name - if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), (char*)WFIFOP(fd,4)); - if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), (char*)WFIFOP(fd,20)); - if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), (char*)WFIFOP(fd,36)); - if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), (char*)WFIFOP(fd,52)); + if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), WFIFOP(fd,4)); + if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), WFIFOP(fd,20)); + if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), WFIFOP(fd,36)); + if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), WFIFOP(fd,52)); WFIFOSET(fd,packet_len(0x11c)); sd->menuskill_id = skill_id; @@ -5491,24 +5603,25 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT). /// 008e <packet len>.W <message>.?B -void clif_displaymessage(const int fd, const char* mes) { +void clif_displaymessage(const int fd, const char *mes) +{ nullpo_retv(mes); - if( map->cpsd_active && fd == 0 ) { + if (map->cpsd_active && fd == 0) { ShowInfo("HCP: %s\n",mes); - } else if ( fd > 0 ) { + } else if (fd > 0) { #if PACKETVER == 20141022 /** for some reason game client crashes depending on message pattern (only for this packet) **/ /** so we redirect to ZC_NPC_CHAT **/ clif->messagecolor_self(fd, COLOR_DEFAULT, mes); #else - size_t len; + int len = (int)strnlen(mes, 255); - if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line. + if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate - safestrncpy((char *)WFIFOP(fd,4), mes, len + 1); + WFIFOW(fd,2) = 5 + len; // 4 + len + NUL terminate + safestrncpy(WFIFOP(fd,4), mes, len + 1); WFIFOSET(fd, 5 + len); } #endif @@ -5529,7 +5642,7 @@ void clif_displaymessage2(const int fd, const char* mes) { line = strtok(message, "\n"); while(line != NULL) { // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) - size_t len = strnlen(line, 255); + int len = (int)strnlen(line, 255); if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. if( map->cpsd_active && fd == 0 ) { @@ -5538,7 +5651,7 @@ void clif_displaymessage2(const int fd, const char* mes) { WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate - safestrncpy((char *)WFIFOP(fd,4), line, len + 1); + safestrncpy(WFIFOP(fd,4), line, len + 1); WFIFOSET(fd, 5 + len); } } @@ -5567,11 +5680,11 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) { /* process */ va_start(ap,mes); - len += vsnprintf((char *)WFIFOP(fd,4), 255, mes, ap); + len += vsnprintf(WFIFOP(fd,4), 255, mes, ap); va_end(ap); /* adjusting */ - ptr = (char *)WFIFOP(fd,4); + ptr = WFIFOP(fd,4); ptr[len - 1] = '\0'; /* */ @@ -5583,7 +5696,7 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) { } /// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST). /// 009a <packet len>.W <message>.?B -void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type, enum send_target target) +void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target) { int lp = (type&BC_COLOR_MASK) ? 4 : 0; unsigned char *buf = NULL; @@ -5607,38 +5720,38 @@ void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type * Displays a message on a 'bl' to all it's nearby clients * Used by npc_globalmessage *------------------------------------------*/ -void clif_GlobalMessage(struct block_list* bl, const char* message) { +void clif_GlobalMessage(struct block_list *bl, const char *message) +{ char buf[256]; - size_t len; + int len; nullpo_retv(bl); - if(!message) + if (message == NULL) return; - len = strlen(message)+1; + len = (int)strlen(message)+1; - if (len > sizeof(buf)-8) { - ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%"PRIuS").\n", message, len); - len = sizeof(buf)-8; + if (len > (int)sizeof(buf)-8) { + ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len); + len = (int)sizeof(buf)-8; } - WBUFW(buf,0)=0x8d; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=bl->id; - safestrncpy((char *) WBUFP(buf,8),message,len); - clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); - + WBUFW(buf,0) = 0x8d; + WBUFW(buf,2) = len+8; + WBUFL(buf,4) = bl->id; + safestrncpy(WBUFP(buf,8),message,len); + clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT); } /// Send broadcast message with font formatting (ZC_BROADCAST2). /// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B -void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target) +void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target) { unsigned char *buf; nullpo_retv(mes); - buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char)); + buf = aMalloc((16 + len)*sizeof(unsigned char)); WBUFW(buf,0) = 0x1c3; WBUFW(buf,2) = len + 16; WBUFL(buf,4) = fontColor; @@ -5658,13 +5771,24 @@ void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigne /// 5 = HP (SP_HP) /// 7 = SP (SP_SP) /// ? = ignored -void clif_heal(int fd,int type,int val) +void clif_heal(int fd, int type, int val) { - WFIFOHEAD(fd,packet_len(0x13d)); - WFIFOW(fd,0)=0x13d; - WFIFOW(fd,2)=type; - WFIFOW(fd,4)=cap_value(val,0,INT16_MAX); - WFIFOSET(fd,packet_len(0x13d)); +#if PACKETVER < 20150513 + short cmd = 0x13d; +#else + short cmd = 0xa27; +#endif + int len = packet_len(cmd); + + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = cmd; + WFIFOW(fd, 2) = type; +#if PACKETVER < 20150513 + WFIFOW(fd, 4) = cap_value(val, 0, INT16_MAX); +#else + WFIFOL(fd, 4) = cap_value(val, 0, INT_MAX); +#endif + WFIFOSET(fd, len); } /// Displays resurrection effect (ZC_RESURRECTION). @@ -5682,7 +5806,7 @@ void clif_resurrection(struct block_list *bl,int type) WBUFW(buf,6)=0; clif->send(buf,packet_len(0x148),bl, type == 1 ? AREA : AREA_WOS); - if (disguised(bl)) { + if (clif->isdisguised(bl)) { struct map_session_data *sd = BL_UCAST(BL_PC, bl); if (sd->fontcolor) { WBUFL(buf,2)=-bl->id; @@ -5806,7 +5930,7 @@ void clif_upgrademessage(int fd, int result, int item_id) /// Whisper is transmitted to the destination player (ZC_WHISPER). /// 0097 <packet len>.W <nick>.24B <message>.?B /// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104) -void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len) +void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len) { #if PACKETVER >= 20091104 struct map_session_data *ssd = NULL; @@ -5815,21 +5939,21 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len) nullpo_retv(mes); #if PACKETVER < 20091104 - WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4); + WFIFOHEAD(fd, mes_len + NAME_LENGTH + 5); WFIFOW(fd,0) = 0x97; - WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4; - safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); - safestrncpy((char*)WFIFOP(fd,28), mes, mes_len); + WFIFOW(fd,2) = mes_len + NAME_LENGTH + 5; + safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH); + safestrncpy(WFIFOP(fd,28), mes, mes_len + 1); WFIFOSET(fd,WFIFOW(fd,2)); #else ssd = map->nick2sd(nick); - WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8); + WFIFOHEAD(fd, mes_len + NAME_LENGTH + 9); WFIFOW(fd,0) = 0x97; - WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8; - safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); + WFIFOW(fd,2) = mes_len + NAME_LENGTH + 9; + safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH); WFIFOL(fd,28) = (ssd && pc_get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char - safestrncpy((char*)WFIFOP(fd,32), mes, mes_len); + safestrncpy(WFIFOP(fd,32), mes, mes_len + 1); WFIFOSET(fd,WFIFOW(fd,2)); #endif } @@ -5865,7 +5989,7 @@ void clif_solved_charname(int fd, int charid, const char* name) WFIFOHEAD(fd,packet_len(0x194)); WFIFOW(fd,0)=0x194; WFIFOL(fd,2)=charid; - safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0x194)); } @@ -5979,7 +6103,7 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * WFIFOW(fd,0)=0x1fc; for (i = c = 0; i < MAX_INVENTORY; i++) { int nameid = dstsd->status.inventory[i].nameid; - if (nameid > 0 && dstsd->status.inventory[i].attribute != 0) { // && skill_can_repair(sd,nameid)) { + if (nameid > 0 && (dstsd->status.inventory[i].attribute & ATTR_BROKEN) != 0) { // && skill_can_repair(sd,nameid)) { WFIFOW(fd,c*13+4) = i; WFIFOW(fd,c*13+6) = nameid; WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine; @@ -6089,7 +6213,7 @@ void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv WFIFOW(fd, 8)=skill_lv; WFIFOW(fd,10)=skill->get_sp(skill_id,skill_lv); WFIFOW(fd,12)=skill->get_range2(&sd->bl, skill_id,skill_lv); - safestrncpy((char*)WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); + safestrncpy(WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); WFIFOB(fd,38)=0; WFIFOSET(fd,packet_len(0x147)); } @@ -6127,7 +6251,7 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) WBUFB(buf,12+offset)=sd->status.cart[n].refine; clif->addcards(WBUFP(buf,13+offset), &sd->status.cart[n]); #if PACKETVER >= 20150226 - clif->add_random_options(WBUFP(buf,21+offset), &sd->status.cart[n]); + clif->add_item_options(WBUFP(buf, 21 + offset), &sd->status.cart[n]); #endif WFIFOSET(fd,packet_len(cartaddType)); } @@ -6176,7 +6300,7 @@ void clif_showvendingboard(struct block_list* bl, const char* message, int fd) WBUFW(buf,0) = 0x131; WBUFL(buf,2) = bl->id; - safestrncpy((char*)WBUFP(buf,6), message, 80); + safestrncpy(WBUFP(buf,6), message, 80); if( fd ) { WFIFOHEAD(fd,packet_len(0x131)); @@ -6255,7 +6379,7 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven WFIFOB(fd,offset+13+i*item_length) = vsd->status.cart[index].refine; clif->addcards(WFIFOP(fd,offset+14+i*item_length), &vsd->status.cart[index]); #if PACKETVER >= 20150226 - clif->add_random_options(WFIFOP(fd,offset+22+i*item_length), &vsd->status.cart[index]); + clif->add_item_options(WFIFOP(fd, offset + 22 + i * item_length), &vsd->status.cart[index]); #endif } WFIFOSET(fd,WFIFOW(fd,2)); @@ -6321,34 +6445,46 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven WFIFOB(fd,21+i*item_length) = sd->status.cart[index].refine; clif->addcards(WFIFOP(fd,22+i*item_length), &sd->status.cart[index]); #if PACKETVER >= 20150226 - clif->add_random_options(WFIFOP(fd,30+22+i*item_length), &sd->status.cart[index]); + clif->add_item_options(WFIFOP(fd, 30 + i * item_length), &sd->status.cart[index]); #endif } WFIFOSET(fd,WFIFOW(fd,2)); -#if PACKETVER >= 20141022 +#if PACKETVER >= 20140625 /** should go elsewhere perhaps? it has to be bundled with this however. **/ - WFIFOHEAD(fd, 3); + WFIFOHEAD(fd, packet_len(0xa28)); WFIFOW(fd, 0) = 0xa28; WFIFOB(fd, 2) = 0;/** 1 is failure. our current responses to failure are working so not yet implemented **/ - WFIFOSET(fd, 3); + WFIFOSET(fd, packet_len(0xa28)); #endif } -/// Inform merchant that someone has bought an item (ZC_DELETEITEM_FROM_MCSTORE). -/// 0137 <index>.W <amount>.W -void clif_vendingreport(struct map_session_data* sd, int index, int amount) +/// Inform merchant that someone has bought an item. +/// 0137 <index>.W <amount>.W (ZC_DELETEITEM_FROM_MCSTORE). +/// 09e5 <index>.W <amount>.W <GID>.L <Date>.L <zeny>.L (ZC_DELETEITEM_FROM_MCSTORE2). +void clif_vendingreport(struct map_session_data* sd, int index, int amount, uint32 char_id, int zeny) { int fd; +#if PACKETVER < 20141016 // TODO : not sure for client date [Napster] + const int cmd = 0x137; +#else + const int cmd = 0x9e5; +#endif + const int len = packet_len(cmd); nullpo_retv(sd); fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x137)); - WFIFOW(fd,0) = 0x137; - WFIFOW(fd,2) = index+2; - WFIFOW(fd,4) = amount; - WFIFOSET(fd,packet_len(0x137)); + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = cmd; + WFIFOW(fd, 2) = index + 2; + WFIFOW(fd, 4) = amount; +#if PACKETVER >= 20141016 + WFIFOL(fd,6) = char_id; // GID + WFIFOL(fd,10) = (int)time(NULL); // Date + WFIFOL(fd,14) = zeny; // zeny +#endif + WFIFOSET(fd, len); } /// Result of organizing a party (ZC_ACK_MAKE_GROUP). @@ -6404,7 +6540,7 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) WBUFB(buf,14) = (p->party.member[i].online)?0:1; memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH); memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH); - mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, (char*)WBUFP(buf,63)); + mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, WBUFP(buf,63)); WBUFB(buf,79) = (p->party.item&1)?1:0; WBUFB(buf,80) = (p->party.item&2)?1:0; clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY); @@ -6437,7 +6573,7 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd) WBUFL(buf,28+c*46) = m->account_id; memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH); - mapindex->getmapname_ext(mapindex_id2name(m->map), (char*)WBUFP(buf,28+c*46+28)); + mapindex->getmapname_ext(mapindex_id2name(m->map), WBUFP(buf,28+c*46+28)); WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1; WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1; c++; @@ -6517,7 +6653,7 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res #if PACKETVER < 20070904 if( result == 7 ) { - clif->message(fd, msg_sd(sd,3)); + clif->message(fd, msg_sd(sd,3)); // Character not found. return; } #endif @@ -6525,13 +6661,13 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res #if PACKETVER < 20070821 WFIFOHEAD(fd,packet_len(0xfd)); WFIFOW(fd,0) = 0xfd; - safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + safestrncpy(WFIFOP(fd,2),nick,NAME_LENGTH); WFIFOB(fd,26) = result; WFIFOSET(fd,packet_len(0xfd)); #else WFIFOHEAD(fd,packet_len(0x2c5)); WFIFOW(fd,0) = 0x2c5; - safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + safestrncpy(WFIFOP(fd,2),nick,NAME_LENGTH); WFIFOL(fd,26) = result; WFIFOSET(fd,packet_len(0x2c5)); #endif @@ -6615,7 +6751,7 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int /// Party chat message (ZC_NOTIFY_CHAT_PARTY). /// 0109 <packet len>.W <account id>.L <message>.?B -void clif_party_message(struct party_data* p, int account_id, const char* mes, int len) +void clif_party_message(struct party_data *p, int account_id, const char *mes, int len) { struct map_session_data *sd; int i; @@ -6623,22 +6759,24 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i nullpo_retv(p); nullpo_retv(mes); - for(i=0; i < MAX_PARTY && !p->data[i].sd;i++); - if(i < MAX_PARTY){ + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL); + + if (i < MAX_PARTY) { unsigned char buf[1024]; + int maxlen = (int)sizeof(buf) - 9; - if (len > sizeof(buf)-8) { - ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%"PRIuS", party_id=%d).\n", - mes, len, sizeof(buf)-8, p->party.party_id); - len = sizeof(buf)-8; + if (len > maxlen) { + ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n", + mes, len, maxlen, p->party.party_id); + len = maxlen; } sd = p->data[i].sd; - WBUFW(buf,0)=0x109; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=account_id; - safestrncpy((char *)WBUFP(buf,8), mes, len); - clif->send(buf,len+8,&sd->bl,PARTY); + WBUFW(buf,0) = 0x109; + WBUFW(buf,2) = len+9; + WBUFL(buf,4) = account_id; + safestrncpy(WBUFP(buf,8), mes, len+1); + clif->send(buf, len+9, &sd->bl, PARTY); } } @@ -6998,21 +7136,31 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) if( src->type == BL_MER ) { struct mercenary_data *md = BL_CAST(BL_MER,src); + int skill_lvl; if( md && md->master && md->devotion_flag ) WBUFL(buf,6) = md->master->bl.id; - WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary->checkskill(md, ML_DEVOTION)); + skill_lvl = mercenary->checkskill(md, ML_DEVOTION); + if (skill_lvl > 0) + WBUFW(buf, 26) = skill->get_range2(src, ML_DEVOTION, skill_lvl); + else + WBUFW(buf, 26) = 0; } else { int i; struct map_session_data *sd = BL_CAST(BL_PC,src); + int skill_lvl; if( sd == NULL ) return; for( i = 0; i < MAX_PC_DEVOTION; i++ ) WBUFL(buf,6+4*i) = sd->devotion[i]; - WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc->checkskill(sd, CR_DEVOTION)); + skill_lvl = pc->checkskill(sd, CR_DEVOTION); + if (skill_lvl > 0) + WBUFW(buf, 26) = skill->get_range2(src, CR_DEVOTION, skill_lvl); + else + WBUFW(buf, 26) = 0; } if( tsd ) @@ -7112,6 +7260,13 @@ void clif_mvp_item(struct map_session_data *sd,int nameid) /// 010b <exp>.L void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) { +#if PACKETVER >= 20131223 // Kro removed this packet [Napster] + if (battle_config.mvp_exp_reward_message) { + char e_msg[CHAT_SIZE_MAX]; + sprintf(e_msg, msg_txt(855), exp); + clif->messagecolor_self(sd->fd, COLOR_CYAN, e_msg); // Congratulations! You are the MVP! Your reward EXP Points are %u !! + } +#else int fd; nullpo_retv(sd); @@ -7121,6 +7276,7 @@ void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) WFIFOW(fd,0)=0x10b; WFIFOL(fd,2)=cap_value(exp,0,INT32_MAX); WFIFOSET(fd,packet_len(0x10b)); +#endif } /// Dropped MVP item reward message (ZC_THROW_MVPITEM). @@ -7303,7 +7459,7 @@ void clif_guild_basicinfo(struct map_session_data *sd) { memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); - safestrncpy((char*)WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles" + safestrncpy(WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles" WFIFOL(fd,110) = 0; // zeny WFIFOSET(fd,packet_len(0x1b6)); @@ -7366,7 +7522,7 @@ void clif_guild_memberlist(struct map_session_data *sd) WFIFOW(fd,c*104+12)=m->hair; WFIFOW(fd,c*104+14)=m->hair_color; WFIFOW(fd,c*104+16)=m->gender; - WFIFOW(fd,c*104+18)=m->class_; + WFIFOW(fd,c*104+18)=m->class; WFIFOW(fd,c*104+20)=m->lv; WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX); WFIFOL(fd,c*104+26)=m->online; @@ -7546,7 +7702,7 @@ void clif_guild_skillinfo(struct map_session_data* sd) WFIFOW(fd, p + 8) = 0; WFIFOW(fd, p + 10) = 0; } - safestrncpy((char*)WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; } @@ -7647,8 +7803,8 @@ void clif_guild_expulsion(struct map_session_data* sd, const char* name, const c nullpo_retv(mes); WBUFW(buf,0) = cmd; - safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); - safestrncpy((char*)WBUFP(buf,26), mes, 40); + safestrncpy(WBUFP(buf,2), name, NAME_LENGTH); + safestrncpy(WBUFP(buf,26), mes, 40); #if PACKETVER < 20100803 memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons) #endif @@ -7715,7 +7871,7 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 5; - safestrncpy((char*)WBUFP(buf,4), mes, len+1); + safestrncpy(WBUFP(buf,4), mes, len+1); if ((sd = guild->getavailablesd(g)) != NULL) clif->send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); @@ -7859,7 +8015,7 @@ void clif_talkiebox(struct block_list* bl, const char* talkie) WBUFW(buf,0) = 0x191; WBUFL(buf,2) = bl->id; - safestrncpy((char*)WBUFP(buf,6),talkie,MESSAGE_SIZE); + safestrncpy(WBUFP(buf,6),talkie,MESSAGE_SIZE); clif->send(buf,packet_len(0x191),bl,AREA); } @@ -7942,7 +8098,7 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess WFIFOW(fd,0) = 0x1e2; WFIFOL(fd,2) = ssd->status.account_id; WFIFOL(fd,6) = ssd->status.char_id; - safestrncpy((char*)WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); WFIFOSET(fd, packet_len(0x1e2)); } */ @@ -7950,24 +8106,26 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess /*========================================== * Displays a message using the guild-chat colors to the specified targets. [Skotlex] *------------------------------------------*/ -void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target) +void clif_disp_message(struct block_list *src, const char *mes, enum send_target target) { unsigned char buf[256]; + int len; + + nullpo_retv(mes); + nullpo_retv(src); + len = (int)strlen(mes); if (len == 0) return; - nullpo_retv(src); - nullpo_retv(mes); - - if (len > sizeof(buf)-5) { - ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id); - len = sizeof(buf)-5; + if (len > (int)sizeof(buf)-5) { + ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id); + len = (int)sizeof(buf)-5; } WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 5; - safestrncpy((char*)WBUFP(buf,4), mes, len+1); + safestrncpy(WBUFP(buf,4), mes, len+1); clif->send(buf, WBUFW(buf,2), src, target); } @@ -8041,7 +8199,7 @@ void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, WFIFOHEAD(fd,packet_len(0x14b)); WFIFOW(fd,0) = 0x14b; WFIFOB(fd,2) = type; - safestrncpy((char*)WFIFOP(fd,3), sd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,3), sd->status.name, NAME_LENGTH); WFIFOSET(fd, packet_len(0x14b)); } @@ -8099,7 +8257,7 @@ void clif_playBGM(struct map_session_data* sd, const char* name) fd = sd->fd; WFIFOHEAD(fd,packet_len(0x7fe)); WFIFOW(fd,0) = 0x7fe; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0x7fe)); } @@ -8127,7 +8285,7 @@ void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const fd = sd->fd; WFIFOHEAD(fd,packet_len(0x1d3)); WFIFOW(fd,0) = 0x1d3; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOB(fd,26) = type; WFIFOL(fd,27) = 0; WFIFOL(fd,31) = bl->id; @@ -8142,7 +8300,7 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum nullpo_retv(name); WBUFW(buf,0) = 0x1d3; - safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); + safestrncpy(WBUFP(buf,2), name, NAME_LENGTH); WBUFB(buf,26) = type; WBUFL(buf,27) = 0; WBUFL(buf,31) = bl->id; @@ -8167,7 +8325,7 @@ void clif_specialeffect(struct block_list* bl, int type, enum send_target target clif->send(buf, packet_len(0x1f3), bl, target); - if (disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; clif->send(buf, packet_len(0x1f3), bl, SELF); } @@ -8199,8 +8357,7 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen clif->send(buf, packet_len(0x284), bl, target); - if( disguised(bl) ) - { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; clif->send(buf, packet_len(0x284), bl, SELF); } @@ -8216,17 +8373,18 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen */ void clif_messagecolor_self(int fd, uint32 color, const char *msg) { - size_t msg_len; + int msg_len; nullpo_retv(msg); - msg_len = strlen(msg) + 1; + msg_len = (int)strlen(msg) + 1; + Assert_retv(msg_len <= INT16_MAX - 12); WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; WFIFOL(fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); + safestrncpy(WFIFOP(fd,12), msg, msg_len); WFIFOSET(fd, msg_len + 12); } @@ -8239,17 +8397,19 @@ void clif_messagecolor_self(int fd, uint32 color, const char *msg) * @param color Message color (RGB format: 0xRRGGBB) * @param msg Message text */ -void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg) +void clif_messagecolor(struct block_list *bl, uint32 color, const char *msg) { - size_t msg_len = strlen(msg) + 1; + int msg_len; uint8 buf[256]; nullpo_retv(bl); nullpo_retv(msg); - if (msg_len > sizeof(buf)-12) { - ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len); - msg_len = sizeof(buf)-12; + msg_len = (int)strlen(msg) + 1; + + if (msg_len > (int)sizeof(buf)-12) { + ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%d).\n", msg, msg_len); + msg_len = (int)sizeof(buf)-12; } WBUFW(buf,0) = 0x2C1; @@ -8272,9 +8432,11 @@ void clif_refresh_storagewindow(struct map_session_data *sd) nullpo_retv(sd); // Notify the client that the storage is open if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { - storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + if (sd->storage.aggregate > 0) { + storage->sortitem(VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); + clif->storagelist(sd, VECTOR_DATA(sd->storage.item), VECTOR_LENGTH(sd->storage.item)); + } + clif->updatestorageamount(sd, sd->storage.aggregate, MAX_STORAGE); } // Notify the client that the gstorage is open otherwise it will // remain locked forever and nobody will be able to access it @@ -8329,7 +8491,7 @@ void clif_refresh(struct map_session_data *sd) clif->elemental_info(sd); map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); clif->weather_check(sd); - if( sd->chatID ) + if (sd->chat_id != 0) chat->leave(sd, false); if( sd->state.vending ) clif->openvending(sd, sd->bl.id, sd->vending); @@ -8345,7 +8507,7 @@ void clif_refresh(struct map_session_data *sd) mail->clear(sd); - if( disguised(&sd->bl) ) {/* refresh-da */ + if (clif->isdisguised(&sd->bl)) {/* refresh-da */ short disguise = sd->disguise; pc->disguise(sd, -1); pc->disguise(sd, disguise); @@ -8475,7 +8637,7 @@ void clif_charnameack (int fd, struct block_list *bl) memcpy(WBUFP(buf,6), BL_UCCAST(BL_ELEM, bl)->db->name, NAME_LENGTH); break; default: - ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); + ShowError("clif_charnameack: bad type %u(%d)\n", bl->type, bl->id); return; } @@ -8560,8 +8722,7 @@ void clif_slide(struct block_list *bl, int x, int y) WBUFW(buf, 8) = y; clif->send(buf, packet_len(0x1ff), bl, AREA); - if( disguised(bl) ) - { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; clif->send(buf, packet_len(0x1ff), bl, SELF); } @@ -8569,34 +8730,33 @@ void clif_slide(struct block_list *bl, int x, int y) /// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well /// 008d <packet len>.W <id>.L <message>.?B -void clif_disp_overhead(struct block_list *bl, const char* mes) +void clif_disp_overhead(struct block_list *bl, const char *mes) { unsigned char buf[256]; //This should be more than sufficient, the theoretical max is CHAT_SIZE + 8 (pads and extra inserted crap) - size_t len_mes; + int mes_len; nullpo_retv(bl); nullpo_retv(mes); - len_mes = strlen(mes)+1; //Account for \0 + mes_len = (int)strlen(mes)+1; //Account for \0 - if (len_mes > sizeof(buf)-8) { - ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes); - len_mes = sizeof(buf)-8; //Trunk it to avoid problems. + if (mes_len > (int)sizeof(buf)-8) { + ShowError("clif_disp_overhead: Message too long (length %d)\n", mes_len); + mes_len = sizeof(buf)-8; //Trunk it to avoid problems. } // send message to others WBUFW(buf,0) = 0x8d; - WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id) + WBUFW(buf,2) = mes_len + 8; // len of message + 8 (command+len+id) WBUFL(buf,4) = bl->id; - safestrncpy((char*)WBUFP(buf,8), mes, len_mes); + safestrncpy(WBUFP(buf,8), mes, mes_len); clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); // send back message to the speaker - if( bl->type == BL_PC ) { + if (bl->type == BL_PC) { WBUFW(buf,0) = 0x8e; - WBUFW(buf, 2) = len_mes + 4; - safestrncpy((char*)WBUFP(buf,4), mes, len_mes); + WBUFW(buf, 2) = mes_len + 4; + safestrncpy(WBUFP(buf,4), mes, mes_len); clif->send(buf, WBUFW(buf,2), bl, SELF); } - } /*========================== @@ -8680,7 +8840,7 @@ void clif_starskill(struct map_session_data* sd, const char* mapname, int monste WFIFOHEAD(fd,packet_len(0x20e)); WFIFOW(fd,0) = 0x20e; - safestrncpy((char*)WFIFOP(fd,2), mapname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), mapname, NAME_LENGTH); WFIFOL(fd,26) = monster_id; WFIFOB(fd,30) = star; WFIFOB(fd,31) = result; @@ -8795,7 +8955,7 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts safestrncpy(viewequip_list.characterName, tsd->status.name, NAME_LENGTH); - viewequip_list.job = tsd->status.class_; + viewequip_list.job = tsd->status.class; viewequip_list.head = tsd->vd.hair_style; viewequip_list.accessory = tsd->vd.head_bottom; viewequip_list.accessory2 = tsd->vd.head_mid; @@ -8880,119 +9040,153 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i WFIFOSET(fd, packet_len(0x7e6)); } -/// Validates one global/guild/party/whisper message packet and tries to recognize its components. -/// Returns true if the packet was parsed successfully. -/// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00 -/// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00 -bool clif_process_message(struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_) { - char *text, *name, *message; - unsigned int packetlen, textlen; - size_t namelen, messagelen; - int fd = sd->fd; +/** + * Validates and processes a global/guild/party message packet. + * + * @param[in] sd The source character. + * @param[in] packet The packet data. + * @param[out] out_buf The output buffer (must be a valid buffer), that will + * be filled with "Name : Message". + * @param[in] out_buflen The size of out_buf (including the NUL terminator). + * @return a pointer to the "Message" part of out_buf. + * @retval NULL if the validation failed, the messages was a command or the + * character can't send chat messages. out_buf shan't be used. + */ +const char *clif_process_chat_message(struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen) +{ + const char *srcname = NULL, *srcmessage = NULL, *message = NULL; + int textlen = 0, namelen = 0, messagelen = 0; - nullpo_retr(false, sd); - nullpo_retr(false, name_); - nullpo_retr(false, namelen_); - nullpo_retr(false, message_); - nullpo_retr(false, messagelen_); - - *name_ = NULL; - *namelen_ = 0; - *message_ = NULL; - *messagelen_ = 0; - - packetlen = RFIFOW(fd,2); - // basic structure checks - if (packetlen < 4 + 1) { + nullpo_ret(sd); + nullpo_ret(packet); + nullpo_ret(out_buf); + + if (packet->packet_len < 4 + 1) { // 4-byte header and at least an empty string is expected - ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name); - return false; + ShowWarning("clif_process_chat_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name); + return NULL; } - text = (char*)RFIFOP(fd,4); - textlen = packetlen - 4; +#if PACKETVER >= 20151001 + // Packet doesn't include a NUL terminator + textlen = packet->packet_len - 4; +#else // PACKETVER < 20151001 + // Packet includes a NUL terminator + textlen = packet->packet_len - 4 - 1; +#endif // PACKETVER > 20151001 - // process <name> part of the packet - if( format == 0 ) - {// name and message are separated by ' : ' - // validate name - name = text; - namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte) + // name and message are separated by ' : ' + srcname = packet->message; + namelen = (int)strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte) - if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name - name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : ' - { - //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another. - ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name); - sockt->eof(fd); // Just kick them out to correct it. - return false; - } + if (strncmp(srcname, sd->status.name, namelen) != 0 // the text must start with the speaker's name + || srcname[namelen] != ' ' || srcname[namelen+1] != ':' || srcname[namelen+2] != ' ' // followed by ' : ' + ) { + //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another. + ShowWarning("clif_process_chat_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name); + sockt->eof(sd->fd); // Just kick them out to correct it. + return NULL; + } - message = name + namelen + 3; - messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included) + srcmessage = packet->message + namelen + 3; // <name> " : " <message> + messagelen = textlen - namelen - 3; + + if (messagelen >= CHAT_SIZE_MAX || textlen >= out_buflen) { + // messages mustn't be too long + // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer. + // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity. + // Neither the official client nor server place any restriction on the length of the data in the packet, + // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table. + ShowWarning("clif_process_chat_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHATBOX_SIZE-1, srcmessage); + return NULL; } - else - {// name has fixed width - if( textlen < NAME_LENGTH + 1 ) - { - ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name); - return false; - } - // validate name - name = text; - namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte) + safestrncpy(out_buf, packet->message, textlen+1); // [!] packet->message is not necessarily NUL terminated + message = out_buf + namelen + 3; - if (name[namelen] != '\0') { - // only restriction is that the name must be zero-terminated - ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name); - return false; - } + if (!pc->process_chat_message(sd, message)) + return NULL; + return message; +} - message = name + NAME_LENGTH; - messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included) - } +/** + * Validates and processes a whisper message packet. + * + * @param[in] sd The source character. + * @param[in] packet The packet data. + * @param[out] out_name The parsed target name buffer (must be a valid + * buffer of size NAME_LENGTH). + * @param[out] out_message The output message buffer (must be a valid buffer). + * @param[in] out_messagelen The size of out_message. + * @retval true if the validation succeeded and the message is a chat message. + * @retval false if the validation failed, the messages was a command or the + * character can't send chat messages. out_name and out_message + * shan't be used. + */ +bool clif_process_whisper_message(struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen) +{ + int namelen = 0, messagelen = 0; - if (messagelen != strnlen(message, messagelen)+1) { - // the declared length must match real length - ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name); + nullpo_retr(false, sd); + nullpo_retr(false, packet); + nullpo_retr(false, out_name); + nullpo_retr(false, out_message); + + if (packet->packet_len < NAME_LENGTH + 4 + 1) { + // 4-byte header and at least an empty string is expected + ShowWarning("clif_process_whisper_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name); return false; } - // verify <message> part of the packet - if (message[messagelen-1] != '\0') { - // message must be zero-terminated - ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name); + + // validate name + namelen = (int)strnlen(packet->name, NAME_LENGTH-1); // name length (w/o zero byte) + + if (packet->name[namelen] != '\0') { + // only restriction is that the name must be zero-terminated + ShowWarning("clif_process_whisper_message: Player '%s' sent an unterminated name!\n", sd->status.name); return false; } - if (messagelen > CHAT_SIZE_MAX-1) { + +#if PACKETVER >= 20151001 + // Packet doesn't include a NUL terminator + messagelen = packet->packet_len - NAME_LENGTH - 4; +#else // PACKETVER < 20151001 + // Packet includes a NUL terminator + messagelen = packet->packet_len - NAME_LENGTH - 4 - 1; +#endif // PACKETVER > 20151001 + + if (messagelen >= CHAT_SIZE_MAX || messagelen >= out_messagelen) { // messages mustn't be too long // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer. // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity. // Neither the official client nor server place any restriction on the length of the data in the packet, // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table. - ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message); + ShowWarning("clif_process_whisper_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, packet->message); return false; } - *name_ = name; - *namelen_ = namelen; - *message_ = message; - *messagelen_ = messagelen; + safestrncpy(out_name, packet->name, namelen+1); // [!] packet->name is not NUL terminated + safestrncpy(out_message, packet->message, messagelen+1); // [!] packet->message is not necessarily NUL terminated + + if (!pc->process_chat_message(sd, out_message)) + return false; + return true; } void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg) { - DBIterator *iter; + struct DBIterator *iter; struct map_session_data *user; - unsigned short msg_len; + int msg_len; uint32 color; nullpo_retv(chan); nullpo_retv(sd); nullpo_retv(msg); iter = db_iterator(chan->users); - msg_len = strlen(msg) + 1; + msg_len = (int)strlen(msg) + 1; + Assert_retv(msg_len <= INT16_MAX - 12); color = channel->config->colors[chan->color]; WFIFOHEAD(sd->fd,msg_len + 12); @@ -9000,7 +9194,7 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch WFIFOW(sd->fd,2) = msg_len + 12; WFIFOL(sd->fd,4) = 0; WFIFOL(sd->fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); + safestrncpy(WFIFOP(sd->fd,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { if( user->fd == sd->fd ) @@ -9017,23 +9211,24 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch void clif_channel_msg2(struct channel_data *chan, char *msg) { - DBIterator *iter; + struct DBIterator *iter; struct map_session_data *user; unsigned char buf[210]; - unsigned short msg_len; + int msg_len; uint32 color; nullpo_retv(chan); nullpo_retv(msg); iter = db_iterator(chan->users); - msg_len = strlen(msg) + 1; + msg_len = (int)strlen(msg) + 1; + Assert_retv(msg_len <= INT16_MAX - 12); color = channel->config->colors[chan->color]; WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = 0; WBUFL(buf,8) = RGB2BGR(color); - safestrncpy((char*)WBUFP(buf,12), msg, msg_len); + safestrncpy(WBUFP(buf,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { WFIFOHEAD(user->fd,msg_len + 12); @@ -9148,7 +9343,7 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { sd->state.warping = 0; sd->state.dialog = 0;/* reset when warping, client dialog will go missing */ - // look + // Character Looks #if PACKETVER < 4 clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); @@ -9158,21 +9353,26 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { if(sd->vd.cloth_color) clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + if (sd->vd.body_style) clif->refreshlook(&sd->bl,sd->bl.id,LOOK_BODY2,sd->vd.body_style,SELF); - // item - clif->inventorylist(sd); // inventory list first, otherwise deleted items in pc->checkitem show up as 'unknown item' - pc->checkitem(sd); - // cart + // Send character inventory to the client. + // call this before pc->checkitem() so that the client isn't called to delete a non-existent item. + clif->inventorylist(sd); + + // Send the cart inventory, counts & weight to the client. if(pc_iscarton(sd)) { clif->cartlist(sd); - clif->updatestatus(sd,SP_CARTINFO); + clif->updatestatus(sd, SP_CARTINFO); } - // weight - clif->updatestatus(sd,SP_WEIGHT); - clif->updatestatus(sd,SP_MAXWEIGHT); + // Check for and delete unavailable/disabled items. + pc->checkitem(sd); + + // Send the character's weight to the client. + clif->updatestatus(sd, SP_WEIGHT); + clif->updatestatus(sd, SP_MAXWEIGHT); // guild // (needs to go before clif_spawn() to show guild emblems correctly) @@ -9392,7 +9592,7 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) { char output[128]; sprintf(output, "[ Kill Steal Protection Disabled. KS is allowed in this map ]"); - clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF); + clif->broadcast(&sd->bl, output, (int)strlen(output) + 1, BC_BLUE, SELF); } map->iwall_get(sd); // Updates Walls Info on this Map to Client @@ -9459,7 +9659,8 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { clif->clearunit_area(&sd->bl, CLR_DEAD); else { skill->usave_trigger(sd); - sd->ud.dir = 0;/* enforce north-facing (not visually, virtually) */ + if (battle_config.player_warp_keep_direction == 1) + clif->changed_dir(&sd->bl, SELF); // Visually updates player facing direction } // Trigger skill effects if you appear standing on them @@ -9474,7 +9675,7 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) { struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. - if( sd->class_ == qi->job ) + if (sd->status.class == qi->job) clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); } else { clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); @@ -9665,11 +9866,9 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) __attribute__((non void clif_parse_QuitGame(int fd, struct map_session_data *sd) { /* Rovert's prevent logout option fixed [Valaris] */ - if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && - (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) - { + if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && !sd->sc.data[SC_SUHIDE] && + (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)) { sockt->eof(fd); - clif->disconnect_ack(sd, 0); } else { clif->disconnect_ack(sd, 1); @@ -9699,7 +9898,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { // 'see people in GM hide' cheat detection #if 0 /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) */ sc = status->get_sc(bl); - if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) && + if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl) && bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple pc_get_group_level(sd) < battle_config.hack_info_GM_level ) { @@ -9718,149 +9917,114 @@ int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data * sd; if( (sd = map->id2sd(id)) ) { sd->fontcolor_tid = INVALID_TIMER; - if( sd->fontcolor && sd->disguise == sd->status.class_ ) + if (sd->fontcolor && sd->disguise == sd->status.class) pc->disguise(sd,-1); } return 0; } -void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -/// Validates and processes global messages -/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT) -/// There are various variants of this packet. -void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) +/** + * Validates and processed global messages. + * + * There are various variants of this packet. + * + * @code + * 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT) + * @endcode + * + * @param fd The incoming file descriptor. + * @param sd The related character. + */ +void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { - const char* text = (char*)RFIFOP(fd,4); - size_t textlen = RFIFOW(fd,2) - 4; - - char *name, *message, *fakename = NULL; - size_t namelen, messagelen; + const struct packet_chat_message *packet = NULL; + char full_message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1]; + const char *message = NULL; + bool is_fakename = false; + int outlen = 0; - bool is_fake; - - // validate packet and retrieve name and message - if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + packet = RP2PTR(fd); + message = clif->process_chat_message(sd, packet, full_message, sizeof full_message); + if (message == NULL) return; - if( atcommand->exec(fd, sd, message, true) ) - return; + pc->check_supernovice_call(sd, message); - if( !pc->can_talk(sd) ) + if (sd->gcbind != NULL) { + channel->send(sd->gcbind, sd, message); return; - - if( battle_config.min_chat_delay ) { //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) - return; - sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; } - if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) { - unsigned int next = pc->nextbaseexp(sd); - if( next == 0 ) next = pc->thisbaseexp(sd); - if( next ) { // 0%, 10%, 20%, ... - int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); - if( (battle_config.snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0% - switch (sd->state.snovice_call_flag) { - case 0: - if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?" - sd->state.snovice_call_flag = 1; - break; - case 1: { - char buf[256]; - snprintf(buf, 256, msg_txt(1480), sd->status.name); - if( strstr(message, buf) ) // "I am %s Super Novice~" - sd->state.snovice_call_flag = 2; - } - break; - case 2: - if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T" - sd->state.snovice_call_flag = 3; - break; - case 3: - sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] - clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions - sd->state.snovice_call_flag = 0; - break; - } - } - } + if (sd->fakename[0] != '\0') { + is_fakename = true; + outlen = (int)strlen(sd->fakename) + (int)strlen(message) + 3 + 1; + } else { + outlen = (int)strlen(full_message) + 1; } - pc->update_idle_time(sd, BCIDLE_CHAT); - - if( sd->gcbind ) { - channel->send(sd->gcbind,sd,message); - return; - } else if ( sd->fontcolor && !sd->chatID ) { - char mout[200]; - unsigned char mylen = 1; + if (sd->fontcolor != 0 && sd->chat_id == 0) { uint32 color = 0; - if( sd->disguise == -1 ) { + if (sd->disguise == -1) { sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0); - pc->disguise(sd,sd->status.class_); - if( pc_isdead(sd) ) + pc->disguise(sd,sd->status.class); + if (pc_isdead(sd)) clif->clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd); - if( unit->is_walking(&sd->bl) ) + if (unit->is_walking(&sd->bl)) clif->move(&sd->ud); - } else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) { + } else if (sd->disguise == sd->status.class && sd->fontcolor_tid != INVALID_TIMER) { const struct TimerData *td; - if( (td = timer->get(sd->fontcolor_tid)) ) { + if ((td = timer->get(sd->fontcolor_tid)) != NULL) timer->settick(sd->fontcolor_tid, td->tick+5000); - } } - mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message); - color = channel->config->colors[sd->fontcolor - 1]; - WFIFOHEAD(fd,mylen + 12); + WFIFOHEAD(fd, outlen + 12); WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = mylen + 12; + WFIFOW(fd,2) = outlen + 12; WFIFOL(fd,4) = sd->bl.id; WFIFOL(fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(fd,12), mout, mylen); + if (is_fakename) + safesnprintf(WFIFOP(fd, 12), outlen, "%s : %s", sd->fakename, message); + else + safestrncpy(WFIFOP(fd, 12), full_message, outlen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); WFIFOL(fd,4) = -sd->bl.id; - WFIFOSET(fd, mylen + 12); + WFIFOSET(fd, outlen + 12); return; } - /** - * Fake Name Design by FatalEror (bug report #9) - **/ - if( ( is_fake = ( sd->fakename[0] ) ) ) { - fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3); - strcpy(fakename, sd->fakename); - strcat(fakename, " : "); - strcat(fakename, message); - textlen = strlen(fakename) + 1; + { + // send message to others + void *buf = aMalloc(8 + outlen); + WBUFW(buf, 0) = 0x8d; + WBUFW(buf, 2) = 8 + outlen; + WBUFL(buf, 4) = sd->bl.id; + if (is_fakename) + safesnprintf(WBUFP(buf, 8), outlen, "%s : %s", sd->fakename, message); + else + safestrncpy(WBUFP(buf, 8), full_message, outlen); + //FIXME: chat has range of 9 only + clif->send(buf, WBUFW(buf, 2), &sd->bl, sd->chat_id != 0 ? CHAT_WOS : AREA_CHAT_WOC); + aFree(buf); } - // send message to others (using the send buffer for temp. storage) - WFIFOHEAD(fd, 8 + textlen); - WFIFOW(fd,0) = 0x8d; - WFIFOW(fd,2) = 8 + textlen; - WFIFOL(fd,4) = sd->bl.id; - safestrncpy((char*)WFIFOP(fd,8), is_fake ? fakename : text, textlen); - //FIXME: chat has range of 9 only - clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); // send back message to the speaker - if( is_fake ) { - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = textlen + 4; - safestrncpy((char*)WFIFOP(fd,4), fakename, textlen); - aFree(fakename); - } else { - memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); - WFIFOW(fd,0) = 0x8e; - } + WFIFOHEAD(fd, 4 + outlen); + WFIFOW(fd, 0) = 0x8e; + WFIFOW(fd, 2) = 4 + outlen; + if (is_fakename) + safesnprintf(WFIFOP(fd, 4), outlen, "%s : %s", sd->fakename, message); + else + safestrncpy(WFIFOP(fd, 4), full_message, outlen); WFIFOSET(fd, WFIFOW(fd,2)); // Chat logging type 'O' / Global Chat logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); // trigger listening npcs - map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); + map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, full_message, strlen(full_message), &sd->bl); } void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -9870,10 +10034,9 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonn void clif_parse_MapMove(int fd, struct map_session_data *sd) { char command[MAP_NAME_LENGTH_EXT+25]; - char* map_name; + char map_name[MAP_NAME_LENGTH_EXT]; - map_name = (char*)RFIFOP(fd,2); - map_name[MAP_NAME_LENGTH_EXT-1]='\0'; + safestrncpy(map_name, RFIFOP(fd,2), MAP_NAME_LENGTH_EXT); sprintf(command, "%cmapmove %s %d %d", atcommand->at_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); atcommand->exec(fd, sd, command, true); } @@ -9905,7 +10068,7 @@ void clif_changed_dir(struct block_list *bl, enum send_target target) clif->send(buf, packet_len(0x9c), bl, target); - if (disguised(bl)) { + if (clif->isdisguised(bl)) { WBUFL(buf,2) = -bl->id; WBUFW(buf,6) = 0; clif->send(buf, packet_len(0x9c), bl, SELF); @@ -9937,7 +10100,7 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) { int emoticon = RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[0]); - if (battle_config.basic_skill_check == 0 || pc->checkskill(sd, NV_BASIC) >= 2) { + if (battle_config.basic_skill_check == 0 || pc->check_basicskill(sd, 2)) { if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris] clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); return; @@ -9997,7 +10160,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, sd->sc.data[SC_TRICKDEAD] || (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) || sd->sc.data[SC_BLADESTOP] || - sd->sc.data[SC_DEEP_SLEEP] ) + sd->sc.data[SC_DEEP_SLEEP] || + sd->sc.data[SC_SUHIDE] ) ) return; @@ -10024,7 +10188,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if( sd->sc.option&OPTION_COSTUME ) return; - if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) { + if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0 && (skill->get_inf2(sd->ud.skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0) { if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); return; @@ -10037,7 +10201,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, } break; case 0x02: // sitdown - if (battle_config.basic_skill_check && pc->checkskill(sd, NV_BASIC) < 3) { + if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 3)) { clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2); break; } @@ -10122,7 +10286,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) { case 0x01: /* Rovert's Prevent logout option - Fixed [Valaris] */ if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] - && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] + && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] && !sd->sc.data[SC_SUHIDE] && (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) { //Send to char-server for character selection. @@ -10134,37 +10298,28 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) { } } -void clif_parse_WisMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -/// Validates and processes whispered messages (CZ_WHISPER). -/// 0096 <packet len>.W <nick>.24B <message>.?B +/** + * Validates and processes whispered messages (CZ_WHISPER). + * + * @code + * 0096 <packet len>.W <nick>.24B <message>.?B + * @endcode + * + * @param fd The incoming file descriptor. + * @param sd The related character. + */ +void clif_parse_WisMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); void clif_parse_WisMessage(int fd, struct map_session_data* sd) { struct map_session_data* dstsd; int i; - char *target, *message; - size_t namelen, messagelen; - - // validate packet and retrieve name and message - if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) ) - return; - - if ( atcommand->exec(fd, sd, message, true) ) - return; + char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1]; + const struct packet_whisper_message *packet = RP2PTR(fd); - // Statuses that prevent the player from whispering - if( !pc->can_talk(sd) ) + if (!clif->process_whisper_message(sd, packet, target, message, sizeof message)) return; - if (battle_config.min_chat_delay) { //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) { - return; - } - sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; - } - - pc->update_idle_time(sd, BCIDLE_CHAT); - // Chat logging type 'W' / Whisper logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); @@ -10172,7 +10327,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // Lordalfa - Paperboy - To whisper NPC commands // //-------------------------------------------------------// if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) { - char* str = target+4; //Skip the NPC: string part. + const char *str = target+4; //Skip the NPC: string part. struct npc_data *nd; if ((nd = npc->name2id(str))) { char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX]; @@ -10207,7 +10362,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) return; } } else if( target[0] == '#' ) { - char *chname = target; + const char *chname = target; struct channel_data *chan = channel->search(chname, sd); if (chan) { @@ -10216,7 +10371,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if (k < sd->channel_count || channel->join(chan, sd, "", true) == HCS_STATUS_OK) { channel->send(chan,sd,message); } else { - clif->message(fd, msg_fd(fd,1402)); + clif->message(fd, msg_fd(fd,1402)); //You're not in that channel, type '@join <#channel_name>' } return; } else if (strcmpi(&chname[1], channel->config->ally_name) == 0) { @@ -10234,7 +10389,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // if there are 'Test' player on an other map-server and 'test' player on this map-server, // and if we ask for 'Test', we must not contact 'test' player // so, we send information to inter-server, which is the only one which decide (and copy correct name). - intif->wis_message(sd, target, message, messagelen); + intif->wis_message(sd, target, message, (int)strlen(message)); return; } @@ -10248,10 +10403,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) } // if player is autotrading - if( dstsd->state.autotrade ) { + if (dstsd->state.autotrade) { char output[256]; sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name); - clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1); + clif->wis_message(fd, map->wisp_server_name, output, (int)strlen(output)); return; } @@ -10268,22 +10423,29 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) clif->wis_end(fd, 0); // 0: success to send wisper // Normal message - clif->wis_message(dstsd->fd, sd->status.name, message, messagelen); + clif->wis_message(dstsd->fd, sd->status.name, message, (int)strlen(message)); } -void clif_parse_Broadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /b /nb (CZ_BROADCAST). /// Request to broadcast a message on whole server. /// 0099 <packet len>.W <text>.?B 00 -void clif_parse_Broadcast(int fd, struct map_session_data* sd) { - char command[CHAT_SIZE_MAX+11]; - char* msg = (char*)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; +void clif_parse_Broadcast(int fd, struct map_session_data *sd) +{ + const char commandname[] = "kami"; + char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' command + ' ' + message + NUL + int len = (int)RFIFOW(fd,2) - 4; + + if (len < 0) + return; + + sprintf(command, "%c%s ", atcommand->at_symbol, commandname); - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + // as the length varies depending on the command used, truncate unreasonably long strings + if (len >= (int)(sizeof command - strlen(command))) + len = (int)(sizeof command - strlen(command)) - 1; - sprintf(command, "%ckami %s", atcommand->at_symbol, msg); + strncat(command, RFIFOP(fd,4), len); atcommand->exec(fd, sd, command, true); } @@ -10312,6 +10474,7 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) sd->sc.data[SC_TRICKDEAD] || sd->sc.data[SC_BLADESTOP] || sd->sc.data[SC_CLOAKINGEXCEED] || + sd->sc.data[SC_SUHIDE] || pc_ismuted(&sd->sc, MANNER_NOITEM) ) ) break; @@ -10378,7 +10541,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) return; } - if ( (!sd->npc_id && pc_istrading(sd)) || sd->chatID ) + if ((!sd->npc_id && pc_istrading(sd)) || sd->chat_id != 0) return; //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] @@ -10395,16 +10558,18 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) __attribute__((non /// Request to equip an item (CZ_REQ_WEAR_EQUIP). /// 00a9 <index>.W <position>.W /// 0998 <index>.W <position>.L -void clif_parse_EquipItem(int fd,struct map_session_data *sd) { - struct packet_equip_item *p = RP2PTR(fd); +void clif_parse_EquipItem(int fd,struct map_session_data *sd) +{ + const struct packet_equip_item *p = RP2PTR(fd); + int index = 0; if(pc_isdead(sd)) { clif->clearunit_area(&sd->bl,CLR_DEAD); return; } - p->index = p->index - 2; - if (p->index >= MAX_INVENTORY) + index = p->index - 2; + if (index >= MAX_INVENTORY) return; //Out of bounds check. if( sd->npc_id ) { @@ -10415,26 +10580,26 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; - if(!sd->status.inventory[p->index].identify) { - clif->equipitemack(sd,p->index,0,EIA_FAIL);// fail + if(!sd->status.inventory[index].identify) { + clif->equipitemack(sd, index, 0, EIA_FAIL);// fail return; } - if(!sd->inventory_data[p->index]) + if(!sd->inventory_data[index]) return; - if(sd->inventory_data[p->index]->type == IT_PETARMOR){ - pet->equipitem(sd,p->index); + if(sd->inventory_data[index]->type == IT_PETARMOR){ + pet->equipitem(sd, index); return; } pc->update_idle_time(sd, BCIDLE_USEITEM); //Client doesn't send the position for ammo. - if(sd->inventory_data[p->index]->type == IT_AMMO) - pc->equipitem(sd,p->index,EQP_AMMO); + if(sd->inventory_data[index]->type == IT_AMMO) + pc->equipitem(sd, index, EQP_AMMO); else - pc->equipitem(sd,p->index,p->wearLocation); + pc->equipitem(sd, index, p->wearLocation); } void clif_parse_UnequipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -10477,9 +10642,11 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) clif->clearunit_area(&sd->bl,CLR_DEAD); return; } - if( sd->npc_id || sd->state.workinprogress&2 ){ -#ifdef RENEWAL - clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. + if (sd->npc_id || sd->state.workinprogress & 2) { +#if PACKETVER >= 20110309 + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); +#else + clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48)); #endif return; } @@ -10492,9 +10659,11 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) clif->pActionRequest_sub(sd, 0x07, bl->id, timer->gettick()); break; case BL_NPC: - if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills -#ifdef RENEWAL + if (sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER) { // TODO: should only work with none 3rd job skills +#if PACKETVER >= 20110309 clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); +#else + clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48)); #endif break; } @@ -10540,14 +10709,30 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) __attribute_ /// 00c8 <packet len>.W { <amount>.W <name id>.W }* void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) { - int n = (RFIFOW(fd,2)-4) /4; - unsigned short* item_list = (unsigned short*)RFIFOP(fd,4); + int n = ((int)RFIFOW(fd,2)-4) / 4; int result; - if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) + Assert_retv(n >= 0); + + if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) { result = 1; - else - result = npc->buylist(sd,n,item_list); + } else { + struct itemlist item_list = { 0 }; + int i; + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + + entry.amount = RFIFOW(fd, 4 + 4 * i); + entry.id = RFIFOW(fd, 4 + 4 * i + 2); + + VECTOR_PUSH(item_list, entry); + } + result = npc->buylist(sd, &item_list); + VECTOR_CLEAR(item_list); + } sd->npc_shopid = 0; //Clear shop data. @@ -10576,15 +10761,32 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) __attribute_ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) { int fail=0,n; - unsigned short *item_list; - n = (RFIFOW(fd,2)-4) /4; - item_list = (unsigned short*)RFIFOP(fd,4); + n = ((int)RFIFOW(fd,2)-4) /4; + + Assert_retv(n >= 0); - if (sd->state.trading || !sd->npc_shopid) + if (sd->state.trading || !sd->npc_shopid) { fail = 1; - else - fail = npc->selllist(sd,n,item_list); + } else { + struct itemlist item_list = { 0 }; + int i; + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + + entry.id = (int)RFIFOW(fd, 4 + 4 * i) - 2; + entry.amount = RFIFOW(fd, 4 + 4 * i + 2); + + VECTOR_PUSH(item_list, entry); + } + fail = npc->selllist(sd, &item_list); + + VECTOR_CLEAR(item_list); + } sd->npc_shopid = 0; //Clear shop data. @@ -10602,14 +10804,14 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); bool pub = (RFIFOB(fd,6) != 0); - const char* password = (char*)RFIFOP(fd,7); //not zero-terminated - const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + const char *password = RFIFOP(fd,7); //not zero-terminated + const char *title = RFIFOP(fd,15); // not zero-terminated char s_password[CHATROOM_PASS_SIZE]; char s_title[CHATROOM_TITLE_SIZE]; if (pc_ismuted(&sd->sc, MANNER_NOROOM)) return; - if(battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 4) { + if(battle_config.basic_skill_check && !pc->check_basicskill(sd, 4)) { clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,3); return; } @@ -10637,7 +10839,7 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) __attribute__ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) { int chatid = RFIFOL(fd,2); - const char* password = (char*)RFIFOP(fd,6); // not zero-terminated + const char *password = RFIFOP(fd,6); // not zero-terminated chat->join(sd,chatid,password); } @@ -10653,8 +10855,8 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); bool pub = (RFIFOB(fd,6) != 0); - const char* password = (char*)RFIFOP(fd,7); // not zero-terminated - const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + const char *password = RFIFOP(fd,7); // not zero-terminated + const char *title = RFIFOP(fd,15); // not zero-terminated char s_password[CHATROOM_PASS_SIZE]; char s_title[CHATROOM_TITLE_SIZE]; @@ -10675,7 +10877,7 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) __attribute /// 1 = normal void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) { - chat->change_owner(sd,(char*)RFIFOP(fd,6)); + chat->change_owner(sd, RFIFOP(fd,6)); } void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -10683,7 +10885,7 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__(( /// 00e2 <name>.24B void clif_parse_KickFromChat(int fd,struct map_session_data *sd) { - chat->kick(sd,(char*)RFIFOP(fd,2)); + chat->kick(sd, RFIFOP(fd,2)); } void clif_parse_ChatLeave(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -10703,10 +10905,10 @@ void clif_noask_sub(struct map_session_data *src, struct map_session_data *targe nullpo_retv(src); // Your request has been rejected by autoreject option. msg = msg_sd(src,392); - clif_disp_onlyself(src, msg, strlen(msg)); + clif_disp_onlyself(src, msg); //Notice that a request was rejected. snprintf(output, 256, msg_sd(target,393+type), src->status.name, 256); - clif_disp_onlyself(target, output, strlen(output)); + clif_disp_onlyself(target, output); } void clif_parse_TradeRequest(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -10717,7 +10919,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) { t_sd = map->id2sd(RFIFOL(fd,2)); - if(!sd->chatID && pc_cant_act(sd)) + if (sd->chat_id == 0 && pc_cant_act(sd)) return; //You can trade while in a chatroom. // @noask [LuzZza] @@ -10726,7 +10928,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) { return; } - if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 1) { + if( battle_config.basic_skill_check && !pc->check_basicskill(sd, 1)) { clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,0); return; } @@ -10837,39 +11039,38 @@ void clif_parse_RemoveOption(int fd,struct map_session_data *sd) void clif_parse_ChangeCart(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change cart's visual look (CZ_REQ_CHANGECART). /// 01af <num>.W -void clif_parse_ChangeCart(int fd,struct map_session_data *sd) +void clif_parse_ChangeCart(int fd, struct map_session_data *sd) {// TODO: State tracking? int type; - if( pc->checkskill(sd, MC_CHANGECART) < 1 ) + if (pc->checkskill(sd, MC_CHANGECART) == 0) return; -#ifdef RENEWAL - if( sd->npc_id || sd->state.workinprogress&1 ){ + if (sd->npc_id || sd->state.workinprogress & 1) { +#if PACKETVER >= 20110309 clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); +#else + clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48)); +#endif return; } -#endif - type = (int)RFIFOW(fd,2); + type = RFIFOW(fd, 2); + + if ( #ifdef NEW_CARTS - if( (type == 9 && sd->status.base_level > 131) || - (type == 8 && sd->status.base_level > 121) || - (type == 7 && sd->status.base_level > 111) || - (type == 6 && sd->status.base_level > 101) || + (type == 9 && sd->status.base_level > 130) || + (type == 8 && sd->status.base_level > 120) || + (type == 7 && sd->status.base_level > 110) || + (type == 6 && sd->status.base_level > 100) || +#endif (type == 5 && sd->status.base_level > 90) || (type == 4 && sd->status.base_level > 80) || (type == 3 && sd->status.base_level > 65) || (type == 2 && sd->status.base_level > 40) || (type == 1)) -#else - if( (type == 5 && sd->status.base_level > 90) || - (type == 4 && sd->status.base_level > 80) || - (type == 3 && sd->status.base_level > 65) || - (type == 2 && sd->status.base_level > 40) || - (type == 1)) -#endif - pc->setcart(sd,type); + + pc->setcart(sd, type); } /// Request to select cart's visual look for new cart design (CZ_SELECTCART). @@ -10882,7 +11083,7 @@ void clif_parse_SelectCart(int fd, struct map_session_data *sd) if (!sd || !pc->checkskill(sd, MC_CARTDECORATE) || RFIFOL(fd, 2) != sd->status.account_id) return; - type = (int)RFIFOB(fd, 6); + type = RFIFOB(fd, 6); if (type <= MAX_BASE_CARTS || type > MAX_CARTS) return; @@ -11056,9 +11257,11 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] pc->update_idle_time(sd, BCIDLE_USESKILLTOID); - if( sd->npc_id || sd->state.workinprogress&1 ){ -#ifdef RENEWAL - clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. + if (sd->npc_id || sd->state.workinprogress & 1) { +#if PACKETVER >= 20110309 + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); +#else + clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48)); #endif return; } @@ -11115,7 +11318,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) sd->skillitem = sd->skillitemlv = 0; - if( skill_id >= GD_SKILLBASE ) { + if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) { if( sd->state.gmaster_flag ) skill_lv = guild->checkskill(sd->guild, skill_id); else @@ -11153,12 +11356,14 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski return; } -#ifdef RENEWAL - if( sd->state.workinprogress&1 ){ - clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. + if (sd->state.workinprogress & 1) { +#if PACKETVER >= 20110309 + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); +#else + clif->messagecolor_self(fd, COLOR_WHITE, msg_fd(fd, 48)); +#endif return; } -#endif //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] pc->update_idle_time(sd, BCIDLE_USESKILLTOPOS); @@ -11171,7 +11376,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski return; } //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. - safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); + safestrncpy(sd->message, RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); } if( sd->ud.skilltimer != INVALID_TIMER ) @@ -11264,7 +11469,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) uint16 skill_id = RFIFOW(fd,2); char map_name[MAP_NAME_LENGTH]; - mapindex->getmapname((char*)RFIFOP(fd,4), map_name); + mapindex->getmapname(RFIFOP(fd,4), map_name); sd->state.workinprogress = 0; if(skill_id != sd->menuskill_id) @@ -11425,7 +11630,7 @@ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) __attribute__ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) { int npcid = RFIFOL(fd,2); - int amount = (int)RFIFOL(fd,6); + int amount = RFIFOL(fd,6); if (amount >= 0) sd->npc_amount = amount; @@ -11439,9 +11644,14 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) __attribute_ /// 01d5 <packet len>.W <npc id>.L <string>.?B void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) { - int message_len = RFIFOW(fd,2)-8; +// [4144] can't confirm exact client version. At least >= correct for 20150513 +#if PACKETVER >= 20151029 + int message_len = RFIFOW(fd, 2) - 7; +#else + int message_len = RFIFOW(fd, 2) - 8; +#endif int npcid = RFIFOL(fd,4); - const char* message = (char*)RFIFOP(fd,8); + const char *message = RFIFOP(fd,8); if( message_len <= 0 ) return; // invalid input @@ -11489,12 +11699,12 @@ void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd) int cmd = RFIFOW(fd,0); short idx = RFIFOW(fd, packet_db[cmd].pos[0]) - 2; int n; - + if (idx < 0 || idx >= MAX_INVENTORY || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].nameid <= 0) return; - + if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND && - pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER) == 0) + pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0) skill->identify(sd, idx); } @@ -11595,20 +11805,26 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { atcommand->exec(fd, sd, cmd, true); } -void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /lb /nlb (CZ_LOCALBROADCAST). /// Request to broadcast a message on current map. /// 019c <packet len>.W <text>.?B -void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) +void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) { - char command[CHAT_SIZE_MAX+16]; - char* msg = (char*)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; + const char commandname[] = "lkami"; + char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' + command + ' ' + message + NUL + int len = (int)RFIFOW(fd,2) - 4; - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + if (len < 0) + return; + + sprintf(command, "%c%s ", atcommand->at_symbol, commandname); - sprintf(command, "%clkami %s", atcommand->at_symbol, msg); + // as the length varies depending on the command used, truncate unreasonably long strings + if (len >= (int)(sizeof command - strlen(command))) + len = (int)(sizeof command - strlen(command)) - 1; + + strncat(command, RFIFOP(fd,4), len); atcommand->exec(fd, sd, command, true); } @@ -11755,16 +11971,18 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) __attribute__(( /// Party creation request /// 00f9 <party name>.24B (CZ_MAKE_GROUP) /// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2) -void clif_parse_CreateParty(int fd, struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; +void clif_parse_CreateParty(int fd, struct map_session_data *sd) +{ + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if( map->list[sd->bl.m].flag.partylock ) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } - if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 7 ) { + if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 7)) { clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); return; } @@ -11773,18 +11991,20 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) { } void clif_parse_CreateParty2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,2); +void clif_parse_CreateParty2(int fd, struct map_session_data *sd) +{ + char name[NAME_LENGTH]; int item1 = RFIFOB(fd,26); int item2 = RFIFOB(fd,27); - name[NAME_LENGTH-1] = '\0'; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if( map->list[sd->bl.m].flag.partylock ) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } - if( battle_config.basic_skill_check && pc->checkskill(sd,NV_BASIC) < 7 ) { + if (battle_config.basic_skill_check && !pc->check_basicskill(sd, 7)) { clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); return; } @@ -11801,7 +12021,7 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { if(map->list[sd->bl.m].flag.partylock) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } @@ -11816,14 +12036,16 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { } void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) { +void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) +{ struct map_session_data *t_sd; - char *name = (char*)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if(map->list[sd->bl.m].flag.partylock) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } @@ -11861,7 +12083,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) __attribute__((n void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { if(map->list[sd->bl.m].flag.partylock) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } party->leave(sd); @@ -11873,10 +12095,10 @@ void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) __attribu void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { if(map->list[sd->bl.m].flag.partylock) { // Party locked. - clif->message(fd, msg_fd(fd,227)); + clif->message(fd, msg_fd(fd,227)); // Party modification is disabled in this map. return; } - party->removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); + party->removemember(sd, RFIFOL(fd,2), RFIFOP(fd,6)); } void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -11910,36 +12132,26 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) #endif } -void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -/// Validates and processes party messages (CZ_REQUEST_CHAT_PARTY). -/// 0108 <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_PartyMessage(int fd, struct map_session_data* sd) +/** + * Validates and processes party messages (CZ_REQUEST_CHAT_PARTY). + * + * @code + * 0108 <packet len>.W <text>.?B (<name> : <message>) 00 + * @endcode + * + * @param fd The incoming file descriptor. + * @param sd The related character. + */ +void clif_parse_PartyMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_PartyMessage(int fd, struct map_session_data *sd) { - const char* text = (char*)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const struct packet_chat_message *packet = RP2PTR(fd); + char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1]; - char *name, *message; - size_t namelen, messagelen; - - // validate packet and retrieve name and message - if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) - return; - - if( atcommand->exec(fd, sd, message, true) ) + if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL) return; - if( !pc->can_talk(sd) ) - return; - - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) - return; - sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; - } - - pc->update_idle_time(sd, BCIDLE_CHAT); - - party->send_message(sd, text, textlen); + party->send_message(sd, message); } void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -12173,7 +12385,7 @@ void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd) { #ifdef PARTY_RECRUIT short level = RFIFOW(fd,2); - const char *notice = (const char*)RFIFOP(fd, 4); + const char *notice = RFIFOP(fd, 4); party->recruit_register(sd, level, notice); #else @@ -12296,9 +12508,7 @@ void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) __att void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) { #ifdef PARTY_RECRUIT - const char *notice; - - notice = (const char*)RFIFOP(fd, 2); + const char *notice = RFIFOP(fd, 2); party->recruit_update(sd, notice); #else @@ -12417,7 +12627,7 @@ void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd) nullpo_retv(sd); WBUFW(buf, 0) = 0x8f2; WBUFL(buf, 2) = sd->status.account_id; - WBUFL(buf, 6) = sd->status.class_; + WBUFL(buf, 6) = sd->status.class; WBUFW(buf, 10) = sd->status.base_level; memcpy(WBUFP(buf, 12), sd->status.name, NAME_LENGTH); @@ -12599,8 +12809,8 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) __attribute__(( void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) { int len = (int)RFIFOW(fd,2) - 8; - int id = (int)RFIFOL(fd,4); - const uint8* data = (uint8*)RFIFOP(fd,8); + int id = RFIFOL(fd,4); + const uint8 *data = RFIFOP(fd,8); vending->purchase(sd, id, sd->vended_id, data, len/4); @@ -12614,9 +12824,9 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) __attribute__( void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) { int len = (int)RFIFOW(fd,2) - 12; - int aid = (int)RFIFOL(fd,4); - int uid = (int)RFIFOL(fd,8); - const uint8* data = (uint8*)RFIFOP(fd,12); + int aid = RFIFOL(fd,4); + int uid = RFIFOL(fd,8); + const uint8 *data = RFIFOP(fd,12); vending->purchase(sd, aid, uid, data, len/4); @@ -12633,9 +12843,9 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) __attribute__(( /// 1 = open void clif_parse_OpenVending(int fd, struct map_session_data* sd) { short len = (short)RFIFOW(fd,2) - 85; - const char* message = (char*)RFIFOP(fd,4); - bool flag = (bool)RFIFOB(fd,84); - const uint8* data = (uint8*)RFIFOP(fd,85); + const char *message = RFIFOP(fd,4); + bool flag = (RFIFOB(fd,84) != 0) ? true : false; + const uint8 *data = RFIFOP(fd,85); if( !flag ) sd->state.prevend = sd->state.workinprogress = 0; @@ -12660,13 +12870,13 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) { void clif_parse_CreateGuild(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild creation request (CZ_REQ_MAKE_GUILD). /// 0165 <char id>.L <guild name>.24B -void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,6); - name[NAME_LENGTH-1] = '\0'; +void clif_parse_CreateGuild(int fd,struct map_session_data *sd) +{ + char name[NAME_LENGTH]; + safestrncpy(name, RFIFOP(fd,6), NAME_LENGTH); if(map->list[sd->bl.m].flag.guildlock) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } @@ -12717,7 +12927,7 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) clif->guild_expulsionlist(sd); break; default: - ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); + ShowError("clif: guild request info: unknown type %u\n", RFIFOL(fd,2)); break; } } @@ -12733,7 +12943,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) return; for(i = 4; i < RFIFOW(fd,2); i += 40 ){ - guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); + guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), RFIFOP(fd,i+16)); } } @@ -12782,7 +12992,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { //uint8 b; //uint8 g; //uint8 r; - unsigned int rgb:24; + uint32 rgb:24; } __attribute__((packed)); #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) @@ -12792,7 +13002,8 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { int header = 0, bitmap = 0, offbits = 0, palettesize = 0; nullpo_retr(false, emblem); - if( decode_zip(buf, &buf_len, emblem, emblem_len) != 0 || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE + if (grfio->decode_zip(buf, &buf_len, emblem, emblem_len) != 0 + || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE || RBUFW(buf,0) != 0x4d42 // BITMAPFILEHEADER.bfType (signature) || RBUFL(buf,2) != buf_len // BITMAPFILEHEADER.bfSize (file size) || RBUFL(buf,14) != BITMAPINFOHEADER_SIZE // BITMAPINFOHEADER.biSize (other headers are not supported) @@ -12848,8 +13059,8 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { switch( RBUFW(buf,28) ) { case 8: // palette indexes { - const uint8 *indexes = (const uint8 *)RBUFP(buf,offbits); - const uint32 *palette = (const uint32 *)RBUFP(buf,BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE); + const uint8 *indexes = RBUFP(buf,offbits); + const uint32 *palette = RBUFP(buf,BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE); for (i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++) { if( indexes[i] >= palettesize ) // Invalid color @@ -12867,7 +13078,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { } case 24: // full colors { - const struct s_bitmaptripple *pixels = (const struct s_bitmaptripple*)RBUFP(buf,offbits); + const struct s_bitmaptripple *pixels = RBUFP(buf,offbits); for (i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++) { // if( pixels[i].r < 0xF8 || pixels[i].g > 0x07 || pixels[i].b < 0xF8 ) @@ -12915,18 +13126,22 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) __attribu void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) { int guild_id = RFIFOL(fd,2); - char* msg1 = (char*)RFIFOP(fd,6); - char* msg2 = (char*)RFIFOP(fd,66); + char *msg1 = NULL, *msg2 = NULL; - if(!sd->state.gmaster_flag) + if (!sd->state.gmaster_flag) return; + msg1 = aStrndup(RFIFOP(fd,6), MAX_GUILDMES1-1); + msg2 = aStrndup(RFIFOP(fd,66), MAX_GUILDMES2-1); + // compensate for some client defects when using multilingual mode if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string guild->change_notice(sd, guild_id, msg1, msg2); + aFree(msg1); + aFree(msg2); } // Helper function for guild invite functions @@ -12937,8 +13152,7 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi nullpo_retr(false, sd); nullpo_retr(false, t_sd); if ( map->list[sd->bl.m].flag.guildlock ) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return false; } @@ -12964,14 +13178,15 @@ void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2). /// 0916 <char name>.24B -void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) { - char *nick = (char*)RFIFOP(fd, 2); - struct map_session_data *t_sd = map->nick2sd(nick); +void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) +{ + char nick[NAME_LENGTH]; + struct map_session_data *t_sd = NULL; - nick[NAME_LENGTH - 1] = '\0'; + safestrncpy(nick, RFIFOP(fd, 2), NAME_LENGTH); + t_sd = map->nick2sd(nick); - if (!clif_sub_guild_invite(fd, sd, t_sd)) - return; + clif_sub_guild_invite(fd, sd, t_sd); } void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12990,8 +13205,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) __attribute__((no /// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { if(map->list[sd->bl.m].flag.guildlock) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } if( sd->bg_id ) { @@ -12999,7 +13213,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { return; } - guild->leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->leave(sd,RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14)); } void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -13007,46 +13221,35 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) __attribute__ /// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { if( map->list[sd->bl.m].flag.guildlock || sd->bg_id ) { - // Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } - guild->expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->expulsion(sd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14)); } -void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -/// Validates and processes guild messages (CZ_GUILD_CHAT). -/// 017e <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_GuildMessage(int fd, struct map_session_data* sd) +/** + * Validates and processes guild messages (CZ_GUILD_CHAT). + * + * @code + * 017e <packet len>.W <text>.?B (<name> : <message>) 00 + * @endcode + * + * @param fd The incoming file descriptor. + * @param sd The related character. + */ +void clif_parse_GuildMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_GuildMessage(int fd, struct map_session_data *sd) { - const char* text = (char*)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const struct packet_chat_message *packet = RP2PTR(fd); + char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1]; - char *name, *message; - size_t namelen, messagelen; - - // validate packet and retrieve name and message - if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) - return; - - if( atcommand->exec(fd, sd, message, true) ) - return; - - if( !pc->can_talk(sd) ) + if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL) return; - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) - return; - sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; - } - - pc->update_idle_time(sd, BCIDLE_CHAT); - - if( sd->bg_id ) - bg->send_message(sd, text, textlen); + if (sd->bg_id) + bg->send_message(sd, message); else - guild->send_message(sd, text, textlen); + guild->send_message(sd, message); } void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -13059,8 +13262,7 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) { return; if(map->list[sd->bl.m].flag.guildlock) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } @@ -13097,8 +13299,7 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) { return; if(map->list[sd->bl.m].flag.guildlock) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } guild->delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); @@ -13114,8 +13315,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) { return; if(map->list[sd->bl.m].flag.guildlock) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } @@ -13138,11 +13338,10 @@ void clif_parse_GuildBreak(int fd, struct map_session_data *sd) __attribute__((n /// field name and size is same as the one in CH_DELETE_CHAR. void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { if( map->list[sd->bl.m].flag.guildlock ) { - //Guild locked. - clif->message(fd, msg_fd(fd,228)); + clif->message(fd, msg_fd(fd,228)); // Guild modification is disabled in this map. return; } - guild->dobreak(sd,(char*)RFIFOP(fd,2)); + guild->dobreak(sd, RFIFOP(fd,2)); } /// Pet @@ -13218,7 +13417,7 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) __attribute__ /// 01a5 <name>.24B void clif_parse_ChangePetName(int fd, struct map_session_data *sd) { - pet->change_name(sd,(char*)RFIFOP(fd,2)); + pet->change_name(sd, RFIFOP(fd,2)); } void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -13241,7 +13440,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) { case BL_PC: { char command[NAME_LENGTH+6]; - sprintf(command, "%ckick %s", atcommand->at_symbol, status->get_name(target)); + sprintf(command, "%ckick %s", atcommand->at_symbol, clif->get_bl_name(target)); atcommand->exec(fd, sd, command, true); } break; @@ -13256,7 +13455,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) { clif->GM_kickack(sd, 0); return; } - sprintf(command, "/kick %s (%d)", status->get_name(target), status->get_class(target)); + sprintf(command, "/kick %s (%d)", clif->get_bl_name(target), status->get_class(target)); logs->atcommand(sd, command); status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' } @@ -13299,12 +13498,12 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonn /// Request to warp to a character with given name. /// 01bb <char name>.24B void clif_parse_GMShift(int fd, struct map_session_data *sd) -{// FIXME: remove is supposed to receive account name for clients prior 20100803RE - char *player_name; +{ + // FIXME: remove is supposed to receive account name for clients prior 20100803RE + char player_name[NAME_LENGTH]; char command[NAME_LENGTH+8]; - player_name = (char*)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + safestrncpy(player_name, RFIFOP(fd,2), NAME_LENGTH); sprintf(command, "%cjumpto %s", atcommand->at_symbol, player_name); atcommand->exec(fd, sd, command, true); @@ -13335,12 +13534,12 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((non /// Request to summon a player with given name to own position. /// 01bd <char name>.24B void clif_parse_GMRecall(int fd, struct map_session_data *sd) -{// FIXME: recall is supposed to receive account name for clients prior 20100803RE - char *player_name; - char command [NAME_LENGTH+8]; +{ + // FIXME: recall is supposed to receive account name for clients prior 20100803RE + char player_name[NAME_LENGTH]; + char command[NAME_LENGTH+8]; - player_name = (char*)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + safestrncpy(player_name, RFIFOP(fd,2), NAME_LENGTH); sprintf(command, "%crecall %s", atcommand->at_symbol, player_name); atcommand->exec(fd, sd, command, true); @@ -13376,16 +13575,16 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute /// /item agitinvest - reset current global agit investments.(not yet implemented) /// 013f <item/mob name>.24B /// 09ce <item/mob name>.100B [Ind/Yommy<3] -void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { - struct packet_gm_monster_item *p = RP2PTR(fd); +void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) +{ + const struct packet_gm_monster_item *p = RP2PTR(fd); int i, count; - char *item_monster_name; + char item_monster_name[sizeof p->str]; struct item_data *item_array[10]; struct mob_db *mob_array[10]; char command[256]; - item_monster_name = p->str; - item_monster_name[(sizeof(struct packet_gm_monster_item)-2)-1] = '\0'; + safestrncpy(item_monster_name, p->str, sizeof(item_monster_name)); if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) { for(i = 0; i < count; i++) { @@ -13506,9 +13705,10 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd) __attribute__((nonnull void clif_parse_GMRc(int fd, struct map_session_data* sd) { char command[NAME_LENGTH+15]; - char *name = (char*)RFIFOP(fd,2); + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); - name[NAME_LENGTH-1] = '\0'; sprintf(command, "%cmute %d %s", atcommand->at_symbol, 60, name); atcommand->exec(fd, sd, command, true); } @@ -13523,7 +13723,7 @@ void clif_account_name(struct map_session_data* sd, int account_id, const char* WFIFOHEAD(fd,packet_len(0x1e0)); WFIFOW(fd,0) = 0x1e0; WFIFOL(fd,2) = account_id; - safestrncpy((char*)WFIFOP(fd,6), accname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), accname, NAME_LENGTH); WFIFOSET(fd,packet_len(0x1e0)); } @@ -13567,13 +13767,14 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) __attribute__((non /// type: /// 0 = (/ex nick) deny speech from nick /// 1 = (/in nick) allow speech from nick -void clif_parse_PMIgnore(int fd, struct map_session_data* sd) { - char* nick; +void clif_parse_PMIgnore(int fd, struct map_session_data* sd) +{ + char nick[NAME_LENGTH]; uint8 type; int i; - nick = (char*)RFIFOP(fd,2); // speed up - nick[NAME_LENGTH-1] = '\0'; // to be sure that the player name has at most 23 characters + safestrncpy(nick, RFIFOP(fd,2), NAME_LENGTH); + type = RFIFOB(fd,26); if( type == 0 ) { // Add name to ignore list (block) @@ -13682,12 +13883,13 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) { if (sd->state.doridori) return; - switch (sd->class_&MAPID_UPPERMASK) { + switch (sd->job & MAPID_UPPERMASK) { case MAPID_SOUL_LINKER: case MAPID_STAR_GLADIATOR: case MAPID_TAEKWON: if (!sd->state.rest) break; + FALLTHROUGH case MAPID_SUPER_NOVICE: sd->state.doridori=1; break; @@ -13709,7 +13911,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) /* game client is currently broken on this (not sure the packetver range) */ /* it sends the request when the criteria doesn't match (and of course we let it fail) */ /* so restoring the old parse_globalmes method. */ - if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) { + if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { unsigned int next = pc->nextbaseexp(sd); if( next == 0 ) next = pc->thisbaseexp(sd); if( next ) { @@ -13831,12 +14033,14 @@ void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_i void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add a player as friend (CZ_ADD_FRIENDS). /// 0202 <name>.24B -void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { +void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) +{ struct map_session_data *f_sd; int i; - char *nick = (char*)RFIFOP(fd,2); + char nick[NAME_LENGTH]; + + safestrncpy(nick, RFIFOP(fd,2), NAME_LENGTH); - nick[NAME_LENGTH - 1] = '\0'; f_sd = map->nick2sd(nick); // ensure that the request player's friend list is not full @@ -13849,7 +14053,7 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { // Friend doesn't exist (no player with this name) if (f_sd == NULL) { - clif->message(fd, msg_fd(fd,3)); + clif->message(fd, msg_fd(fd,3)); // "Character not found." return; } @@ -14055,46 +14259,43 @@ void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) { for( i = 0; i < 10 && i < MAX_FAME_LIST; i++ ) { if( list[i].id > 0 ) { if( strcmp(list[i].name, "-") == 0 && (name = map->charid2nick(list[i].id)) != NULL ) { - strncpy((char *)(WBUFP(buf, 24 * i)), name, NAME_LENGTH); + strncpy(WBUFP(buf, 24 * i), name, NAME_LENGTH); } else { - strncpy((char *)(WBUFP(buf, 24 * i)), list[i].name, NAME_LENGTH); + strncpy(WBUFP(buf, 24 * i), list[i].name, NAME_LENGTH); } } else { - strncpy((char *)(WBUFP(buf, 24 * i)), "None", 5); + strncpy(WBUFP(buf, 24 * i), "None", 5); } WBUFL(buf, 24 * 10 + i * 4) = list[i].fame; //points } for( ;i < 10; i++ ) { // In case the MAX is less than 10. - strncpy((char *)(WBUFP(buf, 24 * i)), "Unavailable", 12); + strncpy(WBUFP(buf, 24 * i), "Unavailable", 12); WBUFL(buf, 24 * 10 + i * 4) = 0; } } /// 097d <RankingType>.W {<CharName>.24B <point>L}*10 <mypoint>L (ZC_ACK_RANKING) -void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) { +void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) +{ +#if PACKETVER >= 20120502 int fd; - int mypoint = 0; - int upperMask; + int len = packet_len(0x97d); nullpo_retv(sd); fd = sd->fd; - upperMask = sd->class_&MAPID_UPPERMASK; - WFIFOHEAD(fd, 288); + WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x97d; WFIFOW(fd, 2) = type; clif_ranklist_sub(WFIFOP(fd,4), type); - if( (upperMask == MAPID_BLACKSMITH && type == RANKTYPE_BLACKSMITH) - || (upperMask == MAPID_ALCHEMIST && type == RANKTYPE_ALCHEMIST) - || (upperMask == MAPID_TAEKWON && type == RANKTYPE_TAEKWON) - ) { - mypoint = sd->status.fame; + if (pc->famelist_type(sd->job) == type) { + WFIFOL(fd, 284) = sd->status.fame; //mypoint } else { - mypoint = 0; + WFIFOL(fd, 284) = 0; //mypoint } - WFIFOL(fd, 284) = mypoint; //mypoint - WFIFOSET(fd, 288); + WFIFOSET(fd, len); +#endif } void clif_parse_ranklist(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -14114,8 +14315,9 @@ void clif_parse_ranklist(int fd, struct map_session_data *sd) { } // 097e <RankingType>.W <point>.L <TotalPoint>.L (ZC_UPDATE_RANKING_POINT) -void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type type, int points) { -#if PACKETVER < 20130710 +void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type type, int points) +{ +#if PACKETVER < 20120502 switch( type ) { case RANKTYPE_BLACKSMITH: clif->fame_blacksmith(sd,points); break; case RANKTYPE_ALCHEMIST: clif->fame_alchemist(sd,points); break; @@ -14124,15 +14326,16 @@ void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type t #else int fd; + int len = packet_len(0x97e); nullpo_retv(sd); fd = sd->fd; - WFIFOHEAD(fd, 12); + WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x97e; WFIFOW(fd, 2) = type; WFIFOL(fd, 4) = points; WFIFOL(fd, 8) = sd->status.fame; - WFIFOSET(fd, 12); + WFIFOSET(fd, len); #endif } @@ -14248,7 +14451,7 @@ void clif_ranking_pk(struct map_session_data* sd) { WFIFOHEAD(fd,packet_len(0x238)); WFIFOW(fd,0) = 0x238; for (i = 0; i < 10;i ++) { - strncpy((char*)WFIFOP(fd, i * 24 + 2), "Unknown", NAME_LENGTH); + strncpy(WFIFOP(fd, i * 24 + 2), "Unknown", NAME_LENGTH); WFIFOL(fd,i*4+242) = 0; } WFIFOSET(fd, packet_len(0x238)); @@ -14308,8 +14511,9 @@ void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv) void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change homunculus' name (CZ_RENAME_MER). /// 0231 <name>.24B -void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { - homun->change_name(sd,(char*)RFIFOP(fd,2)); +void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) +{ + homun->change_name(sd, RFIFOP(fd,2)); } void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -14476,7 +14680,7 @@ void clif_parse_Check(int fd, struct map_session_data *sd) if(!pc_has_permission(sd, PC_PERM_USE_CHECK)) return; - safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname)); + safestrncpy(charname, RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname)); if( ( pl_sd = map->nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { return; @@ -14567,8 +14771,8 @@ void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) WFIFOHEAD(fd,packet_len(0x24a)); WFIFOW(fd,0) = 0x24a; WFIFOL(fd,2) = mail_id; - safestrncpy((char*)WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); - safestrncpy((char*)WFIFOP(fd,46), sender, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); + safestrncpy(WFIFOP(fd,46), sender, NAME_LENGTH); WFIFOSET(fd,packet_len(0x24a)); } @@ -14623,7 +14827,7 @@ void clif_Mail_refreshinbox(struct map_session_data *sd) if( md->full ) {// TODO: is this official? char output[100]; sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX); - clif_disp_onlyself(sd, output, strlen(output)); + clif_disp_onlyself(sd, output); } } @@ -14661,11 +14865,16 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) struct mail_message *msg = &sd->mail.inbox.msg[i]; struct item *item = &msg->item; struct item_data *data; - size_t msg_len = strlen(msg->body), len; + int msg_len = (int)strlen(msg->body), len; - if( msg_len == 0 ) { + if (msg_len == 0) { strcpy(msg->body, "(no message)"); - msg_len = strlen(msg->body); + msg_len = (int)strlen(msg->body); + } + + if (msg_len > UINT8_MAX) { + Assert_report(msg_len > UINT8_MAX); + msg_len = UINT8_MAX; } len = 101 + msg_len; @@ -14674,8 +14883,8 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) WFIFOW(fd,0) = 0x242; WFIFOW(fd,2) = len; WFIFOL(fd,4) = msg->id; - safestrncpy((char*)WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); - safestrncpy((char*)WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); + safestrncpy(WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); + safestrncpy(WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); WFIFOL(fd,72) = 0; WFIFOL(fd,76) = msg->zeny; @@ -14693,8 +14902,8 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) } else // no item, set all to zero memset(WFIFOP(fd,80), 0x00, 19); - WFIFOB(fd,99) = (unsigned char)msg_len; - safestrncpy((char*)WFIFOP(fd,100), msg->body, msg_len + 1); + WFIFOB(fd,99) = (uint8)msg_len; + safestrncpy(WFIFOP(fd,100), msg->body, msg_len + 1); WFIFOSET(fd,len); if (msg->status == MAIL_UNREAD) { @@ -14727,7 +14936,6 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) { int mail_id = RFIFOL(fd,2); int i; - bool fail = false; if( !chrif->isconnected() ) return; @@ -14751,6 +14959,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) if( sd->mail.inbox.msg[i].item.nameid > 0 ) { struct item_data *data; unsigned int weight; + bool fail = false; if ((data = itemdb->exists(sd->mail.inbox.msg[i].item.nameid)) == NULL) return; @@ -14919,15 +15128,15 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) msg.send_id = sd->status.char_id; msg.dest_id = 0; // will attempt to resolve name safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); - safestrncpy(msg.dest_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(msg.title, (char*)RFIFOP(fd,28), MAIL_TITLE_LENGTH); + safestrncpy(msg.dest_name, RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(msg.title, RFIFOP(fd,28), MAIL_TITLE_LENGTH); if (msg.title[0] == '\0') { return; // Message has no length and somehow client verification was skipped. } if (body_len) - safestrncpy(msg.body, (char*)RFIFOP(fd,69), body_len + 1); + safestrncpy(msg.body, RFIFOP(fd,69), body_len + 1); else memset(msg.body, 0x00, MAIL_BODY_LENGTH); @@ -14967,7 +15176,7 @@ void clif_Auction_openwindow(struct map_session_data *sd) /// Returns auction item search results (ZC_AUCTION_ITEM_REQ_SEARCH). /// 0252 <packet len>.W <pages>.L <count>.L { <auction id>.L <seller name>.24B <name id>.W <type>.L <amount>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <now price>.L <max price>.L <buyer name>.24B <delete time>.L }* -void clif_Auction_results(struct map_session_data *sd, short count, short pages, uint8 *buf) +void clif_Auction_results(struct map_session_data *sd, short count, short pages, const uint8 *buf) { int i, fd, len = sizeof(struct auction_data); struct auction_data auction; @@ -14986,7 +15195,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, memcpy(&auction, RBUFP(buf,i * len), len); WFIFOL(fd,k) = auction.auction_id; - safestrncpy((char*)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); if( (item = itemdb->exists(auction.item.nameid)) != NULL && item->view_id > 0 ) WFIFOW(fd,28+k) = item->view_id; @@ -15004,7 +15213,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, WFIFOW(fd,45+k) = auction.item.card[3]; WFIFOL(fd,47+k) = auction.price; WFIFOL(fd,51+k) = auction.buynow; - safestrncpy((char*)WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); WFIFOL(fd,79+k) = (uint32)auction.timestamp; } WFIFOSET(fd,WFIFOW(fd,2)); @@ -15111,10 +15320,10 @@ void clif_Auction_message(int fd, unsigned char flag) /// 2 = Auction ID is incorrect void clif_Auction_close(int fd, unsigned char flag) { - WFIFOHEAD(fd,packet_len(0x25e)); + WFIFOHEAD(fd, 4); WFIFOW(fd,0) = 0x25d; // BUG: The client identifies this packet as 0x25d (CZ_AUCTION_REQ_MY_SELL_STOP) WFIFOW(fd,2) = flag; - WFIFOSET(fd,packet_len(0x25e)); + WFIFOSET(fd, 4); } void clif_parse_Auction_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -15188,7 +15397,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) // Auction checks... if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bound_items(sd) ) { - clif->message(sd->fd, msg_sd(sd,293)); + clif->message(sd->fd, msg_sd(sd,293)); // This bound item cannot be traded to that character. clif->auction_message(fd, 2); // The auction has been canceled return; } @@ -15241,7 +15450,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) int bid = RFIFOL(fd,6); if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish] - clif->message(sd->fd, msg_sd(sd,246)); + clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action. return; } @@ -15278,7 +15487,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) clif->pAuction_cancelreg(fd, sd); - safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); + safestrncpy(search_text, RFIFOP(fd,8), sizeof(search_text)); intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page); } @@ -15414,13 +15623,25 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) int len = RFIFOW(fd,2); int points = RFIFOL(fd,4); int count = RFIFOW(fd,8); - unsigned short* item_list = (unsigned short*)RFIFOP(fd,10); + struct itemlist item_list = { 0 }; + int i; if( len < 10 || len != 10 + count * 4) { - ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4); + ShowWarning("Player %d sent incorrect cash shop buy packet (len %d:%d)!\n", sd->status.char_id, len, 10 + count * 4); return; } - fail = npc->cashshop_buylist(sd,points,count,item_list); + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, count, 1); + for (i = 0; i < count; i++) { + struct itemlist_entry entry = { 0 }; + + entry.amount = RFIFOW(fd, 10 + 4 * i); + entry.id = RFIFOW(fd, 10 + 4 * i + 2); // Nameid + + VECTOR_PUSH(item_list, entry); + } + fail = npc->cashshop_buylist(sd, points, &item_list); + VECTOR_CLEAR(item_list); #endif } @@ -15539,7 +15760,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag) WFIFOW(fd,11) = hours; // Hours WFIFOW(fd,13) = minutes; // Minutes } - safestrncpy((char*)WFIFOP(fd,19), md->db->jname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,19), md->db->jname, NAME_LENGTH); } WFIFOSET(fd,70); @@ -15571,7 +15792,7 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) __attribute__((no /// 1 = enabled void clif_parse_EquipTick(int fd, struct map_session_data* sd) { - bool flag = (bool)RFIFOL(fd,6); + bool flag = (RFIFOL(fd,6) != 0) ? true : false; sd->status.show_equip = flag; clif->equiptickack(sd, flag); } @@ -15605,7 +15826,7 @@ void clif_quest_send_list(struct map_session_data *sd) + sd->avail_quests * (sizeof(struct packet_quest_list_info) + MAX_QUEST_OBJECTIVES * sizeof(struct packet_mission_info_sub)); // >= than the actual length buf = aMalloc(len); - packet = (struct packet_quest_list_header *)WBUFP(buf, 0); + packet = WBUFP(buf, 0); real_len = sizeof(*packet); packet->PacketType = questListType; @@ -15915,7 +16136,7 @@ void clif_mercenary_info(struct map_session_data *sd) { #endif WFIFOW(fd,18) = mstatus->flee; WFIFOW(fd,20) = mstatus->amotion; - safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,22), md->db->name, NAME_LENGTH); WFIFOW(fd,46) = md->db->lv; WFIFOL(fd,48) = mstatus->hp; WFIFOL(fd,52) = mstatus->max_hp; @@ -15957,7 +16178,7 @@ void clif_mercenary_skillblock(struct map_session_data *sd) WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10) = 0; } - safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; } @@ -16028,28 +16249,46 @@ void clif_readbook(int fd, int book_id, int page) /// Battlegrounds /// -/// Updates HP bar of a camp member (ZC_BATTLEFIELD_NOTIFY_HP). -/// 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W +/// Updates HP bar of a camp member. +/// 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W (ZC_BATTLEFIELD_NOTIFY_HP). +/// 0a0e <account id>.L <hp>.L <max hp>.L (ZC_BATTLEFIELD_NOTIFY_HP2) void clif_bg_hp(struct map_session_data *sd) { unsigned char buf[34]; + +// packet version can be wrong, because inconsistend data in other servers. From packets table it start from 20140312 [4144] +#if PACKETVER < 20140613 const int cmd = 0x2e0; nullpo_retv(sd); - WBUFW(buf,0) = cmd; - WBUFL(buf,2) = sd->status.account_id; - memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); + WBUFW(buf, 0) = cmd; + WBUFL(buf, 2) = sd->status.account_id; + memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH); - if( sd->battle_status.max_hp > INT16_MAX ) + if (sd->battle_status.max_hp > INT16_MAX) { // To correctly display the %hp bar. [Skotlex] - WBUFW(buf,30) = sd->battle_status.hp/(sd->battle_status.max_hp/100); - WBUFW(buf,32) = 100; + WBUFW(buf, 30) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); + WBUFW(buf, 32) = 100; } else { - WBUFW(buf,30) = sd->battle_status.hp; - WBUFW(buf,32) = sd->battle_status.max_hp; + WBUFW(buf, 30) = sd->battle_status.hp; + WBUFW(buf, 32) = sd->battle_status.max_hp; } +#else + const int cmd = 0xa0e; + nullpo_retv(sd); + + WBUFW(buf, 0) = cmd; + WBUFL(buf, 2) = sd->status.account_id; + if (sd->battle_status.max_hp > INT32_MAX) { + WBUFL(buf, 6) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); + WBUFL(buf, 10) = 100; + } else { + WBUFL(buf, 6) = sd->battle_status.hp; + WBUFL(buf, 10) = sd->battle_status.max_hp; + } +#endif clif->send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); } @@ -16064,7 +16303,7 @@ void clif_bg_xy(struct map_session_data *sd) WBUFW(buf,0)=0x2df; WBUFL(buf,2)=sd->status.account_id; memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); - WBUFW(buf,30)=sd->status.class_; + WBUFW(buf,30)=sd->status.class; WBUFW(buf,32)=sd->bl.x; WBUFW(buf,34)=sd->bl.y; @@ -16088,58 +16327,53 @@ void clif_bg_xy_remove(struct map_session_data *sd) /// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT). /// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B -void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len) +void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes) { struct map_session_data *sd; unsigned char *buf; + int len; nullpo_retv(bgd); nullpo_retv(name); nullpo_retv(mes); - if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL ) + + if (!bgd->count || (sd = bg->getavailablesd(bgd)) == NULL) return; + len = (int)strlen(mes); + Assert_retv(len <= INT16_MAX - NAME_LENGTH - 8); buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char)); WBUFW(buf,0) = 0x2dc; WBUFW(buf,2) = len + NAME_LENGTH + 8; WBUFL(buf,4) = src_id; memcpy(WBUFP(buf,8), name, NAME_LENGTH); - memcpy(WBUFP(buf,32), mes, len); + memcpy(WBUFP(buf,32), mes, len); // [!] no NUL terminator clif->send(buf,WBUFW(buf,2), &sd->bl, BG); aFree(buf); } -void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -/// Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT). -/// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_BattleChat(int fd, struct map_session_data* sd) +/** + * Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT). + * + * @code + * 0x2db <packet len>.W <text>.?B (<name> : <message>) 00 + * @endcode + * + * @param fd The incoming file descriptor. + * @param sd The related character. + */ +void clif_parse_BattleChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_BattleChat(int fd, struct map_session_data *sd) { - const char* text = (char*)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const struct packet_chat_message *packet = RP2PTR(fd); + char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1]; - char *name, *message; - size_t namelen, messagelen; - - if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) - return; - - if( atcommand->exec(fd, sd, message, true) ) + if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL) return; - if( !pc->can_talk(sd) ) - return; - - if( battle_config.min_chat_delay ) { - if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 ) - return; - sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay; - } - - pc->update_idle_time(sd, BCIDLE_CHAT); - - bg->send_message(sd, text, textlen); + bg->send_message(sd, message); } /// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT). @@ -16179,7 +16413,7 @@ void clif_sendbgemblem_area(struct map_session_data *sd) WBUFW(buf, 0) = 0x2dd; WBUFL(buf,2) = sd->bl.id; - safestrncpy((char*)WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. + safestrncpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. WBUFW(buf,30) = sd->bg_id; clif->send(buf,packet_len(0x2dd), &sd->bl, AREA); } @@ -16190,7 +16424,7 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd) WFIFOHEAD(fd,32); WFIFOW(fd,0) = 0x2dd; WFIFOL(fd,2) = sd->bl.id; - safestrncpy((char*)WFIFOP(fd,6), sd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), sd->status.name, NAME_LENGTH); WFIFOW(fd,30) = sd->bg_id; WFIFOSET(fd,packet_len(0x2dd)); } @@ -16402,36 +16636,51 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd) sd->state.lesseffect = ( isLess != 0 ); } -void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b* -void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) { - int n = (RFIFOW(fd,2)-12) / 4; +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) +{ + int n = ((int)RFIFOW(fd,2) - 12) / 4; int type = RFIFOL(fd,4); int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK - unsigned short* item_list = (unsigned short*)RFIFOP(fd,12); + struct itemlist item_list = { 0 }; + int i; if( sd->state.trading || sd->npc_shopid ) return; - if( flag == 0 || n == 0) { + if (flag == 0 || n <= 0) { clif_menuskill_clear(sd); return; // Canceled by player. } - if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) { + if (n > MAX_INVENTORY) + n = MAX_INVENTORY; // It should be impossible to have more than that. + + if (sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL) { clif_menuskill_clear(sd); return; // Prevent hacking. } + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + entry.id = (int)RFIFOW(fd, 12 + 4 * i) - 2; // Inventory index + entry.amount = RFIFOW(fd, 12 + 4 * i + 2); + VECTOR_PUSH(item_list, entry); + } + switch( type ) { case 0: // Change Material - skill->changematerial(sd,n,item_list); + skill->changematerial(sd, &item_list); break; case 1: // Level 1: Pure to Rough case 2: // Level 2: Rough to Pure - skill->elementalanalysis(sd,n,type,item_list); + skill->elementalanalysis(sd, type, &item_list); break; } + VECTOR_CLEAR(item_list); clif_menuskill_clear(sd); return; @@ -16498,6 +16747,7 @@ void clif_elemental_info(struct map_session_data *sd) { /// 0810 <slots>.B void clif_buyingstore_open(struct map_session_data* sd) { +#if PACKETVER >= 20100303 int fd; nullpo_retv(sd); @@ -16506,6 +16756,7 @@ void clif_buyingstore_open(struct map_session_data* sd) WFIFOW(fd,0) = 0x810; WFIFOB(fd,2) = sd->buyingstore.slots; WFIFOSET(fd,packet_len(0x810)); +#endif } void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -16516,7 +16767,7 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) __attrib /// 1 = open void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 8; - uint8* itemlist; + const uint8 *itemlist; char storename[MESSAGE_SIZE]; unsigned char result; int zenylimit; @@ -16528,13 +16779,13 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { // TODO: Make this check global for all variable length packets. if( packet_len < 89 ) {// minimum packet length - ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id); + ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89U, packet_len, sd->bl.id); return; } zenylimit = RFIFOL(fd,info->pos[1]); result = RFIFOL(fd,info->pos[2]); - safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename)); + safestrncpy(storename, RFIFOP(fd,info->pos[3]), sizeof(storename)); itemlist = RFIFOP(fd,info->pos[4]); // so that buyingstore_create knows, how many elements it has access to @@ -16559,6 +16810,7 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { /// ? = nothing void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight) { +#if PACKETVER >= 20100420 int fd; nullpo_retv(sd); @@ -16568,6 +16820,7 @@ void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short re WFIFOW(fd,2) = result; WFIFOL(fd,4) = weight; WFIFOSET(fd,packet_len(0x812)); +#endif } /// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE). @@ -16600,6 +16853,7 @@ void clif_buyingstore_myitemlist(struct map_session_data* sd) /// 0814 <account id>.L <store name>.80B void clif_buyingstore_entry(struct map_session_data* sd) { +#if PACKETVER >= 20100420 uint8 buf[86]; nullpo_retv(sd); @@ -16608,9 +16862,11 @@ void clif_buyingstore_entry(struct map_session_data* sd) memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); clif->send(buf, packet_len(0x814), &sd->bl, AREA_WOS); +#endif } void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { +#if PACKETVER >= 20100420 int fd; nullpo_retv(sd); @@ -16620,6 +16876,7 @@ void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_sessi WFIFOL(fd,2) = pl_sd->bl.id; memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE); WFIFOSET(fd,packet_len(0x814)); +#endif } void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -16633,6 +16890,7 @@ void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) { /// 0816 <account id>.L void clif_buyingstore_disappear_entry(struct map_session_data* sd) { +#if PACKETVER >= 20100309 uint8 buf[6]; nullpo_retv(sd); @@ -16640,9 +16898,12 @@ void clif_buyingstore_disappear_entry(struct map_session_data* sd) WBUFL(buf,2) = sd->bl.id; clif->send(buf, packet_len(0x816), &sd->bl, AREA_WOS); +#endif } + void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { +#if PACKETVER >= 20100309 int fd; nullpo_retv(sd); @@ -16652,6 +16913,7 @@ void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct WFIFOW(fd,0) = 0x816; WFIFOL(fd,2) = pl_sd->bl.id; WFIFOSET(fd,packet_len(0x816)); +#endif } /// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE). @@ -16698,7 +16960,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) __attri /// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }* void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 6; - uint8* itemlist; + const uint8 *itemlist; int account_id; unsigned int count, packet_len, buyer_id; struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; @@ -16707,7 +16969,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { if( packet_len < 12 ) {// minimum packet length - ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id); + ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12U, packet_len, sd->bl.id); return; } @@ -16720,7 +16982,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { if( packet_len%blocksize ) { - ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%u, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); + ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); return; } count = packet_len/blocksize; @@ -16736,6 +16998,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { /// ? = nothing void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result) { +#if PACKETVER >= 20100420 int fd; nullpo_retv(sd); @@ -16744,22 +17007,36 @@ void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short resu WFIFOW(fd,0) = 0x81a; WFIFOW(fd,2) = result; WFIFOSET(fd,packet_len(0x81a)); +#endif } /// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE). /// 081b <name id>.W <amount>.W <limit zeny>.L -void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount) +void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount, uint32 char_id, int zeny) { int fd; +#if PACKETVER < 20141016 // TODO : not sure for client date [Napster] + const int cmd = 0x81b; +#else + const int cmd = 0x9e6; +#endif + const int len = packet_len(cmd); nullpo_retv(sd); fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x81b)); - WFIFOW(fd,0) = 0x81b; - WFIFOW(fd,2) = nameid; - WFIFOW(fd,4) = amount; // amount of nameid received - WFIFOL(fd,6) = sd->buyingstore.zenylimit; - WFIFOSET(fd,packet_len(0x81b)); + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = cmd; + WFIFOW(fd, 2) = nameid; + WFIFOW(fd, 4) = amount; // amount of nameid received +#if PACKETVER < 20141016 + WFIFOL(fd, 6) = sd->buyingstore.zenylimit; +#else + WFIFOL(fd, 6) = zeny; // zeny + WFIFOL(fd, 10) = sd->buyingstore.zenylimit; + WFIFOL(fd, 14) = char_id; // GID + WFIFOL(fd, 18) = (int)time(NULL); // date +#endif + WFIFOSET(fd, len); } /// Deletes item from inventory, that was sold to a buying store (ZC_ITEM_DELETE_BUYING_STORE). @@ -16770,6 +17047,7 @@ void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short na /// NOTE: This function has to be called _instead_ of clif_delitem/clif_dropitem. void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price) { +#if PACKETVER >= 20100420 int fd; nullpo_retv(sd); @@ -16780,6 +17058,7 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi WFIFOW(fd,4) = amount; WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself WFIFOSET(fd,packet_len(0x81c)); +#endif } /// Notifies the seller, that a buying store trade failed (ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER). @@ -16791,6 +17070,7 @@ void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsi /// ? = nothing void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid) { +#if PACKETVER >= 20100420 int fd; nullpo_retv(sd); @@ -16800,6 +17080,7 @@ void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short res WFIFOW(fd,2) = result; WFIFOW(fd,4) = nameid; WFIFOSET(fd,packet_len(0x824)); +#endif } void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -16827,7 +17108,7 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { if( packet_len < 15 ) {// minimum packet length - ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15, packet_len, sd->bl.id); + ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15U, packet_len, sd->bl.id); return; } @@ -16919,6 +17200,7 @@ void clif_search_store_info_ack(struct map_session_data* sd) /// 4 = "No sale (purchase) information available." (0x705) void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason) { +#if PACKETVER >= 20100601 int fd; nullpo_retv(sd); @@ -16927,6 +17209,7 @@ void clif_search_store_info_failed(struct map_session_data* sd, unsigned char re WFIFOW(fd,0) = 0x837; WFIFOB(fd,2) = reason; WFIFOSET(fd,packet_len(0x837)); +#endif } void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -16944,6 +17227,7 @@ void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) /// 1 = Search Stores (Cash), asks for confirmation, when clicking a store void clif_open_search_store_info(struct map_session_data* sd) { +#if PACKETVER >= 20100608 int fd; nullpo_retv(sd); @@ -16955,6 +17239,7 @@ void clif_open_search_store_info(struct map_session_data* sd) WFIFOB(fd,4) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); #endif WFIFOSET(fd,packet_len(0x83a)); +#endif } void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -16985,6 +17270,7 @@ void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd /// 083d <xPos>.W <yPos>.W void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y) { +#if PACKETVER >= 20100608 int fd; nullpo_retv(sd); @@ -16994,6 +17280,7 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor WFIFOW(fd,2) = x; WFIFOW(fd,4) = y; WFIFOSET(fd,packet_len(0x83d)); +#endif } /// Parse function for packet debugging. @@ -17009,10 +17296,10 @@ void clif_parse_debug(int fd,struct map_session_data *sd) { if( packet_len == -1 ) {// variable length packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received } - ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", (unsigned int)cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); } else { packet_len = (int)RFIFOREST(fd); - ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", (unsigned int)cmd, packet_len, fd); } ShowDump(RFIFOP(fd,0), packet_len); @@ -17262,6 +17549,7 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { *------------------------------------------*/ void clif_charm(struct map_session_data *sd) { +#if PACKETVER >= 20110809 unsigned char buf[10]; nullpo_retv(sd); @@ -17271,6 +17559,7 @@ void clif_charm(struct map_session_data *sd) WBUFW(buf,6) = sd->charm_type; WBUFW(buf,8) = sd->charm_count; clif->send(buf,packet_len(0x08cf),&sd->bl,AREA); +#endif } void clif_parse_MoveItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -17308,8 +17597,8 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { /* [Ind/Hercules] */ void clif_cashshop_db(void) { - config_t cashshop_conf; - config_setting_t *cashshop = NULL, *cats = NULL; + struct config_t cashshop_conf; + struct config_setting_t *cashshop = NULL, *cats = NULL; const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name int i, item_count_t = 0; for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { @@ -17317,16 +17606,14 @@ void clif_cashshop_db(void) { clif->cs.item_count[i] = 0; } - if (libconfig->read_file(&cashshop_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&cashshop_conf, config_filename)) return; - } cashshop = libconfig->lookup(&cashshop_conf, "cash_shop"); if( cashshop != NULL && (cats = libconfig->setting_get_elem(cashshop, 0)) != NULL ) { for(i = 0; i < CASHSHOP_TAB_MAX; i++) { - config_setting_t *cat; + struct config_setting_t *cat; char entry_name[10]; sprintf(entry_name,"cat_%d",i); @@ -17335,7 +17622,7 @@ void clif_cashshop_db(void) { int k, item_count = libconfig->setting_length(cat); for(k = 0; k < item_count; k++) { - config_setting_t *entry = libconfig->setting_get_elem(cat,k); + struct config_setting_t *entry = libconfig->setting_get_elem(cat,k); const char *name = config_setting_name(entry); int price = libconfig->setting_get_int(entry); struct item_data * data = NULL; @@ -17374,6 +17661,7 @@ void clif_cashshop_db(void) { /// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE). /// 0900 <index>.W <favorite>.B void clif_favorite_item(struct map_session_data* sd, unsigned short index) { +#if PACKETVER >= 20120410 int fd; nullpo_retv(sd); @@ -17383,9 +17671,11 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) { WFIFOW(fd,2) = index+2; WFIFOB(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; WFIFOSET(fd,packet_len(0x908)); +#endif } void clif_snap( struct block_list *bl, short x, short y ) { +#if PACKETVER >= 20110809 unsigned char buf[10]; nullpo_retv(bl); @@ -17395,9 +17685,12 @@ void clif_snap( struct block_list *bl, short x, short y ) { WBUFW(buf,8) = y; clif->send(buf,packet_len(0x8d2),bl,AREA); +#endif } -void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) { +void clif_monster_hp_bar(struct mob_data *md, struct map_session_data *sd) +{ +#if PACKETVER >= 20120228 struct packet_monster_hp p; nullpo_retv(md); @@ -17408,6 +17701,7 @@ void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) { p.MaxHP = md->status.max_hp; clif->send(&p, sizeof(p), &sd->bl, SELF); +#endif } /* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */ @@ -17436,7 +17730,9 @@ void clif_parse_CashShopClose(int fd, struct map_session_data *sd) { } void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { +void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) +{ +#if PACKETVER >= 20110614 int i, j = 0; for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { @@ -17456,6 +17752,7 @@ void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { WFIFOSET(fd, 8 + ( clif->cs.item_count[i] * 6 )); } +#endif } void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -17549,7 +17846,9 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /* [Ind/Hercules] */ -void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { +void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) +{ +#if PACKETVER >= 20110222 short tab = RFIFOW(fd, 2); int j; @@ -17568,9 +17867,12 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { } WFIFOSET(fd, 10 + ( clif->cs.item_count[tab] * 6 )); +#endif } + /* [Ind/Hercules] */ -void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { +void clif_maptypeproperty2(struct block_list *bl,enum send_target t) +{ #if PACKETVER >= 20121010 struct packet_maptypeproperty2 p; struct map_session_data *sd = NULL; @@ -17621,26 +17923,29 @@ void clif_partytickack(struct map_session_data* sd, bool flag) { WFIFOSET(sd->fd, packet_len(0x2c9)); } -void clif_ShowScript(struct block_list* bl, const char* message) { +void clif_ShowScript(struct block_list *bl, const char *message) +{ +#if PACKETVER >= 20110111 char buf[256]; - size_t len; + int len; nullpo_retv(bl); - if(!message) + if (message == NULL) return; - len = strlen(message)+1; + len = (int)strlen(message)+1; - if (len > sizeof(buf)-8) { - ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%"PRIuS").\n", message, len); - len = sizeof(buf)-8; + if (len > (int)sizeof(buf)-8) { + ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%d).\n", message, len); + len = (int)sizeof(buf)-8; } - WBUFW(buf,0)=0x8b3; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=bl->id; - safestrncpy((char *) WBUFP(buf,8),message,len); - clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); + WBUFW(buf,0) = 0x8b3; + WBUFW(buf,2) = len+8; + WBUFL(buf,4) = bl->id; + safestrncpy(WBUFP(buf,8),message,len); + clif->send(buf,WBUFW(buf,2),bl,AREA); +#endif } void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) { @@ -17679,7 +17984,8 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK } } -void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name) { +void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, const char *name) +{ struct packet_bgqueue_notice_delete p; nullpo_retv(sd); @@ -17691,8 +17997,9 @@ void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_ } void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) { - struct packet_bgqueue_register *p = RP2PTR(fd); +void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_register *p = RP2PTR(fd); struct bg_arena *arena = NULL; if( !bg->queue_on ) return; /* temp, until feature is complete */ @@ -17729,19 +18036,21 @@ void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_i } void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) { - struct packet_bgqueue_checkstate *p = RP2PTR(fd); +void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_checkstate *p = RP2PTR(fd); - nullpo_retv(sd); - if ( sd->bg_queue.arena && sd->bg_queue.type ) { + if (sd->bg_queue.arena && sd->bg_queue.type) { clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id)); - } else + } else { clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name); + } } void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { - struct packet_bgqueue_revoke_req *p = RP2PTR(fd); +void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_revoke_req *p = RP2PTR(fd); if( sd->bg_queue.arena ) bg->queue_pc_cleanup(sd); @@ -17750,8 +18059,9 @@ void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { } void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) { - struct packet_bgqueue_battlebegin_ack *p = RP2PTR(fd); +void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_battlebegin_ack *p = RP2PTR(fd); struct bg_arena *arena; if( !bg->queue_on ) return; /* temp, until feature is complete */ @@ -17792,14 +18102,17 @@ void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_ clif->send(&p,sizeof(p), &sd->bl, target); } -void clif_scriptclear(struct map_session_data *sd, int npcid) { +void clif_scriptclear(struct map_session_data *sd, int npcid) +{ +#if PACKETVER >= 20110928 struct packet_script_clear p; nullpo_retv(sd); p.PacketType = script_clearType; p.NpcID = npcid; - clif->send(&p,sizeof(p), &sd->bl, SELF); + clif->send(&p, sizeof(p), &sd->bl, SELF); +#endif } /* Made Possible Thanks to Yommy! */ @@ -17887,10 +18200,11 @@ void clif_cart_additem_ack(struct map_session_data *sd, int flag) { clif->send(&p,sizeof(p), &sd->bl, SELF); } -void clif_parse_BankDeposit(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /* Bank System [Yommy/Hercules] */ -void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { - struct packet_banking_deposit_req *p = RP2PTR(fd); +void clif_parse_BankDeposit(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_BankDeposit(int fd, struct map_session_data *sd) +{ + const struct packet_banking_deposit_req *p = RP2PTR(fd); int money; if (!battle_config.feature_banking) { @@ -17903,9 +18217,10 @@ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { pc->bank_deposit(sd,money); } -void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { - struct packet_banking_withdraw_req *p = RP2PTR(fd); +void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) +{ + const struct packet_banking_withdraw_req *p = RP2PTR(fd); int money; if (!battle_config.feature_banking) { @@ -17919,7 +18234,9 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { } void clif_parse_BankCheck(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -void clif_parse_BankCheck(int fd, struct map_session_data* sd) { +void clif_parse_BankCheck(int fd, struct map_session_data* sd) +{ +#if PACKETVER >= 20130313 struct packet_banking_check p; if (!battle_config.feature_banking) { @@ -17932,6 +18249,7 @@ void clif_parse_BankCheck(int fd, struct map_session_data* sd) { p.Reason = (short)0; clif->send(&p,sizeof(p), &sd->bl, SELF); +#endif } void clif_parse_BankOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -17944,7 +18262,9 @@ void clif_parse_BankClose(int fd, struct map_session_data* sd) { return; } -void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) { +void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) +{ +#if PACKETVER >= 20130313 struct packet_banking_deposit_ack p; nullpo_retv(sd); @@ -17954,9 +18274,12 @@ void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK r p.Reason = (short)reason; clif->send(&p,sizeof(p), &sd->bl, SELF); +#endif } -void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) { +void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) +{ +#if PACKETVER >= 20130313 struct packet_banking_withdraw_ack p; nullpo_retv(sd); @@ -17966,6 +18289,7 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK p.Reason = (short)reason; clif->send(&p,sizeof(p), &sd->bl, SELF); +#endif } /* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */ @@ -17978,7 +18302,7 @@ void clif_show_modifiers (struct map_session_data *sd) { snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%", sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death); - clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF); + clif->broadcast2(&sd->bl, output, (int)strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF); } } @@ -18140,32 +18464,30 @@ void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) { sd->npc_shopid = 0; } -void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) { +void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, unsigned char response) +{ #if PACKETVER >= 20131223 unsigned short c = 0; nullpo_retv(sd); - nullpo_retv(req); + nullpo_retv(item_list); npcmarket_result.PacketType = npcmarketresultackType; npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */ - if( npcmarket_result.result ) { - unsigned short i, list_size = (req->PacketLength - 4) / sizeof(req->list[0]), j; - struct npc_data* nd; - struct npc_item_list *shop = NULL; - unsigned short shop_size = 0; - - nd = map->id2nd(sd->npc_shopid); - - shop = nd->u.scr.shop->item; - shop_size = nd->u.scr.shop->items; + if (npcmarket_result.result) { + struct npc_data *nd = map->id2nd(sd->npc_shopid); + struct npc_item_list *shop = nd->u.scr.shop->item; + unsigned short shop_size = nd->u.scr.shop->items; + int i; - for(i = 0; i < list_size; i++) { + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int j; - npcmarket_result.list[i].ITID = req->list[i].ITID; - npcmarket_result.list[i].qty = req->list[i].qty; + npcmarket_result.list[i].ITID = entry->id; + npcmarket_result.list[i].qty = entry->amount; - ARR_FIND( 0, shop_size, j, req->list[i].ITID == shop[j].nameid ); + ARR_FIND( 0, shop_size, j, entry->id == shop[j].nameid); npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0; @@ -18180,11 +18502,32 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc } void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { +void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) +{ #if PACKETVER >= 20131223 - struct packet_npc_market_purchase *p = RP2PTR(fd); + const struct packet_npc_market_purchase *p = RP2PTR(fd); + int response = 0, i; + int count = (p->PacketLength - 4) / sizeof p->list[0]; + struct itemlist item_list; + + Assert_retv(count >= 0 && count <= MAX_INVENTORY); + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, count, 1); + + for (i = 0; i < count; i++) { + struct itemlist_entry entry = { 0 }; + + entry.id = p->list[i].ITID; + entry.amount = p->list[i].qty; + + VECTOR_PUSH(item_list, entry); + } + + response = npc->market_buylist(sd, &item_list); + clif->npc_market_purchase_ack(sd, &item_list, response); - clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p)); + VECTOR_CLEAR(item_list); #endif } @@ -18203,10 +18546,11 @@ void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, i void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /* Roulette System [Yommy/Hercules] */ void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) { +#if PACKETVER >= 20140612 struct packet_roulette_open_ack p; if( !battle_config.feature_roulette ) { - clif->message(fd,"Roulette is disabled"); + clif->message(fd, msg_fd(fd,82)); // Roulette is disabled return; } @@ -18221,15 +18565,18 @@ void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) { p.SilverPoint = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")); clif->send(&p,sizeof(p), &sd->bl, SELF); +#endif } void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) { +void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) +{ +#if PACKETVER >= 20140612 struct packet_roulette_info_ack p; unsigned short i, j, count = 0; if( !battle_config.feature_roulette ) { - clif->message(fd,"Roulette is disabled"); + clif->message(fd, msg_fd(fd,82)); // Roulette is disabled return; } @@ -18247,13 +18594,13 @@ void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) { } } clif->send(&p,sizeof(p), &sd->bl, SELF); - return; +#endif } void clif_parse_RouletteClose(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); void clif_parse_RouletteClose(int fd, struct map_session_data* sd) { if( !battle_config.feature_roulette ) { - clif->message(fd,"Roulette is disabled"); + clif->message(fd, msg_fd(fd,82)); // Roulette is disabled return; } @@ -18269,7 +18616,7 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { short stage = sd->roulette.stage; if( !battle_config.feature_roulette ) { - clif->message(fd,"Roulette is disabled"); + clif->message(fd, msg_fd(fd,82)); // Roulette is disabled return; } @@ -18304,7 +18651,7 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { it.nameid = clif->rd.nameid[stage][0]; it.identify = 1; - pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_OTHER);/** TODO maybe a new log type for roulette items? **/ + pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_ROULETTE);/** TODO maybe a new log type for roulette items? **/ sd->roulette.stage = 0; result = GENERATE_ROULETTE_LOSING; @@ -18321,11 +18668,13 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) __attribut /** * Request to cash in! **/ -void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { +void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) +{ +#if PACKETVER >= 20140612 struct packet_roulette_itemrecv_ack p; if( !battle_config.feature_roulette ) { - clif->message(fd,"Roulette is disabled"); + clif->message(fd, msg_fd(fd,82)); // Roulette is disabled return; } @@ -18339,7 +18688,7 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { it.nameid = clif->rd.nameid[sd->roulette.prizeStage][sd->roulette.prizeIdx]; it.identify = 1; - switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_OTHER)) { + switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_ROULETTE)) { case 0: p.Result = RECV_ITEM_SUCCESS; sd->roulette.claimPrize = false; @@ -18364,12 +18713,12 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { p.Result = RECV_ITEM_FAILED; clif->send(&p,sizeof(p), &sd->bl, SELF); - return; +#endif } bool clif_parse_roulette_db(void) { - config_t roulette_conf; - config_setting_t *roulette = NULL, *levels = NULL; + struct config_t roulette_conf; + struct config_setting_t *roulette = NULL, *levels = NULL; const char *config_filename = "db/roulette_db.conf"; // FIXME hardcoded name int i, j, item_count_t = 0; @@ -18377,15 +18726,13 @@ bool clif_parse_roulette_db(void) { clif->rd.items[i] = 0; } - if (libconfig->read_file(&roulette_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&roulette_conf, config_filename)) return false; - } roulette = libconfig->lookup(&roulette_conf, "roulette"); if( roulette != NULL && (levels = libconfig->setting_get_elem(roulette, 0)) != NULL ) { for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { - config_setting_t *level; + struct config_setting_t *level; char entry_name[10]; sprintf(entry_name,"level_%d",i+1); @@ -18394,7 +18741,7 @@ bool clif_parse_roulette_db(void) { int k, item_count = libconfig->setting_length(level); for(k = 0; k < item_count; k++) { - config_setting_t *entry = libconfig->setting_get_elem(level,k); + struct config_setting_t *entry = libconfig->setting_get_elem(level,k); const char *name = config_setting_name(entry); int qty = libconfig->setting_get_int(entry); struct item_data * data = NULL; @@ -18461,7 +18808,9 @@ bool clif_parse_roulette_db(void) { /** * **/ -void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) { +void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) +{ +#if PACKETVER >= 20140612 struct packet_roulette_generate_ack p; nullpo_retv(sd); @@ -18475,6 +18824,7 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul p.RemainSilver = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")); clif->send(&p,sizeof(p), &sd->bl, SELF); +#endif } /** @@ -18482,6 +18832,7 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul */ void clif_openmergeitem(int fd, struct map_session_data *sd) { +#if PACKETVER > 20120228 int i = 0, n = 0, j = 0; struct merge_item merge_items[MAX_INVENTORY]; struct merge_item *merge_items_[MAX_INVENTORY] = {0}; @@ -18524,6 +18875,7 @@ void clif_openmergeitem(int fd, struct map_session_data *sd) for ( i = 0; i < j; i++ ) WFIFOW(fd,i*2+4) = merge_items_[i]->position; WFIFOSET(fd,2*j+4); +#endif } int clif_comparemergeitem(const void *a, const void *b) @@ -18540,6 +18892,7 @@ int clif_comparemergeitem(const void *a, const void *b) void clif_ackmergeitems(int fd, struct map_session_data *sd) { +#if PACKETVER > 20120228 int i = 0, n = 0, length = 0, count = 0; int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0}; struct item item_data; @@ -18619,6 +18972,7 @@ void clif_ackmergeitems(int fd, struct map_session_data *sd) WFIFOW(fd,4) = count; WFIFOB(fd,6) = MERGEITEM_SUCCESS; WFIFOSET(fd,7); +#endif } void clif_cancelmergeitem (int fd, struct map_session_data *sd) @@ -18629,6 +18983,7 @@ void clif_cancelmergeitem (int fd, struct map_session_data *sd) void clif_dressroom_open(struct map_session_data *sd, int view) { +#if PACKETVER >= 20150513 int fd; nullpo_retv(sd); @@ -18638,6 +18993,7 @@ void clif_dressroom_open(struct map_session_data *sd, int view) WFIFOW(fd,0)=0xa02; WFIFOW(fd,2)=view; WFIFOSET(fd,packet_len(0xa02)); +#endif } /// Request to select cart's visual look for new cart design (ZC_SELECTCART). @@ -18662,6 +19018,64 @@ void clif_selectcart(struct map_session_data *sd) #endif } +/// Starts navigation to the given target on client side +void clif_navigate_to(struct map_session_data *sd, const char* mapname, uint16 x, uint16 y, uint8 flag, bool hideWindow, uint16 mob_id) +{ +// probably this packet with other fields present in older packet versions +#if PACKETVER >= 20120307 + int fd; + + nullpo_retv(sd); + nullpo_retv(mapname); + fd = sd->fd; + WFIFOHEAD(fd, packet_len(0x8e2)); + WFIFOW(fd, 0) = 0x8e2; + + // How detailed will our navigation be? + if (mob_id > 0) { + x = 0; + y = 0; + WFIFOB(fd, 2) = 3; // monster with destination field + } else if (x > 0 && y > 0) { + WFIFOB(fd, 2) = 0; // with coordinates + } else { + x = 0; + y = 0; + WFIFOB(fd, 2) = 1; // without coordinates(will fail if you are already on the map) + } + + // Which services can be used for transportation? + WFIFOB(fd, 3) = flag; + // If this flag is set, the navigation window will not be opened up + WFIFOB(fd, 4) = hideWindow; + // Target map + safestrncpy((char*)WFIFOP(fd, 5), mapname, MAP_NAME_LENGTH_EXT); + // Target x + WFIFOW(fd, 21) = x; + // Target y + WFIFOW(fd, 23) = y; + // Target monster ID + WFIFOW(fd, 25) = mob_id; + WFIFOSET(fd, packet_len(0x8e2)); +#endif +} + +/** + * Returns the name of the given bl, in a client-friendly format. + * + * @param bl The requested bl. + * @return The bl's name (guaranteed to be non-NULL). + */ +const char *clif_get_bl_name(const struct block_list *bl) +{ + const char *name = status->get_name(bl); + + if (name == NULL) + return "Unknown"; + + return name; +} + /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { if( sd ) { @@ -18761,7 +19175,7 @@ int clif_parse(int fd) { // filter out invalid / unsupported packets if (cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0) { ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %"PRIuS" bytes received), disconnecting session #%d.\n", - cmd, RFIFOW(fd,0), RFIFOREST(fd), fd); + (unsigned int)cmd, RFIFOW(fd,0), RFIFOREST(fd), fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif @@ -18777,7 +19191,7 @@ int clif_parse(int fd) { packet_len = RFIFOW(fd,2); if (packet_len < 4 || packet_len > 32768) { - ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); + ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", (unsigned int)cmd, packet_len, fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif @@ -18791,7 +19205,11 @@ int clif_parse(int fd) { return 0; // not enough data received to form the packet if( battle_config.packet_obfuscation == 2 || cmd != RFIFOW(fd, 0) || (sd && sd->parse_cmd_func == clif_parse_cmd_decrypt) ) { - RFIFOW(fd, 0) = cmd; + // Note: Overriding const qualifier to re-inject the decoded packet ID. +#define RFIFOP_mutable(fd, pos) ((void *)(sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos + (pos))) + int16 *packet_id = RFIFOP_mutable(fd, 0); +#undef RFIFOP_mutable + *packet_id = cmd; if( sd ) { sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF; // Update key for the next packet } @@ -18865,12 +19283,12 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) pFunc func; if (cmd > MAX_PACKET_DB) { - ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", cmd, MAX_PACKET_DB); + ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", (unsigned int)cmd, (unsigned int)MAX_PACKET_DB); return; } if (cmd < MIN_PACKET_DB) { - ShowError("Packet Error: packet 0x%x is lower than the minimum allowed (0x%x), skipping...\n", cmd, MIN_PACKET_DB); + ShowError("Packet Error: packet 0x%x is lower than the minimum allowed (0x%x), skipping...\n", (unsigned int)cmd, (unsigned int)MIN_PACKET_DB); return; } @@ -19163,6 +19581,7 @@ void clif_defaults(void) { clif->autoshadowspell_list = clif_autoshadowspell_list; clif->skill_itemlistwindow = clif_skill_itemlistwindow; clif->sc_load = clif_status_change2; + clif->sc_continue = clif_status_change2; clif->sc_end = clif_status_change_end; clif->initialstatus = clif_initialstatus; clif->cooldown_list = clif_skill_cooldown_list; @@ -19196,7 +19615,7 @@ void clif_defaults(void) { clif->skill_poseffect = clif_skill_poseffect; clif->skill_estimation = clif_skill_estimation; clif->skill_warppoint = clif_skill_warppoint; - clif->skillcasting = clif_skillcasting; + clif->useskill = clif_useskill; clif->produce_effect = clif_produceeffect; clif->devotion = clif_devotion; clif->spiritball = clif_spiritball; @@ -19244,7 +19663,8 @@ void clif_defaults(void) { clif->message = clif_displaymessage; clif->messageln = clif_displaymessage2; clif->messages = clif_displaymessage_sprintf; - clif->process_message = clif_process_message; + clif->process_chat_message = clif_process_chat_message; + clif->process_whisper_message = clif_process_whisper_message; clif->wisexin = clif_wisexin; clif->wisall = clif_wisall; clif->PMIgnoreList = clif_PMIgnoreList; @@ -19481,6 +19901,10 @@ void clif_defaults(void) { clif->ackmergeitems = clif_ackmergeitems; /* Cart Deco */ clif->selectcart = clif_selectcart; + /* */ + clif->isdisguised = clif_isdisguised; + clif->navigate_to = clif_navigate_to; + clif->bl_type = clif_bl_type; /*------------------------ *- Parse Incoming Packet @@ -19723,8 +20147,9 @@ void clif_defaults(void) { clif->pNPCMarketClosed = clif_parse_NPCMarketClosed; clif->pNPCMarketPurchase = clif_parse_NPCMarketPurchase; /* */ - clif->add_random_options = clif_add_random_options; + clif->add_item_options = clif_add_item_options; clif->pHotkeyRowShift = clif_parse_HotkeyRowShift; clif->dressroom_open = clif_dressroom_open; clif->pOneClick_ItemIdentify = clif_parse_OneClick_ItemIdentify; + clif->get_bl_name = clif_get_bl_name; } |