diff options
-rw-r--r-- | src/char/char.cpp | 2 | ||||
-rw-r--r-- | src/map/battle.cpp | 4 | ||||
-rw-r--r-- | src/map/clif.cpp | 12 | ||||
-rw-r--r-- | src/map/map.hpp | 2 | ||||
-rw-r--r-- | src/map/npc.cpp | 3 | ||||
-rw-r--r-- | src/map/pc.cpp | 34 | ||||
-rw-r--r-- | src/map/script-fun.cpp | 6 | ||||
-rw-r--r-- | src/map/skill.cpp | 12 | ||||
-rw-r--r-- | src/map/storage.cpp | 3 | ||||
-rw-r--r-- | src/mmo/clif.t.hpp | 2 | ||||
-rw-r--r-- | src/mmo/skill.t.hpp | 7 | ||||
-rw-r--r-- | src/shared/lib.cpp | 32 |
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(); } |