From 1886d63ef5986a3e613b4880dc7ae00636435e0a Mon Sep 17 00:00:00 2001 From: gumi Date: Fri, 12 Apr 2019 12:12:38 -0400 Subject: add gm automod tool --- src/map/clif.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/map/clif.hpp | 1 + src/map/map.hpp | 11 +++++++ src/map/pc.cpp | 33 +++++++++++++++++++ src/map/script-fun.cpp | 4 ++- src/mmo/clif.t.hpp | 1 + 6 files changed, 138 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/map/clif.cpp b/src/map/clif.cpp index a2f3b3a..7d5ff59 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -35,6 +35,8 @@ #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../generic/random.hpp" + #include "../io/cxxstdio.hpp" #include "../io/extract.hpp" #include "../io/write.hpp" @@ -612,6 +614,13 @@ int clif_clearchar(dumb_ptr bl, BeingRemoveWhy type) type == BeingRemoveWhy::DEAD ? SendWho::AREA : SendWho::AREA_WOS); } + if (bl->bl_type == BL::PC) + { + dumb_ptr sd = bl->is_player(); + if (sd->automod == AutoMod::autoblock) + clif_gm_collision(sd, 0); + } + return 0; } @@ -2499,6 +2508,9 @@ void clif_getareachar_pc(dumb_ptr sd, clif_changelook_accessories(sd, dstsd); clif_changelook_accessories(dstsd, sd); + + if (dstsd->automod == AutoMod::autoblock && pc_issit(dstsd)) + clif_update_collision(sd, dstsd->bl_x, dstsd->bl_y, dstsd->bl_x, dstsd->bl_y, dstsd->bl_m->name_, 5); // BlockType::PLAYERWALL } /*========================================== @@ -2759,6 +2771,9 @@ void clif_pcoutsight(dumb_ptr bl, dumb_ptr sd) { clif_clearchar_id(dstsd->bl_id, BeingRemoveWhy::GONE, sd->sess); clif_clearchar_id(sd->bl_id, BeingRemoveWhy::GONE, dstsd->sess); + + if (dstsd->automod == AutoMod::autoblock) + clif_update_collision(sd, dstsd->bl_x, dstsd->bl_y, dstsd->bl_x, dstsd->bl_y, dstsd->bl_m->name_, 0); } break; case BL::NPC: @@ -3369,6 +3384,61 @@ void clif_sitting(Session *, dumb_ptr sd) fixed_8a.damage_type = DamageType::SIT; Buffer buf = create_fpacket<0x008a, 29>(fixed_8a); clif_send(buf, sd, SendWho::AREA); + + if (sd->automod == AutoMod::autoblock) + clif_gm_collision(sd, 5); + + // Prsm-sitting countermeasures + dumb_ptr d_bl = sd->bl_m->blocks.ref(sd->bl_x / BLOCK_SIZE, sd->bl_y / BLOCK_SIZE).normal; + for (; d_bl; d_bl = d_bl->bl_next) + { + if (d_bl->bl_type == BL::PC && d_bl->bl_x == sd->bl_x && d_bl->bl_y == sd->bl_y && d_bl->bl_id != sd->bl_id) + { + dumb_ptr d_sd = d_bl->is_player(); + + switch (d_sd->automod) + { + case AutoMod::autoblock: + // at this point, this should be impossible, so fallback to kill + case AutoMod::autokill: + pc_damage(nullptr, sd, sd->status.hp); + clif_displaymessage(sd->sess, "The holy messenger has given judgement."_s); + // now fallthrough to move + case AutoMod::automove: + { + unsigned short x0 = std::max(0, sd->bl_x - 5), + y0 = std::max(0, sd->bl_y - 5), + x1 = std::min(sd->bl_m->xs, (short)(sd->bl_x + 5)), + y1 = std::min(sd->bl_m->ys, (short)(sd->bl_y + 5)); + unsigned short x = x0, + y = y0; + + for (unsigned short i = 0; i < 1000; i++) + { + x = random_::in(x0, x1); + y = random_::in(y0, y1); + + if (!bool(map_getcell(sd->bl_m, x, y) & MapCell::UNWALKABLE)) + break; + } + pc_setpos(sd, sd->bl_m->name_, x, y, BeingRemoveWhy::WARPED); + + if (sd->status.hp > 0) + { + // we're still sitting + Packet_Fixed<0x008a> fixed_8a_2; + fixed_8a_2.src_id = sd->bl_id; + fixed_8a_2.damage_type = DamageType::SIT; + Buffer buf2 = create_fpacket<0x008a, 29>(fixed_8a_2); + clif_send(buf2, sd, SendWho::SELF); + } + } + break; + case AutoMod::autokick: + clif_GM_kick(d_sd, sd, 1); + } + } + } } static @@ -4075,6 +4145,25 @@ void clif_remote_command(dumb_ptr sd, XString cmd) clif_send(buf, sd, SendWho::SELF, wrap(6)); } +void clif_gm_collision(dumb_ptr sd, int mask) +{ + nullpo_retv(sd); + + VString<15> gat_name = STRPRINTF("%s.gat"_fmt, sd->bl_m->name_); + + Packet_Fixed<0x0231> fixed_231; + fixed_231.x1 = sd->bl_x; + fixed_231.y1 = sd->bl_y; + fixed_231.x2 = sd->bl_x; + fixed_231.y2 = sd->bl_y; + fixed_231.mask = mask; + fixed_231.unused_layer = 0; + fixed_231.map = gat_name; + Buffer buf = create_fpacket<0x0231, 34>(fixed_231); + + clif_send(buf, sd, SendWho::AREA_WOS, wrap(7)); +} + void clif_update_collision(dumb_ptr sd, short x1, short y1, short x2, short y2, MapName map_name, int mask) { diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 1abcfe3..99baea8 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -108,6 +108,7 @@ void clif_npc_send_title(Session *s, BlockId npcid, XString msg); void clif_server_message(dumb_ptr, uint8_t, XString msg); void clif_remote_command(dumb_ptr, XString); void clif_update_collision(dumb_ptr, short, short, short, short, MapName, int); +void clif_gm_collision(dumb_ptr, int); void clif_change_music(dumb_ptr sd, XString music); void clif_npc_action(dumb_ptr, BlockId, short, int, short, short); void clif_send_mask(dumb_ptr, int); diff --git a/src/map/map.hpp b/src/map/map.hpp index 60b3462..eddbfad 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -121,6 +121,15 @@ struct quick_regeneration unsigned char tickdelay; // number of ticks to next update }; +enum class AutoMod +{ + off = 0, + autokill, + automove, + autoblock, + autokick, +}; + struct map_session_data : block_list, SessionData { struct @@ -298,6 +307,8 @@ struct map_session_data : block_list, SessionData unsigned guild:1; } mute; + AutoMod automod; + tick_t flood_rates[0x220]; tick_t packet_flood_reset_due; int packet_flood_in; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 3986113..b9b41d9 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -833,6 +833,8 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->mute.whisper = 0; sd->mute.guild = 0; + sd->automod = AutoMod::off; + for (tick_t& t : sd->flood_rates) t = tick_t(); sd->packet_flood_reset_due = tick_t(); @@ -2414,6 +2416,27 @@ void pc_walk(TimerData *, tick_t tick, BlockId id, unsigned char data) return; } + // Prsm-sitting countermeasures + dumb_ptr d_bl = sd->bl_m->blocks.ref((x + dx) / BLOCK_SIZE, (y + dy) / BLOCK_SIZE).normal; + for (; d_bl; d_bl = d_bl->bl_next) + { + if (d_bl->bl_type == BL::PC && d_bl->bl_x == (x + dx) && d_bl->bl_y == (y + dy)) + { + dumb_ptr d_sd = d_bl->is_player(); + + if (pc_issit(d_sd)) + { + switch (d_sd->automod) + { + case AutoMod::autoblock: + clif_update_collision(sd, x + dx, y + dy, x + dx, y + dy, sd->bl_m->name_, 5); // BlockType::PLAYERWALL + pc_stop_walking(sd, 1); + return; + } + } + } + } + moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE); @@ -3571,6 +3594,9 @@ int pc_readparam(dumb_ptr bl, SP type) case SP::MUTE_GUILD: val = sd ? sd->mute.guild : 0; break; + case SP::AUTOMOD: + val = sd ? (int)sd->automod : 0; + break; } return val; @@ -3816,6 +3842,10 @@ int pc_setparam(dumb_ptr bl, SP type, int val) nullpo_retz(sd); sd->mute.guild = (val == 1); break; + case SP::AUTOMOD: + nullpo_retz(sd); + sd->automod = (AutoMod)val; + break; } return 0; @@ -5205,6 +5235,9 @@ void pc_setstand(dumb_ptr sd) nullpo_retv(sd); sd->state.dead_sit = 0; + + if (sd->automod == AutoMod::autoblock) + clif_gm_collision(sd, 0); } static diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index ab60535..8c90052 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -4637,7 +4637,9 @@ void builtin_getmap(ScriptState *st) else sd = script_rid2sd(st); - nullpo_retv(sd); + if (!sd || !as_raw_pointer(Some(sd->bl_m)) || sd->bl_m == borrow(undefined_gat)) + return; + push_str(st->stack, sd->bl_m->name_); } diff --git a/src/mmo/clif.t.hpp b/src/mmo/clif.t.hpp index 5f07ebd..1d46342 100644 --- a/src/mmo/clif.t.hpp +++ b/src/mmo/clif.t.hpp @@ -480,6 +480,7 @@ enum class SP : uint16_t MUTE_WHISPER = 1083, MUTE_PARTY = 1084, MUTE_GUILD = 1085, + AUTOMOD = 1086, }; constexpr -- cgit v1.2.3-60-g2f50