diff options
Diffstat (limited to 'src/map/script-fun.cpp')
-rw-r--r-- | src/map/script-fun.cpp | 536 |
1 files changed, 305 insertions, 231 deletions
diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index deb781a..64ba542 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -111,7 +111,7 @@ static void builtin_mes(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); sd->state.npc_dialog_mes = 1; RString mes = HARG(0) ? conv_str(st, &AARG(0)) : ""_s; clif_scriptmes(sd, st->oid, mes); @@ -125,7 +125,7 @@ static void builtin_mesq(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); sd->state.npc_dialog_mes = 1; RString mes = HARG(0) ? conv_str(st, &AARG(0)) : ""_s; MString mesq; @@ -145,8 +145,8 @@ void builtin_mesn(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); dumb_ptr<npc_data> nd; nd = map_id_is_npc(st->oid); - script_nullpo_end(nd, "npc not found"); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(nd, "npc not found"_s); + script_nullpo_end(sd, "player not found"_s); sd->state.npc_dialog_mes = 1; RString mes = HARG(0) ? conv_str(st, &AARG(0)) : RString(nd->name.xislice_h(std::find(nd->name.begin(), nd->name.end(), '#'))); // strnpcinf MString mesq; @@ -164,7 +164,7 @@ static void builtin_clear(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); clif_npc_action(sd, st->oid, 9, 0, 0, 0); } @@ -389,7 +389,7 @@ static void builtin_next(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); st->state = ScriptEndState::STOP; clif_scriptnext(sd, st->oid); } @@ -411,7 +411,7 @@ void builtin_close(ScriptState *st) } st->state = ScriptEndState::END; dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (sd->state.npc_dialog_mes) clif_scriptclose(sd, st->oid); @@ -428,7 +428,7 @@ void builtin_close2(ScriptState *st) { st->state = ScriptEndState::STOP; dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (sd->state.npc_dialog_mes) clif_scriptclose(sd, st->oid); else @@ -443,7 +443,7 @@ static void builtin_menu(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (sd->state.menu_or_input == 0) { @@ -676,7 +676,7 @@ void builtin_isat(ScriptState *st) x = conv_num(st, &AARG(1)); y = conv_num(st, &AARG(2)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, (x == sd->bl_x) && (y == sd->bl_y) @@ -695,7 +695,7 @@ void builtin_warp(ScriptState *st) MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); x = conv_num(st, &AARG(1)); y = conv_num(st, &AARG(2)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_setpos(sd, str, x, y, BeingRemoveWhy::GONE); } @@ -748,7 +748,7 @@ void builtin_heal(ScriptState *st) hp = conv_num(st, &AARG(0)); sp = conv_num(st, &AARG(1)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if(sd != nullptr && (sd->status.hp < 1 && hp > 0)){ pc_setstand(sd); @@ -901,7 +901,7 @@ void builtin_input(ScriptState *st) char postfix = name.back(); sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (sd->state.menu_or_input) { // Second time (rerun) @@ -962,7 +962,7 @@ void builtin_requestitem(ScriptState *st) } sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (sd->state.menu_or_input) { // Second time (rerunline) @@ -1055,7 +1055,7 @@ void builtin_requestlang(ScriptState *st) ZString name = variable_names.outtern(reg.base()); char postfix = name.back(); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (postfix != '$') { @@ -1247,7 +1247,7 @@ void builtin_foreach(ScriptState *st) else if (st->rid) sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); map_foreachinarea(std::bind(builtin_foreach_sub, ph::_1, event, sd->bl_id), m, @@ -1279,12 +1279,23 @@ void builtin_destroy(ScriptState *st) /* Not safe to call destroy if others may also be paused on this NPC! */ if (st->rid) { sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); npc_event_dequeue(sd); } + // Cancel all existing timers on the NPC. + // They "would" never fire, and we don't want race conditions here. + for (int i = 0; i < MAX_EVENTTIMER; i++) + { + nd->eventtimer[i].cancel(); + } + // Schedule the NPC to be freed on the next available tick. + // Scripts can be invoked under iteration of the ev_db global event + // database, and we don't want to invalidate active iterators. + nd->deletion_pending = npc_data::DELETION_QUEUED; + nd->eventtimer[0] = Timer(gettick(), std::bind(npc_free, nd)); + nd = nd->is_script(); - npc_free(nd); st->oid = BlockId(); if (!HARG(0)) @@ -1350,7 +1361,7 @@ void builtin_puppet(ScriptState *st) nd->npc_subtype = NpcSubtype::SCRIPT; npc_script++; - nd->deletion_pending = false; + nd->deletion_pending = npc_data::NOT_DELETING; nd->n = map_addnpc(nd->bl_m, nd); @@ -1453,7 +1464,7 @@ void builtin_set(ScriptState *st) else { bl = script_rid2sd(st); - script_nullpo_end(bl, "player not found"); + script_nullpo_end(bl, "player not found"_s); } int val = conv_num(st, &AARG(1)); @@ -1628,14 +1639,14 @@ void builtin_setarray(ScriptState *st) else bl = map_id_is_npc(wrap<BlockId>(tid)); } - script_nullpo_end(bl, "npc not found"); + script_nullpo_end(bl, "npc not found"_s); if (st->oid && bl->bl_id != st->oid) j = getarraysize2(reg, bl); } else if (prefix != '$' && !name.startswith(".@"_s)) { bl = map_id_is_player(st->rid); - script_nullpo_end(bl, "player not found"); + script_nullpo_end(bl, "player not found"_s); } for (; i < st->end - st->start - 2 && j < 256; i++, j++) @@ -1674,7 +1685,7 @@ void builtin_cleararray(ScriptState *st) else if (prefix != '$' && !name.startswith(".@"_s)) { bl = map_id_is_player(st->rid); - script_nullpo_end(bl, "player not found"); + script_nullpo_end(bl, "player not found"_s); } for (int i = 0; i < sz; i++) @@ -1847,7 +1858,7 @@ void builtin_gmlog(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); ZString message = ZString(conv_str(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); log_atcommand(sd, STRPRINTF("{SCRIPT} %s"_fmt, message)); } @@ -1861,7 +1872,7 @@ void builtin_setlook(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); LOOK type = LOOK(conv_num(st, &AARG(0))); int val = conv_num(st, &AARG(1)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_changelook(sd, type, val); @@ -1881,7 +1892,7 @@ void builtin_countitem(ScriptState *st) struct script_data *data; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); data = &AARG(0); get_val(st, data); @@ -1929,7 +1940,7 @@ void builtin_checkweight(ScriptState *st) struct script_data *data; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); data = &AARG(0); get_val(st, data); @@ -1978,7 +1989,7 @@ void builtin_getitem(ScriptState *st) struct script_data *data; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); data = &AARG(0); get_val(st, data); @@ -2082,7 +2093,7 @@ void builtin_delitem(ScriptState *st) struct script_data *data; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); data = &AARG(0); get_val(st, data); @@ -2133,7 +2144,7 @@ static void builtin_getversion(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, unwrap<ClientVersion>(sd->client_version)); } @@ -2220,7 +2231,7 @@ void builtin_strcharinfo(ScriptState *st) else sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); num = conv_num(st, &AARG(0)); if (num == 0) @@ -2277,7 +2288,7 @@ void builtin_getequipid(ScriptState *st) else sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); num = conv_num(st, &AARG(0)); IOff0 i = pc_checkequip(sd, equip[num - 1]); if (i.ok()) @@ -2336,7 +2347,7 @@ void builtin_bonus(ScriptState *st) type = SP(conv_num(st, &AARG(0))); int val = conv_num(st, &AARG(1)); dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_bonus(sd, type, val); } @@ -2357,7 +2368,7 @@ void builtin_bonus2(ScriptState *st) int type2 = conv_num(st, &AARG(1)); int val = conv_num(st, &AARG(2)); dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_bonus2(sd, type, type2, val); } @@ -2378,7 +2389,7 @@ void builtin_skill(ScriptState *st) if (HARG(2)) flag = conv_num(st, &AARG(2)); sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_skill(sd, id, level, flag); clif_skillinfoblock(sd); @@ -2397,7 +2408,7 @@ void builtin_setskill(ScriptState *st) SkillID id = static_cast<SkillID>(conv_num(st, &AARG(0))); level = conv_num(st, &AARG(1)); sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); level = std::min(level, MAX_SKILL_LEVEL); level = std::max(level, 0); @@ -2415,7 +2426,7 @@ void builtin_getskilllv(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); SkillID id = SkillID(conv_num(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, pc_checkskill(sd, id)); } @@ -2427,7 +2438,7 @@ static void builtin_overrideattack(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (HARG(0)) { @@ -2464,7 +2475,7 @@ static void builtin_getgmlevel(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, pc_isGM(sd).get_all_bits()); } @@ -2497,7 +2508,7 @@ void builtin_getopt2(ScriptState *st) dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, static_cast<uint16_t>(sd->opt2)); @@ -2514,7 +2525,7 @@ void builtin_setopt2(ScriptState *st) Opt2 new_opt2 = Opt2(conv_num(st, &AARG(0))); sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (new_opt2 == sd->opt2) return; @@ -2535,7 +2546,7 @@ void builtin_savepoint(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); int x, y; MapName str = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); x = conv_num(st, &AARG(1)); y = conv_num(st, &AARG(2)); @@ -2635,7 +2646,7 @@ void builtin_openstorage(ScriptState *st) // int sync = 0; // if (st->end >= 3) sync = conv_num(st,& (st->stack->stack_data[st->start+2])); dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); // if (sync) { st->state = ScriptEndState::STOP; @@ -2655,7 +2666,7 @@ void builtin_getexp(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); int base = 0, job = 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); base = conv_num(st, &AARG(0)); job = conv_num(st, &AARG(1)); @@ -2672,6 +2683,22 @@ void builtin_getexp(ScriptState *st) *------------------------------------------ */ static +int get_mob_drop_nameid(Species mob_id, int index) +{ + return unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[index].nameid); +} +static +int get_mob_drop_percent(Species mob_id, int index) +{ + return get_mob_db(mob_id).dropitem[index].p.num; +} +static +AString get_mob_drop_name(Species mob_id, int index) +{ + Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[index].nameid)); + return i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); +} +static void builtin_mobinfo(ScriptState *st) { Species mob_id = wrap<Species>(conv_num(st, &AARG(0))); @@ -2686,6 +2713,19 @@ void builtin_mobinfo(ScriptState *st) return; } +#define CASE_MobInfo_DROPID(index) \ + MobInfo::DROPID##index: info = get_mob_drop_nameid(mob_id, index) + +#define CASE_MobInfo_DROPPERCENT(index) \ + MobInfo::DROPPERCENT##index: info = get_mob_drop_percent(mob_id, index) + +#define CASE_MobInfo_DROPNAME(index) \ + MobInfo::DROPNAME##index: \ + { \ + info_str = get_mob_drop_name(mob_id, index); \ + mode = 1; \ + } + switch (request) { case MobInfo::ID: @@ -2789,142 +2829,57 @@ void builtin_mobinfo(ScriptState *st) case MobInfo::MUTATION_POWER: info = get_mob_db(mob_id).mutation_power; break; - case MobInfo::DROPID0: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[0].nameid); - break; - case MobInfo::DROPNAME0: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[0].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT0: - info = get_mob_db(mob_id).dropitem[0].p.num; - break; - case MobInfo::DROPID1: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[0].nameid); - break; - case MobInfo::DROPNAME1: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[0].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT1: - info = get_mob_db(mob_id).dropitem[0].p.num; - break; - case MobInfo::DROPID2: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[1].nameid); - break; - case MobInfo::DROPNAME2: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[1].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT2: - info = get_mob_db(mob_id).dropitem[1].p.num; - break; - case MobInfo::DROPID3: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[2].nameid); - break; - case MobInfo::DROPNAME3: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[2].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT3: - info = get_mob_db(mob_id).dropitem[2].p.num; - break; - case MobInfo::DROPID4: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[3].nameid); - break; - case MobInfo::DROPNAME4: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[3].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT4: - info = get_mob_db(mob_id).dropitem[3].p.num; - break; - case MobInfo::DROPID5: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[4].nameid); - break; - case MobInfo::DROPNAME5: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[4].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT5: - info = get_mob_db(mob_id).dropitem[4].p.num; - break; - case MobInfo::DROPID6: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[5].nameid); - break; - case MobInfo::DROPNAME6: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[5].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT6: - info = get_mob_db(mob_id).dropitem[5].p.num; - break; - case MobInfo::DROPID7: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[6].nameid); - break; - case MobInfo::DROPNAME7: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[6].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT7: - info = get_mob_db(mob_id).dropitem[6].p.num; - break; - case MobInfo::DROPID8: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[7].nameid); - break; - case MobInfo::DROPNAME8: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[7].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT8: - info = get_mob_db(mob_id).dropitem[7].p.num; - break; - case MobInfo::DROPID9: - info = unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[7].nameid); - break; - case MobInfo::DROPNAME9: - { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[7].nameid)); - info_str = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); - mode = 1; - } - break; - case MobInfo::DROPPERCENT9: - info = get_mob_db(mob_id).dropitem[7].p.num; - break; + + case CASE_MobInfo_DROPID(0); break; + case CASE_MobInfo_DROPNAME(0); break; + case CASE_MobInfo_DROPPERCENT(0); break; + + case CASE_MobInfo_DROPID(1); break; + case CASE_MobInfo_DROPNAME(1); break; + case CASE_MobInfo_DROPPERCENT(1); break; + + case CASE_MobInfo_DROPID(2); break; + case CASE_MobInfo_DROPNAME(2); break; + case CASE_MobInfo_DROPPERCENT(2); break; + + case CASE_MobInfo_DROPID(3); break; + case CASE_MobInfo_DROPNAME(3); break; + case CASE_MobInfo_DROPPERCENT(3); break; + + case CASE_MobInfo_DROPID(4); break; + case CASE_MobInfo_DROPNAME(4); break; + case CASE_MobInfo_DROPPERCENT(4); break; + + case CASE_MobInfo_DROPID(5); break; + case CASE_MobInfo_DROPNAME(5); break; + case CASE_MobInfo_DROPPERCENT(5); break; + + case CASE_MobInfo_DROPID(6); break; + case CASE_MobInfo_DROPNAME(6); break; + case CASE_MobInfo_DROPPERCENT(6); break; + + case CASE_MobInfo_DROPID(7); break; + case CASE_MobInfo_DROPNAME(7); break; + case CASE_MobInfo_DROPPERCENT(7); break; + + case CASE_MobInfo_DROPID(8); break; + case CASE_MobInfo_DROPNAME(8); break; + case CASE_MobInfo_DROPPERCENT(8); break; + + case CASE_MobInfo_DROPID(9); break; + case CASE_MobInfo_DROPNAME(9); break; + case CASE_MobInfo_DROPPERCENT(9); break; + default: PRINTF("builtin_mobinfo: unknown request\n"_fmt); push_int<ScriptDataInt>(st->stack, -1); return; break; } +#undef CASE_MobInfo_DROPID +#undef CASE_MobInfo_DROPPERCENT +#undef CASE_MobInfo_DROPNAME + if (!mode) push_int<ScriptDataInt>(st->stack, info); else @@ -2968,7 +2923,7 @@ void builtin_mobinfo_droparrays(ScriptState *st) else if (prefix != '$' && !name.startswith(".@"_s)) { bl = map_id_is_player(st->rid); - script_nullpo_end(bl, "player not found"); + script_nullpo_end(bl, "player not found"_s); } switch (request) @@ -3011,7 +2966,9 @@ void builtin_mobinfo_droparrays(ScriptState *st) } for (int i = 0; i < MaxDrops; ++i) - if (get_mob_db(mob_id).dropitem[i].nameid) + { + auto& dropitem = get_mob_db(mob_id).dropitem[i]; + if (dropitem.nameid) { status = 1; switch (request) @@ -3019,15 +2976,15 @@ void builtin_mobinfo_droparrays(ScriptState *st) case MobInfo_DropArrays::IDS: if (name.startswith(".@"_s)) { - struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid)}); + struct script_data vd = script_data(ScriptDataInt{unwrap<ItemNameId>(dropitem.nameid)}); set_scope_reg(st, reg.iplus(i), &vd); } else - set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(get_mob_db(mob_id).dropitem[i].nameid)); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap<ItemNameId>(dropitem.nameid)); break; case MobInfo_DropArrays::NAMES: { - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid)); + Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid)); RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); if (name.startswith(".@"_s)) @@ -3042,11 +2999,11 @@ void builtin_mobinfo_droparrays(ScriptState *st) case MobInfo_DropArrays::PERCENTS: if (name.startswith(".@"_s)) { - struct script_data vd = script_data(ScriptDataInt{get_mob_db(mob_id).dropitem[i].p.num}); + struct script_data vd = script_data(ScriptDataInt{dropitem.p.num}); set_scope_reg(st, reg.iplus(i), &vd); } else - set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), get_mob_db(mob_id).dropitem[i].p.num); + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), dropitem.p.num); break; } } @@ -3056,7 +3013,7 @@ void builtin_mobinfo_droparrays(ScriptState *st) status = 2; break; } - + } push_int<ScriptDataInt>(st->stack, status); } @@ -3086,16 +3043,19 @@ void builtin_getmobdrops(ScriptState *st) status = 1; + const mob_db_& mob_info = get_mob_db(mob_id); for (; i < MaxDrops; ++i) - if (get_mob_db(mob_id).dropitem[i].nameid) + { + auto& dropitem = mob_info.dropitem[i]; + if (dropitem.nameid) { - set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), get_mob_db(mob_id).dropitem[i].p.num); + set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), dropitem.p.num); - Option<P<struct item_data>> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid)); + Option<P<struct item_data>> i_data = Some(itemdb_search(dropitem.nameid)); RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish<ItemName>(""_s)); set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_name$"_s), i), item_name); - set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), get_mob_db(mob_id).dropitem[i].p.num); + set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_rate"_s), i), dropitem.p.num); } else { @@ -3103,6 +3063,7 @@ void builtin_getmobdrops(ScriptState *st) status = 2; break; } + } if (status == 1) set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_count"_s), 0), i); @@ -3177,8 +3138,8 @@ void builtin_summon(ScriptState *st) } mob->mode |= - MobMode::SUMMONED | MobMode::TURNS_AGAINST_BAD_MASTER; - + MobMode::SUMMONED; // | MobMode::TURNS_AGAINST_BAD_MASTER; <- its fun but bugged. + // This flag identified to be source of AFK PK city exploits, etc. mob->deletetimer = Timer(gettick() + lifespan, std::bind(mob_timer_delete, ph::_1, ph::_2, mob_id)); @@ -3321,7 +3282,7 @@ void builtin_addtimer(ScriptState *st) else if (st->rid) sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_addeventtimer(sd, tick, event); } @@ -3354,7 +3315,7 @@ void builtin_initnpctimer(ScriptState *st) nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(0))))); else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); dumb_ptr<npc_data_script> nd = nd_->is_script(); @@ -3375,7 +3336,7 @@ void builtin_startnpctimer(ScriptState *st) nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(0))))); else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); dumb_ptr<npc_data_script> nd = nd_->is_script(); @@ -3395,7 +3356,7 @@ void builtin_stopnpctimer(ScriptState *st) nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(0))))); else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); dumb_ptr<npc_data_script> nd = nd_->is_script(); @@ -3417,7 +3378,7 @@ void builtin_getnpctimer(ScriptState *st) nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(1))))); else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); dumb_ptr<npc_data_script> nd = nd_->is_script(); @@ -3450,7 +3411,7 @@ void builtin_setnpctimer(ScriptState *st) nd_ = npc_name2id(stringish<NpcName>(ZString(conv_str(st, &AARG(1))))); else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); dumb_ptr<npc_data_script> nd = nd_->is_script(); @@ -3469,7 +3430,7 @@ void builtin_npcaction(ScriptState *st) int id = 0; short x = HARG(2) ? conv_num(st, &AARG(2)) : 0; short y = HARG(3) ? conv_num(st, &AARG(3)) : 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if(HARG(1)) { @@ -3494,7 +3455,7 @@ static void builtin_camera(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (HARG(0)) { @@ -3551,7 +3512,7 @@ void builtin_setnpcdirection(ScriptState *st) else nd_ = map_id_is_npc(st->oid); - script_nullpo_end(nd_, "no npc"); + script_nullpo_end(nd_, "no npc"_s); if (bool(conv_num(st, &AARG(1)))) action = DamageType::SIT; @@ -3567,7 +3528,7 @@ void builtin_setnpcdirection(ScriptState *st) if (st->rid) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); clif_sitnpc_towards(sd, nd_, action); clif_setnpcdirection_towards(sd, nd_, dir); } @@ -3597,7 +3558,7 @@ void builtin_announce(ScriptState *st) bl = map_id2bl(st->oid); else bl = script_rid2sd(st); - script_nullpo_end(bl, "player not found"); + script_nullpo_end(bl, "player not found"_s); clif_GMmessage(bl, str, flag); } else @@ -3716,6 +3677,23 @@ void builtin_aggravate(ScriptState *st) } /*========================================== + * Check for summoned creature + *------------------------------------------ + */ +static +void builtin_issummon(ScriptState *st) +{ + dumb_ptr<mob_data> md = map_id_is_mob(wrap<BlockId>(conv_num(st, &AARG(0)))); + int val = 0; + if (md) + { + val = bool(md->mode & MobMode::SUMMONED); + } + + push_int<ScriptDataInt>(st->stack, val); +} + +/*========================================== * エリア指定ユーザー数所得 * Area Designated User Income *------------------------------------------ @@ -3892,6 +3870,7 @@ void builtin_sc_start(ScriptState *st) // all those use ms so this checks for < 1s are not needed on those // and it would break the cooldown symbol since many spells have cooldowns less than 1s case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_MBARRIER: case StatusChange::SC_COOLDOWN: case StatusChange::SC_COOLDOWN_MG: @@ -3901,7 +3880,11 @@ void builtin_sc_start(ScriptState *st) case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: - break; + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_COOLDOWN_CG: + case StatusChange::SC_SLOWMOVE: + case StatusChange::SC_CANTMOVE: + break; default: // work around old behaviour of: @@ -3979,7 +3962,7 @@ void builtin_resetstatus(ScriptState *st) { dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); pc_resetstate(sd); } @@ -4161,7 +4144,7 @@ void builtin_setpvpchannel(ScriptState *st) if (flag < 1) flag = 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); sd->state.pvpchannel = flag; } @@ -4178,7 +4161,7 @@ void builtin_getpvpflag(ScriptState *st) else sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); int num = conv_num(st, &AARG(0)); int flag = 0; @@ -4334,9 +4317,14 @@ void builtin_getitemlink(ScriptState *st) struct script_data *data; AString buf; data = &AARG(0); - ZString name = conv_str(st, data); + Option<P<struct item_data>> item_data_ = None; + + get_val(st, data); + if (data->is<ScriptDataStr>()) + item_data_ = itemdb_searchname(conv_str(st, data)); + else + item_data_ = itemdb_exists(wrap<ItemNameId>(conv_num(st, data))); - Option<P<struct item_data>> item_data_ = itemdb_searchname(name); OMATCH_BEGIN (item_data_) { OMATCH_CASE_SOME (item_data) @@ -4360,7 +4348,7 @@ static void builtin_getpartnerid2(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, unwrap<CharId>(sd->status.partner_id)); } @@ -4425,7 +4413,7 @@ void builtin_explode(ScriptState *st) else if (prefix != '$' && prefix != '.') { bl = map_id2bl(st->rid)->is_player(); - script_nullpo_end(bl, "target player not found"); + script_nullpo_end(bl, "target player not found"_s); } @@ -4476,7 +4464,7 @@ void builtin_getinventorylist(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); int j = 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); for (IOff0 i : IOff0::iter()) { @@ -4507,7 +4495,7 @@ void builtin_getactivatedpoolskilllist(ScriptState *st) int skill_pool_size = skill_pool(sd, pool_skills); int i, count = 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); for (i = 0; i < skill_pool_size; i++) { @@ -4540,7 +4528,7 @@ void builtin_getunactivatedpoolskilllist(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); int i, count = 0; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); for (i = 0; i < skill_pool_skills.size(); i++) { @@ -4572,7 +4560,7 @@ void builtin_poolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); SkillID skill_id = SkillID(conv_num(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); skill_pool_activate(sd, skill_id); clif_skillinfoblock(sd); @@ -4587,7 +4575,7 @@ void builtin_unpoolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); SkillID skill_id = SkillID(conv_num(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); skill_pool_deactivate(sd, skill_id); clif_skillinfoblock(sd); @@ -4831,7 +4819,7 @@ void builtin_nude(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); for (EQUIP i : EQUIPs) { @@ -4851,7 +4839,7 @@ static void builtin_unequipbyid(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); EQUIP slot_id = EQUIP(conv_num(st, &AARG(0))); @@ -4992,7 +4980,7 @@ void builtin_title(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); ZString msg = ZString(conv_str(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); clif_npc_send_title(sd->sess, st->oid, msg); } @@ -5013,7 +5001,7 @@ void builtin_smsg(ScriptState *st) int type = HARG(1) ? conv_num(st, &AARG(0)) : 0; ZString msg = ZString(conv_str(st, (HARG(1) ? &AARG(1) : &AARG(0)))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (type < 0 || type > 0xFF) type = 0; @@ -5028,7 +5016,7 @@ static void builtin_remotecmd(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (HARG(1)) { @@ -5055,7 +5043,7 @@ void builtin_sendcollision(ScriptState *st) short x1, y1, x2, y2; x1 = x2 = conv_num(st, &AARG(2)); y1 = y2 = conv_num(st, &AARG(3)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); if (HARG(5)) { @@ -5088,7 +5076,7 @@ void builtin_music(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); ZString msg = ZString(conv_str(st, &AARG(0))); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); clif_change_music(sd, msg); } @@ -5113,7 +5101,7 @@ void builtin_mapmask(ScriptState *st) else if(HARG(1) && nd) nd->bl_m->mask = map_mask; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); clif_send_mask(sd, map_mask); } @@ -5195,7 +5183,7 @@ void builtin_getlook(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); LOOK type = LOOK(conv_num(st, &AARG(0))); int val = -1; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); switch (type) { @@ -5239,7 +5227,7 @@ void builtin_getsavepoint(ScriptState *st) { int x, y, type; dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); type = conv_num(st, &AARG(0)); @@ -5333,7 +5321,7 @@ void builtin_isin(ScriptState *st) x2 = conv_num(st, &AARG(3)); y2 = conv_num(st, &AARG(4)); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, (sd->bl_x >= x1 && sd->bl_x <= x2) @@ -5369,7 +5357,7 @@ void builtin_shop(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); dumb_ptr<npc_data> nd; - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); NpcName name = stringish<NpcName>(ZString(conv_str(st, &AARG(0)))); nd = npc_name2id(name); @@ -5387,7 +5375,7 @@ static void builtin_isdead(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, pc_isdead(sd)); } @@ -5421,7 +5409,7 @@ static void builtin_getx(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, sd->bl_x); } @@ -5433,7 +5421,7 @@ static void builtin_gety(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, sd->bl_y); } @@ -5445,7 +5433,7 @@ static void builtin_getdir(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - script_nullpo_end(sd, "player not found"); + script_nullpo_end(sd, "player not found"_s); push_int<ScriptDataInt>(st->stack, static_cast<uint8_t>(sd->dir)); } @@ -5496,6 +5484,86 @@ void builtin_getmapmaxy(ScriptState *st) } /*========================================== + * Get the hash of a map + *------------------------------------------ + */ +static +void builtin_getmaphash(ScriptState *st) +{ + MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); + P<map_local> m = TRY_UNWRAP(map_mapname2mapid(mapname), return); + push_int<ScriptDataInt>(st->stack, m->hash); +} + +/*========================================== + * Get the map name from a hash + *------------------------------------------ + */ +static +void builtin_getmapnamefromhash(ScriptState *st) +{ + int hash = conv_num(st, &AARG(0)); + MapName mapname; + for (auto& mit : maps_db) + { + map_local *ml = static_cast<map_local *>(mit.second.get()); + if (ml->hash == hash) + { + mapname = ml->name_; + break; + } + } + push_str<ScriptDataStr>(st->stack, mapname); +} + +/*========================================== + * Look if a map exists + * return value: + * 0 = map does not exist + * 1 = map exists + *------------------------------------------ + */ +static +void builtin_mapexists(ScriptState *st) +{ + MapName mapname = stringish<MapName>(ZString(conv_str(st, &AARG(0)))); + push_int<ScriptDataInt>(st->stack, map_mapname2mapid(mapname).is_some()); +} + +/*========================================== + * Returns number of available maps + *------------------------------------------ + */ +static +void builtin_numberofmaps(ScriptState *st) +{ + push_int<ScriptDataInt>(st->stack, maps_db.size()); +} + +/*========================================== + * Get the map name of a specific maps_db index + *------------------------------------------ + */ +static +void builtin_getmapnamebyindex(ScriptState *st) +{ + int index = conv_num(st, &AARG(0)); + int count = 0; + + for (auto& mit : maps_db) + { + if (count == index) + { + push_str<ScriptDataStr>(st->stack, mit.second->name_); + return; + } + ++count; + } + + push_str<ScriptDataStr>(st->stack, ""_s); +} + +/*========================================== * Get the NPC's info *------------------------------------------ */ @@ -5524,7 +5592,7 @@ void builtin_strnpcinfo(ScriptState *st) nd = map_id_is_npc(st->oid); } - script_nullpo_end(nd, "npc not found"); + script_nullpo_end(nd, "npc not found"_s); switch(num) { @@ -5562,7 +5630,7 @@ void builtin_getnpcx(ScriptState *st) nd = map_id_is_npc(st->oid); } - script_nullpo_end(nd, "no npc"); + script_nullpo_end(nd, "no npc"_s); push_int<ScriptDataInt>(st->stack, nd->bl_x); } @@ -5584,7 +5652,7 @@ void builtin_getnpcy(ScriptState *st) nd = map_id_is_npc(st->oid); } - script_nullpo_end(nd, "no npc"); + script_nullpo_end(nd, "no npc"_s); push_int<ScriptDataInt>(st->stack, nd->bl_y); } @@ -5746,6 +5814,7 @@ BuiltinFunction builtin_functions[] = BUILTIN(shop, "s"_s, '\0'), BUILTIN(isdead, ""_s, 'i'), BUILTIN(aggravate, "i?"_s, '\0'), + BUILTIN(issummon, "i"_s, 'i'), BUILTIN(fakenpcname, "ssi"_s, '\0'), BUILTIN(puppet, "mxysi??"_s, 'i'), BUILTIN(destroy, "?"_s, '\0'), @@ -5758,6 +5827,11 @@ BuiltinFunction builtin_functions[] = BUILTIN(getmap, "?"_s, 's'), BUILTIN(getmapmaxx, "M"_s, 'i'), BUILTIN(getmapmaxy, "M"_s, 'i'), + BUILTIN(getmaphash, "M"_s, 'i'), + BUILTIN(getmapnamefromhash, "i"_s, 's'), + BUILTIN(mapexists, "M"_s, 'i'), + BUILTIN(numberofmaps, ""_s, 'i'), + BUILTIN(getmapnamebyindex, "i"_s, 's'), BUILTIN(mapexit, ""_s, '\0'), BUILTIN(freeloop, "i"_s, '\0'), BUILTIN(if_then_else, "iii"_s, 'v'), |