diff options
Diffstat (limited to 'src/map/npc.cpp')
-rw-r--r-- | src/map/npc.cpp | 338 |
1 files changed, 177 insertions, 161 deletions
diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 7fe13f1..a6427d6 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -21,10 +21,9 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. #include <cassert> -#include <cstdlib> -#include <cstring> #include <ctime> +#include <algorithm> #include <list> #include "../compat/fun.hpp" @@ -34,16 +33,20 @@ #include "../strings/astring.hpp" #include "../strings/zstring.hpp" #include "../strings/xstring.hpp" +#include "../strings/literal.hpp" #include "../generic/db.hpp" #include "../io/cxxstdio.hpp" #include "../io/read.hpp" +#include "../net/timer.hpp" + #include "../mmo/config_parse.hpp" #include "../mmo/extract.hpp" -#include "../mmo/socket.hpp" -#include "../mmo/timer.hpp" +#include "../mmo/utils.hpp" + +#include "../proto2/map-user.hpp" #include "battle.hpp" #include "clif.hpp" @@ -56,17 +59,22 @@ #include "../poison.hpp" + +namespace tmwa +{ static std::list<AString> npc_srcs; static -int npc_id = START_NPC_NUM; +BlockId npc_id = START_NPC_NUM; static int npc_warp, npc_shop, npc_script, npc_mob; -int npc_get_new_npc_id(void) +BlockId npc_get_new_npc_id(void) { - return npc_id++; + BlockId rv = npc_id; + npc_id = next(npc_id); + return rv; } struct event_data @@ -107,7 +115,7 @@ void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd) NpcEvent aname; aname.npc = nd->name; - aname.label = stringish<ScriptLabel>("OnTouch"); + aname.label = stringish<ScriptLabel>("OnTouch"_s); if (sd->areanpc_id == nd->bl_id) return; sd->areanpc_id = nd->bl_id; @@ -118,9 +126,9 @@ void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd) int npc_enable(NpcName name, bool flag) { dumb_ptr<npc_data> nd = npc_name2id(name); - if (nd == NULL) + if (nd == nullptr) { - PRINTF("npc_enable(%s, %s) failed.\n", name, flag ? "true" : "false"); + PRINTF("npc_enable(%s, %s) failed.\n"_fmt, name, flag ? "true"_s : "false"_s); return 0; } @@ -167,15 +175,15 @@ dumb_ptr<npc_data> npc_name2id(NpcName name) */ int npc_event_dequeue(dumb_ptr<map_session_data> sd) { - nullpo_ret(sd); + nullpo_retz(sd); - sd->npc_id = 0; + sd->npc_id = BlockId(); if (!sd->eventqueuel.empty()) { - if (!pc_addeventtimer(sd, std::chrono::milliseconds(100), sd->eventqueuel.front())) + if (!pc_addeventtimer(sd, 100_ms, sd->eventqueuel.front())) { - PRINTF("npc_event_dequeue(): Event timer is full.\n"); + PRINTF("npc_event_dequeue(): Event timer is full.\n"_fmt); return 0; } @@ -190,7 +198,7 @@ int npc_delete(dumb_ptr<npc_data> nd) { nullpo_retr(1, nd); - if (nd->bl_prev == NULL) + if (nd->bl_prev == nullptr) return 1; clif_clearchar(nd, BeingRemoveWhy::DEAD); @@ -204,9 +212,9 @@ void npc_timer_event(NpcEvent eventname) dumb_ptr<npc_data_script> nd; // int xs,ys; - if ((ev == NULL || (nd = ev->nd) == NULL)) + if ((ev == nullptr || (nd = ev->nd) == nullptr)) { - PRINTF("npc_event: event not found [%s]\n", + PRINTF("npc_event: event not found [%s]\n"_fmt, eventname); return; } @@ -220,7 +228,7 @@ void npc_timer_event(NpcEvent eventname) */ static void npc_event_doall_sub(NpcEvent key, struct event_data *ev, - int *c, ScriptLabel name, int rid, Slice<argrec_t> argv) + int *c, ScriptLabel name, BlockId rid, Slice<argrec_t> argv) { ScriptLabel p = key.label; @@ -234,7 +242,7 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev, } } -int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args) +int npc_event_doall_l(ScriptLabel name, BlockId rid, Slice<argrec_t> args) { int c = 0; @@ -245,7 +253,7 @@ int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args) static void npc_event_do_sub(NpcEvent key, struct event_data *ev, - int *c, NpcEvent name, int rid, Slice<argrec_t> argv) + int *c, NpcEvent name, BlockId rid, Slice<argrec_t> argv) { nullpo_retv(ev); @@ -257,7 +265,7 @@ void npc_event_do_sub(NpcEvent key, struct event_data *ev, } } -int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> args) +int npc_event_do_l(NpcEvent name, BlockId rid, Slice<argrec_t> args) { int c = 0; @@ -283,19 +291,19 @@ void npc_event_do_clock(TimerData *, tick_t) ScriptLabel buf; if (t.tm_min != ev_tm_b.tm_min) { - SNPRINTF(buf, 24, "OnMinute%02d", t.tm_min); + SNPRINTF(buf, 24, "OnMinute%02d"_fmt, t.tm_min); npc_event_doall(buf); - SNPRINTF(buf, 24, "OnClock%02d%02d", t.tm_hour, t.tm_min); + SNPRINTF(buf, 24, "OnClock%02d%02d"_fmt, t.tm_hour, t.tm_min); npc_event_doall(buf); } if (t.tm_hour != ev_tm_b.tm_hour) { - SNPRINTF(buf, 24, "OnHour%02d", t.tm_hour); + SNPRINTF(buf, 24, "OnHour%02d"_fmt, t.tm_hour); npc_event_doall(buf); } if (t.tm_mday != ev_tm_b.tm_mday) { - SNPRINTF(buf, 24, "OnDay%02d%02d", t.tm_mon + 1, t.tm_mday); + SNPRINTF(buf, 24, "OnDay%02d%02d"_fmt, t.tm_mon + 1, t.tm_mday); npc_event_doall(buf); } ev_tm_b = t; @@ -307,12 +315,12 @@ void npc_event_do_clock(TimerData *, tick_t) */ int npc_event_do_oninit(void) { - int c = npc_event_doall(stringish<ScriptLabel>("OnInit")); - PRINTF("npc: OnInit Event done. (%d npc)\n", c); + int c = npc_event_doall(stringish<ScriptLabel>("OnInit"_s)); + PRINTF("npc: OnInit Event done. (%d npc)\n"_fmt, c); - Timer(gettick() + std::chrono::milliseconds(100), + Timer(gettick() + 100_ms, npc_event_do_clock, - std::chrono::seconds(1) + 1_s ).detach(); return 0; @@ -322,10 +330,10 @@ int npc_event_do_oninit(void) /// This will be called later if you call npc_timerevent_start. /// This function may only expire, but not deactivate, the counter. static -void npc_timerevent(TimerData *, tick_t tick, int id, interval_t data) +void npc_timerevent(TimerData *, tick_t tick, BlockId id, interval_t data) { dumb_ptr<npc_data_script> nd = map_id2bl(id)->is_npc()->is_script(); - assert (nd != NULL); + assert (nd != nullptr); assert (nd->npc_subtype == NpcSubtype::SCRIPT); assert (nd->scr.next_event != nd->scr.timer_eventv.end()); @@ -345,7 +353,7 @@ void npc_timerevent(TimerData *, tick_t tick, int id, interval_t data) id, next)); } - run_script(ScriptPointer(nd->scr.script.get(), te->pos), 0, nd->bl_id); + run_script(ScriptPointer(nd->scr.script.get(), te->pos), BlockId(), nd->bl_id); } /// Start (or resume) counting ticks to the next npc_timerevent. @@ -461,15 +469,15 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, dumb_ptr<npc_data_script> nd; int xs, ys; - if (sd == NULL) + if (sd == nullptr) { - PRINTF("npc_event nullpo?\n"); + PRINTF("npc_event nullpo?\n"_fmt); } - if (ev == NULL && eventname.label == stringish<ScriptLabel>("OnTouch")) + if (ev == nullptr && eventname.label == stringish<ScriptLabel>("OnTouch"_s)) return 1; - if (ev == NULL || (nd = ev->nd) == NULL) + if (ev == nullptr || (nd = ev->nd) == nullptr) { if (mob_kill) { @@ -480,7 +488,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, else { if (battle_config.error_log) - PRINTF("npc_event: event not found [%s]\n", + PRINTF("npc_event: event not found [%s]\n"_fmt, eventname); return 0; } @@ -500,7 +508,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, return 1; } - if (sd->npc_id != 0) + if (sd->npc_id) { sd->eventqueuel.push_back(eventname); return 1; @@ -521,12 +529,12 @@ static void npc_command_sub(NpcEvent key, struct event_data *ev, NpcName npcname, XString command) { if (ev->nd->name == npcname - && key.label.startswith("OnCommand")) + && key.label.startswith("OnCommand"_s)) { XString temp = key.label.xslice_t(9); if (command == temp) - run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), 0, ev->nd->bl_id); + run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), BlockId(), ev->nd->bl_id); } } @@ -567,7 +575,7 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) ys = m->npc[i]->is_warp()->warp.ys; break; case NpcSubtype::MESSAGE: - assert (0 && "I'm pretty sure these are never put on a map"); + assert (0 && "I'm pretty sure these are never put on a map"_s); xs = 0; ys = 0; break; @@ -589,7 +597,7 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) if (f) { if (battle_config.error_log) - PRINTF("npc_touch_areanpc : some bug \n"); + PRINTF("npc_touch_areanpc : some bug \n"_fmt); } return 1; } @@ -601,13 +609,13 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) m->npc[i]->is_warp()->warp.x, m->npc[i]->is_warp()->warp.y, BeingRemoveWhy::GONE); break; case NpcSubtype::MESSAGE: - assert (0 && "I'm pretty sure these NPCs are never put on a map."); + assert (0 && "I'm pretty sure these NPCs are never put on a map."_s); break; case NpcSubtype::SCRIPT: { NpcEvent aname; aname.npc = m->npc[i]->name; - aname.label = stringish<ScriptLabel>("OnTouch"); + aname.label = stringish<ScriptLabel>("OnTouch"_s); if (sd->areanpc_id == m->npc[i]->bl_id) return 1; @@ -626,20 +634,20 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) *------------------------------------------ */ static -int npc_checknear(dumb_ptr<map_session_data> sd, int id) +int npc_checknear(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; - nullpo_ret(sd); + nullpo_retz(sd); nd = map_id_is_npc(id); // this actually happens - if (nd == NULL) + if (nd == nullptr) return 1; if (nd->bl_type != BL::NPC) return 1; - if (nd->npc_class < 0) // イベント系は常にOK + if (nd->npc_class == NEGATIVE_SPECIES) return 0; // エリア判定 @@ -657,16 +665,16 @@ int npc_checknear(dumb_ptr<map_session_data> sd, int id) * クリック時のNPC処理 *------------------------------------------ */ -int npc_click(dumb_ptr<map_session_data> sd, int id) +int npc_click(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; nullpo_retr(1, sd); - if (sd->npc_id != 0) + if (sd->npc_id) { if (battle_config.error_log) - PRINTF("npc_click: npc_id != 0\n"); + PRINTF("npc_click: npc_id != 0\n"_fmt); return 1; } @@ -706,7 +714,7 @@ int npc_click(dumb_ptr<map_session_data> sd, int id) * *------------------------------------------ */ -int npc_scriptcont(dumb_ptr<map_session_data> sd, int id) +int npc_scriptcont(dumb_ptr<map_session_data> sd, BlockId id) { dumb_ptr<npc_data> nd; @@ -738,7 +746,7 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, int id) * *------------------------------------------ */ -int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) +int npc_buysellsel(dumb_ptr<map_session_data> sd, BlockId id, int type) { dumb_ptr<npc_data> nd; @@ -751,8 +759,8 @@ int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) if (nd->npc_subtype != NpcSubtype::SHOP) { if (battle_config.error_log) - PRINTF("no such shop npc : %d\n", id); - sd->npc_id = 0; + PRINTF("no such shop npc : %d\n"_fmt, id); + sd->npc_id = BlockId(); return 1; } if (nd->flag & 1) // 無効化されている @@ -775,15 +783,14 @@ int npc_buysellsel(dumb_ptr<map_session_data> sd, int id, int type) *------------------------------------------ */ // TODO enumify return type -int npc_buylist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_buylist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c8>>& item_list) { dumb_ptr<npc_data> nd; double z; int i, j, w, itemamount = 0, new_stacks = 0; nullpo_retr(3, sd); - nullpo_retr(3, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 3; @@ -792,26 +799,29 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, if (nd->npc_subtype != NpcSubtype::SHOP) return 3; - for (i = 0, w = 0, z = 0; i < n; i++) + for (i = 0, w = 0, z = 0; i < item_list.size(); i++) { + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; + for (j = 0; j < nd->is_shop()->shop_items.size(); j++) { - if (nd->is_shop()->shop_items[j].nameid == item_list[i * 2 + 1]) + if (nd->is_shop()->shop_items[j].nameid == item_l_id) break; } if (j == nd->is_shop()->shop_items.size()) return 3; - z += static_cast<double>(nd->is_shop()->shop_items[j].value) * item_list[i * 2]; - itemamount += item_list[i * 2]; + z += static_cast<double>(nd->is_shop()->shop_items[j].value) * item_l_count; + itemamount += item_l_count; - switch (pc_checkadditem(sd, item_list[i * 2 + 1], item_list[i * 2])) + switch (pc_checkadditem(sd, item_l_id, item_l_count)) { case ADDITEM::EXIST: break; case ADDITEM::NEW: - if (itemdb_isequip(item_list[i * 2 + 1])) - new_stacks += item_list[i * 2]; + if (itemdb_isequip(item_l_id)) + new_stacks += item_l_count; else new_stacks++; break; @@ -819,7 +829,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, return 2; } - w += itemdb_weight(item_list[i * 2 + 1]) * item_list[i * 2]; + w += itemdb_weight(item_l_id) * item_l_count; } if (z > static_cast<double>(sd->status.zeny)) @@ -828,18 +838,21 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, return 2; // 重量超過 if (pc_inventoryblank(sd) < new_stacks) return 3; // 種類数超過 - if (sd->trade_partner != 0) + if (sd->trade_partner) return 4; // cant buy while trading pc_payzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { + const uint16_t& item_l_count = item_list[i].count; + const ItemNameId& item_l_id = item_list[i].name_id; + struct item_data *item_data; - if ((item_data = itemdb_exists(item_list[i * 2 + 1])) != NULL) + if ((item_data = itemdb_exists(item_l_id)) != nullptr) { - int amount = item_list[i * 2]; - struct item item_tmp {}; + int amount = item_l_count; + Item item_tmp {}; item_tmp.nameid = item_data->nameid; @@ -868,39 +881,37 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, * *------------------------------------------ */ -int npc_selllist(dumb_ptr<map_session_data> sd, int n, - const uint16_t *item_list) +int npc_selllist(dumb_ptr<map_session_data> sd, + const std::vector<Packet_Repeat<0x00c9>>& item_list) { double z; int i, itemamount = 0; nullpo_retr(1, sd); - nullpo_retr(1, item_list); if (npc_checknear(sd, sd->npc_shopid)) return 1; - for (i = 0, z = 0; i < n; i++) + for (i = 0, z = 0; i < item_list.size(); i++) { - int nameid; - if (item_list[i * 2] - 2 < 0 || item_list[i * 2] - 2 >= MAX_INVENTORY) + if (!item_list[i].ioff2.ok()) return 1; - nameid = sd->status.inventory[item_list[i * 2] - 2].nameid; - if (nameid == 0 || - sd->status.inventory[item_list[i * 2] - 2].amount < item_list[i * 2 + 1]) + ItemNameId nameid = sd->status.inventory[item_list[i].ioff2.unshift()].nameid; + if (!nameid || + sd->status.inventory[item_list[i].ioff2.unshift()].amount < item_list[i].count) return 1; - if (sd->trade_partner != 0) + if (sd->trade_partner) return 2; // cant sell while trading - z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i * 2 + 1]; - itemamount += item_list[i * 2 + 1]; + z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i].count; + itemamount += item_list[i].count; } if (z > MAX_ZENY) z = MAX_ZENY; pc_getzeny(sd, static_cast<int>(z)); - for (i = 0; i < n; i++) + for (i = 0; i < item_list.size(); i++) { - int item_id = item_list[i * 2] - 2; - pc_delitem(sd, item_id, item_list[i * 2 + 1], 0); + IOff0 item_id = item_list[i].ioff2.unshift(); + pc_delitem(sd, item_id, item_list[i].count, 0); } return 0; @@ -927,7 +938,7 @@ void npc_clearsrcfile(void) */ void npc_addsrcfile(AString name) { - if (name == "clear") + if (name == "clear"_s) { npc_clearsrcfile(); return; @@ -942,7 +953,7 @@ void npc_addsrcfile(AString name) */ void npc_delsrcfile(XString name) { - if (name == "all") + if (name == "all"_s) { npc_clearsrcfile(); return; @@ -961,19 +972,19 @@ void npc_delsrcfile(XString name) static void register_npc_name(dumb_ptr<npc_data> nd) { - ZString types[4] = - { - {"WARP"}, - {"SHOP"}, - {"SCRIPT"}, - {"MESSAGE"}, - }; + earray<LString, NpcSubtype, NpcSubtype::COUNT> types //= + {{ + "WARP"_s, + "SHOP"_s, + "SCRIPT"_s, + "MESSAGE"_s, + }}; if (!nd->name) { if (nd->npc_subtype == NpcSubtype::MESSAGE) return; - PRINTF("WARNING: npc with no name:\n%s @ %s,%d,%d\n", - types[static_cast<int>(nd->npc_subtype)], + PRINTF("WARNING: npc with no name:\n%s @ %s,%d,%d\n"_fmt, + types[nd->npc_subtype], nd->bl_m->name_, nd->bl_x, nd->bl_y); return; } @@ -982,12 +993,12 @@ void register_npc_name(dumb_ptr<npc_data> nd) if (nd->npc_subtype != NpcSubtype::WARP || nd_old->npc_subtype != NpcSubtype::WARP) { - PRINTF("WARNING: replacing npc with name: %s\n", nd->name); - PRINTF("old: %s @ %s,%d,%d\n", - types[static_cast<int>(nd_old->npc_subtype)], + PRINTF("WARNING: replacing npc with name: %s\n"_fmt, nd->name); + PRINTF("old: %s @ %s,%d,%d\n"_fmt, + types[nd_old->npc_subtype], nd_old->bl_m->name_, nd_old->bl_x, nd_old->bl_y); - PRINTF("new: %s @ %s,%d,%d\n", - types[static_cast<int>(nd->npc_subtype)], + PRINTF("new: %s @ %s,%d,%d\n"_fmt, + types[nd->npc_subtype], nd->bl_m->name_, nd->bl_x, nd->bl_y); } } @@ -1009,7 +1020,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) if (!extract(w1, record<','>(&mapname, &x, &y)) || !extract(w4, record<','>(&xs, &ys, &to_mapname, &to_x, &to_y))) { - PRINTF("bad warp line : %s\n", w3); + PRINTF("bad warp line : %s\n"_fmt, w3); return 1; } @@ -1019,7 +1030,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) nd->bl_id = npc_get_new_npc_id(); nd->n = map_addnpc(m, nd); - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1031,7 +1042,7 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) nd->npc_class = WARP_CLASS; else nd->npc_class = WARP_DEBUG_CLASS; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; @@ -1059,7 +1070,6 @@ int npc_parse_warp(XString w1, XString, NpcName w3, XString w4) } } -// PRINTF("warp npc %s %d read done\n",mapname,nd->bl_id); npc_warp++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::WARP; @@ -1077,11 +1087,11 @@ bool extract(XString xs, npc_item_list *itv) if (!extract(xs, record<':'>(&name_or_id, &itv->value))) return false; struct item_data *id = nullptr; - if (extract(name_or_id, &itv->nameid) && itv->nameid > 0) + if (extract(name_or_id, &itv->nameid) && itv->nameid) goto return_true; id = itemdb_searchname(name_or_id.rstrip()); - if (id == NULL) + if (id == nullptr) return false; itv->nameid = id->nameid; goto return_true; @@ -1089,7 +1099,7 @@ bool extract(XString xs, npc_item_list *itv) return_true: if (itv->value < 0) { - if (id == NULL) + if (id == nullptr) id = itemdb_search(itv->nameid); itv->value = id->value_buy * abs(itv->value); } @@ -1108,7 +1118,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) MapName mapname; dumb_ptr<npc_data_shop> nd; ZString::iterator w4comma; - int npc_class; + Species npc_class; int dir_; // TODO use enum directly in extract if (!extract(w1, record<','>(&mapname, &x, &y, &dir_)) @@ -1116,7 +1126,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) || (w4comma = std::find(w4a.begin(), w4a.end(), ',')) == w4a.end() || !extract(w4a.xislice_h(w4comma), &npc_class)) { - PRINTF("bad shop line : %s\n", w3); + PRINTF("bad shop line : %s\n"_fmt, w3); return 1; } dir = static_cast<DIR>(dir_); @@ -1127,8 +1137,8 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) if (!extract(w4b, vrec<','>(&nd->shop_items))) { - PRINTF("bad shop items : %s\n", w3); - PRINTF(" somewhere --> %s\n", w4b); + PRINTF("bad shop items : %s\n"_fmt, w3); + PRINTF(" somewhere --> %s\n"_fmt, w4b); nd->shop_items.clear(); } @@ -1138,7 +1148,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) return 1; } - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1147,7 +1157,7 @@ int npc_parse_shop(XString w1, XString, NpcName w3, ZString w4a) nd->flag = 0; nd->name = w3; nd->npc_class = npc_class; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; @@ -1190,13 +1200,14 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int x, y; DIR dir = DIR::S; map_local *m; - int xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov + int xs = 0, ys = 0; // [Valaris] thanks to fov + Species npc_class; MapName mapname; - std::unique_ptr<const ScriptBuffer> script = NULL; + std::unique_ptr<const ScriptBuffer> script = nullptr; dumb_ptr<npc_data_script> nd; int evflag = 0; - if (w1 == "-") + if (w1 == "-"_s) { x = 0; y = 0; @@ -1207,16 +1218,16 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int dir_; // TODO use enum directly in extract if (!extract(w1, record<','>(&mapname, &x, &y, &dir_)) || dir_ < 0 || dir_ >= 8 - || (w2 == "script" && !w4.contains(','))) + || (w2 == "script"_s && !w4.contains(','))) { - PRINTF("bad script line : %s\n", w3); + PRINTF("bad script line : %s\n"_fmt, w3); return 1; } dir = static_cast<DIR>(dir_); m = map_mapname2mapid(mapname); } - if (w2 == "script") + if (w2 == "script"_s) { // may be empty MString srcbuf; @@ -1249,13 +1260,13 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, srcbuf += '\n'; } script = parse_script(AString(srcbuf), startline, false); - if (script == NULL) + if (script == nullptr) // script parse error? return 1; } else { - assert(0 && "duplicate() is no longer supported!\n"); + assert(0 && "duplicate() is no longer supported!\n"_s); return 0; } @@ -1271,7 +1282,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, if (ys >= 0) ys = ys * 2 + 1; - if (npc_class >= 0) + if (npc_class != NEGATIVE_SPECIES) { for (int i = 0; i < ys; i++) @@ -1295,26 +1306,31 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, } else { - npc_class = atoi(w4.c_str()); + XString w4x = w4; + if (w4x.endswith(',')) + w4x = w4x.xrslice_h(1); + if (!extract(w4x, &npc_class)) + abort(); nd->scr.xs = 0; nd->scr.ys = 0; } - if (npc_class < 0 && m != nullptr) + if (npc_class == NEGATIVE_SPECIES && m != nullptr) { evflag = 1; } if (w3.contains(':')) { - assert(false && "feature removed"); + assert(false && "feature removed"_s); abort(); } + { nd->name = w3; } - nd->bl_prev = nd->bl_next = NULL; + nd->bl_prev = nd->bl_next = nullptr; nd->bl_m = m; nd->bl_x = x; nd->bl_y = y; @@ -1322,14 +1338,13 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, nd->dir = dir; nd->flag = 0; nd->npc_class = npc_class; - nd->speed = std::chrono::milliseconds(200); + nd->speed = 200_ms; nd->scr.script = std::move(script); nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; nd->opt3 = Opt3::ZERO; - //PRINTF("script npc %s %d %d read done\n",mapname,nd->bl_id,nd->class); npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; @@ -1361,7 +1376,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, ScriptLabel lname = el.name; int pos = el.pos; - if (lname.startswith("On")) + if (lname.startswith("On"_s)) { struct event_data ev {}; ev.nd = nd; @@ -1380,7 +1395,7 @@ int npc_parse_script(XString w1, XString w2, NpcName w3, ZString w4, int t_ = 0; ScriptLabel lname = el.name; int pos = el.pos; - if (lname.startswith("OnTimer") && extract(lname.xslice_t(7), &t_) && t_ > 0) + if (lname.startswith("OnTimer"_s) && extract(lname.xslice_t(7), &t_) && t_ > 0) { interval_t t = static_cast<interval_t>(t_); @@ -1440,7 +1455,7 @@ int npc_parse_function(XString, XString, XString w3, ZString, srcbuf += '\n'; } std::unique_ptr<const ScriptBuffer> script = parse_script(AString(srcbuf), startline, false); - if (script == NULL) + if (script == nullptr) { // script parse error? return 1; @@ -1458,7 +1473,8 @@ int npc_parse_function(XString, XString, XString w3, ZString, static int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) { - int x, y, xs, ys, mob_class, num; + int x, y, xs, ys, num; + Species mob_class; int i; MapName mapname; NpcEvent eventname; @@ -1469,7 +1485,7 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) if (!extract(w1, record<',', 3>(&mapname, &x, &y, &xs, &ys)) || !extract(w4, record<',', 2>(&mob_class, &num, &delay1_, &delay2_, &eventname))) { - PRINTF("bad monster line : %s\n", w3); + PRINTF("bad monster line : %s\n"_fmt, w3); return 1; } interval_t delay1 = std::chrono::milliseconds(delay1_); @@ -1487,15 +1503,15 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) { md.new_(); - md->bl_prev = NULL; - md->bl_next = NULL; + md->bl_prev = nullptr; + md->bl_next = nullptr; md->bl_m = m; md->bl_x = x; md->bl_y = y; if (w3 == ENGLISH_NAME) - md->name = mob_db[mob_class].name; + md->name = get_mob_db(mob_class).name; else if (w3 == JAPANESE_NAME) - md->name = mob_db[mob_class].jname; + md->name = get_mob_db(mob_class).jname; else md->name = w3; @@ -1512,8 +1528,8 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) really_memzero_this(&md->state); // md->timer = nullptr; - md->target_id = 0; - md->attacked_id = 0; + md->target_id = BlockId(); + md->attacked_id = BlockId(); md->lootitemv.clear(); @@ -1525,7 +1541,6 @@ int npc_parse_mob(XString w1, XString, MobName w3, ZString w4) npc_mob++; } - //PRINTF("warp npc %s %d read done\n",mapname,nd->bl_id); return 0; } @@ -1561,9 +1576,9 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) if (mf == MapFlag::NOSAVE) { - if (w4 == "SavePoint") + if (w4 == "SavePoint"_s) { - m->save.map_ = stringish<MapName>("SavePoint"); + m->save.map_ = stringish<MapName>("SavePoint"_s); m->save.x = -1; m->save.y = -1; } @@ -1589,7 +1604,7 @@ int npc_parse_mapflag(XString w1, XString, XString w3, ZString w4) } dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, - int npc_class, NpcName name, AString message) + Species npc_class, NpcName name, AString message) { dumb_ptr<npc_data_message> retval; retval.new_(); @@ -1605,7 +1620,7 @@ dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, retval->message = message; retval->npc_class = npc_class; - retval->speed = std::chrono::milliseconds(200); + retval->speed = 200_ms; clif_spawnnpc(retval); map_addblock(retval); @@ -1679,11 +1694,11 @@ bool do_init_npc(void) io::ReadFile fp(nsl); if (!fp.is_open()) { - PRINTF("file not found : %s\n", nsl); + PRINTF("file not found : %s\n"_fmt, nsl); rv = false; continue; } - PRINTF("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM, + PRINTF("\rLoading NPCs [%d]: %-54s"_fmt, unwrap<BlockId>(npc_id) - unwrap<BlockId>(START_NPC_NUM), nsl); int lines = 0; AString zline; @@ -1698,7 +1713,7 @@ bool do_init_npc(void) if (!extract(zline, record<'|', 3>(&w1, &w2, &w3, &w4x)) || !w1 || !w2 || !w3) { - FPRINTF(stderr, "%s:%d: Broken script line: %s\n", nsl, lines, zline); + FPRINTF(stderr, "%s:%d: Broken script line: %s\n"_fmt, nsl, lines, zline); rv = false; continue; } @@ -1708,7 +1723,7 @@ bool do_init_npc(void) } assert(bool(w4x) == bool(w4z)); - if (w1 != "-" && w1 != "function") + if (w1 != "-"_s && w1 != "function"_s) { auto comma = std::find(w1.begin(), w1.end(), ','); MapName mapname = stringish<MapName>(w1.xislice_h(comma)); @@ -1716,24 +1731,24 @@ bool do_init_npc(void) if (m == nullptr) { // "mapname" is not assigned to this server - FPRINTF(stderr, "%s:%d: Map not found: %s\n", nsl, lines, mapname); + FPRINTF(stderr, "%s:%d: Map not found: %s\n"_fmt, nsl, lines, mapname); rv = false; continue; } } - if (w2 == "warp") + if (w2 == "warp"_s) { NpcName npcname = stringish<NpcName>(w3); npc_parse_warp(w1, w2, npcname, w4z); } - else if (w2 == "shop") + else if (w2 == "shop"_s) { NpcName npcname = stringish<NpcName>(w3); npc_parse_shop(w1, w2, npcname, w4z); } - else if (w2 == "script") + else if (w2 == "script"_s) { - if (w1 == "function") + if (w1 == "function"_s) { npc_parse_function(w1, w2, w3, w4z, w4x, fp, &lines); @@ -1745,30 +1760,31 @@ bool do_init_npc(void) w4x, fp, &lines); } } - else if (w2 == "monster") + else if (w2 == "monster"_s) { MobName mobname = stringish<MobName>(w3); npc_parse_mob(w1, w2, mobname, w4z); } - else if (w2 == "mapflag") + else if (w2 == "mapflag"_s) { npc_parse_mapflag(w1, w2, w3, w4z); } else { - PRINTF("odd script line: %s\n", zline); + PRINTF("odd script line: %s\n"_fmt, zline); script_errors++; } } fflush(stdout); } - PRINTF("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d] %20s\n", - npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, ""); + PRINTF("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d] %20s\n"_fmt, + unwrap<BlockId>(npc_id) - unwrap<BlockId>(START_NPC_NUM), npc_warp, npc_shop, npc_script, npc_mob, ""_s); if (script_errors) { - PRINTF("Cowardly refusing to continue after %d errors\n", script_errors); + PRINTF("Cowardly refusing to continue after %d errors\n"_fmt, script_errors); rv = false; } return rv; } +} // namespace tmwa |