summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/elogin/send.c2
-rw-r--r--src/emap/clif.c141
-rw-r--r--src/emap/clif.h2
-rw-r--r--src/emap/pc.c116
-rw-r--r--src/emap/pc.h2
-rw-r--r--src/emap/send.c96
-rw-r--r--src/emap/send.h8
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