From bc9a68bd584e572386ef8d21179d1c1eac513775 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Wed, 26 Feb 2025 10:35:48 +0100 Subject: Re-enable SMSG_BEING_SPAWN (0x007c) with additional fields This packet was disabled with the comment "manaplus is skipping this packet". In fact, that isn't entirely true: M+ uses this packet to set a "spawn ID" so that it can later trigger the spawn action after the being is created. Rather than just re-enabling this packet, I've added some additional data (hp, max_hp, attack_range and sex) using previously unused fields, which makes sending SMSG_BEING_VISIBLE (0x0078) obsolete. Starting with client version 9 (M+ and Mana are currently on version 8), we now send either SMSG_BEING_SPAWN or SMSG_BEING_VISIBLE. --- src/map/clif.cpp | 109 ++++++++++++++++++++++++++++-------------------------- src/map/npc.hpp | 1 - tools/protocol.py | 13 +++---- 3 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 1b77be6..cc3d8f8 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -849,7 +849,7 @@ static void clif_mob0078(dumb_ptr md, Buffer& buf) { nullpo_retv(md); - int max_hp = md->stats[mob_stat::MAX_HP]; + int max_hp = battle_get_max_hp(md); int hp = md->hp; Packet_Fixed<0x0078> fixed_78; @@ -897,7 +897,7 @@ static void clif_mob007b(dumb_ptr md, Buffer& buf) { nullpo_retv(md); - int max_hp = md->stats[mob_stat::MAX_HP]; + int max_hp = battle_get_max_hp(md); int hp = md->hp; Packet_Fixed<0x007b> fixed_7b; @@ -1039,26 +1039,25 @@ int clif_spawnnpc(dumb_ptr nd) if (nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS) return 0; - /* manaplus is skipping this packet + Packet_Fixed<0x007c> fixed_7c; fixed_7c.block_id = nd->bl_id; fixed_7c.speed = nd->speed; fixed_7c.species = nd->npc_class; + fixed_7c.sex = nd->sex; fixed_7c.pos.x = nd->bl_x; fixed_7c.pos.y = nd->bl_y; - + fixed_7c.pos.dir = nd->dir; Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); - clif_send(buf, nd, SendWho::AREA); - */ - Buffer buf; - clif_npc0078(nd, buf); - clif_send(buf, nd, SendWho::AREA); - if(nd->sit == DamageType::SIT) + Buffer elseBuf; + clif_npc0078(nd, elseBuf); + clif_send(buf, nd, SendWho::AREA, wrap(9), elseBuf); + + if (nd->sit == DamageType::SIT) { - Buffer buff; - clif_sitnpc_sub(buff, nd, nd->sit); - clif_send(buff, nd, SendWho::AREA); + clif_sitnpc_sub(buf, nd, nd->sit); + clif_send(buf, nd, SendWho::AREA); } return 0; @@ -1073,28 +1072,32 @@ int clif_spawn_fake_npc_for_player(dumb_ptr sd, BlockId fake_n if (!s) return 0; - /* manaplus skips this packet - Packet_Fixed<0x007c> fixed_7c; - fixed_7c.block_id = fake_npc_id; - fixed_7c.speed = interval_t(); - fixed_7c.opt1 = Opt1::ZERO; - fixed_7c.opt2 = Opt2::ZERO; - fixed_7c.option = Opt0::ZERO; - fixed_7c.species = FAKE_NPC_CLASS; - fixed_7c.pos.x = sd->bl_x; - fixed_7c.pos.y = sd->bl_y; - send_fpacket<0x007c, 41>(s, fixed_7c);*/ - - Packet_Fixed<0x0078> fixed_78; - fixed_78.block_id = fake_npc_id; - fixed_78.speed = interval_t(); - fixed_78.opt1 = Opt1::ZERO; - fixed_78.opt2 = Opt2::ZERO; - fixed_78.option = Opt0::ZERO; - fixed_78.species = FAKE_NPC_CLASS; - fixed_78.pos.x = sd->bl_x; - fixed_78.pos.y = sd->bl_y; - send_fpacket<0x0078, 54>(s, fixed_78); + if (sd->client_version >= wrap(9)) + { + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = fake_npc_id; + fixed_7c.speed = interval_t(); + fixed_7c.opt1 = Opt1::ZERO; + fixed_7c.opt2 = Opt2::ZERO; + fixed_7c.option = Opt0::ZERO; + fixed_7c.species = FAKE_NPC_CLASS; + fixed_7c.pos.x = sd->bl_x; + fixed_7c.pos.y = sd->bl_y; + send_fpacket<0x007c, 41>(s, fixed_7c); + } + else + { + Packet_Fixed<0x0078> fixed_78; + fixed_78.block_id = fake_npc_id; + fixed_78.speed = interval_t(); + fixed_78.opt1 = Opt1::ZERO; + fixed_78.opt2 = Opt2::ZERO; + fixed_78.option = Opt0::ZERO; + fixed_78.species = FAKE_NPC_CLASS; + fixed_78.pos.x = sd->bl_x; + fixed_78.pos.y = sd->bl_y; + send_fpacket<0x0078, 54>(s, fixed_78); + } return 0; } @@ -1107,24 +1110,24 @@ int clif_spawnmob(dumb_ptr md) { nullpo_retz(md); - /*{ manaplus skips this packet - Packet_Fixed<0x007c> fixed_7c; - fixed_7c.block_id = md->bl_id; - fixed_7c.speed = interval_t(md->stats[mob_stat::SPEED]); - fixed_7c.opt1 = md->opt1; - fixed_7c.opt2 = md->opt2; - fixed_7c.option = md->option; - fixed_7c.species = md->mob_class; - fixed_7c.pos.x = md->bl_x; - fixed_7c.pos.y = md->bl_y; - Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); - clif_send(buf, md, SendWho::AREA); - }*/ - { - Buffer buf; - clif_mob0078(md, buf); - clif_send(buf, md, SendWho::AREA); - } + Packet_Fixed<0x007c> fixed_7c; + fixed_7c.block_id = md->bl_id; + fixed_7c.speed = battle_get_speed(md); + fixed_7c.opt1 = md->opt1; + fixed_7c.opt2 = md->opt2; + fixed_7c.option = md->option; + fixed_7c.species = md->mob_class; + fixed_7c.hp = md->hp; + fixed_7c.max_hp = battle_get_max_hp(md); + fixed_7c.attack_range = battle_get_range(md); + fixed_7c.pos.x = md->bl_x; + fixed_7c.pos.y = md->bl_y; + fixed_7c.pos.dir = md->dir; + Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); + + Buffer elseBuf; + clif_mob0078(md, elseBuf); + clif_send(buf, md, SendWho::AREA, wrap(9), elseBuf); // custom mob names if (md->name != MobName() && md->name != get_mob_db(md->mob_class).name && md->name.size() >= 4) diff --git a/src/map/npc.hpp b/src/map/npc.hpp index e230ffe..9f3650c 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -38,7 +38,6 @@ namespace map { constexpr BlockId START_NPC_NUM = wrap(110000000); -// TODO make these species, see npc_class in npc_data constexpr Species WARP_CLASS = wrap(45); constexpr Species FAKE_NPC_CLASS = wrap(127); constexpr Species INVISIBLE_CLASS = wrap(32767); diff --git a/tools/protocol.py b/tools/protocol.py index c4c8657..0c84b2a 100755 --- a/tools/protocol.py +++ b/tools/protocol.py @@ -2391,14 +2391,13 @@ def build_context(): at(18, u16, 'unknown 3'), at(20, species, 'species'), at(22, u16, 'unknown 4'), - at(24, u16, 'unknown 5'), - at(26, u16, 'unknown 6'), - at(28, u16, 'unknown 7'), - at(30, u16, 'unknown 8'), - at(32, u16, 'unknown 9'), - at(34, u16, 'unknown 10'), + at(24, u32, 'hp'), + at(28, u32, 'max hp'), + at(32, u16, 'unknown 5'), + at(34, u8, 'attack range'), + at(35, sex, 'sex'), at(36, pos1, 'pos'), - at(39, u16, 'unknown 11'), + at(39, u16, 'unknown 6'), ], fixed_size=41, pre=[BOOT, FINISH, GM, MAGIC, SCRIPT, TIMER, 0x0089, 0x008c, 0x00b8, 0x00b9, 0x00e6, 0x00f7, 0x0143, 0x0146, 0x01d5], -- cgit v1.2.3-70-g09d2