From 5c8f6e5cc6b4036c997e5f1b68f3da332d61733a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Mon, 3 Aug 2026 16:55:45 +0900 Subject: [PATCH 1/4] Fix old packetver cloth color build (#10066) --- src/map/clif.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/map/clif.cpp b/src/map/clif.cpp index ae118e5ac74..9067c7653c6 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -1653,7 +1653,7 @@ static inline bool clif_npc_mayapurple( const block_list& bl ){ } /// For the stupid cloth-dye bug. Resends the given view data to the area specified by bl. -void clif_refresh_clothcolor( const block_list& bl, enum send_target target, block_list* tbl = nullptr ){ +void clif_refresh_clothcolor( const block_list& bl, enum send_target target, const block_list* tbl = nullptr ){ // Unconfirmed when this was fixed, if you encounter any problems, feel free to report them #if PACKETVER < 20091103 const view_data* vd = status_get_viewdata( &bl ); From 023afcbf3c41568a5163d866462c6ab8354da828 Mon Sep 17 00:00:00 2001 From: Atemo Date: Mon, 3 Aug 2026 11:33:46 +0200 Subject: [PATCH 2/4] 6th rebalance - Shadow Cross - Part 2 (#10002) * Shadow Exceed - Reduces AP consumption from 125 to 120 based on level 10. * Savage Impact - Increases base damage from 1050% ATK to 1300% ATK per hit based on level 10. - Increases base damage (Shadow Exceed) from 1250% ATK to 1600% ATK per hit based on level 10. * Impact Crater - Increases base damage from 400% ATK to 1000% ATK per hit based on level 5. * Fatal Shadow Claw - Reduces AP consumption from 150 to 125. --- db/re/skill_db.yml | 20 ++++++++++---------- src/map/skills/thief/impactcrater.cpp | 4 +++- src/map/skills/thief/savageimpact.cpp | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index f4aecf46759..da9d0570edd 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -37404,25 +37404,25 @@ Body: SpCost: 100 ApCost: - Level: 1 - Amount: 152 + Amount: 156 - Level: 2 - Amount: 149 + Amount: 152 - Level: 3 - Amount: 146 + Amount: 148 - Level: 4 - Amount: 143 + Amount: 144 - Level: 5 Amount: 140 - Level: 6 - Amount: 137 + Amount: 136 - Level: 7 - Amount: 134 + Amount: 132 - Level: 8 - Amount: 131 - - Level: 9 Amount: 128 + - Level: 9 + Amount: 124 - Level: 10 - Amount: 125 + Amount: 120 Status: Shadow_Exceed - Id: 5286 Name: SHC_DANCING_KNIFE @@ -37729,7 +37729,7 @@ Body: FixedCastTime: 500 Requires: SpCost: 150 - ApCost: 150 + ApCost: 120 Status: Darkcrow - Id: 5295 Name: MT_AXE_STOMP diff --git a/src/map/skills/thief/impactcrater.cpp b/src/map/skills/thief/impactcrater.cpp index 420bbf7109d..49ed83c9d74 100644 --- a/src/map/skills/thief/impactcrater.cpp +++ b/src/map/skills/thief/impactcrater.cpp @@ -14,7 +14,9 @@ SkillImpactCrater::SkillImpactCrater() : SkillImplRecursiveDamageSplash(SHC_IMPA void SkillImpactCrater::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { const status_data* sstatus = status_get_status_data(*src); - skillratio += -100 + 80 * skill_lv + 5 * sstatus->pow; + skillratio += -100 + 200 * skill_lv; + skillratio += 5 * sstatus->pow; + RE_LVL_DMOD(100); } diff --git a/src/map/skills/thief/savageimpact.cpp b/src/map/skills/thief/savageimpact.cpp index d9d213f2a5b..ecdff3e50a2 100644 --- a/src/map/skills/thief/savageimpact.cpp +++ b/src/map/skills/thief/savageimpact.cpp @@ -21,11 +21,11 @@ void SkillSavageImpact::calculateSkillRatio(const Damage *wd, const block_list * const status_data* sstatus = status_get_status_data(*src); const status_change *sc = status_get_sc(src); - skillratio += -100 + 105 * skill_lv; + skillratio += -100 + 130 * skill_lv; skillratio += 5 * sstatus->pow; if( sc != nullptr && sc->hasSCE( SC_SHADOW_EXCEED ) ){ - skillratio += 20 * skill_lv; + skillratio += 30 * skill_lv; skillratio += 2 * sstatus->pow; } From f6e2e6ff7deebe15c74ab57e1f439c955deebb72 Mon Sep 17 00:00:00 2001 From: Atemo Date: Mon, 3 Aug 2026 11:34:58 +0200 Subject: [PATCH 3/4] 6th rebalance - Arch Mage - Part 2 (#10003) * Mystical Amplification (High Wizard) - Increases skill duration from 60 seconds to 180 seconds. * Soul Vulcan Strike - Increases base damage from 1500% MATK to 1700% MATK per hit based on level 5. * Destructive Hurricane - Increases base damage from 14850% MATK to 16850% MATK based on level 5. - Increases factor weight of SPL in skill formula from 5 to 10. * Crystal Impact - Increases base damage from 6750% MATK to 7400% MATK based on level 5. - Increases factor weight of SPL in skill formula from 5 to 10 (affects additional damage as well). * Astral Strike - Increases base damage of initial damage from 18300% MATK to 26700% MATK based on level 10. - Increases base damage of initial damage (Undead, Dragon) from 21400% MATK to 28200% MATK based on level 10. ** there is no change regarding overtime damage ** --- db/re/skill_db.yml | 2 +- src/map/skills/mage/astralstrike.cpp | 6 ++++-- src/map/skills/mage/crystalimpact.cpp | 8 ++++++-- src/map/skills/mage/destructivehurricane.cpp | 4 +++- src/map/skills/mage/soulvulcanstrike.cpp | 4 +++- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index da9d0570edd..8f3f554cddb 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -9895,7 +9895,7 @@ Body: Hit: Single HitCount: 1 CastTime: 700 - Duration1: 60000 + Duration1: 180000 FixedCastTime: 700 CastTimeFlags: IgnoreDex: true diff --git a/src/map/skills/mage/astralstrike.cpp b/src/map/skills/mage/astralstrike.cpp index 7ecb2c55361..94e28998dac 100644 --- a/src/map/skills/mage/astralstrike.cpp +++ b/src/map/skills/mage/astralstrike.cpp @@ -15,9 +15,11 @@ void SkillAstralStrike::calculateSkillRatio(const Damage *wd, const block_list * const status_data* sstatus = status_get_status_data(*src); const status_data* tstatus = status_get_status_data(*target); - skillratio += -100 + 300 + 1800 * skill_lv + 10 * sstatus->spl; + skillratio += -100 + 700 + 2600 * skill_lv; + skillratio += 10 * sstatus->spl; + if (tstatus->race == RC_UNDEAD || tstatus->race == RC_DRAGON) - skillratio += 100 + 300 * skill_lv; + skillratio += 150 * skill_lv; RE_LVL_DMOD(100); } diff --git a/src/map/skills/mage/crystalimpact.cpp b/src/map/skills/mage/crystalimpact.cpp index 5225436d08f..8760b126dde 100644 --- a/src/map/skills/mage/crystalimpact.cpp +++ b/src/map/skills/mage/crystalimpact.cpp @@ -22,7 +22,9 @@ void SkillCrystalImpact::modifyDamageData(Damage& dmg, const block_list& src, co void SkillCrystalImpact::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { const status_data* sstatus = status_get_status_data(*src); - skillratio += -100 + 250 + 1300 * skill_lv + 5 * sstatus->spl; + skillratio += -100 + 400 + 1400 * skill_lv; + skillratio += 10 * sstatus->spl; + // (climax buff applied with pc_skillatk_bonus) RE_LVL_DMOD(100); } @@ -66,7 +68,9 @@ SkillCrystalImpactAttack::SkillCrystalImpactAttack() : SkillImplRecursiveDamageS void SkillCrystalImpactAttack::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { const status_data* sstatus = status_get_status_data(*src); - skillratio += -100 + 250 + 1300 * skill_lv + 5 * sstatus->spl; + skillratio += -100 + 400 + 1400 * skill_lv; + skillratio += 10 * sstatus->spl; + // (climax buff applied with pc_skillatk_bonus) RE_LVL_DMOD(100); } diff --git a/src/map/skills/mage/destructivehurricane.cpp b/src/map/skills/mage/destructivehurricane.cpp index 886d0a4cb6b..b0dc38d394b 100644 --- a/src/map/skills/mage/destructivehurricane.cpp +++ b/src/map/skills/mage/destructivehurricane.cpp @@ -22,7 +22,9 @@ void SkillDestructiveHurricane::modifyDamageData(Damage& dmg, const block_list& void SkillDestructiveHurricane::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { const status_data* sstatus = status_get_status_data(*src); - skillratio += -100 + 600 + 2850 * skill_lv + 5 * sstatus->spl; + skillratio += -100 + 600 + 3250 * skill_lv; + skillratio += 10 * sstatus->spl; + // (climax buff applied with pc_skillatk_bonus) RE_LVL_DMOD(100); } diff --git a/src/map/skills/mage/soulvulcanstrike.cpp b/src/map/skills/mage/soulvulcanstrike.cpp index b366a1b2673..cc0a0697f59 100644 --- a/src/map/skills/mage/soulvulcanstrike.cpp +++ b/src/map/skills/mage/soulvulcanstrike.cpp @@ -13,6 +13,8 @@ SkillSoulVulcanStrike::SkillSoulVulcanStrike() : SkillImplRecursiveDamageSplash( void SkillSoulVulcanStrike::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { const status_data* sstatus = status_get_status_data(*src); - skillratio += -100 + 300 * skill_lv + 3 * sstatus->spl; + skillratio += -100 + 50 + 330 * skill_lv; + skillratio += 3 * sstatus->spl; + RE_LVL_DMOD(100); } From 463952820f6e2e7354899ef3b7d61c18e2f0d535 Mon Sep 17 00:00:00 2001 From: Stingor Date: Mon, 3 Aug 2026 14:09:09 +0200 Subject: [PATCH 4/4] Normalize path separators in atcommands (#9969) Normalize path separators for loadnpc, unloadnpcfile, reloadnpc, so Windows-style paths work on all platforms Fixes #9968 --- src/map/atcommand.cpp | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 1e70bbac7f8..f367e9b8486 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -244,6 +244,13 @@ static const char* atcommand_help_string( const char* command ){ return info->help.c_str(); } +/// Normalize path separators so Windows-style paths work on all platforms. +static void atcommand_normalize_npc_path(char* dst, const char* src, size_t size) { + safestrncpy(dst, src, size); + for (char* p = dst; *p; ++p) + if (*p == '\\') + *p = '/'; +} /*========================================== * @send (used for testing packet sends from the client) @@ -5350,16 +5357,19 @@ ACMD_FUNC(loadnpc) clif_displaymessage(fd, msg_txt(sd,1132)); // Please enter a script file name (usage: @loadnpc ). return -1; } - - if (!npc_addsrcfile(message, true)) { + + char path[1024]; + atcommand_normalize_npc_path(path, message, sizeof(path)); + + if (!npc_addsrcfile(path, true)) { clif_displaymessage(fd, msg_txt(sd,261)); // Script could not be loaded. return -1; } npc_read_event_script(); - ShowStatus( "NPC file '" CL_WHITE "%s" CL_RESET "' was loaded.\n", message ); - npc_event_doall_path( script_config.init_event_name, message ); + ShowStatus( "NPC file '" CL_WHITE "%s" CL_RESET "' was loaded.\n", path ); + npc_event_doall_path( script_config.init_event_name, path ); clif_displaymessage(fd, msg_txt(sd,262)); // Script loaded. return 0; @@ -5396,18 +5406,21 @@ ACMD_FUNC(reloadnpcfile) { return -1; } - if (npc_unloadfile(message)) + char path[1024]; + atcommand_normalize_npc_path(path, message, sizeof(path)); + + if (npc_unloadfile(path)) clif_displaymessage(fd, msg_txt(sd,1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. - if (!npc_addsrcfile(message, true)) { + if (!npc_addsrcfile(path, true)) { clif_displaymessage(fd, msg_txt(sd,261)); // Script could not be loaded. return -1; } npc_read_event_script(); - ShowStatus( "NPC file '" CL_WHITE "%s" CL_RESET "' was reloaded.\n", message ); - npc_event_doall_path( script_config.init_event_name, message ); + ShowStatus( "NPC file '" CL_WHITE "%s" CL_RESET "' was reloaded.\n", path ); + npc_event_doall_path( script_config.init_event_name, path ); clif_displaymessage(fd, msg_txt(sd,262)); // Script loaded. return 0; @@ -10358,12 +10371,18 @@ ACMD_FUNC(unloadnpcfile) { return -1; } - if( npc_unloadfile(message) ) + char path[1024]; + atcommand_normalize_npc_path(path, message, sizeof(path)); + + if( npc_unloadfile(path) ) { clif_displaymessage(fd, msg_txt(sd,1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. + ShowStatus( "NPC file '" CL_WHITE "%s" CL_RESET "' was unloaded.\n", path ); + } else { clif_displaymessage(fd, msg_txt(sd,1387)); // File not found. return -1; } + return 0; } ACMD_FUNC(cart) {