summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2016-01-05 18:56:23 +0300
committerAndrei Karas <akaras@inbox.ru>2016-01-05 19:13:48 +0300
commitf5c9f9f42da5889d38104e8b44956a7da461393d (patch)
tree0ad9f52a70c4a8654923932ca54e52f24eb4016b
parent06cc7bcd13ab0b7b3ee0e244ea72142ab1720650 (diff)
downloadplugin-f5c9f9f42da5889d38104e8b44956a7da461393d.tar.gz
plugin-f5c9f9f42da5889d38104e8b44956a7da461393d.tar.bz2
plugin-f5c9f9f42da5889d38104e8b44956a7da461393d.tar.xz
plugin-f5c9f9f42da5889d38104e8b44956a7da461393d.zip
Reimpliment packet 0x915 for old clients.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/emap/clif.c193
-rw-r--r--src/emap/clif.h4
-rw-r--r--src/emap/packets_struct.h94
4 files changed, 292 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 56a2b35..1a21bb2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,7 @@ MAP_SRC = emap/atcommand.c \
emap/mob.h \
emap/npc.c \
emap/npc.h \
+ emap/packets_struct.h \
emap/parse.c \
emap/parse.h \
emap/pc.c \
diff --git a/src/emap/clif.c b/src/emap/clif.c
index b04b3b5..8e81d80 100644
--- a/src/emap/clif.c
+++ b/src/emap/clif.c
@@ -14,6 +14,7 @@
#include "common/socket.h"
#include "common/strlib.h"
#include "common/cbasetypes.h"
+//#include "common/utils.h"
#include "common/timer.h"
#include "map/guild.h"
#include "map/mob.h"
@@ -24,6 +25,7 @@
#include "emap/clif.h"
#include "emap/lang.h"
#include "emap/map.h"
+#include "emap/packets_struct.h"
#include "emap/send.h"
#include "emap/data/mapd.h"
#include "emap/data/session.h"
@@ -346,7 +348,37 @@ bool eclif_send(const void* buf __attribute__ ((unused)),
enum send_target *type)
{
if (*type == SELF)
+ {
+ if (*len >= 2)
+ {
+ const int packet = RBUFW (buf, 0);
+ if (packet == 0x9dd)
+ {
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ struct SessionExt *data = session_get_bysd(sd);
+ if (!data)
+ return true;
+ if (data->clientVersion < 16)
+ { // not sending new packet to old clients
+ hookStop();
+ return true;
+ }
+ }
+ if (packet == 0x915)
+ {
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ struct SessionExt *data = session_get_bysd(sd);
+ if (!data)
+ return true;
+ if (data->clientVersion >= 16)
+ { // not sending old packet to new clients
+ hookStop();
+ return true;
+ }
+ }
+ }
return true;
+ }
eclif_handle_invisible_map(bl, *type);
return true;
}
@@ -477,16 +509,177 @@ int eclif_send_actual(int *fd, void *buf, int *len)
return 0;
}
}
+ if (packet == 0x9dd)
+ {
+ struct SessionExt *data = session_get(*fd);
+ if (!data)
+ return 0;
+ if (data->clientVersion < 16)
+ { // not sending new packets to old clients
+ hookStop();
+ return 0;
+ }
+ }
+ if (packet == 0x915)
+ {
+ struct SessionExt *data = session_get(*fd);
+ if (!data)
+ return 0;
+ if (data->clientVersion >= 16)
+ { // not sending old packets to new clients
+ hookStop();
+ return 0;
+ }
+ }
}
return 0;
}
+uint16 GetWord(uint32 val, int idx)
+{
+ switch( idx )
+ {
+ case 0: return (uint16)( (val & 0x0000FFFF) );
+ case 1: return (uint16)( (val & 0xFFFF0000) >> 0x10 );
+ default:
+#if defined(DEBUG)
+ ShowDebug("GetWord: invalid index (idx=%d)\n", idx);
+#endif
+ return 0;
+ }
+}
+
+//To make the assignation of the level based on limits clearer/easier. [Skotlex]
+static int clif_setlevel_sub(int lv) {
+ if( lv < battle->bc->max_lv ) {
+ ;
+ } else if( lv < battle->bc->aura_lv ) {
+ lv = battle->bc->max_lv - 1;
+ } else {
+ lv = battle->bc->max_lv;
+ }
+
+ return lv;
+}
+
+static int clif_setlevel(struct block_list* bl) {
+ int lv = status->get_lv(bl);
+ nullpo_retr(0, bl);
+ if( battle->bc->client_limit_unit_lv&bl->type )
+ return clif_setlevel_sub(lv);
+ if (bl->type == BL_NPC || bl->type == BL_PET)
+ return 0;
+ return lv;
+}
+
+//To identify disguised characters.
+static inline bool disguised(struct block_list* bl) {
+ return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1 );
+}
+
+static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) {
+ p += pos;
+ p[0] = (uint8)(x>>2);
+ p[1] = (uint8)((x<<6) | ((y>>4)&0x3f));
+ p[2] = (uint8)((y<<4) | (dir&0xf));
+}
+
+static inline unsigned char clif_bl_type_old(struct block_list *bl) {
+ nullpo_retr(0x1, bl);
+ switch (bl->type) {
+ case BL_PC: return (disguised(bl) && !pc->db_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
+ case BL_ITEM: return 0x2; //ITEM_TYPE
+ case BL_SKILL: return 0x3; //SKILL_TYPE
+ case BL_CHAT: return 0x4; //UNKNOWN_TYPE
+ case BL_MOB: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
+ case BL_NPC: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE
+ case BL_PET: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
+ case BL_HOM: return 0x8; //NPC_HOM_TYPE
+ case BL_MER: return 0x9; //NPC_MERSOL_TYPE
+ case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
+ default: return 0x1; //NPC_TYPE
+ }
+}
+
+// this function must be used only by clients version < 16
+void eclif_set_unit_idle_old(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_old p;
+ int g_id = status->get_guild_id(bl);
+
+ nullpo_retv(bl);
+
+ sd = BL_CAST(BL_PC, bl);
+
+ p.PacketType = 0x915;
+ p.PacketLength = sizeof(p);
+ p.objecttype = clif_bl_type_old(bl);
+// p.AID = bl->id;
+// p.GID = (sd) ? sd->status.char_id : 0; // CCODE
+ p.GID = bl->id;
+ p.speed = status->get_speed(bl);
+ p.bodyState = (sc) ? sc->opt1 : 0;
+ p.healthState = (sc) ? sc->opt2 : 0;
+ p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
+ p.job = vd->class_;
+ p.head = vd->hair_style;
+ p.weapon = vd->weapon;
+ p.accessory = vd->head_bottom;
+ 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 = status->get_emblem_id(bl);
+ 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;
+ p.robe = vd->robe;
+ 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) ? 1 : 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);
+ p.font = (sd) ? sd->status.font : 0;
+ if (battle->bc->show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
+ 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;
+ }
+
+ clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
+
+ if( disguised(bl) ) {
+ p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+ p.GID = -bl->id;
+ clif->send(&p,sizeof(p),bl,SELF);
+ }
+
+}
+
void eclif_set_unit_idle_post(struct block_list* bl, TBL_PC *tsd,
enum send_target *target)
{
if (!bl || !tsd)
return;
+ eclif_set_unit_idle_old(bl, tsd, *target);
+
if (bl->type == BL_MOB)
send_mob_info(bl, &tsd->bl, *target);
else if (bl->type == BL_PC)
diff --git a/src/emap/clif.h b/src/emap/clif.h
index 64bdaef..32605b0 100644
--- a/src/emap/clif.h
+++ b/src/emap/clif.h
@@ -37,4 +37,8 @@ void eclif_disp_message(struct block_list* src,
const char* mes, size_t *lenPtr,
enum send_target *targetPtr);
+void eclif_set_unit_idle_old(struct block_list* bl,
+ struct map_session_data *tsd,
+ enum send_target target);
+
#endif // EVOL_MAP_CLIF
diff --git a/src/emap/packets_struct.h b/src/emap/packets_struct.h
new file mode 100644
index 0000000..1098953
--- /dev/null
+++ b/src/emap/packets_struct.h
@@ -0,0 +1,94 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2013-2015 Hercules Dev Team
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Hercules Renewal: Phase Two http://herc.ws/board/topic/383-hercules-renewal-phase-two/ */
+
+#ifndef EVOL_MAP_PACKETS_STRUCT_H
+#define EVOL_MAP_PACKETS_STRUCT_H
+
+#include "common/cbasetypes.h"
+#include "common/mmo.h"
+
+struct packet_idle_unit_old {
+ short PacketType;
+#if PACKETVER >= 20091103
+ short PacketLength;
+ unsigned char objecttype;
+#endif
+//#if PACKETVER >= 20131223
+// unsigned int AID;
+//#endif
+ unsigned int GID;
+ short speed;
+ short bodyState;
+ short healthState;
+#if PACKETVER < 20080102
+ short effectState;
+#else
+ int effectState;
+#endif
+ short job;
+ short head;
+#if PACKETVER < 7
+ short weapon;
+#else
+ int weapon;
+#endif
+ short accessory;
+#if PACKETVER < 7
+ short shield;
+#endif
+ short accessory2;
+ short accessory3;
+ short headpalette;
+ short bodypalette;
+ short headDir;
+#if PACKETVER >= 20101124
+ short robe;
+#endif
+ unsigned int GUID;
+ short GEmblemVer;
+ short honor;
+#if PACKETVER > 7
+ int virtue;
+#else
+ short virtue;
+#endif
+ uint8 isPKModeON;
+ unsigned char sex;
+ unsigned char PosDir[3];
+ unsigned char xSize;
+ unsigned char ySize;
+ unsigned char state;
+ short clevel;
+#if PACKETVER >= 20080102
+ short font;
+#endif
+#if PACKETVER >= 20120221
+ int maxHP;
+ int HP;
+ unsigned char isBoss;
+#endif
+#if PACKETVER >= 20150513
+ short body;
+#endif
+} __attribute__((packed));
+
+#endif /* EVOL_MAP_PACKETS_STRUCT_H */