summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/battle.cpp2
-rw-r--r--src/map/clif.cpp6
-rw-r--r--src/map/fwd.hpp1
-rw-r--r--src/map/map.hpp1
-rw-r--r--src/map/map.t.hpp1
-rw-r--r--src/map/mob.cpp13
-rw-r--r--src/map/npc.cpp47
-rw-r--r--src/map/pc.cpp19
-rw-r--r--src/map/script-call.cpp20
-rw-r--r--src/map/script-fun.cpp202
-rw-r--r--src/map/script-parse.cpp1
11 files changed, 209 insertions, 104 deletions
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 554ef14..031b79d 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -85,6 +85,8 @@ Species battle_get_class(dumb_ptr<block_list> bl)
nullpo_retr(Species(), bl);
if (bl->bl_type == BL::MOB)
return bl->is_mob()->mob_class;
+ else if (bl->bl_type == BL::NPC)
+ return bl->is_npc()->npc_class;
else if (bl->bl_type == BL::PC)
return bl->is_player()->status.species;
else
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 4cf1de2..ea11bbf 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -2550,7 +2550,9 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst,
nullpo_retz(src);
nullpo_retz(dst);
- sc_data = battle_get_sc_data(dst);
+ int target_hp = battle_get_hp(dst);
+ if (target_hp < damage)
+ damage = target_hp; // limit damage to hp
Packet_Fixed<0x008a> fixed_8a;
fixed_8a.src_id = src->bl_id;
@@ -4423,6 +4425,8 @@ RecvResult clif_parse_NpcClicked(Session *s, dumb_ptr<map_session_data> sd)
}
if (sd->npc_id)
return rv;
+ if (battle_get_class(map_id2bl(fixed.block_id)) == INVISIBLE_CLASS)
+ return rv;
npc_click(sd, fixed.block_id);
return rv;
diff --git a/src/map/fwd.hpp b/src/map/fwd.hpp
index de65216..74e0ccf 100644
--- a/src/map/fwd.hpp
+++ b/src/map/fwd.hpp
@@ -61,7 +61,6 @@ struct map_local;
class npc_data_script;
class npc_data_shop;
class npc_data_warp;
-class npc_data_message;
struct item_data;
struct quest_data;
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 2919d04..25fdba5 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -332,7 +332,6 @@ struct npc_data : block_list
Opt3 opt3;
Opt0 option;
short flag;
- bool disposable;
std::list<RString> eventqueuel;
Array<Timer, MAX_EVENTTIMER> eventtimer;
diff --git a/src/map/map.t.hpp b/src/map/map.t.hpp
index ea7ead5..d685c01 100644
--- a/src/map/map.t.hpp
+++ b/src/map/map.t.hpp
@@ -49,7 +49,6 @@ enum class NpcSubtype : uint8_t
WARP,
SHOP,
SCRIPT,
- MESSAGE,
COUNT,
};
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 1be40f0..0da946a 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -2701,7 +2701,6 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
} // [MouseJstr]
// SCRIPT実行
- if (md->npc_event)
{
if (sd == nullptr)
{
@@ -2711,7 +2710,17 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
}
}
if (sd)
- npc_event(sd, md->npc_event, 0);
+ {
+ if (md->npc_event)
+ npc_event(sd, md->npc_event, 0);
+
+ // TODO: in the future, OnPCKillEvent, OnMobKillEvent and OnPCDieEvent should be combined
+ argrec_t arg[1] =
+ {
+ {"@mobID"_s, static_cast<int32_t>(unwrap<Species>(md->mob_class))},
+ };
+ npc_event_doall_l(stringish<ScriptLabel>("OnMobKillEvent"_s), sd->bl_id, arg);
+ }
}
clif_clearchar(md, BeingRemoveWhy::DEAD);
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index a8c90d8..5b0ee7b 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -202,23 +202,23 @@ int magic_message(dumb_ptr<map_session_data> caster, XString source_invocation)
auto pair = magic_tokenise(source_invocation);
// Spell Cast
NpcEvent spell_event = spell_event2id(pair.first);
- PRINTF("Cast: %s\n"_fmt, RString(pair.first));
RString spell_params = pair.second;
- dumb_ptr<npc_data> nd = npc_name2id(spell_event.npc);
-
- if (nd)
+ if (spell_event.npc)
{
- PRINTF("NPC: '%s' %d\n"_fmt, nd->name, nd->bl_id);
- PRINTF("Params: '%s'\n"_fmt, spell_params);
- argrec_t arg[1] =
+ dumb_ptr<npc_data> nd = npc_name2id(spell_event.npc);
+
+ if (nd)
{
- {"@args$"_s, spell_params},
- };
+ argrec_t arg[1] =
+ {
+ {"@args$"_s, spell_params},
+ };
- npc_event(caster, spell_event, 0, arg);
- return 1;
+ npc_event(caster, spell_event, 0, arg);
+ return 1;
+ }
}
return 0;
}
@@ -274,7 +274,7 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev,
if (name == p)
{
- if (ev->nd->disposable)
+ if (ev->nd->scr.parent != BlockId())
return; // temporary npcs only respond to commands directly issued to them
run_script_l(ScriptPointer(script_or_parent(ev->nd), ev->pos), rid, ev->nd->bl_id,
argv);
@@ -647,7 +647,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname,
*/
int npc_touch_areanpc(dumb_ptr<map_session_data> sd, Borrowed<map_local> m, int x, int y)
{
- int i, f = 1;
+ int i;
int xs, ys;
nullpo_retr(1, sd);
@@ -658,10 +658,7 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, Borrowed<map_local> m, int
for (i = 0; i < m->npc_num; i++)
{
if (m->npc[i]->flag & 1)
- { // 無効化されている
- f = 0;
continue;
- }
switch (m->npc[i]->npc_subtype)
{
@@ -684,11 +681,6 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, Borrowed<map_local> m, int
}
if (i == m->npc_num)
{
- if (f)
- {
- if (battle_config.error_log)
- PRINTF("npc_touch_areanpc : some bug \n"_fmt);
- }
return 1;
}
switch (m->npc[i]->npc_subtype)
@@ -1005,6 +997,19 @@ void npc_free_internal(dumb_ptr<npc_data> nd_)
dumb_ptr<npc_data_script> nd = nd_->is_script();
nd->scr.timerid.cancel();
nd->scr.timer_eventv.clear();
+ nd->eventqueuel.clear();
+ for (int i = 0; i < MAX_EVENTTIMER; i++)
+ nd->eventtimer[i].cancel();
+
+ // destroy all children (puppets), if any
+ if (nd_->name && nd->scr.parent == BlockId())
+ {
+ for (auto& pair : npcs_by_name)
+ if (pair.second->npc_subtype == NpcSubtype::SCRIPT
+ && pair.second->is_script()->scr.parent == nd_->bl_id)
+ npc_free(pair.second);
+ }
+
nd->scr.script.reset();
nd->scr.label_listv.clear();
}
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 929143c..db3b372 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -2731,7 +2731,8 @@ int pc_attack(dumb_ptr<map_session_data> sd, BlockId target_id, int type)
if (bl->bl_type == BL::NPC)
{ // monster npcs [Valaris]
- npc_click(sd, target_id);
+ if (battle_get_class(bl) != INVISIBLE_CLASS && !pc_isdead(sd))
+ npc_click(sd, target_id);
return 0;
}
@@ -3352,13 +3353,10 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd,
if (src && src->bl_type == BL::PC)
{
// [Fate] PK death, trigger scripts
- argrec_t arg[3] =
+ argrec_t arg[1] =
{
- {"@killerrid"_s, static_cast<int32_t>(unwrap<BlockId>(src->bl_id))},
{"@victimrid"_s, static_cast<int32_t>(unwrap<BlockId>(sd->bl_id))},
- {"@victimlvl"_s, sd->status.base_level},
};
- 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;
@@ -3487,7 +3485,10 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type)
case SP::INT:
case SP::DEX:
case SP::LUK:
- val = battle_get_stat(type, bl);
+ if (bl && bl->bl_type == BL::PC)
+ val = bl->is_player()->status.attrs[sp_to_attr(type)];
+ else
+ val = battle_get_stat(type, bl);
break;
case SP::SPEED:
val = battle_get_speed(bl).count();
@@ -3531,6 +3532,12 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type)
case SP::CHAR_ID:
val = sd ? unwrap<CharId>(sd->status_key.char_id) : 0;
break;
+ case SP::ELTLVL:
+ val = static_cast<int>(battle_get_element(sd).level);
+ break;
+ case SP::ELTTYPE:
+ val = static_cast<int>(battle_get_element(sd).element);
+ break;
}
return val;
diff --git a/src/map/script-call.cpp b/src/map/script-call.cpp
index fbb9b97..085d90a 100644
--- a/src/map/script-call.cpp
+++ b/src/map/script-call.cpp
@@ -908,7 +908,6 @@ void run_script_main(ScriptState *st, Borrowed<const ScriptBuffer> rootscript)
if (st->state != ScriptEndState::END)
{
// 再開するためにスタック情報を保存
- dumb_ptr<map_session_data> sd = map_id2sd(st->rid);
if (sd)
{
sd->npc_stackbuf = stack->stack_datav;
@@ -938,17 +937,20 @@ int run_script_l(ScriptPointer sp, BlockId rid, BlockId oid,
if (oid)
{
dumb_ptr<block_list> oid_bl = map_id2bl(oid);
- if (oid_bl->bl_type == BL::NPC)
+ if (oid_bl)
{
- dumb_ptr<npc_data> nd = oid_bl->is_npc();
- if(nd->npc_subtype == NpcSubtype::SCRIPT)
+ if (oid_bl->bl_type == BL::NPC)
{
- dumb_ptr<npc_data_script> nds = nd->is_script();
- if (nds->scr.parent)
+ dumb_ptr<npc_data> nd = oid_bl->is_npc();
+ if(nd->npc_subtype == NpcSubtype::SCRIPT)
{
- dumb_ptr<npc_data_script> parent = map_id2bl(nds->scr.parent)->is_npc()->is_script();
- assert(parent->bl_type == BL::NPC && parent->npc_subtype == NpcSubtype::SCRIPT);
- sp = ScriptPointer(borrow(*parent->scr.script), sp.pos);
+ dumb_ptr<npc_data_script> nds = nd->is_script();
+ if (nds->scr.parent)
+ {
+ dumb_ptr<npc_data_script> parent = map_id2bl(nds->scr.parent)->is_npc()->is_script();
+ assert(parent->bl_type == BL::NPC && parent->npc_subtype == NpcSubtype::SCRIPT);
+ sp = ScriptPointer(borrow(*parent->scr.script), sp.pos);
+ }
}
}
}
diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp
index faa8c81..beabef3 100644
--- a/src/map/script-fun.cpp
+++ b/src/map/script-fun.cpp
@@ -472,14 +472,43 @@ void builtin_max(ScriptState *st)
static
void builtin_min(ScriptState *st)
{
- int min, num;
- min = conv_num(st, &AARG(0));
+ int min = 0xFFFFFFF6, num;
- for (int i = 1; HARG(i); i++)
+ if (HARG(1))
{
- num = conv_num(st, &AARG(i));
- if (num < min)
- min = num;
+ min = conv_num(st, &AARG(0));
+ for (int i = 1; HARG(i); i++)
+ {
+ num = conv_num(st, &AARG(i));
+ if (num < min)
+ min = num;
+ }
+ }
+ else
+ {
+ SIR reg = AARG(0).get_if<ScriptDataVariable>()->reg;
+ ZString name = variable_names.outtern(reg.base());
+ char prefix = name.front();
+ if (prefix != '$' && prefix != '@' && prefix != '.')
+ {
+ PRINTF("builtin_max: illegal scope!\n"_fmt);
+ return;
+ }
+ for (int i = reg.index(); i < 256; i++)
+ {
+ struct script_data vd = get_val2(st, reg.iplus(i));
+ MATCH_BEGIN (vd)
+ {
+ MATCH_CASE (const ScriptDataInt&, u)
+ {
+ if (u.numi < min)
+ min = u.numi;
+ continue;
+ }
+ }
+ MATCH_END ();
+ abort();
+ }
}
push_int<ScriptDataInt>(st->stack, min);
@@ -618,28 +647,6 @@ void builtin_heal(ScriptState *st)
*------------------------------------------
*/
static
-void builtin_elttype(ScriptState *st)
-{
- int element_type = static_cast<int>(battle_get_element(map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))))).element);
- push_int<ScriptDataInt>(st->stack, element_type);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static
-void builtin_eltlvl(ScriptState *st)
-{
- int element_lvl = static_cast<int>(battle_get_element(map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))))).level);
- push_int<ScriptDataInt>(st->stack, element_lvl);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static
void builtin_distance(ScriptState *st)
{
dumb_ptr<block_list> source = map_id2bl(wrap<BlockId>(conv_num(st, &AARG(0))));
@@ -816,8 +823,7 @@ void builtin_requestitem(ScriptState *st)
if (prefix != '$' && prefix != '@' && prefix != '.')
{
PRINTF("builtin_requestitem: illegal scope!\n"_fmt);
- runflag = 0;
- return;
+ abort();
}
sd = script_rid2sd(st);
@@ -867,7 +873,7 @@ void builtin_requestitem(ScriptState *st)
RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s));
if (item_name == ""_s)
goto fail;
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
{
struct script_data vd = script_data(ScriptDataStr{item_name});
set_scope_reg(st, reg.iplus(j), &vd);
@@ -877,7 +883,7 @@ void builtin_requestitem(ScriptState *st)
}
else
{
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
{
struct script_data vd = script_data(ScriptDataInt{num});
set_scope_reg(st, reg.iplus(j), &vd);
@@ -907,21 +913,19 @@ void builtin_requestlang(ScriptState *st)
assert (scrd.is<ScriptDataVariable>());
SIR reg = scrd.get_if<ScriptDataVariable>()->reg;
ZString name = variable_names.outtern(reg.base());
- char prefix = name.front();
char postfix = name.back();
if (postfix != '$')
{
PRINTF("builtin_requestlang: illegal type (expects string)!\n"_fmt);
- runflag = 0;
- return;
+ abort();
}
if (sd->state.menu_or_input)
{
// Second time (rerunline)
sd->state.menu_or_input = 0;
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
{
struct script_data vd = script_data(ScriptDataStr{sd->npc_str});
set_scope_reg(st, reg, &vd);
@@ -1102,7 +1106,7 @@ void builtin_destroy(ScriptState *st)
dumb_ptr<npc_data_script> nd = map_id2bl(id)->is_npc()->is_script();
if(!nd)
return;
- assert(nd->disposable == true);
+ //assert(nd->disposable == true); we don't care about it anymore
npc_free(nd);
if (!HARG(0))
st->state = ScriptEndState::END;
@@ -1131,11 +1135,9 @@ void builtin_puppet(ScriptState *st)
nd->bl_prev = nd->bl_next = nullptr;
nd->scr.event_needs_map = false;
- nd->disposable = true; // allow to destroy
// PlayerName::SpellName
NpcName npc = stringish<NpcName>(ZString(conv_str(st, &AARG(3))));
- PRINTF("Npc: %s\n"_fmt, npc);
nd->name = npc;
// Dynamically set location
@@ -1285,7 +1287,7 @@ void builtin_set(ScriptState *st)
get_val(st, sdata);
if(prefix == '.')
{
- if (name_[1] == '@')
+ if (name_.startswith(".@"_s))
{
PRINTF("builtin_set: illegal scope!\n"_fmt);
return;
@@ -1322,7 +1324,7 @@ void builtin_set(ScriptState *st)
{
if(prefix == '.')
{
- if (name_[1] == '@')
+ if (name_.startswith(".@"_s))
{
set_scope_reg(st, reg, &AARG(1));
return;
@@ -1351,6 +1353,45 @@ void builtin_set(ScriptState *st)
}
+// this is a special function that returns array index for a variable stored in another being
+static
+int getarraysize2(SIR reg, dumb_ptr<block_list> bl)
+{
+ int i = reg.index(), c = i;
+ bool zero = true; // index zero is empty
+ for (; i < 256; i++)
+ {
+ struct script_data vd = ScriptDataVariable{reg.iplus(i)};
+ get_val(bl, &vd);
+ MATCH_BEGIN (vd)
+ {
+ MATCH_CASE (const ScriptDataStr&, u)
+ {
+ if (u.str[0])
+ {
+ if (i == 0)
+ zero = false; // index zero is not empty
+ c = i;
+ }
+ continue;
+ }
+ MATCH_CASE (const ScriptDataInt&, u)
+ {
+ if (u.numi)
+ {
+ if (i == 0)
+ zero = false; // index zero is not empty
+ c = i;
+ }
+ continue;
+ }
+ }
+ MATCH_END ();
+ abort();
+ }
+ return (c == 0 && zero) ? c : (c + 1);
+}
+
/*==========================================
* 配列変数設定
*------------------------------------------
@@ -1363,20 +1404,51 @@ void builtin_setarray(ScriptState *st)
ZString name = variable_names.outtern(reg.base());
char prefix = name.front();
char postfix = name.back();
+ int i = 1, j = 0;
if (prefix != '$' && prefix != '@' && prefix != '.')
{
PRINTF("builtin_setarray: illegal scope!\n"_fmt);
return;
}
- if (prefix == '.' && name[1] != '@')
- bl = map_id2bl(st->oid)->is_npc();
- else if (prefix != '$' && !(prefix == '.' && name[1] == '@'))
+ if (prefix == '.' && !name.startswith(".@"_s))
+ {
+ struct script_data *sdata = &AARG(1);
+ get_val(st, sdata);
+ i++; // 2nd argument is npc, not an array element
+ if (sdata->is<ScriptDataStr>())
+ {
+ ZString tn = conv_str(st, sdata);
+ if (tn == "this"_s || tn == "oid"_s)
+ bl = map_id2bl(st->oid)->is_npc();
+ else
+ {
+ NpcName name_ = stringish<NpcName>(tn);
+ bl = npc_name2id(name_);
+ }
+ }
+ else
+ {
+ int tid = conv_num(st, sdata);
+ if (tid == 0)
+ bl = map_id2bl(st->oid)->is_npc();
+ else
+ bl = map_id2bl(wrap<BlockId>(tid))->is_npc();
+ }
+ if (!bl)
+ {
+ PRINTF("builtin_setarray: npc not found\n"_fmt);
+ return;
+ }
+ if (st->oid && bl->bl_id != st->oid)
+ j = getarraysize2(reg, bl);
+ }
+ else if (prefix != '$' && !name.startswith(".@"_s))
bl = map_id2bl(st->rid)->is_player();
- for (int j = 0, i = 1; i < st->end - st->start - 2 && j < 256; i++, j++)
+ for (; i < st->end - st->start - 2 && j < 256; i++, j++)
{
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
set_scope_reg(st, reg.iplus(j), &AARG(i));
else if (postfix == '$')
set_reg(bl, VariableCode::VARIABLE, reg.iplus(j), conv_str(st, &AARG(i)));
@@ -1404,14 +1476,14 @@ void builtin_cleararray(ScriptState *st)
PRINTF("builtin_cleararray: illegal scope!\n"_fmt);
return;
}
- if (prefix == '.' && name[1] != '@')
+ if (prefix == '.' && !name.startswith(".@"_s))
bl = map_id2bl(st->oid)->is_npc();
- else if (prefix != '$' && !(prefix == '.' && name[1] == '@'))
+ else if (prefix != '$' && !name.startswith(".@"_s))
bl = map_id2bl(st->rid)->is_player();
for (int i = 0; i < sz; i++)
{
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
set_scope_reg(st, reg.iplus(i), &AARG(i));
else if (postfix == '$')
set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), conv_str(st, &AARG(1)));
@@ -2673,8 +2745,7 @@ void builtin_camera(ScriptState *st)
{
dumb_ptr<block_list> bl;
short x = 0, y = 0;
- int id;
- bool rel;
+ bool rel = false;
if (auto *u = AARG(0).get_if<ScriptDataInt>())
bl = map_id2bl(wrap<BlockId>(u->numi));
if (auto *g = AARG(0).get_if<ScriptDataStr>())
@@ -3109,7 +3180,13 @@ void builtin_resetstatus(ScriptState *st)
static
void builtin_attachrid(ScriptState *st)
{
- st->rid = wrap<BlockId>(conv_num(st, &AARG(0)));
+ dumb_ptr<map_session_data> sd = map_id2sd(st->rid);
+ BlockId newid = wrap<BlockId>(conv_num(st, &AARG(0)));
+
+ if (sd && newid != st->rid)
+ sd->npc_id = BlockId();
+
+ st->rid = newid;
push_int<ScriptDataInt>(st->stack, (map_id2sd(st->rid) != nullptr));
}
@@ -3121,6 +3198,9 @@ void builtin_attachrid(ScriptState *st)
static
void builtin_detachrid(ScriptState *st)
{
+ dumb_ptr<map_session_data> sd = map_id2sd(st->rid);
+ if (sd)
+ sd->npc_id = BlockId();
st->rid = BlockId();
}
@@ -3433,7 +3513,7 @@ void builtin_chr(ScriptState *st)
static
void builtin_ord(ScriptState *st)
{
- const char ascii = conv_str(st, &AARG(0))[0];
+ const char ascii = conv_str(st, &AARG(0)).front();
push_int<ScriptDataInt>(st->stack, static_cast<int>(ascii));
}
@@ -3443,7 +3523,7 @@ void builtin_explode(ScriptState *st)
dumb_ptr<block_list> bl = nullptr;
SIR reg = AARG(0).get_if<ScriptDataVariable>()->reg;
ZString name = variable_names.outtern(reg.base());
- const char separator = conv_str(st, &AARG(2))[0];
+ const char separator = conv_str(st, &AARG(2)).front();
RString str = conv_str(st, &AARG(1));
RString val;
char prefix = name.front();
@@ -3454,7 +3534,7 @@ void builtin_explode(ScriptState *st)
PRINTF("builtin_explode: illegal scope!\n"_fmt);
return;
}
- if (prefix == '.' && name[1] != '@')
+ if (prefix == '.' && !name.startswith(".@"_s))
bl = map_id2bl(st->oid)->is_npc();
else if (prefix != '$' && prefix != '.')
bl = map_id2bl(st->rid)->is_player();
@@ -3464,7 +3544,7 @@ void builtin_explode(ScriptState *st)
auto find = std::find(str.begin(), str.end(), separator);
if (find == str.end())
{
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
{
struct script_data vd = script_data(ScriptDataInt{atoi(str.c_str())});
if (postfix == '$')
@@ -3481,7 +3561,7 @@ void builtin_explode(ScriptState *st)
val = str.xislice_h(find);
str = str.xislice_t(find + 1);
- if (prefix == '.' && name[1] == '@')
+ if (name.startswith(".@"_s))
{
struct script_data vd = script_data(ScriptDataInt{atoi(val.c_str())});
if (postfix == '$')
@@ -3749,7 +3829,7 @@ void builtin_get(ScriptState *st)
if(prefix == '.')
{
- if (name_[1] == '@')
+ if (name_.startswith(".@"_s))
{
PRINTF("builtin_get: illegal scope!\n"_fmt);
return;
@@ -3807,7 +3887,7 @@ void builtin_get(ScriptState *st)
int var;
if (prefix == '#' && bl)
{
- if (name_[1] == '#')
+ if (name_.startswith("##"_s))
var = pc_readaccountreg2(bl->is_player(), stringish<VarName>(name_));
else
var = pc_readaccountreg(bl->is_player(), stringish<VarName>(name_));
@@ -4546,8 +4626,6 @@ BuiltinFunction builtin_functions[] =
BUILTIN(warp, "Mxy"_s, '\0'),
BUILTIN(areawarp, "MxyxyMxy"_s, '\0'),
BUILTIN(heal, "ii?"_s, '\0'),
- BUILTIN(elttype, "i"_s, 'i'),
- BUILTIN(eltlvl, "i"_s, 'i'),
BUILTIN(injure, "iii"_s, '\0'),
BUILTIN(input, "N"_s, '\0'),
BUILTIN(requestitem, "N?"_s, '\0'),
@@ -4680,7 +4758,7 @@ BuiltinFunction builtin_functions[] =
BUILTIN(freeloop, "i"_s, '\0'),
BUILTIN(if_then_else, "iii"_s, '.'),
BUILTIN(max, "e?*"_s, 'i'),
- BUILTIN(min, "ii*"_s, 'i'),
+ BUILTIN(min, "e?*"_s, 'i'),
BUILTIN(average, "ii*"_s, 'i'),
BUILTIN(sqrt, "i"_s, 'i'),
BUILTIN(cbrt, "i"_s, 'i'),
diff --git a/src/map/script-parse.cpp b/src/map/script-parse.cpp
index a69df40..f8d7b6b 100644
--- a/src/map/script-parse.cpp
+++ b/src/map/script-parse.cpp
@@ -617,6 +617,7 @@ ZString::iterator ScriptBuffer::parse_line(ZString::iterator p, bool *can_step)
{
// TODO should be LString, but no heterogenous lookup yet
+ // FIXME / TODO: allow destroy to both be a statement and a terminator
static
std::set<ZString> terminators =
{