diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ints/wrap.hpp | 17 | ||||
-rw-r--r-- | src/map/atcommand.cpp | 5 | ||||
-rw-r--r-- | src/map/clif.cpp | 267 | ||||
-rw-r--r-- | src/map/clif.hpp | 7 | ||||
-rw-r--r-- | src/map/magic-stmt.cpp | 10 | ||||
-rw-r--r-- | src/map/map.cpp | 5 | ||||
-rw-r--r-- | src/map/map.hpp | 2 | ||||
-rw-r--r-- | src/map/mapflag.cpp | 2 | ||||
-rw-r--r-- | src/map/mapflag.hpp | 2 | ||||
-rw-r--r-- | src/map/mapflag.py | 2 | ||||
-rw-r--r-- | src/map/npc-parse.cpp | 15 | ||||
-rw-r--r-- | src/map/pc.cpp | 10 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 131 | ||||
-rw-r--r-- | src/mmo/version.hpp | 3 | ||||
-rw-r--r-- | src/wire/packets.cpp | 1 |
15 files changed, 359 insertions, 120 deletions
diff --git a/src/ints/wrap.hpp b/src/ints/wrap.hpp index 707c787..25b03c1 100644 --- a/src/ints/wrap.hpp +++ b/src/ints/wrap.hpp @@ -64,6 +64,14 @@ namespace ints } template<class T> + struct Sub : T + { + constexpr + Sub(typename T::wrapped_type v2) + : T(v2) + {} + }; + template<class T> constexpr typename T::wrapped_type unwrap(typename std::enable_if<true, T>::type w) { @@ -73,14 +81,7 @@ namespace ints constexpr T wrap(typename T::wrapped_type v) { - struct Sub : T - { - constexpr - Sub(typename T::wrapped_type v2) - : T(v2) - {} - }; - return Sub(v); + return Sub<T>(v); } template<class W> diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 63a1159..5db8288 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -4108,6 +4108,9 @@ ATCE atcommand_pvp(Session *s, dumb_ptr<map_session_data> sd, clif_displaymessage(s, "##3PvP : ##BOff"_s); } + sd->state.pvp_rank = 0; + clif_pvpstatus(sd); // send my channel to others + pc_setpvptimer(sd, battle_config.player_pvp_time); return ATCE::OKAY; } @@ -4127,6 +4130,8 @@ ATCE atcommand_charpvp(Session *, dumb_ptr<map_session_data>, return ATCE::EXIST; pl_sd->state.pvpchannel = channel; + pl_sd->state.pvp_rank = 0; + clif_pvpstatus(pl_sd); // send their channel to others return ATCE::OKAY; } diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 248f74a..35cc463 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -217,7 +217,7 @@ AString clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type, XString */ static void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, - dumb_ptr<block_list> src_bl, SendWho type) + dumb_ptr<block_list> src_bl, SendWho type, short min_version) { nullpo_retv(bl); dumb_ptr<map_session_data> sd = bl->is_player(); @@ -246,6 +246,7 @@ void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, if (sd->sess != nullptr) { { + if (sd->client_version >= min_version) { send_buffer(sd->sess, buf); } @@ -258,7 +259,7 @@ void clif_send_sub(dumb_ptr<block_list> bl, const Buffer& buf, *------------------------------------------ */ static -int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) +int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type, short min_version) { int x0 = 0, x1 = 0, y0 = 0, y1 = 0; @@ -323,14 +324,14 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) break; case SendWho::AREA: case SendWho::AREA_WOS: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, type), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, type, min_version), bl->bl_m, bl->bl_x - AREA_SIZE, bl->bl_y - AREA_SIZE, bl->bl_x + AREA_SIZE, bl->bl_y + AREA_SIZE, BL::PC); break; case SendWho::AREA_CHAT_WOC: - map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, SendWho::AREA_CHAT_WOC), + map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, bl, SendWho::AREA_CHAT_WOC, min_version), bl->bl_m, bl->bl_x - (AREA_SIZE), bl->bl_y - (AREA_SIZE), bl->bl_x + (AREA_SIZE), bl->bl_y + (AREA_SIZE), @@ -380,6 +381,7 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) (sd->bl_x < x0 || sd->bl_y < y0 || sd->bl_x > x1 || sd->bl_y > y1)) continue; + if (sd->client_version >= min_version) { send_buffer(sd->sess, buf); } @@ -395,6 +397,7 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) { if (sd->partyspy == p.party_id) { + if (sd->client_version >= min_version) { send_buffer(sd->sess, buf); } @@ -410,7 +413,8 @@ int clif_send(const Buffer& buf, dumb_ptr<block_list> bl, SendWho type) dumb_ptr<map_session_data> sd = bl->is_player(); { - send_buffer(sd->sess, buf); + if (sd->client_version >= min_version) + send_buffer(sd->sess, buf); } } break; @@ -528,7 +532,7 @@ int clif_dropflooritem(dumb_ptr<flooritem_data> fitem) Buffer buf; clif_set009e(fitem, buf); - clif_send(buf, fitem, SendWho::AREA); + clif_send(buf, fitem, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -547,7 +551,7 @@ int clif_clearflooritem(dumb_ptr<flooritem_data> fitem, Session *s) if (!s) { Buffer buf = create_fpacket<0x00a1, 6>(fixed_a1); - clif_send(buf, fitem, SendWho::AREA); + clif_send(buf, fitem, SendWho::AREA, MIN_CLIENT_VERSION); } else { @@ -572,14 +576,14 @@ int clif_clearchar(dumb_ptr<block_list> bl, BeingRemoveWhy type) { fixed_80.type = BeingRemoveWhy::GONE; Buffer buf = create_fpacket<0x0080, 7>(fixed_80); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); } else { fixed_80.type = type; Buffer buf = create_fpacket<0x0080, 7>(fixed_80); clif_send(buf, bl, - type == BeingRemoveWhy::DEAD ? SendWho::AREA : SendWho::AREA_WOS); + type == BeingRemoveWhy::DEAD ? SendWho::AREA : SendWho::AREA_WOS, MIN_CLIENT_VERSION); } return 0; @@ -796,6 +800,24 @@ void clif_mob0078(dumb_ptr<mob_data> md, Buffer& buf) buf = create_fpacket<0x0078, 54>(fixed_78); } +void clif_npc_action(dumb_ptr<map_session_data> sd, BlockId npcid, + short command, int id, short x, short y) +{ + nullpo_retv(sd); + if(sd->client_version < 2) + return; + + Packet_Fixed<0x0212> fixed_212; + fixed_212.npc_id = npcid; + fixed_212.command = command; + fixed_212.id = id; + fixed_212.x = x; + fixed_212.y = y; + + Buffer buf = create_fpacket<0x0212, 16>(fixed_212); + send_buffer(sd->sess, buf); +} + /*========================================== * MOB表示2 *------------------------------------------ @@ -835,21 +857,6 @@ void clif_mob007b(dumb_ptr<mob_data> md, Buffer& buf) *------------------------------------------ */ static -void clif_0225_being_move3_sub(dumb_ptr<block_list> bl, const Buffer& buf) -{ - nullpo_retv(bl); - dumb_ptr<map_session_data> sd = bl->is_player(); - - if (sd->sess != nullptr) - { - if(sd->client_version >= 3) - { - send_buffer(sd->sess, buf); - } - } -} - -static int clif_0225_being_move3(dumb_ptr<mob_data> md) { Packet_Head<0x0225> head_225; @@ -869,11 +876,7 @@ int clif_0225_being_move3(dumb_ptr<mob_data> md) Buffer buf = create_vpacket<0x0225, 14, 1>(head_225, repeat_225); - map_foreachinarea(std::bind(clif_0225_being_move3_sub, ph::_1, buf), - md->bl_m, - md->bl_x - AREA_SIZE, md->bl_y - AREA_SIZE, - md->bl_x + AREA_SIZE, md->bl_y + AREA_SIZE, - BL::PC); + clif_send(buf, md, SendWho::AREA, 3); return 0; } @@ -928,7 +931,9 @@ int clif_spawnpc(dumb_ptr<map_session_data> sd) Buffer buf; clif_set0078_alt_1d9(sd, buf); - clif_send(buf, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS, MIN_CLIENT_VERSION); + + clif_pvpstatus(sd); if (sd->bl_m->flag.get(MapFlag::SNOW)) clif_specialeffect(sd, 162, 1); @@ -965,17 +970,17 @@ int clif_spawnnpc(dumb_ptr<npc_data> nd) fixed_7c.pos.y = nd->bl_y; Buffer buf = create_fpacket<0x007c, 41>(fixed_7c); - clif_send(buf, nd, SendWho::AREA); + clif_send(buf, nd, SendWho::AREA, MIN_CLIENT_VERSION); */ Buffer buf; clif_npc0078(nd, buf); - clif_send(buf, nd, SendWho::AREA); + clif_send(buf, nd, SendWho::AREA, MIN_CLIENT_VERSION); if(nd->sit == DamageType::SIT) { Buffer buff; clif_sitnpc_sub(buff, nd, nd->sit); - clif_send(buff, nd, SendWho::AREA); + clif_send(buff, nd, SendWho::AREA, MIN_CLIENT_VERSION); } return 0; @@ -1034,12 +1039,12 @@ int clif_spawnmob(dumb_ptr<mob_data> md) 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); + clif_send(buf, md, SendWho::AREA, MIN_CLIENT_VERSION); } Buffer buf; clif_mob0078(md, buf); - clif_send(buf, md, SendWho::AREA); + clif_send(buf, md, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -1093,7 +1098,7 @@ int clif_movechar(dumb_ptr<map_session_data> sd) Buffer buf; clif_set007b(sd, buf); - clif_send(buf, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS, MIN_CLIENT_VERSION); if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0) clif_changelook(sd, LOOK::CLOTHES_COLOR, @@ -1150,6 +1155,9 @@ void clif_changemap(dumb_ptr<map_session_data> sd, MapName mapname, int x, int y fixed_91.x = x; fixed_91.y = y; send_fpacket<0x0091, 22>(s, fixed_91); + + if(sd->bl_m->mask > 0) + clif_send_mask(sd, sd->bl_m->mask); } /*========================================== @@ -1185,7 +1193,7 @@ void clif_fixpos(dumb_ptr<block_list> bl) fixed_88.y = bl->bl_y; Buffer buf = create_fpacket<0x0088, 10>(fixed_88); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); } /*========================================== @@ -1863,9 +1871,9 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF, MIN_CLIENT_VERSION); else - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); } else { @@ -1877,9 +1885,9 @@ int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val, Buffer buf = create_fpacket<0x01d7, 11>(fixed_1d7); if (dstsd) - clif_send(buf, dstsd, SendWho::SELF); + clif_send(buf, dstsd, SendWho::SELF, MIN_CLIENT_VERSION); else - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); } return 0; } @@ -2043,11 +2051,42 @@ int clif_misceffect(dumb_ptr<block_list> bl, int type) fixed_19b.type = type; Buffer buf = create_fpacket<0x019b, 10>(fixed_19b); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } +void clif_map_pvp(dumb_ptr<map_session_data> sd) +{ + nullpo_retv(sd); + + Packet_Fixed<0x0199> fixed_199; + fixed_199.status = sd->bl_m->flag.get(MapFlag::PVP)? 1: 0; + Buffer buf = create_fpacket<0x0199, 4>(fixed_199); + + clif_send(buf, sd, SendWho::SELF, 2); +} + +static +void clif_pvpstatus_towards(Buffer& buf, dumb_ptr<map_session_data> sd) +{ + nullpo_retv(sd); + + Packet_Fixed<0x019a> fixed_19a; + fixed_19a.block_id = sd->bl_id; + fixed_19a.rank = sd->state.pvp_rank; + fixed_19a.channel = sd->state.pvpchannel; + buf = create_fpacket<0x019a, 14>(fixed_19a); +} + +void clif_pvpstatus(dumb_ptr<map_session_data> sd) +{ + nullpo_retv(sd); + Buffer buf; + clif_pvpstatus_towards(buf, sd); + clif_send(buf, sd, SendWho::AREA, 2); +} + /*========================================== * 表示オプション変更 *------------------------------------------ @@ -2069,7 +2108,7 @@ int clif_changeoption(dumb_ptr<block_list> bl) fixed_119.zero = 0; Buffer buf = create_fpacket<0x0119, 13>(fixed_119); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -2101,7 +2140,7 @@ int clif_useitemack(dumb_ptr<map_session_data> sd, IOff0 index, int amount, fixed_1c8.amount = amount; fixed_1c8.ok = ok; Buffer buf = create_fpacket<0x01c8, 13>(fixed_1c8); - clif_send(buf, sd, SendWho::SELF); + clif_send(buf, sd, SendWho::SELF, MIN_CLIENT_VERSION); } return 0; @@ -2356,6 +2395,10 @@ void clif_getareachar_pc(dumb_ptr<map_session_data> sd, } send_buffer(sd->sess, buf); + Buffer buff; + clif_pvpstatus_towards(buff, dstsd); + clif_send(buff, sd, SendWho::SELF, 2); + if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0) clif_changelook(dstsd, LOOK::CLOTHES_COLOR, dstsd->status.clothes_color); @@ -2399,7 +2442,7 @@ int clif_movemob(dumb_ptr<mob_data> md) Buffer buf; clif_mob007b(md, buf); - clif_send(buf, md, SendWho::AREA); + clif_send(buf, md, SendWho::AREA, MIN_CLIENT_VERSION); clif_0225_being_move3(md); return 0; @@ -2417,13 +2460,13 @@ int clif_fixmobpos(dumb_ptr<mob_data> md) { Buffer buf; clif_mob007b(md, buf); - clif_send(buf, md, SendWho::AREA); + clif_send(buf, md, SendWho::AREA, MIN_CLIENT_VERSION); } else { Buffer buf; clif_mob0078(md, buf); - clif_send(buf, md, SendWho::AREA); + clif_send(buf, md, SendWho::AREA, MIN_CLIENT_VERSION); } return 0; @@ -2441,13 +2484,13 @@ int clif_fixpcpos(dumb_ptr<map_session_data> sd) { Buffer buf; clif_set007b(sd, buf); - clif_send(buf, sd, SendWho::AREA); + clif_send(buf, sd, SendWho::AREA, MIN_CLIENT_VERSION); } else { Buffer buf; clif_set0078_main_1d8(sd, buf); - clif_send(buf, sd, SendWho::AREA); + clif_send(buf, sd, SendWho::AREA, MIN_CLIENT_VERSION); } clif_changelook_accessories(sd, nullptr); @@ -2480,7 +2523,7 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, fixed_8a.damage_type = type; fixed_8a.damage2 = 0; Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); - clif_send(buf, src, SendWho::AREA); + clif_send(buf, src, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -2687,7 +2730,7 @@ void clif_skillinfoblock(dumb_ptr<map_session_data> sd) std::vector<Packet_Repeat<0x010f>> repeat_10f; for (SkillID i : erange(SkillID(), MAX_SKILL)) { - if (sd->status.skill[i].lv && sd->client_version >= 1) + if (sd->status.skill[i].lv) { Packet_Repeat<0x010f> info; // [Fate] Version 1 and later don't crash because of bad skill IDs anymore @@ -2802,7 +2845,7 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst, fixed_1de.div = div; fixed_1de.type_or_hit = (type > 0) ? type : skill_get_hit(skill_id); Buffer buf = create_fpacket<0x01de, 33>(fixed_1de); - clif_send(buf, src, SendWho::AREA); + clif_send(buf, src, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -2820,7 +2863,7 @@ int clif_status_change(dumb_ptr<block_list> bl, StatusChange type, int flag) fixed_196.block_id = bl->bl_id; fixed_196.flag = flag; Buffer buf = create_fpacket<0x0196, 9>(fixed_196); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); return 0; } @@ -2850,7 +2893,7 @@ void clif_GMmessage(dumb_ptr<block_list> bl, XString mes, int flag) (flag == 1) ? SendWho::ALL_SAMEMAP : (flag == 2) ? SendWho::AREA : (flag == 3) ? SendWho::SELF : - SendWho::ALL_CLIENT); + SendWho::ALL_CLIENT, MIN_CLIENT_VERSION); } /*========================================== @@ -2867,7 +2910,7 @@ void clif_resurrection(dumb_ptr<block_list> bl, int type) Buffer buf = create_fpacket<0x0148, 8>(fixed_148); clif_send(buf, bl, - type == 1 ? SendWho::AREA : SendWho::AREA_WOS); + type == 1 ? SendWho::AREA : SendWho::AREA_WOS, MIN_CLIENT_VERSION); } /*========================================== @@ -2954,7 +2997,7 @@ int clif_party_info(PartyPair p, Session *s) if (sd != nullptr) { Buffer buf = create_vpacket<0x00fb, 28, 46>(head_fb, repeat_fb); - clif_send(buf, sd, SendWho::PARTY); + clif_send(buf, sd, SendWho::PARTY, MIN_CLIENT_VERSION); } return 0; } @@ -3031,7 +3074,7 @@ void clif_party_option(PartyPair p, dumb_ptr<map_session_data> sd, int flag) if (flag == 0) { Buffer buf = create_fpacket<0x0101, 6>(fixed_101); - clif_send(buf, sd, SendWho::PARTY); + clif_send(buf, sd, SendWho::PARTY, MIN_CLIENT_VERSION); } else { @@ -3065,7 +3108,7 @@ void clif_party_leaved(PartyPair p, dumb_ptr<map_session_data> sd, if (sd != nullptr) { Buffer buf = create_fpacket<0x0105, 31>(fixed_105); - clif_send(buf, sd, SendWho::PARTY); + clif_send(buf, sd, SendWho::PARTY, MIN_CLIENT_VERSION); } } else if (sd != nullptr) @@ -3095,7 +3138,7 @@ void clif_party_message(PartyPair p, AccountId account_id, XString mes) Packet_Head<0x0109> head_109; head_109.account_id = account_id; Buffer buf = create_vpacket<0x0109, 8, 1>(head_109, mes); - clif_send(buf, sd, SendWho::PARTY); + clif_send(buf, sd, SendWho::PARTY, MIN_CLIENT_VERSION); } } @@ -3112,7 +3155,7 @@ int clif_party_xy(PartyPair , dumb_ptr<map_session_data> sd) fixed_107.x = sd->bl_x; fixed_107.y = sd->bl_y; Buffer buf = create_fpacket<0x0107, 10>(fixed_107); - clif_send(buf, sd, SendWho::PARTY_SAMEMAP_WOS); + clif_send(buf, sd, SendWho::PARTY_SAMEMAP_WOS, MIN_CLIENT_VERSION); return 0; } @@ -3130,7 +3173,7 @@ int clif_party_hp(PartyPair , dumb_ptr<map_session_data> sd) fixed_106.max_hp = (sd->status.max_hp > 0x7fff) ? 0x7fff : sd->status.max_hp; Buffer buf = create_fpacket<0x0106, 10>(fixed_106); - clif_send(buf, sd, SendWho::PARTY_AREA_WOS); + clif_send(buf, sd, SendWho::PARTY_AREA_WOS, MIN_CLIENT_VERSION); return 0; } @@ -3167,7 +3210,7 @@ void clif_emotion(dumb_ptr<block_list> bl, int type) fixed_c0.block_id = bl->bl_id; fixed_c0.type = type; Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); } void clif_emotion_towards(dumb_ptr<block_list> bl, @@ -3200,7 +3243,7 @@ void clif_sitting(Session *, dumb_ptr<map_session_data> sd) fixed_8a.src_id = sd->bl_id; fixed_8a.damage_type = DamageType::SIT; Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); - clif_send(buf, sd, SendWho::AREA); + clif_send(buf, sd, SendWho::AREA, MIN_CLIENT_VERSION); } static @@ -3224,7 +3267,7 @@ void clif_sitnpc_towards(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd, D Buffer buf; clif_sitnpc_sub(buf, nd, dmg); - clif_send(buf, sd, SendWho::SELF); + clif_send(buf, sd, SendWho::SELF, MIN_CLIENT_VERSION); } void clif_sitnpc(dumb_ptr<npc_data> nd, DamageType dmg) @@ -3233,7 +3276,7 @@ void clif_sitnpc(dumb_ptr<npc_data> nd, DamageType dmg) Buffer buf; clif_sitnpc_sub(buf, nd, dmg); - clif_send(buf, nd, SendWho::AREA); + clif_send(buf, nd, SendWho::AREA, MIN_CLIENT_VERSION); } static @@ -3270,7 +3313,7 @@ void clif_setnpcdirection_towards(dumb_ptr<map_session_data> sd, dumb_ptr<npc_da Buffer buf; clif_setnpcdirection_sub(buf, nd, direction); - clif_send(buf, sd, SendWho::SELF); + clif_send(buf, sd, SendWho::SELF, MIN_CLIENT_VERSION); } void clif_setnpcdirection(dumb_ptr<npc_data> nd, DIR direction) @@ -3279,7 +3322,7 @@ void clif_setnpcdirection(dumb_ptr<npc_data> nd, DIR direction) Buffer buf; clif_setnpcdirection_sub(buf, nd, direction); - clif_send(buf, nd, SendWho::AREA); + clif_send(buf, nd, SendWho::AREA, MIN_CLIENT_VERSION); } /*========================================== @@ -3338,9 +3381,9 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag) } } else if (flag == 1) - clif_send(buf, bl, SendWho::SELF); + clif_send(buf, bl, SendWho::SELF, MIN_CLIENT_VERSION); else if (!flag) - clif_send(buf, bl, SendWho::AREA); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); return 0; @@ -3455,6 +3498,8 @@ RecvResult clif_parse_LoadEndAck(Session *s, dumb_ptr<map_session_data> sd) map_addblock(sd); // ブロック登録 clif_spawnpc(sd); // spawn + clif_map_pvp(sd); // send map pvp status + // weight max , now clif_updatestatus(sd, SP::MAXWEIGHT); clif_updatestatus(sd, SP::WEIGHT); @@ -3758,7 +3803,7 @@ RecvResult clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) XString repeat_8d = mbuf; Buffer sendbuf = create_vpacket<0x008d, 8, 1>(head_8d, repeat_8d); - clif_send(sendbuf, sd, SendWho::AREA_CHAT_WOC); + clif_send(sendbuf, sd, SendWho::AREA_CHAT_WOC, MIN_CLIENT_VERSION); } /* Send the message back to the speaker. */ @@ -3767,19 +3812,81 @@ RecvResult clif_parse_GlobalMessage(Session *s, dumb_ptr<map_session_data> sd) return rv; } -void clif_message(dumb_ptr<block_list> bl, XString msg) +static +void clif_message_sub(Buffer& buf, dumb_ptr<block_list> bl, XString msg) { size_t msg_len = msg.size() + 1; if (msg_len + 16 > 512) return; - nullpo_retv(bl); - Packet_Head<0x008d> head_8d; head_8d.block_id = bl->bl_id; - Buffer buf = create_vpacket<0x008d, 8, 1>(head_8d, msg); + buf = create_vpacket<0x008d, 8, 1>(head_8d, msg); +} + +void clif_npc_send_title(Session *s, BlockId npcid, XString msg) +{ + size_t msg_len = msg.size() + 1; + if (msg_len > 50) + return; + + Packet_Head<0x0228> head_228; + head_228.npc_id = npcid; + head_228.string_length = msg_len; + Buffer buf = create_vpacket<0x0228, 10, 1>(head_228, msg); + + send_buffer(s, buf); +} + +void clif_change_music(dumb_ptr<map_session_data> sd, XString music) +{ + nullpo_retv(sd); + if(sd->client_version < 2) + return; + + size_t msg_len = music.size(); + if (msg_len > 128) + return; + + Packet_Head<0x0227> head_227; + Buffer buf = create_vpacket<0x0227, 4, 1>(head_227, music); + + send_buffer(sd->sess, buf); +} + +void clif_message_towards(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl, XString msg) +{ + nullpo_retv(bl); + nullpo_retv(sd); + + if(!sd) + return; + + Buffer buf; + clif_message_sub(buf, bl, msg); + clif_send(buf, sd, SendWho::SELF, MIN_CLIENT_VERSION); +} + +void clif_message(dumb_ptr<block_list> bl, XString msg) +{ + nullpo_retv(bl); - clif_send(buf, bl, SendWho::AREA); + Buffer buf; + clif_message_sub(buf, bl, msg); + clif_send(buf, bl, SendWho::AREA, MIN_CLIENT_VERSION); +} + +void clif_send_mask(dumb_ptr<map_session_data> sd, int map_mask) +{ + nullpo_retv(sd); + if(sd->client_version < 2) + return; + + Packet_Fixed<0x0226> fixed_226; + fixed_226.mask = map_mask; + + Buffer buf = create_fpacket<0x0226, 10>(fixed_226); + send_buffer(sd->sess, buf); } /*========================================== @@ -3823,7 +3930,7 @@ RecvResult clif_parse_ChangeDir(Session *s, dumb_ptr<map_session_data> sd) fixed_9c.client_dir = client_dir; Buffer buf = create_fpacket<0x009c, 9>(fixed_9c); - clif_send(buf, sd, SendWho::AREA_WOS); + clif_send(buf, sd, SendWho::AREA_WOS, MIN_CLIENT_VERSION); return rv; } @@ -3848,7 +3955,7 @@ RecvResult clif_parse_Emotion(Session *s, dumb_ptr<map_session_data> sd) fixed_c0.block_id = sd->bl_id; fixed_c0.type = emote; Buffer buf = create_fpacket<0x00c0, 7>(fixed_c0); - clif_send(buf, sd, SendWho::AREA); + clif_send(buf, sd, SendWho::AREA, MIN_CLIENT_VERSION); } else clif_skill_fail(sd, SkillID::ONE, 0, 1); @@ -3919,7 +4026,7 @@ RecvResult clif_parse_ActionRequest(Session *s, dumb_ptr<map_session_data> sd) fixed_8a.src_id = sd->bl_id; fixed_8a.damage_type = DamageType::STAND; Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); - clif_send(buf, sd, SendWho::AREA); + clif_send(buf, sd, SendWho::AREA, MIN_CLIENT_VERSION); break; } @@ -4817,7 +4924,7 @@ void clif_sendallquest(dumb_ptr<map_session_data> sd) if (!sd->sess) return; - if(sd->client_version < 2) + if(sd->client_version < 2) // require 1.5.5.9 or above return; Session *s = sd->sess; @@ -4854,7 +4961,7 @@ void clif_sendquest(dumb_ptr<map_session_data> sd, QuestId questid, int value) if (!sd->sess) return; - if(sd->client_version < 2) + if(sd->client_version < 2) // require 1.5.5.9 or above return; Session *s = sd->sess; diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 3cc308c..28f58a9 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -72,6 +72,7 @@ void clif_scriptclose(dumb_ptr<map_session_data>, BlockId); //self void clif_scriptmenu(dumb_ptr<map_session_data>, BlockId, XString); //self void clif_scriptinput(dumb_ptr<map_session_data>, BlockId); //self void clif_scriptinputstr(dumb_ptr<map_session_data> sd, BlockId npcid); // self +void clif_map_pvp(dumb_ptr<map_session_data>); // self int clif_additem(dumb_ptr<map_session_data>, IOff0, int, PickupFail); //self void clif_delitem(dumb_ptr<map_session_data>, IOff0, int); //self @@ -92,6 +93,7 @@ int clif_statusupack(dumb_ptr<map_session_data>, SP, int, int); // self int clif_equipitemack(dumb_ptr<map_session_data>, IOff0, EPOS, int); // self int clif_unequipitemack(dumb_ptr<map_session_data>, IOff0, EPOS, int); // self int clif_misceffect(dumb_ptr<block_list>, int); // area +void clif_pvpstatus(dumb_ptr<map_session_data>); // area int clif_changeoption(dumb_ptr<block_list>); // area int clif_useitemack(dumb_ptr<map_session_data>, IOff0, int, int); // self @@ -102,6 +104,10 @@ void clif_sitnpc(dumb_ptr<npc_data> nd, DamageType dmg); void clif_sitnpc_towards(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd, DamageType dmg); void clif_setnpcdirection(dumb_ptr<npc_data> nd, DIR direction); void clif_setnpcdirection_towards(dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd, DIR direction); +void clif_npc_send_title(Session *s, BlockId npcid, XString msg); +void clif_change_music(dumb_ptr<map_session_data> sd, XString music); +void clif_npc_action(dumb_ptr<map_session_data>, BlockId, short, int, short, short); +void clif_send_mask(dumb_ptr<map_session_data>, int); // trade void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name); @@ -174,6 +180,7 @@ void clif_resurrection(dumb_ptr<block_list> bl, int type); int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag); // special effects [Valaris] void clif_message(dumb_ptr<block_list> bl, XString msg); // messages (from mobs/npcs) [Valaris] +void clif_message_towards(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> bl, XString msg); int clif_GM_kick(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> tsd, int type); diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index 4d8330a..1a8085b 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -771,10 +771,12 @@ int op_injure(dumb_ptr<env_t> env, Slice<val_t> args) int target_hp = battle_get_hp(target); int mdef = battle_get_mdef(target); - if (target->bl_type == BL::PC - && !target->bl_m->flag.get(MapFlag::PVP) - && (caster->bl_type == BL::PC) - && ((caster->is_player()->state.pvpchannel > 1) && (target->is_player()->state.pvpchannel != caster->is_player()->state.pvpchannel))) + if (target->bl_type == BL::PC // target is player + && !target->bl_m->flag.get(MapFlag::PVP) // there is no pvpon flag + && (caster->bl_type == BL::PC) // caster is player + && ((target->is_player()->state.pvpchannel == 0) + || ((caster->is_player()->state.pvpchannel > 0) + && (target->is_player()->state.pvpchannel != caster->is_player()->state.pvpchannel)))) return 0; /* Cannot damage other players outside of pvp */ if (target != caster) diff --git a/src/map/map.cpp b/src/map/map.cpp index 7d219a9..0c73b59 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -183,7 +183,7 @@ int map_addblock(dumb_ptr<block_list> bl) if (bl->bl_next) bl->bl_next->bl_prev = bl; m->blocks.ref(x / BLOCK_SIZE, y / BLOCK_SIZE).normal = bl; - if (bl->bl_type == BL::PC) + if (bl->bl_type == BL::PC && !bool(bl->is_player()->status.option & Opt0::HIDE)) m->users++; } @@ -1237,7 +1237,8 @@ int map_setipport(MapName name, IP4Address ip, int port) mdos->gat = nullptr; mdos->ip = ip; mdos->port = port; - maps_db.put(mdos->name_, std::move(mdos)); + MapName mName = mdos->name_; + maps_db.put(mName, std::move(mdos)); } } OMATCH_END (); diff --git a/src/map/map.hpp b/src/map/map.hpp index aac646b..aea35b7 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -143,6 +143,7 @@ struct map_session_data : block_list, SessionData unsigned shroud_disappears_on_talk:1; unsigned seen_motd:1; unsigned pvpchannel; + unsigned pvp_rank; } state; struct { @@ -504,6 +505,7 @@ struct map_local : map_abstract MapFlags flag; Point save; Point resave; + int mask; Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc; }; diff --git a/src/map/mapflag.cpp b/src/map/mapflag.cpp index 9f3c9ab..22c4878 100644 --- a/src/map/mapflag.cpp +++ b/src/map/mapflag.cpp @@ -71,7 +71,7 @@ bool impl_extract(XString str, MapFlag *mf) {"nowarp"_s, MapFlag::NOWARP}, {"nowarpto"_s, MapFlag::NOWARPTO}, {"nopvp"_s, MapFlag::NOPVP}, - //{"noicewall"_s, MapFlag::NOICEWALL}, + {"mask"_s, MapFlag::MASK}, {"snow"_s, MapFlag::SNOW}, {"fog"_s, MapFlag::FOG}, {"sakura"_s, MapFlag::SAKURA}, diff --git a/src/map/mapflag.hpp b/src/map/mapflag.hpp index 3538c56..9223d70 100644 --- a/src/map/mapflag.hpp +++ b/src/map/mapflag.hpp @@ -54,7 +54,7 @@ enum class MapFlag NOWARP = 1 << 13, NOWARPTO = 1 << 26, NOPVP = 1 << 14, - //NOICEWALL = 1 << 15, + MASK = 1 << 15, SNOW = 1 << 16, FOG = 1 << 17, SAKURA = 1 << 18, diff --git a/src/map/mapflag.py b/src/map/mapflag.py index b0a2f24..728aa81 100644 --- a/src/map/mapflag.py +++ b/src/map/mapflag.py @@ -40,7 +40,7 @@ class MapFlags(object): ('NOWARP', 13), ('NOWARPTO', 26), ('NOPVP', 14), - #('NOICEWALL', 15), + ('MASK', 15), ('SNOW', 16), ('FOG', 17), ('SAKURA', 18), diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index 0a0d682..9ee84d2 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -354,7 +354,7 @@ bool npc_load_mapflag(ast::npc::MapFlag& mapflag) } MapName savemap; - int savex, savey; + int savex, savey, mask; if (mf == MapFlag::NOSAVE) { @@ -392,6 +392,19 @@ bool npc_load_mapflag(ast::npc::MapFlag& mapflag) return false; } } + else if (mf == MapFlag::MASK) + { + if (mapflag.vec_extra.data.size() == 1 + && extract(mapflag.vec_extra.data[0].data, &mask)) + { + m->mask = mask; + } + else + { + mapflag.vec_extra.span.error("Unable to extract map mask"_s); + return false; + } + } else { if (mapflag.vec_extra.data.size()) diff --git a/src/map/pc.cpp b/src/map/pc.cpp index d2b2f44..96233e1 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -796,6 +796,9 @@ int pc_authok(AccountId id, int login_id2, pc_calcstatus(sd, 1); + if(sd->bl_m->mask > 0) + clif_send_mask(sd, sd->bl_m->mask); + // Init Quest Log clif_sendallquest(sd); return 0; @@ -944,7 +947,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_mdef = sd->mdef; b_mdef2 = sd->mdef2; b_base_atk = sd->base_atk; - if (!pc_isdead(sd) && sd->state.pvpchannel == 1) + if (sd->state.pvpchannel == 1) b_pvpchannel = sd->state.pvpchannel; sd->max_weight = max_weight_base_0 + sd->status.attrs[ATTR::STR] * 300; @@ -3313,6 +3316,11 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, }; npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"_s), sd->bl_id, arg); npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"_s), src->bl_id, arg); + + sd->state.pvp_rank = 0; + src->is_player()->state.pvp_rank++; + clif_pvpstatus(sd); + clif_pvpstatus(src->is_player()); } npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"_s), sd->bl_id, nullptr); diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 3949627..2822550 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -66,21 +66,6 @@ namespace tmwa { namespace map { -static -Array<LString, 11> pos_str //= -{{ - "Head"_s, - "Body"_s, - "Left hand"_s, - "Right hand"_s, - "Robe"_s, - "Shoes"_s, - "Accessory 1"_s, - "Accessory 2"_s, - "Head 2"_s, - "Head 3"_s, - "Not Equipped"_s, -}}; #define AARG(n) (st->stack->stack_datav[st->start + 2 + (n)]) #define HARG(n) (st->end > st->start + 2 + (n)) @@ -1630,6 +1615,30 @@ void builtin_setnpctimer(ScriptState *st) } static +void builtin_npcaction(ScriptState *st) +{ + dumb_ptr<map_session_data> sd = script_rid2sd(st); + short command = conv_num(st, &AARG(0)); + int id = 0; + short x = HARG(2) ? conv_num(st, &AARG(2)) : 0; + short y = HARG(3) ? conv_num(st, &AARG(3)) : 0; + + if(HARG(1)) + { + if(command == 2) + { + dumb_ptr<npc_data> nd_; + nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(1))))); + id = unwrap<BlockId>(nd_->bl_id); + } + else + id = conv_num(st, &AARG(1)); + } + + clif_npc_action(sd, st->oid, command, id, x, y); +} + +static void builtin_setnpcdirection(ScriptState *st) { dumb_ptr<npc_data> nd_; @@ -2675,6 +2684,70 @@ void builtin_message(ScriptState *st) } +static +void builtin_title(ScriptState *st) +{ + dumb_ptr<map_session_data> sd = script_rid2sd(st); + ZString msg = ZString(conv_str(st, &AARG(0))); + if (sd == nullptr) + return; + clif_npc_send_title(sd->sess, st->oid, msg); +} + +static +void builtin_music(ScriptState *st) +{ + dumb_ptr<map_session_data> sd = script_rid2sd(st); + ZString msg = ZString(conv_str(st, &AARG(0))); + if (sd == nullptr) + return; + clif_change_music(sd, msg); +} + +static +void builtin_mapmask(ScriptState *st) +{ + dumb_ptr<npc_data> nd; + dumb_ptr<map_session_data> sd; + int map_mask = conv_num(st, &AARG(0)); + + if(st->oid) + nd = map_id_is_npc(st->oid); + if(st->rid) + sd = script_rid2sd(st); + + if(HARG(1) && sd != nullptr) + sd->bl_m->mask = map_mask; + else if(HARG(1) && nd) + nd->bl_m->mask = map_mask; + + if (sd == nullptr) + return; + clif_send_mask(sd, map_mask); +} + +static +void builtin_getmask(ScriptState *st) +{ + dumb_ptr<npc_data> nd; + dumb_ptr<map_session_data> sd; + int map_mask; + + if(st->oid) + nd = map_id_is_npc(st->oid); + if(st->rid) + sd = script_rid2sd(st); + + if(sd != nullptr) + map_mask = sd->bl_m->mask; + else if(nd) + map_mask = nd->bl_m->mask; + else + map_mask = -1; + + push_int<ScriptDataInt>(st->stack, map_mask); +} + /*========================================== * npctalk (sends message to surrounding * area) [Valaris] @@ -2684,13 +2757,24 @@ void builtin_message(ScriptState *st) static void builtin_npctalk(ScriptState *st) { - dumb_ptr<npc_data> nd = map_id_is_npc(st->oid); - RString str = conv_str(st, &AARG(0)); + dumb_ptr<npc_data> nd; + RString str = conv_str(st, &AARG(1)); - if (nd) - { - clif_message(nd, str); + dumb_ptr<npc_data> nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(0))))); + assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); + nd = nd_->is_script(); + + + if(HARG(2)){ + CharName player = stringish<CharName>(ZString(conv_str(st, &AARG(2)))); + dumb_ptr<map_session_data> pl_sd = map_nick2sd(player); + if (pl_sd == nullptr) + return; + clif_message_towards(pl_sd, nd, str); } + + else + clif_message(nd, str); } /*========================================== @@ -3098,6 +3182,7 @@ BuiltinFunction builtin_functions[] = BUILTIN(getnpctimer, "i?"_s, 'i'), BUILTIN(setnpctimer, "i?"_s, '\0'), BUILTIN(setnpcdirection, "iii?"_s, '\0'), + BUILTIN(npcaction, "i???"_s, '\0'), BUILTIN(announce, "si"_s, '\0'), BUILTIN(mapannounce, "Msi"_s, '\0'), BUILTIN(getusers, "i"_s, 'i'), @@ -3144,7 +3229,11 @@ BuiltinFunction builtin_functions[] = BUILTIN(npcwarp, "xys"_s, '\0'), BUILTIN(npcareawarp, "xyxyis"_s, '\0'), BUILTIN(message, "Ps"_s, '\0'), - BUILTIN(npctalk, "s"_s, '\0'), + BUILTIN(npctalk, "ss?"_s, '\0'), + BUILTIN(title, "s"_s, '\0'), + BUILTIN(music, "s"_s, '\0'), + BUILTIN(mapmask, "i?"_s, '\0'), + BUILTIN(getmask, ""_s, 'i'), BUILTIN(getlook, "i"_s, 'i'), BUILTIN(getsavepoint, "i"_s, '.'), BUILTIN(areatimer, "MxyxytE"_s, '\0'), diff --git a/src/mmo/version.hpp b/src/mmo/version.hpp index 6de3a9c..20cb1d9 100644 --- a/src/mmo/version.hpp +++ b/src/mmo/version.hpp @@ -36,6 +36,9 @@ namespace tmwa #define TMWA_SERVER_MAP 0x08 // increase the min version when the protocol is incompatible with old m+ versions +// 1 = latest mana, old manaplus, bots +// 2 = manaplus 1.5.5.9 and above +// 3 = manaplus 1.5.5.23 and above #define MIN_CLIENT_VERSION 1 // TODO now that I generate the protocol, split 'flags' out of the struct diff --git a/src/wire/packets.cpp b/src/wire/packets.cpp index be06283..22a996a 100644 --- a/src/wire/packets.cpp +++ b/src/wire/packets.cpp @@ -76,6 +76,7 @@ void packet_dump(Session *s) if ((i & 15) == 0) FPRINTF(stderr, "%04X "_fmt, i); Byte rfifob_ib; + rfifob_ib.value = 0; packet_fetch(s, i, &rfifob_ib, 1); uint8_t rfifob_i = rfifob_ib.value; FPRINTF(stderr, "%02x "_fmt, rfifob_i); |