From cfaf7b65b33fb94ba96be48c0c0187116616279a Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 12 Aug 2015 19:26:18 +0300 Subject: Send to client if possible equipped items with inserted cards. Change server version to 7. --- src/elogin/send.c | 2 +- src/emap/clif.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/emap/clif.h | 2 + src/emap/pc.c | 116 +++++++++++++++++++++++++++++++++++++------- src/emap/pc.h | 2 +- src/emap/send.c | 96 +++++++++++++++++++++++++++++++++---- src/emap/send.h | 8 +++- 7 files changed, 337 insertions(+), 30 deletions(-) diff --git a/src/elogin/send.c b/src/elogin/send.c index 396c314..bcee1b5 100644 --- a/src/elogin/send.c +++ b/src/elogin/send.c @@ -21,7 +21,7 @@ void send_server_version(int fd) WFIFOW(fd, 0) = 0x7531; WFIFOW(fd, 2) = 4 + 8; WFIFOL(fd, 4) = 0; // unused - WFIFOL(fd, 8) = 6; // server version + WFIFOL(fd, 8) = 7; // server version WFIFOSET(fd, WFIFOW(fd,2)); } diff --git a/src/emap/clif.c b/src/emap/clif.c index c1aa1d4..9ebc21e 100644 --- a/src/emap/clif.c +++ b/src/emap/clif.c @@ -199,7 +199,7 @@ void eclif_charnameack(int *fdPtr, struct block_list *bl) { \ item = sd->inventory_data[equip]; \ if (item && item->look) \ - send_changelook(fd, id, field, item->look); \ + send_changelook(sd, sd2, fd, id, field, item->look, 0, item, equip); \ } static void eclif_send_additional_slots(TBL_PC* sd, TBL_PC* sd2) @@ -343,6 +343,28 @@ int eclif_send_actual(int *fd, void *buf, int *len) return 0; } } + if (packet == 0x1d7) + { + struct SessionExt *data = session_get(*fd); + if (!data) + return 0; + if (data->clientVersion >= 9) + { // not sending old packets to new clients + hookStop(); + return 0; + } + } + if (packet == 0xb17) + { + struct SessionExt *data = session_get(*fd); + if (!data) + return 0; + if (data->clientVersion < 9) + { // not sending new packets to old clients + hookStop(); + return 0; + } + } } return 0; } @@ -381,3 +403,120 @@ void eclif_parse_LoadEndAck_pre(int *fdPtr __attribute__ ((unused)), { sd->state.warp_clean = 0; } + +void eclif_changelook2(struct block_list *bl, int type, int val, + struct item_data *id, int n) +{ + struct map_session_data* sd; + struct status_change* sc; + struct view_data* vd; + enum send_target target = AREA; + int val2 = 0; + if (!bl) + return; + + sd = BL_CAST(BL_PC, bl); + sc = status->get_sc(bl); + vd = status->get_viewdata(bl); + + if (vd) + { + switch(type) + { + case LOOK_WEAPON: + if (sd) + { + clif->get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->weapon; + } + else + { + vd->weapon = val; + } + break; + + case LOOK_SHIELD: + if (sd) + { + clif->get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->shield; + } + else + { + vd->shield = val; + } + break; + case LOOK_BASE: + if (!sd) + break; + + if (val == INVISIBLE_CLASS) /* nothing to change look */ + return; + + if (sd->sc.option & OPTION_COSTUME) + vd->weapon = vd->shield = 0; + +// if (!vd->cloth_color) +// break; + break; + case LOOK_HAIR: + vd->hair_style = val; + break; + case LOOK_HEAD_BOTTOM: + vd->head_bottom = val; + break; + case LOOK_HEAD_TOP: + vd->head_top = val; + break; + case LOOK_HEAD_MID: + vd->head_mid = val; + break; + case LOOK_HAIR_COLOR: + vd->hair_color = val; + break; + case LOOK_CLOTHES_COLOR: + vd->cloth_color = val; + break; + case LOOK_SHOES: +// if (sd) { +// int n; +// if((n = sd->equip_index[2]) >= 0 && sd->inventory_data[n]) { +// if(sd->inventory_data[n]->view_id > 0) +// val = sd->inventory_data[n]->view_id; +// else +// val = sd->status.inventory[n].nameid; +// } else +// val = 0; +// } + break; + case LOOK_BODY: + case LOOK_FLOOR: + // unknown purpose + break; + case LOOK_ROBE: + vd->robe = val; + break; + } + } + + // prevent leaking the presence of GM-hidden objects + if (sc && sc->option&OPTION_INVISIBLE && !( bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1)) + target = SELF; + if (type == LOOK_WEAPON || type == LOOK_SHIELD) + { + if (!vd) + return; + type = LOOK_WEAPON; + val = vd->weapon; + val2 = vd->shield; + } + if ((bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1)) + { + send_changelook2(sd, bl, bl->id, type, val, val2, id, n, AREA_WOS); + send_changelook2(sd, bl, -bl->id, type, val, val2, id, n, SELF); + } + else + { + send_changelook2(sd, bl, bl->id, type, val, val2, id, n, target); + } +} diff --git a/src/emap/clif.h b/src/emap/clif.h index 4c706cf..b83d817 100644 --- a/src/emap/clif.h +++ b/src/emap/clif.h @@ -24,5 +24,7 @@ void eclif_set_unit_walking(struct block_list* bl, TBL_PC *tsd, void eclif_move(struct unit_data *ud); void eclif_parse_LoadEndAck_pre(int *fdPtr, struct map_session_data *sd); +void eclif_changelook2(struct block_list *bl, int type, int val, + struct item_data *id, int n); #endif // EVOL_MAP_CLIF diff --git a/src/emap/pc.c b/src/emap/pc.c index 59ac6e2..feb1980 100644 --- a/src/emap/pc.c +++ b/src/emap/pc.c @@ -10,9 +10,11 @@ #include "common/mmo.h" #include "common/socket.h" #include "common/strlib.h" +#include "common/timer.h" #include "map/itemdb.h" #include "map/pc.h" +#include "emap/clif.h" #include "emap/pc.h" #include "emap/data/itemd.h" #include "emap/data/mapd.h" @@ -51,38 +53,100 @@ int epc_setregistry(TBL_PC *sd, int64 *reg, int *val) } #define equipPos(mask, field, lookf) \ - if (pos & mask) \ + if (pos & (mask)) \ { \ if (id) \ sd->status.field = id->look; \ else \ sd->status.field = 0; \ - clif->changelook(&sd->bl, lookf, sd->status.field); \ - hookStop(); \ + eclif_changelook2(&sd->bl, lookf, sd->status.field, id, n); \ } #define equipPos2(mask, lookf) \ - if (pos & mask) \ + if (pos & (mask)) \ { \ if (id) \ - clif->changelook(&sd->bl, lookf, id->look); \ + eclif_changelook2(&sd->bl, lookf, id->look, id, n); \ else \ - clif->changelook(&sd->bl, lookf, 0); \ - hookStop(); \ + eclif_changelook2(&sd->bl, lookf, 0, id, n); \ } -void epc_equipitem_pos(TBL_PC *sd, struct item_data *id, int *posPtr) +void epc_equipitem_pos(TBL_PC *sd, struct item_data *id, int *nPtr, int *posPtr) { + const int n = *nPtr; int pos = *posPtr; + hookStop(); + if (!id) return; + if (pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) + { + if(id) + { + sd->weapontype1 = id->look; + } + else + { + sd->weapontype1 = 0; + } + pc->calcweapontype(sd); + eclif_changelook2(&sd->bl, LOOK_WEAPON, sd->status.weapon, id, n); + if (sd->status.weapon) + { + for (int i = 0; i < id->slot; i++ ) + { + struct item_data *data; + if (!sd->status.inventory[n].card[i]) + continue; + if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) + { + ShowWarning("equip: for pos %d card %d\n", LOOK_WEAPON, data->nameid); + } + } + } + } + if (pos & (EQP_HAND_L|EQP_SHADOW_SHIELD)) + { + if (id) + { + if(id->type == IT_WEAPON) + { + sd->status.shield = 0; + sd->weapontype2 = id->look; + } + else if (id->type == IT_ARMOR) + { + sd->status.shield = id->look; + sd->weapontype2 = 0; + } + } + else + { + sd->status.shield = sd->weapontype2 = 0; + } + pc->calcweapontype(sd); + eclif_changelook2(&sd->bl, LOOK_SHIELD, sd->status.shield, id, n); + if (sd->status.shield) + { + for (int i = 0; i < id->slot; i++ ) + { + struct item_data *data; + if (!sd->status.inventory[n].card[i]) + continue; + if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) + { + ShowWarning("equip: for pos %d card %d\n", LOOK_SHIELD, data->nameid); + } + } + } + } + equipPos(EQP_HEAD_LOW, head_bottom, LOOK_HEAD_BOTTOM); equipPos(EQP_HEAD_TOP, head_top, LOOK_HEAD_TOP); equipPos(EQP_HEAD_MID, head_mid, LOOK_HEAD_MID); equipPos(EQP_GARMENT, robe, LOOK_ROBE); - //skip EQP_ARMOR equipPos2(EQP_SHOES, LOOK_SHOES); equipPos2(EQP_COSTUME_HEAD_TOP, 13); equipPos2(EQP_COSTUME_HEAD_MID, 14); @@ -90,35 +154,51 @@ void epc_equipitem_pos(TBL_PC *sd, struct item_data *id, int *posPtr) equipPos2(EQP_COSTUME_GARMENT, 16); equipPos2(EQP_ARMOR, 17); //skipping SHADOW slots + } #undef equipPos #undef equipPos2 #define unequipPos(mask, field, lookf) \ - if (pos & mask) \ + if (pos & (mask)) \ { \ sd->status.field = 0; \ - clif->changelook(&sd->bl, lookf, sd->status.field); \ - hookStop(); \ + eclif_changelook2(&sd->bl, lookf, sd->status.field, 0, n); \ } #define unequipPos2(mask, lookf) \ - if (pos & mask) \ - { \ - clif->changelook(&sd->bl, lookf, 0); \ - hookStop(); \ - } + if (pos & (mask)) \ + eclif_changelook2(&sd->bl, lookf, 0, 0, n); void epc_unequipitem_pos(TBL_PC *sd, - int *nPtr __attribute__ ((unused)), + int *nPtr, int *posPtr) { if (!sd) return; + hookStop(); + + const int n = *nPtr; int pos = *posPtr; + if (pos & EQP_HAND_R) + { + sd->weapontype1 = 0; + sd->status.weapon = sd->weapontype2; + pc->calcweapontype(sd); + eclif_changelook2(&sd->bl, LOOK_WEAPON, sd->status.weapon, 0, n); + if (!battle->bc->dancing_weaponswitch_fix) + status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); + } + if (pos & EQP_HAND_L) + { + sd->status.shield = sd->weapontype2 = 0; + pc->calcweapontype(sd); + eclif_changelook2(&sd->bl, LOOK_SHIELD, sd->status.shield, 0, n); + } + unequipPos(EQP_HEAD_LOW, head_bottom, LOOK_HEAD_BOTTOM); unequipPos(EQP_HEAD_TOP, head_top, LOOK_HEAD_TOP); unequipPos(EQP_HEAD_MID, head_mid, LOOK_HEAD_MID); diff --git a/src/emap/pc.h b/src/emap/pc.h index e850b81..388c606 100644 --- a/src/emap/pc.h +++ b/src/emap/pc.h @@ -13,7 +13,7 @@ int epc_readparam_pre(TBL_PC* sd, int *type); int epc_setregistry(TBL_PC *sd, int64 *reg, int *val); -void epc_equipitem_pos(TBL_PC *sd, struct item_data *id, int *posPtr); +void epc_equipitem_pos(TBL_PC *sd, struct item_data *id, int *nPtr, int *posPtr); void epc_unequipitem_pos(TBL_PC *sd, int *nPtr, int *posPtr); diff --git a/src/emap/send.c b/src/emap/send.c index 6f3f257..8c74d3b 100644 --- a/src/emap/send.c +++ b/src/emap/send.c @@ -77,15 +77,56 @@ void send_local_message(int fd, struct block_list* bl, const char* msg) WFIFOSET (fd, msg_len + 8); } -void send_changelook(int fd, int id, int type, int val) +void send_changelook(struct map_session_data* sd, struct map_session_data* sd2, int fd, + int id, int type, int val, int val2, + struct item_data *data, int n) { - WFIFOHEAD (fd, 11); - WFIFOW (fd, 0) = 0x1d7; - WFIFOL (fd, 2) = id; - WFIFOB (fd, 6) = type; - WFIFOW (fd, 7) = val; - WFIFOW (fd, 9) = 0; - WFIFOSET (fd, 11); + struct SessionExt *tdata = session_get_bysd(sd2); + if (!tdata || tdata->clientVersion < 9) + { + WFIFOHEAD (fd, 11); + WFIFOW (fd, 0) = 0x1d7; + WFIFOL (fd, 2) = id; + WFIFOB (fd, 6) = type; + WFIFOW (fd, 7) = val; + WFIFOW (fd, 9) = val2; + WFIFOSET (fd, 11); + } + else + { + WFIFOHEAD (fd, 19); + WFIFOW (fd, 0) = 0xb17; + WFIFOL (fd, 2) = id; + WFIFOB (fd, 6) = type; + WFIFOW (fd, 7) = val; + WFIFOW (fd, 9) = val2; + if (data) + { + //ShowWarning("equip: for type %d\n", type); + for (int i = 0; i < data->slot; i++ ) + { + struct item_data *data; + if (!sd->status.inventory[n].card[i]) + continue; + if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) + { + //ShowWarning("card %d\n", data->nameid); + WFIFOW (fd, 11 + i * 2) = data->nameid; + } + } + for (int i = data->slot; i < MAX_SLOTS; i ++) + WFIFOW (fd, 11 + i * 2) = 0; + } + else + { + //ShowWarning("unequip: for type %d\n", type); + WFIFOW (fd, 11) = 0; + WFIFOW (fd, 13) = 0; + WFIFOW (fd, 15) = 0; + WFIFOW (fd, 17) = 0; + } + WFIFOSET (fd, 19); + } } void send_mapmask(int fd, int mask) @@ -303,3 +344,42 @@ void send_client_command(TBL_PC *sd, const char *const command) memcpy (WFIFOP (fd, 4), command, len); WFIFOSET (fd, len + 4); } + +void send_changelook2(struct map_session_data* sd, struct block_list *bl, int id, int type, int val, int val2, + struct item_data *data, int n, enum send_target target) +{ + unsigned char buf[32]; + WBUFW(buf, 0) = 0x1d7; + WBUFL(buf, 2) = id; + WBUFB(buf, 6) = type; + WBUFW(buf, 7) = val; + WBUFW(buf, 9) = val2; + clif->send(buf, 11, bl, target); + WBUFW(buf, 0) = 0xb17; + if (data) + { + //ShowWarning("equip: for type %d\n", type); + for (int i = 0; i < data->slot; i++ ) + { + struct item_data *data; + if (!sd->status.inventory[n].card[i]) + continue; + if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) + { + //ShowWarning("card %d\n", data->nameid); + WBUFW(buf, 11 + i * 2) = data->nameid; + } + } + for (int i = data->slot; i < MAX_SLOTS; i ++) + WBUFW(buf, 11 + i * 2) = 0; + } + else + { + //ShowWarning("unequip: for type %d\n", type); + WBUFW(buf, 11) = 0; + WBUFW(buf, 13) = 0; + WBUFW(buf, 15) = 0; + WBUFW(buf, 17) = 0; + } + clif->send(buf, 19, bl, target); +} diff --git a/src/emap/send.h b/src/emap/send.h index efa89ad..fd93d8b 100644 --- a/src/emap/send.h +++ b/src/emap/send.h @@ -7,7 +7,9 @@ void send_npccommand (TBL_PC *sd, int npcId, int cmd); void send_npccommand2 (TBL_PC *sd, int npcId, int cmd, int id, int x, int y); void send_local_message(int fd, struct block_list* bl, const char* msg); -void send_changelook(int fd, int id, int type, int val); +void send_changelook(struct map_session_data* sd, struct map_session_data* sd2, int fd, + int id, int type, int val, int val2, + struct item_data *data, int n); void send_mapmask(int fd, int mask); void send_mapmask_brodcast(const int map, const int mask); void send_mob_info(struct block_list* bl1, struct block_list* bl2, enum send_target target); @@ -27,5 +29,9 @@ void send_slave_say(TBL_PC *sd, const char *const message); void send_online_list(int fd, const char *buf, unsigned size); void send_client_command(TBL_PC *sd, const char *const command); +void send_changelook2(struct map_session_data* sd, struct block_list *bl, + int id, int type, + int val, int val2, struct item_data *data, int n, + enum send_target target); #endif // EVOL_MAP_PC -- cgit v1.2.3-70-g09d2