diff options
Diffstat (limited to 'src/map/clif.c')
-rw-r--r-- | src/map/clif.c | 1428 |
1 files changed, 881 insertions, 547 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 56fdb4193..7ada310e2 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -44,6 +44,8 @@ #include "clif.h" #include "mail.h" #include "quest.h" +#include "packets_struct.h" +#include "irc-bot.h" #include <stdio.h> #include <stdlib.h> @@ -256,7 +258,7 @@ static inline unsigned char clif_bl_type(struct block_list *bl) { int clif_send_sub(struct block_list *bl, va_list ap) { struct block_list *src_bl; struct map_session_data *sd; - unsigned char *buf; + void *buf; int len, type, fd; nullpo_ret(bl); @@ -266,7 +268,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) { if (!fd) //Don't send to disconnected clients. return 0; - buf = va_arg(ap,unsigned char*); + buf = va_arg(ap,void*); len = va_arg(ap,int); nullpo_ret(src_bl = va_arg(ap,struct block_list*)); type = va_arg(ap,int); @@ -319,7 +321,7 @@ int clif_send_sub(struct block_list *bl, va_list ap) { * Packet Delegation (called on all packets that require data to be sent to more than one client) * functions that are sent solely to one use whose ID it posses use WFIFOSET *------------------------------------------*/ -int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type) { +int clif_send(const void* buf, int len, struct block_list* bl, enum send_target type) { int i; struct map_session_data *sd, *tsd; struct party_data *p = NULL; @@ -555,29 +557,23 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target return 0; } - /// Notifies the client, that it's connection attempt was accepted. /// 0073 <start time>.L <position>.3B <x size>.B <y size>.B (ZC_ACCEPT_ENTER) /// 02eb <start time>.L <position>.3B <x size>.B <y size>.B <font>.W (ZC_ACCEPT_ENTER2) void clif_authok(struct map_session_data *sd) { -#if PACKETVER < 20080102 - const int cmd = 0x73; -#else - const int cmd = 0x2eb; -#endif - int fd = sd->fd; - - WFIFOHEAD(fd,packet_len(cmd)); - WFIFOW(fd, 0) = cmd; - WFIFOL(fd, 2) = gettick(); - WFIFOPOS(fd, 6, sd->bl.x, sd->bl.y, sd->ud.dir); - WFIFOB(fd, 9) = 5; // ignored - WFIFOB(fd,10) = 5; // ignored + struct packet_authok p; + + p.PacketType = authokType; + p.startTime = gettick(); + WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */ + p.xSize = p.ySize = 5; /* not-used */ + #if PACKETVER >= 20080102 - WFIFOW(fd,11) = sd->user_font; // FIXME: Font is currently not saved. + p.font = sd->user_font; // FIXME: Font is currently not saved. #endif - WFIFOSET(fd,packet_len(cmd)); + + clif->send(&p,sizeof(p),&sd->bl,SELF); } @@ -666,27 +662,29 @@ void clif_charselectok(int id, uint8 ok) /// Makes an item appear on the ground. /// 009e <id>.L <name id>.W <identified>.B <x>.W <y>.W <subX>.B <subY>.B <amount>.W (ZC_ITEM_FALL_ENTRY) /// 084b (ZC_ITEM_FALL_ENTRY4) -void clif_dropflooritem(struct flooritem_data* fitem) -{ - uint8 buf[17]; +void clif_dropflooritem(struct flooritem_data* fitem) { + struct packet_dropflooritem p; int view; nullpo_retv(fitem); if (fitem->item_data.nameid <= 0) return; - - WBUFW(buf, 0) = 0x9e; - WBUFL(buf, 2) = fitem->bl.id; - WBUFW(buf, 6) = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; - WBUFB(buf, 8) = fitem->item_data.identify; - WBUFW(buf, 9) = fitem->bl.x; - WBUFW(buf,11) = fitem->bl.y; - WBUFB(buf,13) = fitem->subx; - WBUFB(buf,14) = fitem->suby; - WBUFW(buf,15) = fitem->item_data.amount; - - clif->send(buf, packet_len(0x9e), &fitem->bl, AREA); + + p.PacketType = dropflooritemType; + p.ITAID = fitem->bl.id; + p.ITID = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; +#if PACKETVER >= 20130000 /* not sure date */ + p.type = itemtype(itemdb_type(fitem->item_data.nameid)); +#endif + p.IsIdentified = fitem->item_data.identify; + p.xPos = fitem->bl.x; + p.yPos = fitem->bl.y; + p.subX = fitem->subx; + p.subY = fitem->suby; + p.count = fitem->item_data.amount; + + clif->send(&p, sizeof(p), &fitem->bl, AREA); } @@ -836,12 +834,91 @@ static int clif_setlevel(struct block_list* bl) { } /*========================================== - * Prepares 'unit standing/spawning' packet + * Prepares 'unit standing' packet *------------------------------------------*/ -int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) { +void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enum send_target target) { struct map_session_data* sd; struct status_change* sc = status_get_sc(bl); struct view_data* vd = status_get_viewdata(bl); + struct packet_idle_unit p; + int g_id = status_get_emblem_id(bl); + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = idle_unitType; +#if PACKETVER >= 20091103 + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); +#endif + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodypalette = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; +#if PACKETVER < 7 + p.shield = vd->shield; +#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? + p.accessory = g_id; + p.accessory2 = GetWord(g_id, 1); + p.accessory3 = GetWord(g_id, 0); + } + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; +#endif + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl)); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.state = vd->dead_sit; + p.clevel = clif_setlevel(bl); +#if PACKETVER >= 20080102 + p.font = (sd) ? sd->user_font : 0; +#endif +#if PACKETVER >= 20120712 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } +#endif + + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); + + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; +#else + p.GID = -bl->id; +#endif + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF); + } + +} +/* todo for packetver 20091103 0x7c non-pc-looking unit handling */ +int clif_spawn_unit2(struct block_list* bl, enum send_target target) { + return 0; + /*struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); unsigned char *buf = WBUFP(buffer,0); #if PACKETVER < 20091103 bool type = !pcdb_checkid(vd->class_); @@ -851,26 +928,26 @@ int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) const char *name; #endif sd = BL_CAST(BL_PC, bl); - + #if PACKETVER < 20091103 if(type) - WBUFW(buf,0) = spawn?0x7c:0x78; + WBUFW(buf,0) = 0x7c; else #endif #if PACKETVER < 4 - WBUFW(buf,0) = spawn?0x79:0x78; + WBUFW(buf,0) = 0x79; #elif PACKETVER < 7 - WBUFW(buf,0) = spawn?0x1d9:0x1d8; + WBUFW(buf,0) = 0x1d9; #elif PACKETVER < 20080102 - WBUFW(buf,0) = spawn?0x22b:0x22a; + WBUFW(buf,0) = 0x22b; #elif PACKETVER < 20091103 - WBUFW(buf,0) = spawn?0x2ed:0x2ee; + WBUFW(buf,0) = 0x2ed; #elif PACKETVER < 20101124 - WBUFW(buf,0) = spawn?0x7f8:0x7f9; + WBUFW(buf,0) = 0x7f8; #else - WBUFW(buf,0) = spawn?0x858:0x857; + WBUFW(buf,0) = 0x858; #endif - + #if PACKETVER >= 20091103 name = status_get_name(bl); #if PACKETVER < 20110111 @@ -931,14 +1008,14 @@ int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) #endif WBUFW(buf,24) = vd->head_top; WBUFW(buf,26) = vd->head_mid; - + if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? WBUFW(buf,22) = status_get_emblem_id(bl); WBUFW(buf,24) = GetWord(status_get_guild_id(bl), 1); WBUFW(buf,26) = GetWord(status_get_guild_id(bl), 0); } - + WBUFW(buf,28) = vd->hair_color; WBUFW(buf,30) = vd->cloth_color; WBUFW(buf,32) = (sd)? sd->head_dir : 0; @@ -998,130 +1075,160 @@ int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) #else return packet_len(WBUFW(buffer,0)); #endif + */ } -/*========================================== - * Prepares 'unit walking' packet - *------------------------------------------*/ -int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, unsigned char* buffer) { +void clif_spawn_unit(struct block_list* bl, enum send_target target) { struct map_session_data* sd; struct status_change* sc = status_get_sc(bl); struct view_data* vd = status_get_viewdata(bl); - unsigned char* buf = WBUFP(buffer,0); -#if PACKETVER >= 7 - unsigned short offset = 0; -#endif -#if PACKETVER >= 20091103 - const char *name; -#endif + struct packet_spawn_unit p; + int g_id = status_get_emblem_id(bl); sd = BL_CAST(BL_PC, bl); - -#if PACKETVER < 4 - WBUFW(buf, 0) = 0x7b; -#elif PACKETVER < 7 - WBUFW(buf, 0) = 0x1da; -#elif PACKETVER < 20080102 - WBUFW(buf, 0) = 0x22c; -#elif PACKETVER < 20091103 - WBUFW(buf, 0) = 0x2ec; -#elif PACKETVER < 20101124 - WBUFW(buf, 0) = 0x7f7; -#else - WBUFW(buf, 0) = 0x856; -#endif - + + p.PacketType = spawn_unitType; #if PACKETVER >= 20091103 - name = status_get_name(bl); -#if PACKETVER < 20110111 - WBUFW(buf, 2) = 69+strlen(name); -#else - WBUFW(buf, 2) = 71+strlen(name); + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); #endif - offset+=2; - buf = WBUFP(buffer,offset); + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodypalette = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; +#if PACKETVER < 7 + p.shield = vd->shield; #endif -#if PACKETVER >= 20071106 - WBUFB(buf, 2) = clif_bl_type(bl); - offset++; - buf = WBUFP(buffer,offset); + 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? + p.accessory = g_id; + p.accessory2 = GetWord(g_id, 1); + p.accessory3 = GetWord(g_id, 0); + } + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; #endif - WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = status_get_speed(bl); - WBUFW(buf, 8) = (sc)? sc->opt1 : 0; - WBUFW(buf,10) = (sc)? sc->opt2 : 0; -#if PACKETVER < 7 - WBUFW(buf,12) = (sc)? sc->option : 0; -#else - WBUFL(buf,12) = (sc)? sc->option : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl)); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.clevel = clif_setlevel(bl); +#if PACKETVER >= 20080102 + p.font = (sd) ? sd->user_font : 0; #endif - WBUFW(buf,14) = vd->class_; - WBUFW(buf,16) = vd->hair_style; - WBUFW(buf,18) = vd->weapon; -#if PACKETVER < 4 - WBUFW(buf,20) = vd->head_bottom; - WBUFL(buf,22) = gettick(); - WBUFW(buf,26) = vd->shield; +#if PACKETVER >= 20120712 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } +#endif + clif->send(&p,sizeof(p),bl,target); + + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; #else - WBUFW(buf,20) = vd->shield; - WBUFW(buf,22) = vd->head_bottom; - WBUFL(buf,24) = gettick(); + p.GID = -bl->id; #endif - WBUFW(buf,28) = vd->head_top; - WBUFW(buf,30) = vd->head_mid; - WBUFW(buf,32) = vd->hair_color; - WBUFW(buf,34) = vd->cloth_color; - WBUFW(buf,36) = (sd)? sd->head_dir : 0; -#if PACKETVER >= 20110111 - WBUFW(buf,38) = vd->robe; - offset+= 2; - buf = WBUFP(buffer,offset); + clif->send(&p,sizeof(p),bl,SELF); + } + +} + +/*========================================== + * Prepares 'unit walking' packet + *------------------------------------------*/ +void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, struct unit_data* ud, enum send_target target) { + struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); + struct packet_unit_walking p; + int g_id = status_get_emblem_id(bl); + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = unit_walkingType; +#if PACKETVER >= 20091103 + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); #endif - WBUFL(buf,38) = status_get_guild_id(bl); - WBUFW(buf,42) = status_get_emblem_id(bl); - WBUFW(buf,44) = (sd)? sd->status.manner : 0; + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodypalette = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; + p.moveStartTime = gettick(); #if PACKETVER < 7 - WBUFW(buf,46) = (sc)? sc->opt3 : 0; -#else - WBUFL(buf,46) = (sc)? sc->opt3 : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + p.shield = vd->shield; +#endif + p.accessory2 = vd->head_top; + p.accessory3 = vd->head_mid; + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; #endif - WBUFB(buf,48) = (sd)? sd->status.karma : 0; - WBUFB(buf,49) = vd->sex; - WBUFPOS2(buf,50,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFB(buf,56) = (sd)? 5 : 0; - WBUFB(buf,57) = (sd)? 5 : 0; - WBUFW(buf,58) = clif_setlevel(bl); + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS2(&p.MoveData[0],0,bl->x,bl->y,ud->to_x,ud->to_y,8,8); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.clevel = clif_setlevel(bl); #if PACKETVER >= 20080102 - WBUFW(buf,60) = sd?sd->user_font:0; + p.font = (sd) ? sd->user_font : 0; #endif -#if PACKETVER >= 20091103 - memcpy((char*)WBUFP(buf,62), name, NAME_LENGTH); - return WBUFW(buffer,2); -#else - return packet_len(WBUFW(buffer,0)); +#if PACKETVER >= 20120712 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } #endif -} + + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); -//Modifies the buffer for disguise characters and sends it to self. -//Used for spawn/walk packets, where the ID offset changes for packetver >=9 -void clif_setdisguise(struct block_list *bl, unsigned char *buf,int len) { -#if PACKETVER >= 20091103 - WBUFB(buf,4)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,5)=-bl->id; -#elif PACKETVER >= 20071106 - WBUFB(buf,2)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,3)=-bl->id; + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; #else - WBUFL(buf,2)=-bl->id; -#endif - clif->send(buf, len, bl, SELF); + p.GID = -bl->id; +#endif + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF); + } } - /// Changes sprite of an NPC object (ZC_NPCSPRITE_CHANGE). /// 01b0 <id>.L <type>.B <value>.L /// type: @@ -1220,9 +1327,7 @@ void clif_weather(int16 m) **/ int clif_spawn(struct block_list *bl) { - unsigned char buf[128]; struct view_data *vd; - int len; vd = status_get_viewdata(bl); if( !vd || vd->class_ == INVISIBLE_CLASS ) @@ -1234,67 +1339,63 @@ int clif_spawn(struct block_list *bl) if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) return 0; - len = clif->set_unit_idle(bl, buf,true); - clif->send(buf, len, bl, AREA_WOS); - if (disguised(bl)) - clif->setdisguise(bl, buf, len); + clif->spawn_unit(bl,AREA_WOS); if (vd->cloth_color) clif->refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - switch (bl->type) - { - case BL_PC: - { - TBL_PC *sd = ((TBL_PC*)bl); - int i; - if (sd->spiritball > 0) - clif->spiritball(&sd->bl); - if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif->specialeffect(bl,423,AREA); - else if(sd->state.size==SZ_MEDIUM) - clif->specialeffect(bl,421,AREA); - if( sd->bg_id && map[sd->bl.m].flag.battleground ) - clif->sendbgemblem_area(sd); - if( sd->sc.option&OPTION_MOUNTING ) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. - clif->sc_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + switch (bl->type) { + case BL_PC: + { + TBL_PC *sd = ((TBL_PC*)bl); + int i; + if (sd->spiritball > 0) + clif->spiritball(&sd->bl); + if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif->specialeffect(bl,423,AREA); + else if(sd->state.size==SZ_MEDIUM) + clif->specialeffect(bl,421,AREA); + if( sd->bg_id && map[sd->bl.m].flag.battleground ) + clif->sendbgemblem_area(sd); + if( sd->sc.option&OPTION_MOUNTING ) { + //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. + clif->sc_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + } + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif->talisman(sd, i); + } + #ifdef NEW_CARTS + if( sd->sc.data[SC_PUSH_CART] ) + clif->sc_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); + #endif + if (sd->status.robe) + clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); + } + break; + case BL_MOB: + { + TBL_MOB *md = ((TBL_MOB*)bl); + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif->specialeffect(&md->bl,423,AREA); + else if(md->special_state.size==SZ_MEDIUM) + clif->specialeffect(&md->bl,421,AREA); } - for(i = 1; i < 5; i++){ - if( sd->talisman[i] > 0 ) - clif->talisman(sd, i); + break; + case BL_NPC: + { + TBL_NPC *nd = ((TBL_NPC*)bl); + if( nd->size == SZ_BIG ) + clif->specialeffect(&nd->bl,423,AREA); + else if( nd->size == SZ_MEDIUM ) + clif->specialeffect(&nd->bl,421,AREA); } - #ifdef NEW_CARTS - if( sd->sc.data[SC_PUSH_CART] ) - clif->sc_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); - #endif - if (sd->status.robe) - clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); - } - break; - case BL_MOB: - { - TBL_MOB *md = ((TBL_MOB*)bl); - if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif->specialeffect(&md->bl,423,AREA); - else if(md->special_state.size==SZ_MEDIUM) - clif->specialeffect(&md->bl,421,AREA); - } - break; - case BL_NPC: - { - TBL_NPC *nd = ((TBL_NPC*)bl); - if( nd->size == SZ_BIG ) - clif->specialeffect(&nd->bl,423,AREA); - else if( nd->size == SZ_MEDIUM ) - clif->specialeffect(&nd->bl,421,AREA); - } - break; - case BL_PET: - if (vd->head_bottom) - clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly - break; + break; + case BL_PET: + if (vd->head_bottom) + clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly + break; } return 0; } @@ -1464,13 +1565,8 @@ void clif_walkok(struct map_session_data *sd) void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) { - uint8 buf[128]; - int len; - len = clif->set_unit_walking(bl,ud,buf); - clif->send(buf,len,bl,AREA_WOS); - if (disguised(bl)) - clif->setdisguise(bl, buf, len); + clif->set_unit_walking(bl,NULL,ud,AREA_WOS); if(vd->cloth_color) clif->refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); @@ -1694,6 +1790,9 @@ void clif_hercules_chsys_create(struct hChSysCh *channel, char *name, char *pass safestrncpy(channel->pass, pass, HCHSYS_NAME_LENGTH); channel->opt = hChSys_OPT_BASE; + channel->banned = NULL; + + channel->msg_delay = 0; if( channel->type != hChSys_MAP && channel->type != hChSys_ALLY ) strdb_put(clif->channel_db, channel->name, channel); @@ -2057,79 +2156,99 @@ void clif_addcards(unsigned char* buf, struct item* item) { WBUFW(buf,6) = item->card[i]; } +void clif_addcards2(unsigned short *cards, struct item* item) { + int i=0,j; + if( item == NULL ) { //Blank data + cards[0] = 0; + cards[1] = 0; + cards[2] = 0; + cards[3] = 0; + return; + } + if( item->card[0] == CARD0_PET ) { //pet eggs + cards[0] = 0; + cards[1] = 0; + cards[2] = 0; + cards[3] = item->card[3]; //Pet renamed flag. + return; + } + if( item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE ) { //Forged/created items + cards[0] = item->card[0]; + cards[1] = item->card[1]; + cards[2] = item->card[2]; + cards[3] = item->card[3]; + return; + } + //Client only receives four cards.. so randomly send them a set of cards. [Skotlex] + if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 ) + i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3; + + //Normal items. + if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[0] = j; + else + cards[0] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[1] = j; + else + cards[1] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[2] = j; + else + cards[2] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[3] = j; + else + cards[3] = item->card[i]; +} + /// Notifies the client, about a received inventory item or the result of a pick-up request. /// 00a0 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B (ZC_ITEM_PICKUP_ACK) /// 029a <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L (ZC_ITEM_PICKUP_ACK2) /// 02d4 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK3) -void clif_additem(struct map_session_data *sd, int n, int amount, int fail) -{ - int fd; -#if PACKETVER < 20061218 - const int cmd = 0xa0; -#elif PACKETVER < 20071002 - const int cmd = 0x29a; -#else - const int cmd = 0x2d4; -#endif +void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { + struct packet_additem p; nullpo_retv(sd); - fd = sd->fd; - if( !session_isActive(fd) ) //Sasuke- + if( !session_isActive(sd->fd) ) //Sasuke- return; - WFIFOHEAD(fd,packet_len(cmd)); if( fail ) - { - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; - WFIFOW(fd,6)=0; - WFIFOB(fd,8)=0; - WFIFOB(fd,9)=0; - WFIFOB(fd,10)=0; - WFIFOW(fd,11)=0; - WFIFOW(fd,13)=0; - WFIFOW(fd,15)=0; - WFIFOW(fd,17)=0; - WFIFOW(fd,19)=0; - WFIFOB(fd,21)=0; - WFIFOB(fd,22)=fail; -#if PACKETVER >= 20061218 - WFIFOL(fd,23)=0; -#endif -#if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown -#endif - } - else - { + memset(&p, 0, sizeof(p)); + + p.PacketType = additemType; + p.Index = n+2; + p.count = amount; + + if( !fail ) { if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; - - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; + if (sd->inventory_data[n]->view_id > 0) - WFIFOW(fd,6)=sd->inventory_data[n]->view_id; + p.nameid = sd->inventory_data[n]->view_id; else - WFIFOW(fd,6)=sd->status.inventory[n].nameid; - WFIFOB(fd,8)=sd->status.inventory[n].identify; - WFIFOB(fd,9)=sd->status.inventory[n].attribute; - WFIFOB(fd,10)=sd->status.inventory[n].refine; - clif->addcards(WFIFOP(fd,11), &sd->status.inventory[n]); - WFIFOW(fd,19)=pc_equippoint(sd,n); - WFIFOB(fd,21)=itemtype(sd->inventory_data[n]->type); - WFIFOB(fd,22)=fail; + p.nameid = sd->status.inventory[n].nameid; + + p.IsIdentified = sd->status.inventory[n].identify; + p.IsDamaged = sd->status.inventory[n].attribute; + p.refiningLevel =sd->status.inventory[n].refine; + clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]); + p.location = pc_equippoint(sd,n); + p.type = itemtype(sd->inventory_data[n]->type); #if PACKETVER >= 20061218 - WFIFOL(fd,23)=sd->status.inventory[n].expire_time; + p.HireExpireDate = sd->status.inventory[n].expire_time; #endif #if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown + p.bindOnEquipType = 0; // unused #endif } + p.result = (unsigned char)fail; - WFIFOSET(fd,packet_len(cmd)); + clif->send(&p,sizeof(p),&sd->bl,SELF); } @@ -2588,10 +2707,12 @@ void read_channels_config(void) { config_setting_t *colors; int i,k; const char *local_name, *ally_name, - *local_color, *ally_color; + *local_color, *ally_color, + *irc_name, *irc_color; int ally_enabled = 0, local_enabled = 0, local_autojoin = 0, ally_autojoin = 0, - allow_user_channel_creation = 0; + allow_user_channel_creation = 0, + irc_enabled = 0; if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) ) local_name = "map"; @@ -2601,13 +2722,66 @@ void read_channels_config(void) { ally_name = "ally"; safestrncpy(hChSys.ally_name, ally_name, HCHSYS_NAME_LENGTH); + if( !config_setting_lookup_string(settings, "irc_channel_name", &irc_name) ) + irc_name = "irc"; + safestrncpy(hChSys.irc_name, irc_name, HCHSYS_NAME_LENGTH); + config_setting_lookup_bool(settings, "map_local_channel", &local_enabled); config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); + config_setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled); if( local_enabled ) hChSys.local = true; if( ally_enabled ) hChSys.ally = true; + if( irc_enabled ) + hChSys.irc = true; + + hChSys.irc_server[0] = hChSys.irc_channel[0] = hChSys.irc_nick[0] = hChSys.irc_nick_pw[0] = '\0'; + + if( hChSys.irc ) { + const char *irc_server, *irc_channel, + *irc_nick, *irc_nick_pw; + if( config_setting_lookup_string(settings, "irc_channel_network", &irc_server) ) { + if( !strstr(irc_server,":") ) { + hChSys.irc = false; + ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n"); + } else { + unsigned char d = 0, dlen = strlen(irc_server); + char server[40]; + for(d = 0; d < dlen; d++) { + if(irc_server[d] == ':') { + memcpy(server, irc_server, d); + safestrncpy(hChSys.irc_server, server, 40); + memcpy(server, &irc_server[d+1], dlen); + hChSys.irc_server_port = atoi(server); + break; + } + } + } + } else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_channel", &irc_channel) ) + safestrncpy(hChSys.irc_channel, irc_channel, 20); + else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) { + if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) { + sprintf(hChSys.irc_nick, "Hercules_chSysBot%d",rand()%777); + } else + safestrncpy(hChSys.irc_nick, irc_nick, 30); + } else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) + safestrncpy(hChSys.irc_nick_pw, irc_nick_pw, 30); + + } config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); @@ -2649,7 +2823,7 @@ void read_channels_config(void) { if( k < hChSys.colors_count ) { hChSys.local_color = k; } else { - ShowError("channels.conf: unknown color '%s' for channel 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); + ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); hChSys.local = false; } @@ -2663,10 +2837,35 @@ void read_channels_config(void) { if( k < hChSys.colors_count ) { hChSys.ally_color = k; } else { - ShowError("channels.conf: unknown color '%s' for channel 'ally_channel_color', disabling '#%s'...\n",local_color,ally_name); + ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name); hChSys.ally = false; } + config_setting_lookup_string(settings, "irc_channel_color", &irc_color); + + for (k = 0; k < hChSys.colors_count; k++) { + if( strcmpi(hChSys.colors_name[k],irc_color) == 0 ) + break; + } + + if( k < hChSys.colors_count ) { + hChSys.irc_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name); + hChSys.irc = false; + } + + if( hChSys.irc ) { + struct hChSysCh *chd; + CREATE( chd, struct hChSysCh, 1 ); + + safestrncpy(chd->name, hChSys.irc_name, HCHSYS_NAME_LENGTH); + chd->type = hChSys_IRC; + + clif->chsys_create(chd,NULL,NULL,hChSys.irc_color); + ircbot->channel = chd; + } + if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) { int channel_count = config_setting_length(channels); @@ -2684,7 +2883,7 @@ void read_channels_config(void) { ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); continue; } - if( strcmpi(name,hChSys.local_name) == 0 || strcmpi(name,hChSys.ally_name) == 0 || strdb_exists(clif->channel_db, name) ) { + if( strcmpi(name,hChSys.local_name) == 0 || strcmpi(name,hChSys.ally_name) == 0 || strcmpi(name,hChSys.irc_name) == 0 || strdb_exists(clif->channel_db, name) ) { ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); continue; @@ -3534,9 +3733,18 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) } void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, char *msg) { - char message[150]; - snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); - clif->chsys_msg(channel,sd,message); + if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + clif->colormes(sd->fd,COLOR_RED,msg_txt(1455)); + return; + } else { + char message[150]; + snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); + clif->chsys_msg(channel,sd,message); + if( channel->type == hChSys_IRC ) + ircbot->relay(sd->status.name,msg); + if( channel->msg_delay != 0 ) + sd->hchsysch_tick = gettick(); + } } /// Inform client whether chatroom creation was successful or not (ZC_ACK_CREATE_CHATROOM). @@ -4115,10 +4323,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds } void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { - uint8 buf[128]; struct unit_data *ud; struct view_data *vd; - int len; vd = status_get_viewdata(bl); if (!vd || vd->class_ == INVISIBLE_CLASS) @@ -4130,66 +4336,64 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) return; - ud = unit_bl2ud(bl); - len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif->set_unit_walking(bl,ud,buf) : clif->set_unit_idle(bl,buf,false); - clif->send(buf,len,&sd->bl,SELF); + if ( ( ud = unit_bl2ud(bl) ) && ud->walktimer != INVALID_TIMER ) + clif->set_unit_walking(bl,sd,ud,SELF); + else + clif->set_unit_idle(bl,sd,SELF); if (vd->cloth_color) clif->refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); - switch (bl->type) - { - case BL_PC: - { - TBL_PC* tsd = (TBL_PC*)bl; - clif->getareachar_pc(sd, tsd); - if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif->specialeffect_single(bl,423,sd->fd); - else if(tsd->state.size==SZ_MEDIUM) - clif->specialeffect_single(bl,421,sd->fd); - if( tsd->bg_id && map[tsd->bl.m].flag.battleground ) - clif->sendbgemblem_single(sd->fd,tsd); - if( tsd->sc.data[SC_CAMOUFLAGE] ) - clif->status_change(bl, SI_CAMOUFLAGE, 1, 0, 0, 0, 0); - if ( tsd->status.robe ) - clif->refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); - } - break; - case BL_MER: // Devotion Effects - if( ((TBL_MER*)bl)->devotion_flag ) - clif->devotion(bl, sd); - break; - case BL_NPC: - { - TBL_NPC* nd = (TBL_NPC*)bl; - if( nd->chat_id ) - clif->dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); - if( nd->size == SZ_BIG ) - clif->specialeffect_single(bl,423,sd->fd); - else if( nd->size == SZ_MEDIUM ) - clif->specialeffect_single(bl,421,sd->fd); - } - break; - case BL_MOB: - { - TBL_MOB* md = (TBL_MOB*)bl; - if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif->specialeffect_single(bl,423,sd->fd); - else if(md->special_state.size==SZ_MEDIUM) - clif->specialeffect_single(bl,421,sd->fd); -#if PACKETVER >= 20120404 - if( !(md->status.mode&MD_BOSS) ){ - int i; - for(i = 0; i < DAMAGELOG_SIZE; i++)// must show hp bar to all char who already hit the mob. - if( md->dmglog[i].id == sd->status.char_id ) - clif->monster_hp_bar(md, sd->fd); + switch (bl->type) { + case BL_PC: + { + TBL_PC* tsd = (TBL_PC*)bl; + clif->getareachar_pc(sd, tsd); + if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif->specialeffect_single(bl,423,sd->fd); + else if(tsd->state.size==SZ_MEDIUM) + clif->specialeffect_single(bl,421,sd->fd); + if( tsd->bg_id && map[tsd->bl.m].flag.battleground ) + clif->sendbgemblem_single(sd->fd,tsd); + if( tsd->sc.data[SC_CAMOUFLAGE] ) + clif->status_change(bl, SI_CAMOUFLAGE, 1, 0, 0, 0, 0); + if ( tsd->status.robe ) + clif->refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); } -#endif - } - break; - case BL_PET: - if (vd->head_bottom) - clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly - break; + break; + case BL_MER: // Devotion Effects + if( ((TBL_MER*)bl)->devotion_flag ) + clif->devotion(bl, sd); + break; + case BL_NPC: + { + TBL_NPC* nd = (TBL_NPC*)bl; + if( nd->chat_id ) + clif->dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); + if( nd->size == SZ_BIG ) + clif->specialeffect_single(bl,423,sd->fd); + else if( nd->size == SZ_MEDIUM ) + clif->specialeffect_single(bl,421,sd->fd); + } + break; + case BL_MOB: + { + TBL_MOB* md = (TBL_MOB*)bl; + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif->specialeffect_single(bl,423,sd->fd); + else if(md->special_state.size==SZ_MEDIUM) + clif->specialeffect_single(bl,421,sd->fd); + /* only between 04-04 and 07-12 (afterwards its bundled on the other packet) */ + #if PACKETVER >= 20120404 + #if PACKETVER <= 20120712 + clif->monster_hp_bar(md); + #endif + #endif + } + break; + case BL_PET: + if (vd->head_bottom) + clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly + break; } } @@ -5369,6 +5573,27 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id } } +void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) { + struct packet_sc_notick p; + struct map_session_data *sd; + + nullpo_retv(bl); + + if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client + return; + + if (type == SI_BLANK) //It shows nothing on the client... + return; + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = sc_notickType; + p.index = type; + p.AID = bl->id; + p.state = (unsigned char)flag; + + clif->send(&p,packet_len(p.PacketType), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); +} /// Notifies clients of a status change. /// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)] @@ -5376,9 +5601,8 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id /// 08ff <id>.L <index>.W <remain msec>.L { <val>.L }*3 (PACKETVER >= 20111108) /// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618) /// 0984 <id>.L <index>.W <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618) -void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) -{ - unsigned char buf[32]; +void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) { + struct packet_status_change p; struct map_session_data *sd; if (type == SI_BLANK) //It shows nothing on the client... @@ -5386,46 +5610,26 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val nullpo_retv(bl); - sd = BL_CAST(BL_PC, bl); - if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client return; + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = status_changeType; + p.index = type; + p.AID = bl->id; + p.state = (unsigned char)flag; #if PACKETVER >= 20120618 - if(flag && battle_config.display_status_timers && sd) - WBUFW(buf,0)=0x983; - else -#elif PACKETVER >= 20090121 - if(flag && battle_config.display_status_timers && sd) - WBUFW(buf,0)=0x43f; - else + p.Total = tick; /* at this stage remain and total are the same value I believe */ #endif - WBUFW(buf,0)=0x196; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; -#if PACKETVER >= 20120618 - WBUFL(buf,9)=tick;/* at this stage remain and total are the same value I believe */ - WBUFL(buf,13)=tick; - if(flag && battle_config.display_status_timers && sd) { - if (tick <= 0) - tick = 9999; // this is indeed what official servers do - - WBUFL(buf,17) = val1; - WBUFL(buf,21) = val2; - WBUFL(buf,25) = val3; - } -#elif PACKETVER >= 20090121 - if(flag && battle_config.display_status_timers && sd) { - if (tick <= 0) - tick = 9999; // this is indeed what official servers do - - WBUFL(buf,9) = tick; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; - } +#if PACKETVER >= 20090121 + p.Left = tick; + p.val1 = val1; + p.val2 = val2; + p.val3 = val3; #endif - clif->send(buf,packet_len(WBUFW(buf,0)),bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); + + clif->send(&p,sizeof(p), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); } /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT). @@ -5570,7 +5774,7 @@ void clif_map_property(struct map_session_data* sd, enum map_property property) int fd; nullpo_retv(sd); - + fd=sd->fd; WFIFOHEAD(fd,packet_len(0x199)); WFIFOW(fd,0)=0x199; @@ -5632,7 +5836,7 @@ void clif_map_property_mapall(int map, enum map_property property) { struct block_list bl; unsigned char buf[16]; - + bl.id = 0; bl.type = BL_NUL; bl.m = map; @@ -6113,7 +6317,7 @@ void clif_closevendingboard(struct block_list* bl, int fd) /// Sends a list of items in a shop. /// R 0133 <packet len>.W <owner id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC) /// R 0800 <packet len>.W <owner id>.L <unique id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC2) -void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending) +void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_vending* vending) { int i,fd; int count; @@ -6349,7 +6553,7 @@ void clif_partyinvitationstate(struct map_session_data* sd) WFIFOHEAD(fd, packet_len(0x2c9)); WFIFOW(fd, 0) = 0x2c9; - WFIFOB(fd, 2) = 0; // not implemented + WFIFOB(fd, 2) = sd->status.allow_party ? 1 : 0; WFIFOSET(fd, packet_len(0x2c9)); } @@ -8181,16 +8385,16 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen } // Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead) /// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg) { +int clif_colormes(int fd, enum clif_colors color, const char* msg) { unsigned short msg_len = strlen(msg) + 1; - WFIFOHEAD(sd->fd,msg_len + 12); - WFIFOW(sd->fd,0) = 0x2C1; - WFIFOW(sd->fd,2) = msg_len + 12; - WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = color_table[color]; - safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); - WFIFOSET(sd->fd, msg_len + 12); + WFIFOHEAD(fd,msg_len + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = msg_len + 12; + WFIFOL(fd,4) = 0; + WFIFOL(fd,8) = color_table[color]; + safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); + WFIFOSET(fd, msg_len + 12); return 0; } @@ -8288,7 +8492,7 @@ void clif_refresh(struct map_session_data *sd) clif->changed_dir(&sd->bl, SELF); // unlike vending, resuming buyingstore crashes the client. - buyingstore_close(sd); + buyingstore->close(sd); mail_clear(sd); @@ -8954,6 +9158,27 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data * dbi_destroy(iter); } +void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) { + DBIterator *iter = db_iterator(channel->users); + struct map_session_data *user; + unsigned char buf[210]; + unsigned short msg_len = strlen(msg) + 1; + + WBUFW(buf,0) = 0x2C1; + WBUFW(buf,2) = msg_len + 12; + WBUFL(buf,4) = 0; + WBUFL(buf,8) = hChSys.colors[channel->color]; + safestrncpy((char*)WBUFP(buf,12), msg, msg_len); + + for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { + WFIFOHEAD(user->fd,msg_len + 12); + memcpy(WFIFOP(user->fd,0), WBUFP(buf,0), msg_len + 12); + WFIFOSET(user->fd, msg_len + 12); + } + + dbi_destroy(iter); +} + // ------------ // clif_parse_* // ------------ @@ -9037,12 +9262,17 @@ void clif_hercules_chsys_mjoin(struct map_session_data *sd) { clif->chsys_create(map[sd->bl.m].channel,NULL,NULL,hChSys.local_color); } + + if( map[sd->bl.m].channel->banned && idb_exists(map[sd->bl.m].channel->banned, sd->status.account_id) ) { + return; + } + clif->chsys_join(map[sd->bl.m].channel,sd); if( !( map[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { char mout[60]; sprintf(mout, msg_txt(1435),hChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s' - clif->message(sd->fd, mout); + clif->colormes(sd->fd, COLOR_DEFAULT, mout); } } @@ -9147,7 +9377,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if( map_flag_gvg(sd->bl.m) ) clif->map_property(sd, MAPPROPERTY_AGITZONE); - // info about nearby objects // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange) map_foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd); @@ -9305,6 +9534,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) mail_clear(sd); + clif->maptypeproperty2(&sd->bl,SELF); + /* Guild Aura Init */ if( sd->state.gmaster_flag ) { guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); @@ -9587,7 +9818,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -9656,7 +9887,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) #endif // Chat logging type 'O' / Global Chat - log_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); + 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); } @@ -9670,8 +9901,8 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) map_name = (char*)RFIFOP(fd,2); map_name[MAP_NAME_LENGTH_EXT-1]='\0'; - sprintf(command, "%cmapmove %s %d %d", atcommand_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmapmove %s %d %d", atcommand->at_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); + atcommand->parse(fd, sd, command, 1); } @@ -9901,6 +10132,74 @@ void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data } +void clif_hercules_chsys_quitg(struct map_session_data *sd) { + unsigned char i; + struct hChSysCh *channel = NULL; + + for( i = 0; i < sd->channel_count; i++ ) { + if( (channel = sd->channels[i] ) != NULL && channel->type == hChSys_ALLY ) { + idb_remove(channel->users,sd->status.char_id); + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { + clif->chsys_delete(channel); + } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + sd->channels[i] = NULL; + } + } + + if( i < sd->channel_count ) { + unsigned char cursor = 0; + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == NULL ) + continue; + if( cursor != i ) { + sd->channels[cursor] = sd->channels[i]; + } + cursor++; + } + if ( !(sd->channel_count = cursor) ) { + aFree(sd->channels); + sd->channels = NULL; + } + } + +} + + +void clif_hercules_chsys_quit(struct map_session_data *sd) { + unsigned char i; + struct hChSysCh *channel = NULL; + + for( i = 0; i < sd->channel_count; i++ ) { + if( (channel = sd->channels[i] ) != NULL ) { + idb_remove(channel->users,sd->status.char_id); + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { + clif->chsys_delete(channel); + } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + + } + } + + sd->channel_count = 0; + aFree(sd->channels); + sd->channels = NULL; +} + /// Request for an action. /// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT) /// 0437 <target id>.L <action>.B (CZ_REQUEST_ACT2) @@ -9960,7 +10259,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) ) return; - if ( is_atcommand(fd, sd, message, 1) ) + if ( atcommand->parse(fd, sd, message, 1) ) return; if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) @@ -9974,7 +10273,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) } // Chat logging type 'W' / Whisper - log_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); + 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); //-------------------------------------------------------// // Lordalfa - Paperboy - To whisper NPC commands // @@ -10038,7 +10337,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) } if( k < sd->channel_count ) { clif->chsys_send(channel,sd,message); - } else if( channel->pass[0] == '\0' ) { + } else if( channel->pass[0] == '\0' && !(channel->banned && idb_exists(channel->banned, sd->status.account_id)) ) { clif->chsys_join(channel,sd); clif->chsys_send(channel,sd,message); } else { @@ -10104,8 +10403,8 @@ void clif_parse_Broadcast(int fd, struct map_session_data* sd) { // as the length varies depending on the command used, just block unreasonably long strings mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%ckami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%ckami %s", atcommand->at_symbol, msg); + atcommand->parse(fd, sd, command, 1); } @@ -10288,6 +10587,10 @@ void clif_hercules_chsys_delete(struct hChSysCh *channel) { } dbi_destroy(iter); } + if( channel->banned ) { + db_destroy(channel->banned); + channel->banned = NULL; + } db_destroy(channel->users); if( channel->m ) { map[channel->m].channel = NULL; @@ -11172,13 +11475,13 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) uint8 select = RFIFOB(fd,6); if( (select > sd->npc_menu && select != 0xff) || select == 0 ) { -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT if( sd->npc_idle_timer != INVALID_TIMER ) { #endif TBL_NPC* nd = map_id2nd(npc_id); ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); clif->GM_kick(NULL,sd); -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT } #endif return; @@ -11340,11 +11643,11 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { char cmd[15]; if( RFIFOW(fd,2) ) - sprintf(cmd,"%cresetskill",atcommand_symbol); + sprintf(cmd,"%cresetskill",atcommand->at_symbol); else - sprintf(cmd,"%cresetstat",atcommand_symbol); + sprintf(cmd,"%cresetstat",atcommand->at_symbol); - is_atcommand(fd, sd, cmd, 1); + atcommand->parse(fd, sd, cmd, 1); } @@ -11360,8 +11663,8 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) // as the length varies depending on the command used, just block unreasonably long strings mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%clkami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%clkami %s", atcommand->at_symbol, msg); + atcommand->parse(fd, sd, command, 1); } @@ -11675,7 +11978,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -11876,7 +12179,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) /// 012e void clif_parse_CloseVending(int fd, struct map_session_data* sd) { - vending_closevending(sd); + vending->close(sd); } @@ -11887,7 +12190,7 @@ void clif_parse_VendingListReq(int fd, struct map_session_data* sd) if( sd->npc_id ) {// using an NPC return; } - vending_vendinglistreq(sd,RFIFOL(fd,2)); + vending->list(sd,RFIFOL(fd,2)); } @@ -11899,7 +12202,7 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) int id = (int)RFIFOL(fd,4); const uint8* data = (uint8*)RFIFOP(fd,8); - vending_purchasereq(sd, id, sd->vended_id, data, len/4); + vending->purchase(sd, id, sd->vended_id, data, len/4); // whether it fails or not, the buy window is closed sd->vended_id = 0; @@ -11915,7 +12218,7 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) int uid = (int)RFIFOL(fd,8); const uint8* data = (uint8*)RFIFOP(fd,12); - vending_purchasereq(sd, aid, uid, data, len/4); + vending->purchase(sd, aid, uid, data, len/4); // whether it fails or not, the buy window is closed sd->vended_id = 0; @@ -11952,7 +12255,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) if( message[0] == '\0' ) // invalid input return; - vending_openvending(sd, message, data, len/8); + vending->open(sd, message, data, len/8); } /// Guild creation request (CZ_REQ_MAKE_GUILD). @@ -12195,7 +12498,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -12409,8 +12712,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) case BL_PC: { char command[NAME_LENGTH+6]; - sprintf(command, "%ckick %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%ckick %s", atcommand->at_symbol, status_get_name(target)); + atcommand->parse(fd, sd, command, 1); } break; @@ -12420,12 +12723,12 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) case BL_MOB: { char command[100]; - if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) { + if( !pc_can_use_command(sd, "@killmonster")) { clif->GM_kickack(sd, 0); return; } sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); - log_atcommand(sd, command); + logs->atcommand(sd, command); status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' } break; @@ -12433,8 +12736,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) case BL_NPC: { char command[NAME_LENGTH+11]; - sprintf(command, "%cunloadnpc %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cunloadnpc %s", atcommand->at_symbol, status_get_name(target)); + atcommand->parse(fd, sd, command, 1); } break; @@ -12449,8 +12752,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) /// 00ce void clif_parse_GMKickAll(int fd, struct map_session_data* sd) { char cmd[15]; - sprintf(cmd,"%ckickall",atcommand_symbol); - is_atcommand(fd, sd, cmd, 1); + sprintf(cmd,"%ckickall",atcommand->at_symbol); + atcommand->parse(fd, sd, cmd, 1); } @@ -12469,8 +12772,8 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cjumpto %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cjumpto %s", atcommand->at_symbol, player_name); + atcommand->parse(fd, sd, command, 1); } @@ -12485,8 +12788,8 @@ void clif_parse_GMRemove2(int fd, struct map_session_data* sd) account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); if( (pl_sd = map_id2sd(account_id)) != NULL ) { char command[NAME_LENGTH+8]; - sprintf(command, "%cjumpto %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cjumpto %s", atcommand->at_symbol, pl_sd->status.name); + atcommand->parse(fd, sd, command, 1); } } @@ -12506,8 +12809,8 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%crecall %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%crecall %s", atcommand->at_symbol, player_name); + atcommand->parse(fd, sd, command, 1); } @@ -12522,8 +12825,8 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); if( (pl_sd = map_id2sd(account_id)) != NULL ) { char command[NAME_LENGTH+8]; - sprintf(command, "%crecall %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%crecall %s", atcommand->at_symbol, pl_sd->status.name); + atcommand->parse(fd, sd, command, 1); } } @@ -12542,16 +12845,16 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) // FIXME: Should look for item first, then for monster. // FIXME: /monster takes mob_db Sprite_Name as argument if( mobdb_searchname(monster_item_name) ) { - snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); + snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand->at_symbol, monster_item_name); + atcommand->parse(fd, sd, command, 1); return; } // FIXME: Stackables have a quantity of 20. // FIXME: Equips are supposed to be unidentified. if( itemdb_searchname(monster_item_name) ) { - snprintf(command, sizeof(command)-1, "%citem %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); + snprintf(command, sizeof(command)-1, "%citem %s", atcommand->at_symbol, monster_item_name); + atcommand->parse(fd, sd, command, 1); return; } } @@ -12564,9 +12867,9 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) void clif_parse_GMHide(int fd, struct map_session_data *sd) { char cmd[6]; - sprintf(cmd,"%chide",atcommand_symbol); + sprintf(cmd,"%chide",atcommand->at_symbol); - is_atcommand(fd, sd, cmd, 1); + atcommand->parse(fd, sd, cmd, 1); } @@ -12598,8 +12901,8 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) if( dstsd == NULL ) return; - sprintf(command, "%cmute %d %s", atcommand_symbol, value, dstsd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmute %d %s", atcommand->at_symbol, value, dstsd->status.name); + atcommand->parse(fd, sd, command, 1); } @@ -12612,8 +12915,8 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd) char *name = (char*)RFIFOP(fd,2); name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cmute %d %s", atcommand_symbol, 60, name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmute %d %s", atcommand->at_symbol, 60, name); + atcommand->parse(fd, sd, command, 1); } @@ -14558,6 +14861,16 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) clif->equiptickack(sd, flag); } +/// Request to change party invitation tick. +/// value: +/// 0 = disabled +/// 1 = enabled +void clif_parse_PartyTick(int fd, struct map_session_data* sd) +{ + bool flag = RFIFOB(fd,6)?true:false; + sd->status.allow_party = flag; + clif->partytickack(sd, flag); +} /// Questlog System [Kevin] [Inkfish] /// @@ -15040,7 +15353,7 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -15451,7 +15764,7 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { } count = packet_len/blocksize; - buyingstore_create(sd, zenylimit, result, storename, itemlist, count); + buyingstore->create(sd, zenylimit, result, storename, itemlist, count); } @@ -15526,7 +15839,7 @@ void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_sessi /// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE). /// 0815 void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) { - buyingstore_close(sd); + buyingstore->close(sd); } @@ -15560,7 +15873,7 @@ void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); - buyingstore_open(sd, account_id); + buyingstore->open(sd, account_id); } @@ -15616,12 +15929,12 @@ 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=%d, 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=%u, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); return; } count = packet_len/blocksize; - buyingstore_trade(sd, account_id, buyer_id, itemlist, count); + buyingstore->trade(sd, account_id, buyer_id, itemlist, count); } @@ -15747,7 +16060,7 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { return; } - searchstore_query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); + searchstore->query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); } @@ -15772,7 +16085,7 @@ void clif_search_store_info_ack(struct map_session_data* sd) WFIFOW(fd,0) = 0x836; WFIFOW(fd,2) = 7+(end-start)*blocksize; WFIFOB(fd,4) = !sd->searchstore.pages; - WFIFOB(fd,5) = searchstore_querynext(sd); + WFIFOB(fd,5) = searchstore->querynext(sd); WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); for( i = start; i < end; i++ ) { @@ -15824,7 +16137,7 @@ void clif_search_store_info_failed(struct map_session_data* sd, unsigned char re /// 0838 void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) { - searchstore_next(sd); + searchstore->next(sd); } @@ -15851,7 +16164,7 @@ void clif_open_search_store_info(struct map_session_data* sd) /// 083b void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) { - searchstore_close(sd); + searchstore->close(sd); } @@ -15867,7 +16180,7 @@ void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd store_id = RFIFOL(fd,info->pos[1]); nameid = RFIFOW(fd,info->pos[2]); - searchstore_click(sd, account_id, store_id, nameid); + searchstore->click(sd, account_id, store_id, nameid); } @@ -16245,99 +16558,74 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { } /* [Ind/Hercules] */ void clif_cashshop_db(void) { - FILE *fp; - char line[254]; - int ln = 0;/* line num */ - char *str[3], *p; - struct item_data * data; - int val, type, j; - - for( j = 0; j < CASHSHOP_TAB_MAX; j++ ) { - CREATE(clif->cs.data[j], struct hCSData *, 1); - clif->cs.item_count[j] = 0; + config_t cashshop_conf; + config_setting_t *cashshop = NULL; + const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name + int i; + for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { + CREATE(clif->cs.data[i], struct hCSData *, 1); + clif->cs.item_count[i] = 0; } - if( (fp=fopen("db/cashshop_db.txt","r"))==NULL ){ - ShowError("can't read %s\n", "db/cashshop_db.txt"); + if (conf_read_file(&cashshop_conf, config_filename)) { + ShowError("can't read %s\n", config_filename); return; } - while(fgets(line, sizeof(line), fp)) { - ln++; - if( line[0]=='/' && line[1]=='/' ) - continue; - - memset(str,0,sizeof(str)); - data = NULL; - - for(j=0,p=line;j<3 && p;j++){ - str[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + cashshop = config_lookup(&cashshop_conf, "cash_shop"); + + if (cashshop != NULL) { + config_setting_t *cats = config_setting_get_elem(cashshop, 0); + config_setting_t *cat; + int k, item_count_t = 0; - if(str[0]==NULL) - continue; + for(i = 0; i < CASHSHOP_TAB_MAX; i++) { + char entry_name[10]; + + sprintf(entry_name,"cat_%d",i); + + if( (cat = config_setting_get_member(cats, entry_name)) != NULL ) { + int item_count = config_setting_length(cat); - if ( j < 3 ) { - if ( j > 1 ) - ShowWarning("cashshop_db: insufficient fields for entry at %s:%d\n", "db/cashshop_db.txt", ln); - continue; - } - if( ISALPHA(str[0][0]) ) { - if( strcmpi(str[0],"new") == 0 ) - type = CASHSHOP_TAB_NEW; - else if( strcmpi(str[0],"popular") == 0 ) - type = CASHSHOP_TAB_POPULAR; - else if( strcmpi(str[0],"limited") == 0 ) - type = CASHSHOP_TAB_LIMITED; - else if( strcmpi(str[0],"rental") == 0 ) - type = CASHSHOP_TAB_RENTAL; - else if( strcmpi(str[0],"permanent") == 0 ) - type = CASHSHOP_TAB_PERPETUITY; - else if( strcmpi(str[0],"scroll") == 0 ) - type = CASHSHOP_TAB_BUFF; - else if( strcmpi(str[0],"usable") == 0 ) - type = CASHSHOP_TAB_RECOVERY; - else if( strcmpi(str[0],"other") == 0 ) - type = CASHSHOP_TAB_ETC; - else { - ShowWarning("cashshop_db: unknown type %s for entry at %s:%d\n", str[0], "db/cashshop_db.txt", ln); - continue; - } - } else { - type = atoi(str[0]); - if( type < 0 || type > CASHSHOP_TAB_MAX ) { - ShowWarning("cashshop_db: unknown type %d for entry at %s:%d\n", type, "db/cashshop_db.txt", ln); - continue; - } - } - - if( ISALPHA(str[1][0]) ) { - if( !( data = itemdb_searchname(str[1]) ) ) { - ShowWarning("cashshop_db: unknown item name %s for entry at %s:%d\n", str[1], "db/cashshop_db.txt", ln); - continue; - } - } else { - if( !( data = itemdb_exists(atoi(str[1]))) ) { - ShowWarning("cashshop_db: unknown item id %s for entry at %s:%d\n", str[1], "db/cashshop_db.txt", ln); - continue; + for(k = 0; k < item_count; k++) { + config_setting_t *entry = config_setting_get_elem(cat,k); + const char *name = config_setting_name(entry); + int price = config_setting_get_int(entry); + struct item_data * data = NULL; + + if( price < 1 ) { + ShowWarning("cashshop_db: unsupported price '%d' for entry named '%s' in category '%s'\n", price, name, entry_name); + continue; + } + + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { + if( !( data = itemdb_exists(atoi(name+2))) ) { + ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name); + continue; + } + } else { + if( !( data = itemdb_searchname(name) ) ) { + ShowWarning("cashshop_db: unknown item name '%s' in category '%s'\n", name, entry_name); + continue; + } + } + + + RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); + CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); + + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = data->nameid; + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = price; + item_count_t++; + } + } else { + ShowError("cashshop_db: category '%s' (%d) not found!!\n",entry_name,i); } } - if( ( val = atoi(str[2]) ) < 1 ) { - ShowWarning("cashshop_db: unsupported price '%d' for entry at %s:%d\n", val, "db/cashshop_db.txt", ln); - continue; - } - - RECREATE(clif->cs.data[type], struct hCSData *, ++clif->cs.item_count[type]); - CREATE(clif->cs.data[type][ clif->cs.item_count[type] - 1 ], struct hCSData , 1); - - clif->cs.data[type][ clif->cs.item_count[type] - 1 ]->id = data->nameid; - clif->cs.data[type][ clif->cs.item_count[type] - 1 ]->price = val; - + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); + config_destroy(&cashshop_conf); } - fclose(fp); } /// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE). /// 0900 <index>.W <favorite>.B @@ -16362,17 +16650,15 @@ void clif_snap( struct block_list *bl, short x, short y ) { clif->send(buf,packet_len(0x8d2),bl,AREA); } -void clif_monster_hp_bar( struct mob_data* md, int fd ) { -#if PACKETVER >= 20120404 - WFIFOHEAD(fd,packet_len(0x977)); - - WFIFOW(fd,0) = 0x977; - WFIFOL(fd,2) = md->bl.id; - WFIFOL(fd,6) = md->status.hp; - WFIFOL(fd,10) = md->status.max_hp; - - WFIFOSET(fd,packet_len(0x977)); -#endif +void clif_monster_hp_bar( struct mob_data* md ) { + struct packet_monster_hp p; + + p.PacketType = monsterhpType; + p.GID = md->bl.id; + p.HP = md->status.hp; + p.MaxHP = md->status.max_hp; + + clif->send(&p,sizeof(p),&md->bl,AREA_WOS); } /* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd) { @@ -16382,13 +16668,13 @@ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { WFIFOHEAD(fd, 10); WFIFOW(fd, 0) = 0x845; - WFIFOL(fd, 2) = sd->cashPoints;/* kafra for now disabled until we know how to apply it */ - WFIFOL(fd, 6) = sd->cashPoints; + WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values + WFIFOL(fd, 6) = sd->kafraPoints; WFIFOSET(fd, 10); } void clif_parse_CashShopClose(int fd, struct map_session_data *sd) { - + /* TODO apply some state tracking */ } void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { @@ -16411,8 +16697,7 @@ void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { } void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { unsigned short limit = RFIFOW(fd, 4), i, j; - - /* no idea what data is on 6-10 */ + unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash curreny for us, confusing) for(i = 0; i < limit; i++) { int qty = RFIFOL(fd, 14 + ( i * 10 )); @@ -16429,7 +16714,9 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { } if( j < clif->cs.item_count[tab] ) { struct item_data *data; - if( sd->cashPoints < (clif->cs.data[tab][j]->price * qty) ) { + if( sd->kafraPoints < kafra_pay ) { + result = CSBR_SHORTTAGE_CASH; + } else if( (sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty) ) { result = CSBR_SHORTTAGE_CASH; } else if ( !( data = itemdb_exists(clif->cs.data[tab][j]->id) ) ) { result = CSBR_UNKONWN_ITEM; @@ -16442,7 +16729,7 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { if (!itemdb_isstackable2(data)) get_count = 1; - pc_paycash(sd, clif->cs.data[tab][j]->price * qty, 0);/* kafra point support is missing */ + pc_paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki] for (k = 0; k < qty; k += get_count) { if (!pet_create_egg(sd, data->nameid)) { memset(&item_tmp, 0, sizeof(item_tmp)); @@ -16471,7 +16758,7 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { } if( result != CSBR_SUCCESS ) - pc_getcash(sd, clif->cs.data[tab][j]->price * get_count, 0);/* kafra point support is missing */ + pc_getcash(sd, clif->cs.data[tab][j]->price * get_count,0); } } } @@ -16484,12 +16771,43 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { WFIFOL(fd, 2) = id; WFIFOW(fd, 6) = result;/* result */ WFIFOL(fd, 8) = sd->cashPoints;/* current cash point */ - WFIFOL(fd, 12) = 0;/* no idea (kafra cash?) */ + WFIFOL(fd, 12) = sd->kafraPoints;// [Ryuuzaki] WFIFOSET(fd, 16); } } +/* [Ind/Hercules] */ +void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { +#if PACKETVER >= 20130000 /* not entirely sure when this started */ + struct packet_maptypeproperty2 p; + + p.PacketType = maptypeproperty2Type; + p.type = 0x28; + p.flag.usecart = 1; + p.flag.party = 1; + p.flag.guild = 1; + p.flag.siege = map_flag_gvg2(bl->m) ? 1: 0; + p.flag.mineffect = 1; + p.flag.nolockon = 0; + p.flag.countpk = map[bl->m].flag.pvp ? 1 : 0; + p.flag.nopartyformation = 0; + p.flag.noitemconsumption = 0; + p.flag.summonstarmiracle = 0; + p.flag.bg = map[bl->m].flag.battleground ? 1 : 0; + + clif->send(&p,sizeof(p),bl,t); +#endif +} + +void clif_partytickack(struct map_session_data* sd, bool flag) { + + WFIFOHEAD(sd->fd, packet_len(0x2c9)); + WFIFOW(sd->fd, 0) = 0x2c9; + WFIFOB(sd->fd, 2) = flag; + WFIFOSET(sd->fd, packet_len(0x2c9)); +} + /*========================================== * Main client packet processing function *------------------------------------------*/ @@ -16655,11 +16973,17 @@ void packetdb_loaddb(void) { #include "packets.h" /* load structure data */ #undef packet } +void clif_bc_ready(void) { + if( battle_config.display_status_timers ) + clif->status_change = clif_status_change; + else + clif->status_change = clif_status_change_notick; +} /*========================================== * *------------------------------------------*/ int do_init_clif(void) { - const char* colors[COLOR_MAX] = { "0xFF0000" }; + const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00" }; int i; /** * Setup Color Table (saves unnecessary load of strtoul on every call) @@ -16683,7 +17007,7 @@ int do_init_clif(void) { clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH); - hChSys.ally = hChSys.local = hChSys.ally_autojoin = hChSys.local_autojoin = false; + hChSys.ally = hChSys.local = hChSys.irc = hChSys.ally_autojoin = hChSys.local_autojoin = false; clif->chann_config_read(); return 0; @@ -16757,6 +17081,7 @@ void clif_defaults(void) { clif->unequipitemack = clif_unequipitemack; clif->useitemack = clif_useitemack; clif->addcards = clif_addcards; + clif->addcards2 = clif_addcards2; clif->item_sub = clif_item_sub; clif->getareachar_item = clif_getareachar_item; /* unit-related */ @@ -16778,7 +17103,7 @@ void clif_defaults(void) { clif->skillunit_update = clif_skillunit_update; clif->clearunit_delayed_sub = clif_clearunit_delayed_sub; clif->set_unit_idle = clif_set_unit_idle; - clif->setdisguise = clif_setdisguise; + clif->spawn_unit = clif_spawn_unit; clif->set_unit_walking = clif_set_unit_walking; clif->calc_walkdelay = clif_calc_walkdelay; clif->getareachar_skillunit = clif_getareachar_skillunit; @@ -16795,6 +17120,7 @@ void clif_defaults(void) { clif->map_property_mapall = clif_map_property_mapall; clif->bossmapinfo = clif_bossmapinfo; clif->map_type = clif_map_type; + clif->maptypeproperty2 = clif_maptypeproperty2; /* multi-map-server */ clif->changemapserver = clif_changemapserver; /* npc-shop-related */ @@ -16868,6 +17194,7 @@ void clif_defaults(void) { clif->hate_info = clif_hate_info; clif->mission_info = clif_mission_info; clif->feel_hate_reset = clif_feel_hate_reset; + clif->partytickack = clif_partytickack; clif->equiptickack = clif_equiptickack; clif->viewequip_ack = clif_viewequip_ack; clif->viewequip_fail = clif_viewequip_fail; @@ -17155,12 +17482,16 @@ void clif_defaults(void) { clif->noask_sub = clif_noask_sub; clif->chsys_create = clif_hercules_chsys_create; clif->chsys_msg = clif_hercules_chsys_msg; + clif->chsys_msg2 = clif_hercules_chsys_msg2; clif->chsys_send = clif_hercules_chsys_send; clif->chsys_join = clif_hercules_chsys_join; clif->chsys_left = clif_hercules_chsys_left; clif->chsys_delete = clif_hercules_chsys_delete; clif->chsys_mjoin = clif_hercules_chsys_mjoin; + clif->chsys_quit = clif_hercules_chsys_quit; + clif->chsys_quitg = clif_hercules_chsys_quitg; clif->cashshop_load = clif_cashshop_db; + clif->bc_ready = clif_bc_ready; /*------------------------ *- Parse Incoming Packet *------------------------*/ @@ -17357,10 +17688,13 @@ void clif_defaults(void) { clif->pDebug = clif_parse_debug; clif->pSkillSelectMenu = clif_parse_SkillSelectMenu; clif->pMoveItem = clif_parse_MoveItem; - clif->pDull = clif_parse_dull; /* RagExe Cash Shop [Ind/Hercules] */ clif->pCashShopOpen = clif_parse_CashShopOpen; clif->pCashShopClose = clif_parse_CashShopClose; clif->pCashShopSchedule = clif_parse_CashShopSchedule; clif->pCashShopBuy = clif_parse_CashShopBuy; + /* */ + clif->pPartyTick = clif_parse_PartyTick; + /* dull */ + clif->pDull = clif_parse_dull; } |