|
@@ -279,7 +279,7 @@ uint16 clif_getport(void)
|
|
|
}
|
|
|
|
|
|
#if PACKETVER >= 20071106
|
|
|
-static inline unsigned char clif_bl_type(struct block_list *bl) {
|
|
|
+static inline unsigned char clif_bl_type(struct block_list *bl, bool walking) {
|
|
|
switch (bl->type) {
|
|
|
case BL_PC: return (disguised(bl) && !pcdb_checkid(status_get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
|
|
|
case BL_ITEM: return 0x2; //ITEM_TYPE
|
|
@@ -287,10 +287,13 @@ static inline unsigned char clif_bl_type(struct block_list *bl) {
|
|
|
case BL_CHAT: return 0x4; //UNKNOWN_TYPE
|
|
|
case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
|
|
|
case BL_NPC:
|
|
|
+// From 2017-07-26 on NPC type units can also use player sprites.
|
|
|
+// There is one exception and this is if they are walking.
|
|
|
+// Since walking NPCs are not supported on official servers, the client does not know how to handle it.
|
|
|
#if PACKETVER >= 20170726
|
|
|
- return 0x6; //NPC_EVT_TYPE
|
|
|
+ return ( pcdb_checkid(status_get_viewdata(bl)->class_) && walking ) ? 0x0 : 0x6; //NPC_EVT_TYPE
|
|
|
#else
|
|
|
- return (pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x6);
|
|
|
+ return pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x6; //NPC_EVT_TYPE
|
|
|
#endif
|
|
|
case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
|
|
|
case BL_HOM: return 0x8; //NPC_HOM_TYPE
|
|
@@ -980,7 +983,7 @@ static int clif_setlevel(struct block_list* bl) {
|
|
|
/*==========================================
|
|
|
* Prepares 'unit standing/spawning' packet
|
|
|
*------------------------------------------*/
|
|
|
-static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn, bool option, unsigned int option_val)
|
|
|
+static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn, bool option, bool walking, unsigned int option_val)
|
|
|
{
|
|
|
struct map_session_data* sd;
|
|
|
struct status_change* sc = status_get_sc(bl);
|
|
@@ -1035,7 +1038,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
|
|
|
#else
|
|
|
WBUFW(buf,2) = (uint16)((spawn ? 79 : 80)+strlen(name));
|
|
|
#endif
|
|
|
- WBUFB(buf,4) = clif_bl_type(bl);
|
|
|
+ WBUFB(buf,4) = clif_bl_type(bl,walking);
|
|
|
offset+=3;
|
|
|
buf = WBUFP(buffer,offset);
|
|
|
#elif PACKETVER >= 20071106
|
|
@@ -1236,7 +1239,7 @@ static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, un
|
|
|
buf = WBUFP(buffer,offset);
|
|
|
#endif
|
|
|
#if PACKETVER >= 20071106
|
|
|
- WBUFB(buf, 2) = clif_bl_type(bl);
|
|
|
+ WBUFB(buf, 2) = clif_bl_type(bl,true);
|
|
|
offset++;
|
|
|
buf = WBUFP(buffer,offset);
|
|
|
#endif
|
|
@@ -1465,7 +1468,7 @@ void clif_weather(int16 m)
|
|
|
/**
|
|
|
* Main function to spawn a unit on the client (player/mob/pet/etc)
|
|
|
**/
|
|
|
-int clif_spawn(struct block_list *bl)
|
|
|
+int clif_spawn(struct block_list *bl, bool walking)
|
|
|
{
|
|
|
unsigned char buf[128];
|
|
|
struct view_data *vd;
|
|
@@ -1481,7 +1484,7 @@ 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, (bl->type == BL_NPC && vd->dead_sit ? false : true), false, 0);
|
|
|
+ len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true), false, walking, 0);
|
|
|
clif_send(buf, len, bl, AREA_WOS);
|
|
|
if (disguised(bl))
|
|
|
clif_setdisguise(bl, buf, len);
|
|
@@ -4732,7 +4735,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
|
|
|
if (std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id) != sd->cloaked_npc.end())
|
|
|
option_val ^= OPTION_CLOAK;
|
|
|
}
|
|
|
- len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false,option,option_val);
|
|
|
+ len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false,option,false,option_val);
|
|
|
clif_send(buf,len,&sd->bl,SELF);
|
|
|
|
|
|
if (vd->cloth_color)
|