From 93595818978b50428c311d5ba20f2b8f102b6a4b Mon Sep 17 00:00:00 2001 From: gumi Date: Fri, 23 Aug 2019 14:06:56 -0400 Subject: allow to summon multiple mobs with @summon --- src/map/atcommand.cpp | 84 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 20 deletions(-) (limited to 'src/map/atcommand.cpp') diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index a9774f0..868daa6 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -4523,37 +4523,81 @@ ATCE atcommand_leaves(Session *, dumb_ptr sd, } static -ATCE atcommand_summon(Session *, dumb_ptr sd, +ATCE atcommand_summon(Session *s, dumb_ptr sd, ZString message) { MobName name; Species mob_id; - int x = 0; - int y = 0; - tick_t tick = gettick(); + int number = 0; + int minutes = 0; - if (!extract(message, &name) || !name) + if (!extract(message, record<' ', 1>(&name, &number, &minutes))) return ATCE::USAGE; - if ((mob_id = wrap(static_cast(atoi(name.c_str())))) == Species()) - mob_id = mobdb_searchname(name); + if ((mob_id = mobdb_searchname(name)) == Species()) + mob_id = mobdb_checkid(wrap(atoi(name.c_str()))); + if (mob_id == Species()) return ATCE::EXIST; - x = sd->bl_x + random_::in(-5, 4); - y = sd->bl_y + random_::in(-5, 4); + if (number <= 0) + number = 1; + + if (minutes <= 0) + minutes = 10; + + if (battle_config.atcommand_spawn_quantity_limit >= 1 + && number > battle_config.atcommand_spawn_quantity_limit) + number = battle_config.atcommand_spawn_quantity_limit; + + int count = 0; + int range = (sqrt(number) / 2) * 2 + 5; + + for (int i = 0; i < number; i++) + { + int j = 0; + BlockId k; + + while (j++ < 8 && !k) + { + // try 8 times to spawn the monster (needed for close area) + int mx = sd->bl_x + random_::in(-range / 2, range / 2 ); + int my = sd->bl_y + random_::in(-range / 2, range / 2); + k = mob_once_spawn(sd, MOB_THIS_MAP, mx, my, MobName(), mob_id, 1, NpcEvent()); + } + + if (k) + { + dumb_ptr md = map_id_is_mob(k); + tick_t tick = gettick(); + + md->master_id = sd->bl_id; + md->state.special_mob_ai = 1; + md->mode = get_mob_db(md->mob_class).mode | MobMode::AGGRESSIVE; + md->deletetimer = Timer(tick + (std::max(minutes, 120) * 1_min), + std::bind(mob_timer_delete, ph::_1, ph::_2, + k)); + count++; + } + } - BlockId id = mob_once_spawn(sd, MOB_THIS_MAP, x, y, JAPANESE_NAME, mob_id, 1, NpcEvent()); - dumb_ptr md = map_id_is_mob(id); - if (md) + if (count != 0) { - md->master_id = sd->bl_id; - md->state.special_mob_ai = 1; - md->mode = get_mob_db(md->mob_class).mode | MobMode::AGGRESSIVE; - md->deletetimer = Timer(tick + 1_min, - std::bind(mob_timer_delete, ph::_1, ph::_2, - id)); - clif_misceffect(md, 344); + if (number == count) + { + clif_displaymessage(s, "All monster summoned!"_s); + } + else + { + AString output = STRPRINTF("%d monster(s) summoned!"_fmt, + count); + clif_displaymessage(s, output); + } + } + else + { + clif_displaymessage(s, "Invalid monster ID or name."_s); + return ATCE::EXIST; } return ATCE::OKAY; @@ -5548,7 +5592,7 @@ Map atcommand_info = {"leaves"_s, {""_s, 98, atcommand_leaves, "Enable the leaves mapflag"_s}}, - {"summon"_s, {""_s, + {"summon"_s, {" [count] [minutes]"_s, 50, atcommand_summon, "Summon a slave monster temporarily"_s}}, {"adjgmlvl"_s, {" "_s, -- cgit v1.2.3-60-g2f50