summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.cpp2
-rw-r--r--src/conf/install.hpp.in (renamed from src/conf/install.hpp)7
-rw-r--r--src/conf/version.hpp.in (renamed from src/conf/version.hpp)21
-rw-r--r--src/main-gdb-head.py2
-rw-r--r--src/map/battle.cpp32
-rw-r--r--src/map/clif.cpp33
-rw-r--r--src/map/map.cpp17
-rw-r--r--src/map/map.hpp9
-rw-r--r--src/map/mob.cpp175
-rw-r--r--src/map/npc-parse.cpp15
-rw-r--r--src/map/npc.cpp41
-rw-r--r--src/map/pc.cpp62
-rw-r--r--src/map/script-fun.cpp536
-rw-r--r--src/map/script-parse.py2
-rw-r--r--src/map/skill.cpp14
-rw-r--r--src/map/storage.cpp11
-rw-r--r--src/mmo/clif.t.hpp2
-rw-r--r--src/mmo/enums.hpp2
-rw-r--r--src/mmo/skill.t.hpp8
-rw-r--r--src/mmo/version.cpp2
-rw-r--r--src/shared/lib.cpp34
21 files changed, 626 insertions, 401 deletions
diff --git a/src/char/char.cpp b/src/char/char.cpp
index 7ffdd0f..2194ef2 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -777,8 +777,8 @@ void create_online_files(void)
stamp_time(timetemp);
// write heading
FPRINTF(fp2, "<HTML>\n"_fmt);
- FPRINTF(fp2, " <META http-equiv=\"Refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds
FPRINTF(fp2, " <HEAD>\n"_fmt);
+ FPRINTF(fp2, " <META http-equiv=\"refresh\" content=\"%d\">\n"_fmt, char_conf.online_refresh_html); // update on client explorer every x seconds
FPRINTF(fp2, " <TITLE>Online Players on %s</TITLE>\n"_fmt,
char_conf.server_name);
FPRINTF(fp2, " </HEAD>\n"_fmt);
diff --git a/src/conf/install.hpp b/src/conf/install.hpp.in
index 42fd125..e63164a 100644
--- a/src/conf/install.hpp
+++ b/src/conf/install.hpp.in
@@ -20,10 +20,9 @@
// just mention "fwd.hpp" to make formatter happy
-#include "conf-raw/str-PACKAGESYSCONFDIR.h"
-#include "conf-raw/str-PACKAGELOCALSTATEDIR.h"
-#include "conf-raw/str-PACKAGEDATADIR.h"
-
+#define PACKAGESYSCONFDIR "@SYSCONFDIR@/tmwa"_s
+#define PACKAGELOCALSTATEDIR "@LOCALSTATEDIR@/tmwa"_s
+#define PACKAGEDATADIR "@PACKAGEDATADIR@"_s
namespace tmwa
{
diff --git a/src/conf/version.hpp b/src/conf/version.hpp.in
index df8a8b6..126fae2 100644
--- a/src/conf/version.hpp
+++ b/src/conf/version.hpp.in
@@ -20,20 +20,19 @@
// just mention "fwd.hpp" to make formatter happy
-#include "conf-raw/str-VERSION_FULL.h"
-#include "conf-raw/str-VERSION_HASH.h"
+#define VERSION_FULL "@VERSION_FULL@"_s
+#define VERSION_HASH "@VERSION_HASH@"_s
-#include "conf-raw/int-VERSION_MAJOR.h"
-#include "conf-raw/int-VERSION_MINOR.h"
-#include "conf-raw/int-VERSION_PATCH.h"
-#include "conf-raw/int-VERSION_DEVEL.h"
+#define VERSION_MAJOR @PROJECT_VERSION_MAJOR@
+#define VERSION_MINOR @PROJECT_VERSION_MINOR@
+#define VERSION_PATCH @PROJECT_VERSION_PATCH@
+#define VERSION_DEVEL @PROJECT_VERSION_TWEAK@
-#include "conf-raw/str-VENDOR_NAME.h"
-#include "conf-raw/int-VENDOR_POINT.h"
-#include "conf-raw/str-VENDOR_SOURCE.h"
-
-#include "conf-raw/str-VERSION_STRING.h"
+#define VENDOR_NAME "@VENDOR_NAME@"_s
+#define VENDOR_POINT @VENDOR_POINT@
+#define VENDOR_SOURCE "@VENDOR_SOURCE@"_s
+#define VERSION_STRING "@VERSION_STRING@"_s
namespace tmwa
{
diff --git a/src/main-gdb-head.py b/src/main-gdb-head.py
index a465c97..09e22fe 100644
--- a/src/main-gdb-head.py
+++ b/src/main-gdb-head.py
@@ -5,7 +5,7 @@
# gdb sticks everything in one scope.
# This lets us enumerate what *we* added.
-initial_globals = {id(v):v for v in globals().values()}
+initial_globals = {id(v):v for v in list(globals().values())}
import re
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index b745e05..d66308d 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -2060,18 +2060,28 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target,
// 攻撃対象となりうるので攻撃 | Attack because it can be attacked
if (sd && sd->status.weapon == ItemLook::W_BOW)
{
- IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW];
- if (aidx.ok())
- {
- if (battle_config.arrow_decrement)
- pc_delitem(sd, aidx, 1, 0);
- }
- else
+ IOff0 widx = sd->equip_index_maybe[EQUIP::WEAPON];
+
+ OMATCH_BEGIN_SOME (sdidw, sd->inventory_data[widx])
{
- clif_arrow_fail(sd, 0);
- return ATK::ZERO;
+ if (!bool(sdidw->mode & ItemMode::DONT_USE_AMMO))
+ {
+ IOff0 aidx = sd->equip_index_maybe[EQUIP::ARROW];
+ if (aidx.ok())
+ {
+ if (battle_config.arrow_decrement)
+ pc_delitem(sd, aidx, 1, 0);
+ }
+ else
+ {
+ clif_arrow_fail(sd, 0);
+ return ATK::ZERO;
+ }
+ }
}
+ OMATCH_END ();
}
+
wd = battle_calc_weapon_attack(src, target, SkillID::ZERO, 0, 0);
// significantly increase injuries for hasted characters
@@ -2081,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 9edf2af..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);
@@ -4617,11 +4623,18 @@ RecvResult clif_parse_DropItem(Session *s, dumb_ptr<map_session_data> sd)
clif_displaymessage(sd->sess, "Can't drop items here."_s);
return rv;
}
- if (bool(itemdb_search(sd->status.inventory[fixed.ioff2.unshift()].nameid)->mode & ItemMode::NO_DROP))
+
+ OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.ioff2.unshift()])
{
- clif_displaymessage(sd->sess, "This item can't be dropped."_s);
- return rv;
+ 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;
+ }
}
+ OMATCH_END ();
+
if (sd->npc_id
|| sd->opt1 != Opt1::ZERO)
{
@@ -4901,11 +4914,17 @@ RecvResult clif_parse_TradeAddItem(Session *s, dumb_ptr<map_session_data> sd)
if (fixed.zeny_or_ioff2.index != 0 && !fixed.zeny_or_ioff2.ok())
return RecvResult::Error;
if (fixed.zeny_or_ioff2.ok())
- if (bool(itemdb_search(sd->status.inventory[fixed.zeny_or_ioff2.unshift()].nameid)->mode & ItemMode::NO_TRADE))
+ OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[fixed.zeny_or_ioff2.unshift()])
{
- clif_displaymessage(sd->sess, "This item can't be traded."_s);
- return rv;
+ 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;
+ }
}
+ OMATCH_END ();
+
trade_tradeadditem(sd, fixed.zeny_or_ioff2, fixed.amount);
return rv;
diff --git a/src/map/map.cpp b/src/map/map.cpp
index ff69a56..f8e8bea 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -1241,6 +1241,20 @@ int map_setipport(MapName name, IP4Address ip, int port)
}
/*==========================================
+ * creates a hash of a map name
+ *------------------------------------------
+ */
+int map_create_hash(XString str) {
+ const int k = 67;
+ const int m = 3067;
+ int hash = 0;
+ for (int i = 0; i < str.size(); i++) {
+ hash += (str[i] * (int)pow(k, i)) % m;
+ }
+ return hash;
+}
+
+/*==========================================
* マップ1枚読み込み
*------------------------------------------
*/
@@ -1265,6 +1279,9 @@ bool map_readmap(map_local *m, size_t num, MapName fn)
m->npc_num = 0;
m->users = 0;
+
+ m->hash = map_create_hash(fn);
+
really_memzero_this(&m->flag);
if (battle_config.pk_mode)
m->flag.set(MapFlag::PVP, 1);
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 7cf43d5..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;
@@ -360,7 +360,11 @@ struct npc_data : block_list
Opt0 option;
short flag;
- bool deletion_pending;
+ enum {
+ NOT_DELETING = 0,
+ DELETION_QUEUED = 1,
+ DELETION_ACTIVE = 2
+ } deletion_pending;
Array<Timer, MAX_EVENTTIMER> eventtimer;
@@ -527,6 +531,7 @@ struct map_local : map_abstract
Point save;
Point resave;
int mask;
+ int hash;
Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc;
};
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index f2f6815..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++)
@@ -2556,10 +2557,12 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
// activity
if (sd)
+ {
if (sd->activity.attacks == 2147483647)
sd->activity.attacks = 1;
else
sd->activity.attacks++;
+ }
if (md->hp > 0)
{
@@ -2594,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;
@@ -2658,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]
}
@@ -2728,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
@@ -2743,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;
@@ -2794,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);
}
@@ -3499,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;
}
@@ -3652,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();
- 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
+ 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
- if (get_mob_db(mob_class).base_exp == 0)
- get_mob_db(mob_class).base_exp = mob_gen_exp(&get_mob_db(mob_class));
+ if (mdbv.base_exp == 0)
+ mdbv.base_exp = mob_gen_exp(&mdbv);
+
+ 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 47b851c..8865ea6 100644
--- a/src/map/npc-parse.cpp
+++ b/src/map/npc-parse.cpp
@@ -164,7 +164,7 @@ bool npc_load_warp(ast::npc::Warp& warp)
nd->warp.xs = xs;
nd->warp.ys = ys;
- nd->deletion_pending = false;
+ nd->deletion_pending = npc_data::NOT_DELETING;
npc_warp++;
nd->bl_type = BL::NPC;
@@ -228,7 +228,7 @@ bool npc_load_shop(ast::npc::Shop& shop)
nd->opt2 = Opt2::ZERO;
nd->opt3 = Opt3::ZERO;
- nd->deletion_pending = false;
+ nd->deletion_pending = npc_data::NOT_DELETING;
npc_shop++;
nd->bl_type = BL::NPC;
@@ -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;
@@ -458,7 +459,7 @@ bool npc_load_script_none(ast::script::ScriptBody& body, ast::npc::ScriptNone& s
nd->opt2 = Opt2::ZERO;
nd->opt3 = Opt3::ZERO;
- nd->deletion_pending = false;
+ nd->deletion_pending = npc_data::NOT_DELETING;
npc_script++;
nd->bl_type = BL::NPC;
@@ -568,7 +569,7 @@ bool npc_load_script_map(ast::script::ScriptBody& body, ast::npc::ScriptMap& scr
nd->opt2 = Opt2::ZERO;
nd->opt3 = Opt3::ZERO;
- nd->deletion_pending = false;
+ nd->deletion_pending = npc_data::NOT_DELETING;
npc_script++;
nd->bl_type = BL::NPC;
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index e8d6d4b..0a7bfc2 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -357,7 +357,7 @@ void npc_eventtimer(TimerData *, tick_t, BlockId, NpcEvent data)
data);
return;
});
- if ((nd = ev->nd) == nullptr || nd->deletion_pending == true)
+ if ((nd = ev->nd) == nullptr || nd->deletion_pending != npc_data::NOT_DELETING)
{
if (battle_config.error_log)
PRINTF("npc_event: event not found [%s]\n"_fmt,
@@ -591,7 +591,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname,
ev.pos = ev2->pos;
}
- if ((nd = ev.nd) == nullptr || nd->deletion_pending == true)
+ if ((nd = ev.nd) == nullptr || nd->deletion_pending != npc_data::NOT_DELETING)
{
if (!mob_kill && battle_config.error_log)
PRINTF("npc_event: event not found [%s]\n"_fmt,
@@ -767,13 +767,22 @@ int npc_click(dumb_ptr<map_session_data> sd, BlockId id)
}
}
- if (npc_checknear(sd, id)) {
+ if (npc_checknear(sd, id))
+ {
clif_scriptclose(sd, id);
return 1;
}
nd = map_id_is_npc(id);
+ // If someone clicked on an NPC that is about to no longer exist, then
+ // release them
+ if (nd->deletion_pending != npc_data::NOT_DELETING)
+ {
+ clif_scriptclose(sd, id);
+ return 1;
+ }
+
if (nd->flag & 1) // 無効化されている
return 1;
@@ -818,18 +827,19 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, BlockId id)
nd = map_id_is_npc(id);
- if (!nd /* NPC was disposed? */)
+ // If the NPC is about to be deleted, release the PC
+ if (nd->deletion_pending != npc_data::NOT_DELETING)
{
clif_scriptclose(sd, id);
npc_event_dequeue(sd);
- return 0;
+ return 1;
}
if (nd->is_script()->scr.parent &&
map_id2bl(nd->is_script()->scr.parent) == nullptr)
{
npc_free(nd);
- return 0;
+ return 1;
}
sd->npc_pos = run_script(ScriptPointer(script_or_parent(nd->is_script()), sd->npc_pos), sd->bl_id, id);
@@ -993,12 +1003,19 @@ int npc_selllist(dumb_ptr<map_session_data> sd,
if (!nameid ||
sd->status.inventory[item_list[i].ioff2.unshift()].amount < item_list[i].count)
return 1;
- if (bool(itemdb_search(nameid)->mode & ItemMode::NO_SELL_TO_NPC))
+
+ OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[item_list[i].ioff2.unshift()])
{
- //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.
- return 3;
+ 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.
+ return 3;
+ }
}
+ OMATCH_END ();
+
if (sd->trade_partner)
return 2; // cant sell while trading
z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i].count;
@@ -1091,10 +1108,10 @@ void npc_propagate_update(dumb_ptr<npc_data> nd)
void npc_free(dumb_ptr<npc_data> nd)
{
- if (nd == nullptr || nd->deletion_pending == true)
+ if (nd == nullptr || nd->deletion_pending == npc_data::DELETION_ACTIVE)
return;
- nd->deletion_pending = true;
+ nd->deletion_pending = npc_data::DELETION_ACTIVE;
nd->flag |= 1;
clif_clearchar(nd, BeingRemoveWhy::GONE);
npc_propagate_update(nd);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 12af48f..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,
@@ -2404,8 +2425,12 @@ int pc_useitem(dumb_ptr<map_session_data> sd, IOff0 n)
}
P<const ScriptBuffer> script = borrow(*sdidn->use_script);
- clif_useitemack(sd, n, amount - 1, 1);
- pc_delitem(sd, n, 1, 1);
+
+ if (!bool(sdidn->mode & ItemMode::KEEP_AFTER_USE))
+ {
+ clif_useitemack(sd, n, amount - 1, 1);
+ pc_delitem(sd, n, 1, 1);
+ }
// activity
if (sd)
@@ -3717,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;
@@ -3866,19 +3894,19 @@ int pc_readparam(dumb_ptr<block_list> bl, SP type)
val = sd ? sd->mute.guild : 0;
break;
case SP::KILLS:
- val = sd->activity.kills;
+ val = sd ? sd->activity.kills : 0;
break;
case SP::CASTS:
- val = sd->activity.casts;
+ val = sd ? sd->activity.casts : 0;
break;
case SP::ITEMS_USED:
- val = sd->activity.items_used;
+ val = sd ? sd->activity.items_used : 0;
break;
case SP::TILES_WALKED:
- val = sd->activity.tiles_walked;
+ val = sd ? sd->activity.tiles_walked : 0;
break;
case SP::ATTACKS:
- val = sd->activity.attacks;
+ val = sd ? sd->activity.attacks : 0;
break;
case SP::AUTOMOD:
val = sd ? static_cast<int>(sd->automod) : 0;
@@ -4044,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
@@ -4131,18 +4164,23 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val)
break;
// atm only setting of casts is needed since magic is handled in serverdata but I let the others here as well for whatever reason
case SP::KILLS:
+ nullpo_retz(sd);
sd->activity.kills = val;
break;
case SP::CASTS:
+ nullpo_retz(sd);
sd->activity.casts = val;
break;
case SP::ITEMS_USED:
+ nullpo_retz(sd);
sd->activity.items_used = val;
break;
case SP::TILES_WALKED:
+ nullpo_retz(sd);
sd->activity.tiles_walked = val;
break;
case SP::ATTACKS:
+ nullpo_retz(sd);
sd->activity.attacks = val;
break;
case SP::AUTOMOD:
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'),
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 54398f3..dc1fe62 100644
--- a/src/map/storage.cpp
+++ b/src/map/storage.cpp
@@ -186,11 +186,16 @@ int storage_storageadd(dumb_ptr<map_session_data> sd, IOff0 index, int amount)
if (amount < 1 || amount > sd->status.inventory[index].amount)
return 0;
- if (bool(itemdb_search(sd->status.inventory[index].nameid)->mode & ItemMode::NO_STORAGE))
+ OMATCH_BEGIN_SOME (sdidn, sd->inventory_data[index])
{
- clif_displaymessage(sd->sess, "This item can't be stored."_s);
- return 0;
+ 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;
+ }
}
+ OMATCH_END ();
// log_tostorage(sd, index, 0);
if (storage_additem(sd, stor, &sd->status.inventory[index], amount) == 0)
diff --git a/src/mmo/clif.t.hpp b/src/mmo/clif.t.hpp
index f8350a7..c1f7ed3 100644
--- a/src/mmo/clif.t.hpp
+++ b/src/mmo/clif.t.hpp
@@ -265,6 +265,8 @@ enum class SP : uint16_t
WEIGHT = 24,
// sent to client
MAXWEIGHT = 25,
+ MAXWEIGHT_ADD = 26,
+ MAXWEIGHT_OVERRIDE = 27,
// sent to client
USTR = 32,
diff --git a/src/mmo/enums.hpp b/src/mmo/enums.hpp
index c4a1b17..377f7d7 100644
--- a/src/mmo/enums.hpp
+++ b/src/mmo/enums.hpp
@@ -135,6 +135,8 @@ enum class ItemMode : uint8_t
NO_TRADE = 2,
NO_SELL_TO_NPC = 4,
NO_STORAGE = 8,
+ KEEP_AFTER_USE = 16,
+ DONT_USE_AMMO = 32,
};
ENUM_BITWISE_OPERATORS(ItemMode)
}
diff --git a/src/mmo/skill.t.hpp b/src/mmo/skill.t.hpp
index 782980c..bab10f4 100644
--- a/src/mmo/skill.t.hpp
+++ b/src/mmo/skill.t.hpp
@@ -60,11 +60,17 @@ enum class StatusChange : uint16_t
SC_COOLDOWN_ENCH = 76, // Enchanter cooldown
SC_COOLDOWN_KOY = 77, // Koyntety cooldown
SC_COOLDOWN_UPMARMU = 78, // Upmarmu cooldown
+ SC_COOLDOWN_SG = 79, // Stone Golem cooldown
+ SC_COOLDOWN_CG = 80, // Coal Golem cooldown
SC_POISON = 132, // bad; actually used
+ SC_SLOWMOVE = 133, // slows down movement
+ SC_CANTMOVE = 134, // stops all movement
SC_ATKPOT = 185, // item script
- SC_MATKPOT = 186, // unused, but kept for parallel
+ SC_MATKPOT = 186, // `Matk' spell from items (val1 : power)
+
+ SC_PHYS_SHIELD_ITEM = 193, // `Protect' spell from items, reduce damage (val1: power) can't be chancelled with detsanc
// Added for Fate's spells
SC_HIDE = 194, // Hide from `detect' magic (PCs only)
diff --git a/src/mmo/version.cpp b/src/mmo/version.cpp
index f91b748..c75c25c 100644
--- a/src/mmo/version.cpp
+++ b/src/mmo/version.cpp
@@ -20,7 +20,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include "../conf/version.hpp"
+#include "src/conf/version.hpp"
#include "../strings/xstring.hpp"
diff --git a/src/shared/lib.cpp b/src/shared/lib.cpp
index 0eebf17..37b2e93 100644
--- a/src/shared/lib.cpp
+++ b/src/shared/lib.cpp
@@ -18,7 +18,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include "../conf/install.hpp"
+#include "src/conf/install.hpp"
#include "../strings/literal.hpp"
#include "../strings/astring.hpp"
@@ -35,25 +35,37 @@
namespace tmwa
{
static
- void try_read(const io::DirFd& dirfd, ZString filename)
+ void try_read(const io::DirFd& dirfd, LString dir_path, ZString filename)
{
io::ReadFile rf(dirfd, filename);
if (!rf.is_open())
+ {
+ FPRINTF(stderr, "Could not open %s/%s\n"_fmt, dir_path, filename);
abort();
+ }
AString line;
if (!rf.getline(line))
+ {
+ FPRINTF(stderr, "Could not read from %s/%s\n"_fmt, dir_path, filename);
abort();
+ }
}
static
- void try_write(const io::DirFd& dirfd, ZString filename)
+ void try_write(const io::DirFd& dirfd, LString dir_path, ZString filename)
{
io::WriteFile wf(dirfd, filename);
if (!wf.is_open())
+ {
+ FPRINTF(stderr, "Could not open %s/%s\n"_fmt, dir_path, filename);
abort();
+ }
wf.put_line("Hello, World!"_s);
if (!wf.close())
+ {
+ FPRINTF(stderr, "Could not write to %s/%s\n"_fmt, dir_path, filename);
abort();
+ }
}
void check_paths()
@@ -65,13 +77,17 @@ namespace tmwa
io::DirFd root(portable_root);
- io::DirFd etc(root, PACKAGESYSCONFDIR.xslice_t(portable));
- io::DirFd var(root, PACKAGELOCALSTATEDIR.xslice_t(portable));
- io::DirFd share(root, PACKAGEDATADIR.xslice_t(portable));
+ LString etc_path = PACKAGESYSCONFDIR.xslice_t(portable);
+ LString var_path = PACKAGELOCALSTATEDIR.xslice_t(portable);
+ LString share_path = PACKAGEDATADIR.xslice_t(portable);
- try_read(etc, "shared.conf"_s);
- try_read(share, "shared.data"_s);
- try_write(var, "shared.test"_s);
+ io::DirFd etc(root, etc_path);
+ io::DirFd var(root, var_path);
+ io::DirFd share(root, share_path);
+
+ try_read(etc, etc_path, "shared.conf"_s);
+ try_read(share, share_path, "shared.data"_s);
+ try_write(var, var_path, "shared.test"_s);
// io::FD::open();
}