From 148ab787d51c7c9c71540f799d37fb748cf19135 Mon Sep 17 00:00:00 2001 From: HoraK-FDF Date: Thu, 17 Nov 2022 13:37:20 +0000 Subject: MobInfo * includes @mobinfo ingame command aswell as mobinfo functions for scripts * enhanced summon script command to take a name to support spawn names * moved @summon to where other mob related commands are * added enchanter and koyntety cooldown symbols * some translations * some constants added for drops and mobs --- src/map/script-fun.cpp | 441 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 433 insertions(+), 8 deletions(-) (limited to 'src/map/script-fun.cpp') diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index bcb5a45..58646bc 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -2623,6 +2623,423 @@ void builtin_getexp(ScriptState *st) } +/*========================================== + * Returns attributes of a monster + * return value -1 = mob not found + *------------------------------------------ + */ +static +void builtin_mobinfo(ScriptState *st) +{ + Species mob_id = wrap(conv_num(st, &AARG(0))); + MobInfo request = MobInfo(conv_num(st, &AARG(1))); + int info = 0; + AString info_str; + char mode = 0; // 0 = int, 1 = str + + if (mobdb_checkid(mob_id) == Species()) + { + push_int(st->stack, -1); + return; + } + + switch (request) + { + case MobInfo::ID: + info = unwrap(mob_id); + break; + case MobInfo::ENG_NAME: + info_str = get_mob_db(mob_id).name; + mode = 1; + break; + case MobInfo::JAP_NAME: + info_str = get_mob_db(mob_id).jname; + mode = 1; + break; + case MobInfo::LVL: + info = get_mob_db(mob_id).lv; + break; + case MobInfo::HP: + info = get_mob_db(mob_id).max_hp; + break; + case MobInfo::SP: + info = get_mob_db(mob_id).max_sp; + break; + case MobInfo::BASE_EXP: + info = get_mob_db(mob_id).base_exp; + break; + case MobInfo::JOB_EXP: + info = get_mob_db(mob_id).job_exp; + break; + case MobInfo::RANGE1: + info = get_mob_db(mob_id).range; + break; + case MobInfo::ATK1: + info = get_mob_db(mob_id).atk1; + break; + case MobInfo::ATK2: + info = get_mob_db(mob_id).atk2; + break; + case MobInfo::DEF: + info = get_mob_db(mob_id).def; + break; + case MobInfo::MDEF: + info = get_mob_db(mob_id).mdef; + break; + case MobInfo::STR: + info = get_mob_db(mob_id).attrs[ATTR::STR]; + break; + case MobInfo::AGI: + info = get_mob_db(mob_id).attrs[ATTR::AGI]; + break; + case MobInfo::VIT: + info = get_mob_db(mob_id).attrs[ATTR::VIT]; + break; + case MobInfo::INT: + info = get_mob_db(mob_id).attrs[ATTR::INT]; + break; + case MobInfo::DEX: + info = get_mob_db(mob_id).attrs[ATTR::DEX]; + break; + case MobInfo::LUK: + info = get_mob_db(mob_id).attrs[ATTR::LUK]; + break; + case MobInfo::RANGE2: + info = get_mob_db(mob_id).range2; + break; + case MobInfo::RANGE3: + info = get_mob_db(mob_id).range3; + break; + case MobInfo::SCALE: + info = get_mob_db(mob_id).size; + break; + case MobInfo::RACE: + info = int(get_mob_db(mob_id).race); + break; + case MobInfo::ELEMENT: + info = int(get_mob_db(mob_id).element.element); + break; + case MobInfo::ELEMENT_LVL: + info = get_mob_db(mob_id).element.level; + break; + case MobInfo::MODE: + info = int(get_mob_db(mob_id).mode); + break; + case MobInfo::SPEED: + info = get_mob_db(mob_id).speed.count(); + break; + case MobInfo::ADELAY: + info = get_mob_db(mob_id).adelay.count(); + break; + case MobInfo::AMOTION: + info = get_mob_db(mob_id).amotion.count(); + break; + case MobInfo::DMOTION: + info = get_mob_db(mob_id).dmotion.count(); + break; + case MobInfo::MUTATION_NUM: + info = get_mob_db(mob_id).mutations_nr; + break; + case MobInfo::MUTATION_POWER: + info = get_mob_db(mob_id).mutation_power; + break; + case MobInfo::DROPID1: + info = unwrap(get_mob_db(mob_id).dropitem[0].nameid); + break; + case MobInfo::DROPNAME1: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT1: + info = get_mob_db(mob_id).dropitem[0].p.num; + break; + case MobInfo::DROPID2: + info = unwrap(get_mob_db(mob_id).dropitem[1].nameid); + break; + case MobInfo::DROPNAME2: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT2: + info = get_mob_db(mob_id).dropitem[1].p.num; + break; + case MobInfo::DROPID3: + info = unwrap(get_mob_db(mob_id).dropitem[2].nameid); + break; + case MobInfo::DROPNAME3: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT3: + info = get_mob_db(mob_id).dropitem[2].p.num; + break; + case MobInfo::DROPID4: + info = unwrap(get_mob_db(mob_id).dropitem[3].nameid); + break; + case MobInfo::DROPNAME4: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT4: + info = get_mob_db(mob_id).dropitem[3].p.num; + break; + case MobInfo::DROPID5: + info = unwrap(get_mob_db(mob_id).dropitem[4].nameid); + break; + case MobInfo::DROPNAME5: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT5: + info = get_mob_db(mob_id).dropitem[4].p.num; + break; + case MobInfo::DROPID6: + info = unwrap(get_mob_db(mob_id).dropitem[5].nameid); + break; + case MobInfo::DROPNAME6: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT6: + info = get_mob_db(mob_id).dropitem[5].p.num; + break; + case MobInfo::DROPID7: + info = unwrap(get_mob_db(mob_id).dropitem[6].nameid); + break; + case MobInfo::DROPNAME7: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT7: + info = get_mob_db(mob_id).dropitem[6].p.num; + break; + case MobInfo::DROPID8: + info = unwrap(get_mob_db(mob_id).dropitem[7].nameid); + break; + case MobInfo::DROPNAME8: + { + Option> 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(""_s)); + mode = 1; + } + break; + case MobInfo::DROPPERCENT8: + info = get_mob_db(mob_id).dropitem[7].p.num; + break; + default: + PRINTF("builtin_mobinfo: unknown request\n"_fmt); + push_int(st->stack, -1); + return; + break; + } + if (!mode) + push_int(st->stack, info); + else + push_str(st->stack, info_str); +} + +/*========================================== + * Returns drops of a monster to an array + * return values: + * 0 = mob not found or error + * 1 = mob found and has drops + * 2 = mob found and has no drops + *------------------------------------------ + */ +static +void builtin_mobinfo_droparrays(ScriptState *st) +{ + dumb_ptr bl = nullptr; + + Species mob_id = wrap(conv_num(st, &AARG(0))); + + MobInfo_DropArrays request = MobInfo_DropArrays(conv_num(st, &AARG(1))); + + SIR reg = AARG(2).get_if()->reg; + ZString name = variable_names.outtern(reg.base()); + + char prefix = name.front(); + char postfix = name.back(); + + int status = 0; // 0 = mob not found or error, 1 = mob found and has drops, 2 = mob found and has no drops + + if (prefix != '$' && prefix != '@' && prefix != '.') + { + PRINTF("builtin_mobinfo_droparrays: illegal scope!\n"_fmt); + push_int(st->stack, 0); + return; + } + + if (prefix == '.' && !name.startswith(".@"_s)) + bl = map_id_is_npc(st->oid); + else if (prefix != '$' && !name.startswith(".@"_s)) + { + bl = map_id_is_player(st->rid); + script_nullpo_end(bl, "player not found"); + } + + switch (request) + { + case MobInfo_DropArrays::IDS: + if (postfix == '$') + { + PRINTF("builtin_mobinfo_droparrays: wrong array type for ID's (Int expected but String found)!\n"_fmt); + push_int(st->stack, 0); + return; + } + break; + case MobInfo_DropArrays::NAMES: + if (postfix != '$') + { + PRINTF("builtin_mobinfo_droparrays: wrong array type for Names (String expected but Int found)!\n"_fmt); + push_int(st->stack, 0); + return; + } + break; + case MobInfo_DropArrays::PERCENTS: + if (postfix == '$') + { + PRINTF("builtin_mobinfo_droparrays: wrong array type for Percents (Int expected but String found)!\n"_fmt); + push_int(st->stack, 0); + return; + } + break; + default: + PRINTF("builtin_mobinfo_droparrays: unknown request\n"_fmt); + push_int(st->stack, 0); + return; + break; + } + + if (mobdb_checkid(mob_id) == Species()) + { + push_int(st->stack, status); + return; + } + + for (int i = 0; i < MaxDrops; ++i) + if (get_mob_db(mob_id).dropitem[i].nameid) + { + status = 1; + switch (request) + { + case MobInfo_DropArrays::IDS: + if (name.startswith(".@"_s)) + { + struct script_data vd = script_data(ScriptDataInt{unwrap(get_mob_db(mob_id).dropitem[i].nameid)}); + set_scope_reg(st, reg.iplus(i), &vd); + } + else + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), unwrap(get_mob_db(mob_id).dropitem[i].nameid)); + break; + case MobInfo_DropArrays::NAMES: + { + Option> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid)); + RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish(""_s)); + + if (name.startswith(".@"_s)) + { + struct script_data vd = script_data(ScriptDataStr{item_name}); + set_scope_reg(st, reg.iplus(i), &vd); + } + else + set_reg(bl, VariableCode::VARIABLE, reg.iplus(i), item_name); + break; + } + case MobInfo_DropArrays::PERCENTS: + if (name.startswith(".@"_s)) + { + struct script_data vd = script_data(ScriptDataInt{get_mob_db(mob_id).dropitem[i].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); + break; + } + } + else + { + if (i == 0) + status = 2; + break; + } + + push_int(st->stack, status); +} + +/*========================================== + * Returns drops of a monster to standardized arrays + * return values: + * 0 = mob not found + * 1 = mob found and has drops + * 2 = mob found and has no drops + *------------------------------------------ + */ +static +void builtin_getmobdrops(ScriptState *st) +{ + dumb_ptr bl = nullptr; + + Species mob_id = wrap(conv_num(st, &AARG(0))); + + int status = 0; // 0 = mob not found, 1 = mob found and has drops, 2 = mob found and has no drops + int i = 0; + + if (mobdb_checkid(mob_id) == Species()) + { + push_int(st->stack, status); + return; + } + + status = 1; + + for (; i < MaxDrops; ++i) + if (get_mob_db(mob_id).dropitem[i].nameid) + { + set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_item"_s), i), get_mob_db(mob_id).dropitem[i].p.num); + + Option> i_data = Some(itemdb_search(get_mob_db(mob_id).dropitem[i].nameid)); + RString item_name = i_data.pmd_pget(&item_data::name).copy_or(stringish(""_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); + } + else + { + if (i == 0) + status = 2; + break; + } + + if (status == 1) + set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_count"_s), 0), i); + else + set_reg(bl, VariableCode::VARIABLE, SIR::from(variable_names.intern("$@MobDrop_count"_s), 0), 0); + + push_int(st->stack, status); +} + /*========================================== * *------------------------------------------ @@ -2636,11 +3053,12 @@ void builtin_summon(ScriptState *st) int y = conv_num(st, &AARG(2)); dumb_ptr owner_e = map_id2bl(wrap(conv_num(st, &AARG(3)))); dumb_ptr owner = nullptr; - Species monster_id = wrap(conv_num(st, &AARG(4))); - MonsterAttitude monster_attitude = static_cast(conv_num(st, &AARG(5))); - interval_t lifespan = static_cast(conv_num(st, &AARG(6))); + MobName str = stringish(ZString(conv_str(st, &AARG(4)))); + Species monster_id = wrap(conv_num(st, &AARG(5))); + MonsterAttitude monster_attitude = static_cast(conv_num(st, &AARG(6))); + interval_t lifespan = static_cast(conv_num(st, &AARG(7))); if (HARG(7)) - extract(ZString(conv_str(st, &AARG(7))), &event); + extract(ZString(conv_str(st, &AARG(8))), &event); if (!owner_e) { @@ -2652,7 +3070,9 @@ void builtin_summon(ScriptState *st) && owner_e->bl_type == BL::PC) owner = owner_e->is_player(); // XXX in the future this should also work with mobs as owner - BlockId mob_id = mob_once_spawn(owner, map, x, y, MobName(), monster_id, 1, event); + if (!str) + str = MobName(); + BlockId mob_id = mob_once_spawn(owner, map, x, y, str, monster_id, 1, event); dumb_ptr mob = map_id_is_mob(mob_id); if (mob) @@ -3157,9 +3577,9 @@ void builtin_getusers(ScriptState *st) int val = 0; switch (flag & 0x07) { - /*case 0: + case 0: val = bl->bl_m->users; - break;*/ + break; case 1: val = map_getusers(); break; @@ -3404,6 +3824,8 @@ void builtin_sc_start(ScriptState *st) case StatusChange::SC_COOLDOWN_MT: case StatusChange::SC_COOLDOWN_R: case StatusChange::SC_COOLDOWN_AR: + case StatusChange::SC_COOLDOWN_ENCH: + case StatusChange::SC_COOLDOWN_KOY: break; default: @@ -5129,7 +5551,10 @@ BuiltinFunction builtin_functions[] = BUILTIN(gettime, "i"_s, 'i'), BUILTIN(openstorage, ""_s, '\0'), BUILTIN(getexp, "ii"_s, '\0'), - BUILTIN(summon, "Mxysmii?"_s, '\0'), + BUILTIN(mobinfo, "ii"_s, 'v'), + BUILTIN(mobinfo_droparrays, "iiN"_s, 'i'), + BUILTIN(getmobdrops, "i"_s, 'i'), + BUILTIN(summon, "Mxyssmii?"_s, '\0'), BUILTIN(monster, "Mxysmi?"_s, '\0'), BUILTIN(areamonster, "Mxyxysmi?"_s, '\0'), BUILTIN(killmonster, "ME"_s, '\0'), -- cgit v1.2.3-60-g2f50