diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.cpp | 4 | ||||
-rw-r--r-- | src/map/clif.cpp | 14 | ||||
-rw-r--r-- | src/map/map.hpp | 2 | ||||
-rw-r--r-- | src/map/mob.cpp | 173 | ||||
-rw-r--r-- | src/map/npc-parse.cpp | 7 | ||||
-rw-r--r-- | src/map/npc.cpp | 3 | ||||
-rw-r--r-- | src/map/pc.cpp | 39 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 298 | ||||
-rw-r--r-- | src/map/script-parse.py | 2 | ||||
-rw-r--r-- | src/map/skill.cpp | 14 | ||||
-rw-r--r-- | src/map/storage.cpp | 3 |
11 files changed, 311 insertions, 248 deletions
diff --git a/src/map/battle.cpp b/src/map/battle.cpp index ac8dcf2..d66308d 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -2091,10 +2091,10 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, } if (wd.damage > 0 - && t_sc_data[StatusChange::SC_PHYS_SHIELD].timer + && (t_sc_data[StatusChange::SC_PHYS_SHIELD].timer || t_sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].timer) && target->bl_type == BL::PC) { - int reduction = t_sc_data[StatusChange::SC_PHYS_SHIELD].val1; + int reduction = std::max(t_sc_data[StatusChange::SC_PHYS_SHIELD].val1, t_sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active if (reduction > wd.damage) reduction = wd.damage; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index a5bb2ba..1b77be6 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -3865,6 +3865,12 @@ RecvResult clif_parse_WalkToXY(Session *s, dumb_ptr<map_session_data> sd) if (bool(sd->opt1) && sd->opt1 != (Opt1::_stone6)) return rv; + if (sd->sc_data[StatusChange::SC_CANTMOVE].timer) + { + pc_stop_walking(sd, 1); // this is a little hack since client is a bit bugged and still moves several tiles and then gets reset to the position where status was triggered with this it only moves 1 pixel or so and gets set back + return rv; + } + if (sd->invincible_timer) pc_delinvincibletimer(sd); @@ -4014,7 +4020,7 @@ RecvResult clif_parse_GetCharNameRequest(Session *s, dumb_ptr<map_session_data> dumb_ptr<mob_data> md = bl->is_mob(); nullpo_retr(rv, md); - if (md->name != MobName() && md->name != get_mob_db(md->mob_class).name && md->name.size() >= 4) + if (md->name.size() >= 4) fixed_95.char_name = stringish<CharName>(md->name); else fixed_95.char_name = stringish<CharName>(get_mob_db(md->mob_class).name); @@ -4620,7 +4626,8 @@ RecvResult clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd) OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.ioff2.unshift()]) { - if (bool(sdidn->mode & ItemMode::NO_DROP)) + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_DROP) && gmlvl.get_all_bits() < 60) { clif_displaymessage(sd->sess, "This item can't be dropped."_s); return rv; @@ -4909,7 +4916,8 @@ RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr<map_session_data> sd) if (fixed.zeny_or_ioff2.ok()) OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.zeny_or_ioff2.unshift()]) { - if (bool(sdidn->mode & ItemMode::NO_TRADE)) + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_TRADE) && gmlvl.get_all_bits() < 60) { clif_displaymessage(sd->sess, "This item can't be traded."_s); return rv; diff --git a/src/map/map.hpp b/src/map/map.hpp index de0e10b..8bb5aa7 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -184,7 +184,7 @@ struct map_session_data : block_list, SessionData None, None, None, None, None, None, None, None, None, None, }}; // explicit is better than implicit earray<IOff0, EQUIP, EQUIP::COUNT> equip_index_maybe; - int weight, max_weight; + int weight, max_weight, max_weight_override; MapName mapname_; Session *sess; // use this, you idiots! short to_x, to_y; diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 996e2bb..fc41d19 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -355,24 +355,25 @@ void mob_init(dumb_ptr<mob_data> md) { int i; const Species mob_class = md->mob_class; - const int mutations_nr = get_mob_db(mob_class).mutations_nr; - const int mutation_power = get_mob_db(mob_class).mutation_power; - - md->stats[mob_stat::LV] = get_mob_db(mob_class).lv; - md->stats[mob_stat::MAX_HP] = get_mob_db(mob_class).max_hp; - md->stats[mob_stat::STR] = get_mob_db(mob_class).attrs[ATTR::STR]; - md->stats[mob_stat::AGI] = get_mob_db(mob_class).attrs[ATTR::AGI]; - md->stats[mob_stat::VIT] = get_mob_db(mob_class).attrs[ATTR::VIT]; - md->stats[mob_stat::INT] = get_mob_db(mob_class).attrs[ATTR::INT]; - md->stats[mob_stat::DEX] = get_mob_db(mob_class).attrs[ATTR::DEX]; - md->stats[mob_stat::LUK] = get_mob_db(mob_class).attrs[ATTR::LUK]; - md->stats[mob_stat::ATK1] = get_mob_db(mob_class).atk1; - md->stats[mob_stat::ATK2] = get_mob_db(mob_class).atk2; - md->stats[mob_stat::ADELAY] = get_mob_db(mob_class).adelay.count(); - md->stats[mob_stat::DEF] = get_mob_db(mob_class).def; - md->stats[mob_stat::MDEF] = get_mob_db(mob_class).mdef; - md->stats[mob_stat::CRITICAL_DEF] = get_mob_db(mob_class).critical_def; - md->stats[mob_stat::SPEED] = get_mob_db(mob_class).speed.count(); + const mob_db_& mob_info = get_mob_db(mob_class); + const int mutations_nr = mob_info.mutations_nr; + const int mutation_power = mob_info.mutation_power; + + md->stats[mob_stat::LV] = mob_info.lv; + md->stats[mob_stat::MAX_HP] = mob_info.max_hp; + md->stats[mob_stat::STR] = mob_info.attrs[ATTR::STR]; + md->stats[mob_stat::AGI] = mob_info.attrs[ATTR::AGI]; + md->stats[mob_stat::VIT] = mob_info.attrs[ATTR::VIT]; + md->stats[mob_stat::INT] = mob_info.attrs[ATTR::INT]; + md->stats[mob_stat::DEX] = mob_info.attrs[ATTR::DEX]; + md->stats[mob_stat::LUK] = mob_info.attrs[ATTR::LUK]; + md->stats[mob_stat::ATK1] = mob_info.atk1; + md->stats[mob_stat::ATK2] = mob_info.atk2; + md->stats[mob_stat::ADELAY] = mob_info.adelay.count(); + md->stats[mob_stat::DEF] = mob_info.def; + md->stats[mob_stat::MDEF] = mob_info.mdef; + md->stats[mob_stat::CRITICAL_DEF] = mob_info.critical_def; + md->stats[mob_stat::SPEED] = mob_info.speed.count(); md->stats[mob_stat::XP_BONUS] = MOB_XP_BONUS_BASE; for (i = 0; i < mutations_nr; i++) @@ -2596,6 +2597,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, ); { + const mob_db_& mob_info = get_mob_db(md->mob_class); struct DmgLogParty { PartyPair p; @@ -2660,23 +2662,23 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, per = 1; base_exp = - ((get_mob_db(md->mob_class).base_exp * + ((mob_info.base_exp * md->stats[mob_stat::XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256; if (base_exp < 1) base_exp = 1; - if (sd && md && battle_config.pk_mode == 1 - && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) + if (sd && battle_config.pk_mode == 1 + && (mob_info.lv - sd->status.base_level >= 20)) { base_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris] } if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) base_exp = 0; // Added [Valaris] - job_exp = get_mob_db(md->mob_class).job_exp * per / 256; + job_exp = mob_info.job_exp * per / 256; if (job_exp < 1) job_exp = 1; - if (sd && md && battle_config.pk_mode == 1 - && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) + if (sd && battle_config.pk_mode == 1 + && (mob_info.lv - sd->status.base_level >= 20)) { job_exp *= 1.15; // pk_mode additional exp if monster >20 levels [Valaris] } @@ -2730,13 +2732,14 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris] break; // End - if (!get_mob_db(md->mob_class).dropitem[i].nameid) + const auto& drop_info = mob_info.dropitem[i]; + if (!drop_info.nameid) continue; - random_::Fixed<int, 10000> drop_rate = get_mob_db(md->mob_class).dropitem[i].p; - if (battle_config.drops_by_luk > 0 && sd && md) + random_::Fixed<int, 10000> drop_rate = drop_info.p; + if (sd && battle_config.drops_by_luk > 0) drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] - if (sd && md && battle_config.pk_mode == 1 - && (get_mob_db(md->mob_class).lv - sd->status.base_level >= 20)) + if (sd && battle_config.pk_mode == 1 + && (mob_info.lv - sd->status.base_level >= 20)) drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] // server-wide drop rate scaling @@ -2745,7 +2748,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, continue; struct delay_item_drop ditem {}; - ditem.nameid = get_mob_db(md->mob_class).dropitem[i].nameid; + ditem.nameid = drop_info.nameid; ditem.amount = 1; ditem.m = md->bl_m; ditem.x = md->bl_x; @@ -2796,9 +2799,11 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, npc_event(sd, md->npc_event, 0); // TODO: in the future, OnPCKillEvent, OnMobKillEvent and OnPCDieEvent should be combined - argrec_t arg[1] = + argrec_t arg[3] = { {"@mobID"_s, static_cast<int32_t>(unwrap<Species>(md->mob_class))}, + {"@mobX"_s, static_cast<int32_t>(md->bl_x)}, + {"@mobY"_s, static_cast<int32_t>(md->bl_y)}, }; npc_event_doall_l(stringish<ScriptLabel>("OnMobKillEvent"_s), sd->bl_id, arg); } @@ -3501,40 +3506,39 @@ int mobskill_event(dumb_ptr<mob_data> md, BF flag) static int mob_makedummymobdb(Species mob_class) { - int i; - - SNPRINTF(get_mob_db(mob_class).name, 24, "mob%d"_fmt, mob_class); - SNPRINTF(get_mob_db(mob_class).jname, 24, "mob%d"_fmt, mob_class); - get_mob_db(mob_class).lv = 1; - get_mob_db(mob_class).max_hp = 1000; - get_mob_db(mob_class).max_sp = 1; - get_mob_db(mob_class).base_exp = 2; - get_mob_db(mob_class).job_exp = 1; - get_mob_db(mob_class).range = 1; - get_mob_db(mob_class).atk1 = 7; - get_mob_db(mob_class).atk2 = 10; - get_mob_db(mob_class).def = 0; - get_mob_db(mob_class).mdef = 0; - get_mob_db(mob_class).attrs[ATTR::STR] = 1; - get_mob_db(mob_class).attrs[ATTR::AGI] = 1; - get_mob_db(mob_class).attrs[ATTR::VIT] = 1; - get_mob_db(mob_class).attrs[ATTR::INT] = 1; - get_mob_db(mob_class).attrs[ATTR::DEX] = 6; - get_mob_db(mob_class).attrs[ATTR::LUK] = 2; - get_mob_db(mob_class).range2 = 10; - get_mob_db(mob_class).range3 = 10; - get_mob_db(mob_class).size = 0; // 1 - get_mob_db(mob_class).race = Race::formless; - get_mob_db(mob_class).element = LevelElement{0, Element::neutral}; - get_mob_db(mob_class).mode = MobMode::ZERO; - get_mob_db(mob_class).speed = 300_ms; - get_mob_db(mob_class).adelay = 1000_ms; - get_mob_db(mob_class).amotion = 500_ms; - get_mob_db(mob_class).dmotion = 500_ms; - for (i = 0; i < MaxDrops; i++) - { - get_mob_db(mob_class).dropitem[i].nameid = ItemNameId(); - get_mob_db(mob_class).dropitem[i].p.num = 0; + mob_db_& mob_info = get_mob_db(mob_class); + SNPRINTF(mob_info.name, 24, "mob%d"_fmt, mob_class); + SNPRINTF(mob_info.jname, 24, "mob%d"_fmt, mob_class); + mob_info.lv = 1; + mob_info.max_hp = 1000; + mob_info.max_sp = 1; + mob_info.base_exp = 2; + mob_info.job_exp = 1; + mob_info.range = 1; + mob_info.atk1 = 7; + mob_info.atk2 = 10; + mob_info.def = 0; + mob_info.mdef = 0; + mob_info.attrs[ATTR::STR] = 1; + mob_info.attrs[ATTR::AGI] = 1; + mob_info.attrs[ATTR::VIT] = 1; + mob_info.attrs[ATTR::INT] = 1; + mob_info.attrs[ATTR::DEX] = 6; + mob_info.attrs[ATTR::LUK] = 2; + mob_info.range2 = 10; + mob_info.range3 = 10; + mob_info.size = 0; // 1 + mob_info.race = Race::formless; + mob_info.element = LevelElement{0, Element::neutral}; + mob_info.mode = MobMode::ZERO; + mob_info.speed = 300_ms; + mob_info.adelay = 1000_ms; + mob_info.amotion = 500_ms; + mob_info.dmotion = 500_ms; + for (int i = 0; i < MaxDrops; i++) + { + mob_info.dropitem[i].nameid = ItemNameId(); + mob_info.dropitem[i].p.num = 0; } return 0; } @@ -3654,56 +3658,55 @@ bool mob_readdb(ZString filename) continue; } - if (get_mob_db(mob_class).base_exp < 0) + if (mdbv.base_exp < 0) { PRINTF("bad mob line: Xp needs to be greater than 0. %s\n"_fmt, line); rv = false; continue; } - if (get_mob_db(mob_class).base_exp > 1000000000) + if (mdbv.base_exp > 1000000000) { PRINTF("bad mob line: Xp needs to be less than 1000000000. %s\n"_fmt, line); rv = false; continue; } - if (get_mob_db(mob_class).job_exp < 0) + if (mdbv.job_exp < 0) { PRINTF("bad mob line: Job Xp needs to be greater than 0. %s\n"_fmt, line); rv = false; continue; } - if (get_mob_db(mob_class).job_exp > 1000000000) + if (mdbv.job_exp > 1000000000) { PRINTF("bad mob line: Job Xp needs to be less than 1000000000. %s\n"_fmt, line); rv = false; continue; } - // TODO move this lower - get_mob_db(mob_class) = std::move(mdbv); - for (int i = 0; i < MaxDrops; i++) { - int rate = get_mob_db(mob_class).dropitem[i].p.num; + int rate = mdbv.dropitem[i].p.num; if (rate < 1) rate = 1; if (rate > 10000) rate = 10000; - get_mob_db(mob_class).dropitem[i].p.num = rate; + mdbv.dropitem[i].p.num = rate; } - get_mob_db(mob_class).skills.clear(); + mdbv.skills.clear(); + + mdbv.hair = 0; + mdbv.hair_color = 0; + mdbv.weapon = 0; + mdbv.shield = ItemNameId(); + mdbv.head_top = ItemNameId(); + mdbv.head_mid = ItemNameId(); + mdbv.head_buttom = ItemNameId(); + mdbv.clothes_color = 0; //Add for player monster dye - Valaris - get_mob_db(mob_class).hair = 0; - get_mob_db(mob_class).hair_color = 0; - get_mob_db(mob_class).weapon = 0; - get_mob_db(mob_class).shield = ItemNameId(); - get_mob_db(mob_class).head_top = ItemNameId(); - get_mob_db(mob_class).head_mid = ItemNameId(); - get_mob_db(mob_class).head_buttom = ItemNameId(); - get_mob_db(mob_class).clothes_color = 0; //Add for player monster dye - Valaris + if (mdbv.base_exp == 0) + mdbv.base_exp = mob_gen_exp(&mdbv); - if (get_mob_db(mob_class).base_exp == 0) - get_mob_db(mob_class).base_exp = mob_gen_exp(&get_mob_db(mob_class)); + get_mob_db(mob_class) = std::move(mdbv); } PRINTF("read %s done\n"_fmt, filename); } diff --git a/src/map/npc-parse.cpp b/src/map/npc-parse.cpp index df1a09a..8865ea6 100644 --- a/src/map/npc-parse.cpp +++ b/src/map/npc-parse.cpp @@ -273,15 +273,16 @@ bool npc_load_monster(ast::npc::Monster& monster) md->bl_m = m; md->bl_x = x; md->bl_y = y; - MobName expected = get_mob_db(mob_class).jname; + const mob_db_& mob_info = get_mob_db(mob_class); + MobName expected = mob_info.jname; if (monster.name.data != expected) { monster.name.span.warning(STRPRINTF("Visible label/jname should match: %s"_fmt, expected)); } if (monster.name.data == ENGLISH_NAME) - md->name = get_mob_db(mob_class).name; + md->name = mob_info.name; else if (monster.name.data == JAPANESE_NAME) - md->name = get_mob_db(mob_class).jname; + md->name = mob_info.jname; else md->name = monster.name.data; diff --git a/src/map/npc.cpp b/src/map/npc.cpp index a6d3dda..0a7bfc2 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -1006,7 +1006,8 @@ int npc_selllist(dumb_ptr<map_session_data> sd, OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[item_list[i].ioff2.unshift()]) { - if (bool(sdidn->mode & ItemMode::NO_SELL_TO_NPC)) + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_SELL_TO_NPC) && gmlvl.get_all_bits() < 60) { //clif_displaymessage(sd->sess, "This item can't be sold to an NPC."_s); // M+ already outputs "Unable to sell unsellable item." on return value 3. diff --git a/src/map/pc.cpp b/src/map/pc.cpp index b6bce38..ecfd50e 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -870,6 +870,12 @@ int pc_authok(AccountId id, int login_id2, ClientVersion client_version, sd->quick_regeneration_hp.amount = 0; sd->quick_regeneration_sp.amount = 0; sd->heal_xp = 0; + sd->max_weight_override = 0; + sd->activity.kills = 0; + sd->activity.casts = 0; + sd->activity.items_used = 0; + sd->activity.tiles_walked = 0; + sd->activity.attacks = 0; sd->canact_tick = tick; sd->canmove_tick = tick; sd->attackabletime = tick; @@ -1121,7 +1127,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) b_attackrange, b_matk1, b_matk2, b_mdef, b_mdef2; int b_base_atk; int bl; - int aspd_rate, refinedef = 0; + int aspd_rate, speed_rate, refinedef = 0; int str, dstr, dex; int b_pvpchannel = 0; @@ -1473,6 +1479,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) } aspd_rate = sd->aspd_rate; + speed_rate = sd->speed_rate; //攻撃速度増加 | Increased attack speed @@ -1483,6 +1490,9 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->hit += skill_power(sd, SkillID::AC_OWL) / 10; // 20 for 200 } + if (sd->max_weight_override) + sd->max_weight = sd->max_weight_override; + sd->max_weight += 1000; bl = sd->status.base_level; @@ -1548,12 +1558,15 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) /* Slow down if protected */ - if (sd->sc_data[StatusChange::SC_PHYS_SHIELD].timer) - aspd_rate += sd->sc_data[StatusChange::SC_PHYS_SHIELD].val1; + if (sd->sc_data[StatusChange::SC_PHYS_SHIELD].timer || sd->sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].timer) + aspd_rate += std::max(sd->sc_data[StatusChange::SC_PHYS_SHIELD].val1, sd->sc_data[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active + + if (sd->sc_data[StatusChange::SC_SLOWMOVE].timer) + speed_rate += sd->sc_data[StatusChange::SC_SLOWMOVE].val1; } - if (sd->speed_rate != 100) - sd->speed = sd->speed * sd->speed_rate / 100; + if (speed_rate != 100) + sd->speed = sd->speed * speed_rate / 100; sd->speed = std::max(sd->speed, 1_ms); if (sd->speed_cap < interval_t::zero()) sd->speed_cap = interval_t::zero(); @@ -1894,6 +1907,14 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) if (!sd->state.lr_flag_is_arrow_2) sd->base_weapon_delay_adjust += interval_t(val); break; + case SP::MAXWEIGHT: + if (!sd->state.lr_flag_is_arrow_2) + sd->max_weight = val; + break; + case SP::MAXWEIGHT_ADD: + if (!sd->state.lr_flag_is_arrow_2) + sd->max_weight += val; + break; default: if (battle_config.error_log) PRINTF("pc_bonus: unknown type %d %d !\n"_fmt, @@ -3721,6 +3742,9 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type) case SP::MAXWEIGHT: val = sd ? sd->max_weight : 0; break; + case SP::MAXWEIGHT_OVERRIDE: + val = sd ? sd->max_weight_override : 0; + break; case SP::BASEEXP: val = sd ? sd->status.base_exp : 0; break; @@ -4048,6 +4072,11 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val) sd->max_weight = val; clif_updatestatus(sd, type); break; + case SP::MAXWEIGHT_OVERRIDE: + nullpo_retz(sd); + sd->max_weight_override = val; + pc_calcstatus(sd, (int)CalcStatusKind::NORMAL_RECALC); + break; case SP::HP: nullpo_retz(sd); // TODO: mob mutation diff --git a/src/map/script-fun.cpp b/src/map/script-fun.cpp index 74a70b3..64ba542 100644 --- a/src/map/script-fun.cpp +++ b/src/map/script-fun.cpp @@ -2683,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))); @@ -2697,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: @@ -2800,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 @@ -3022,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) @@ -3030,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)) @@ -3053,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; } } @@ -3067,7 +3013,7 @@ void builtin_mobinfo_droparrays(ScriptState *st) status = 2; break; } - + } push_int<ScriptDataInt>(st->stack, status); } @@ -3097,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 { @@ -3114,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); @@ -3920,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: @@ -3929,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: @@ -4362,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) @@ -5557,6 +5517,53 @@ void builtin_getmapnamefromhash(ScriptState *st) } /*========================================== + * 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 *------------------------------------------ */ @@ -5822,6 +5829,9 @@ BuiltinFunction builtin_functions[] = 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'), diff --git a/src/map/script-parse.py b/src/map/script-parse.py index 199e348..3346b92 100644 --- a/src/map/script-parse.py +++ b/src/map/script-parse.py @@ -106,7 +106,7 @@ class ScriptBuffer(object): code_begin = code['_M_impl']['_M_start'] code_end = code['_M_impl']['_M_finish'] code_size = int(code_end - code_begin) - r = iter(range(code_size)) + r = iter(list(range(code_size))) for i in r: buf = [] for label in labels_dict.get(i, []): diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 87bbbda..f70a626 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -201,9 +201,9 @@ int skill_additional_effect(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, } sc_def_phys_shield_spell = 0; - if (battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].timer) + if (battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].timer || battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD_ITEM].timer) sc_def_phys_shield_spell = - battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].val1; + std::max(battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD].val1, battle_get_sc_data(bl)[StatusChange::SC_PHYS_SHIELD_ITEM].val1); // highest value is taken here but serverdata should make sure only one of those is active // 対象の耐性 | Target resistance luk = battle_get_luk(bl); @@ -753,7 +753,9 @@ void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerDa case StatusChange::SC_ATKPOT: /* attack potion [Valaris] */ case StatusChange::SC_MATKPOT: /* magic attack potion [Valaris] */ case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_HASTE: + case StatusChange::SC_SLOWMOVE: calc_flag = 1; break; @@ -765,6 +767,9 @@ void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerDa case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_COOLDOWN_CG: + case StatusChange::SC_CANTMOVE: break; /* option2 */ @@ -1030,7 +1035,9 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, case StatusChange::SC_HASTE: case StatusChange::SC_PHYS_SHIELD: + case StatusChange::SC_PHYS_SHIELD_ITEM: case StatusChange::SC_MBARRIER: + case StatusChange::SC_SLOWMOVE: calc_flag = 1; break; case StatusChange::SC_HALT_REGENERATE: @@ -1043,6 +1050,9 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type, case StatusChange::SC_COOLDOWN_ENCH: case StatusChange::SC_COOLDOWN_KOY: case StatusChange::SC_COOLDOWN_UPMARMU: + case StatusChange::SC_COOLDOWN_SG: + case StatusChange::SC_COOLDOWN_CG: + case StatusChange::SC_CANTMOVE: break; case StatusChange::SC_FLYING_BACKPACK: updateflag = SP::WEIGHT; diff --git a/src/map/storage.cpp b/src/map/storage.cpp index cab3f0f..dc1fe62 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -188,7 +188,8 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount) OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[index]) { - if (bool(sdidn->mode & ItemMode::NO_STORAGE)) + GmLevel gmlvl = pc_isGM(sd); + if (bool(sdidn->mode & ItemMode::NO_STORAGE) && gmlvl.get_all_bits() < 60) { clif_displaymessage(sd->sess, "This item can't be stored."_s); return 0; |