summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/char/char.cpp2
-rw-r--r--src/map/battle.cpp4
-rw-r--r--src/map/clif.cpp12
-rw-r--r--src/map/map.hpp2
-rw-r--r--src/map/npc.cpp3
-rw-r--r--src/map/pc.cpp34
-rw-r--r--src/map/script-fun.cpp6
-rw-r--r--src/map/skill.cpp12
-rw-r--r--src/map/storage.cpp3
-rw-r--r--src/mmo/clif.t.hpp2
-rw-r--r--src/mmo/skill.t.hpp7
-rw-r--r--src/shared/lib.cpp32
12 files changed, 94 insertions, 25 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/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..4d36f17 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);
@@ -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/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..9ef70fe 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -870,6 +870,7 @@ 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->canact_tick = tick;
sd->canmove_tick = tick;
sd->attackabletime = tick;
@@ -1121,7 +1122,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 +1474,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 +1485,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 +1553,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 +1902,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 +3737,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 +4067,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..fee39d6 100644
--- a/src/map/script-fun.cpp
+++ b/src/map/script-fun.cpp
@@ -3920,6 +3920,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 +3930,10 @@ 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_SLOWMOVE:
+ case StatusChange::SC_CANTMOVE:
+ break;
default:
// work around old behaviour of:
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index 87bbbda..7454cc3 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,8 @@ 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_CANTMOVE:
break;
/* option2 */
@@ -1030,7 +1034,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 +1049,8 @@ 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_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;
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/skill.t.hpp b/src/mmo/skill.t.hpp
index 782980c..b0b6b8d 100644
--- a/src/mmo/skill.t.hpp
+++ b/src/mmo/skill.t.hpp
@@ -60,11 +60,16 @@ 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_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/shared/lib.cpp b/src/shared/lib.cpp
index 0eebf17..c0a4371 100644
--- a/src/shared/lib.cpp
+++ b/src/shared/lib.cpp
@@ -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();
}