summaryrefslogtreecommitdiff
path: root/src/map/npc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/npc.cpp')
-rw-r--r--src/map/npc.cpp338
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