summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/battle.cpp4
-rw-r--r--src/map/clif.cpp14
-rw-r--r--src/map/map.hpp2
-rw-r--r--src/map/mob.cpp173
-rw-r--r--src/map/npc-parse.cpp7
-rw-r--r--src/map/npc.cpp3
-rw-r--r--src/map/pc.cpp39
-rw-r--r--src/map/script-fun.cpp298
-rw-r--r--src/map/script-parse.py2
-rw-r--r--src/map/skill.cpp14
-rw-r--r--src/map/storage.cpp3
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;