From beba2e766c3c62973a18f0ac90ecaa16b4b2096b Mon Sep 17 00:00:00 2001 From: Atemo Date: Tue, 20 Jan 2026 14:02:20 +0100 Subject: [PATCH] Split up Sniper skills (#9757) --- src/map/battle.cpp | 9 --- src/map/map-server-generator.vcxproj | 6 ++ src/map/map-server-generator.vcxproj.filters | 18 ++++++ src/map/map-server.vcxproj | 6 ++ src/map/map-server.vcxproj.filters | 18 ++++++ src/map/skill.cpp | 19 ------- src/map/skills/archer/falconassault.cpp | 11 ++++ src/map/skills/archer/falconassault.hpp | 13 +++++ src/map/skills/archer/focusedarrowstrike.cpp | 56 +++++++++++++++++++ src/map/skills/archer/focusedarrowstrike.hpp | 14 +++++ .../skills/archer/skill_factory_archer.cpp | 9 +++ src/map/skills/archer/windwalker.cpp | 24 ++++++++ src/map/skills/archer/windwalker.hpp | 13 +++++ 13 files changed, 188 insertions(+), 28 deletions(-) create mode 100644 src/map/skills/archer/falconassault.cpp create mode 100644 src/map/skills/archer/falconassault.hpp create mode 100644 src/map/skills/archer/focusedarrowstrike.cpp create mode 100644 src/map/skills/archer/focusedarrowstrike.hpp create mode 100644 src/map/skills/archer/windwalker.cpp create mode 100644 src/map/skills/archer/windwalker.hpp diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 44fbb23a7da..b170a4d0be4 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -4868,15 +4868,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b RE_LVL_DMOD(100); break; #endif - case SN_SHARPSHOOTING: - if (src->type == BL_MOB) { // TODO: Did these formulas change in the renewal balancing? - if (wd->miscflag & 2) // Splash damage bonus - skillratio += -100 + 140 * skill_lv; - else - skillratio += 100 + 50 * skill_lv; - break; - } - [[fallthrough]]; case MA_SHARPSHOOTING: #ifdef RENEWAL skillratio += -100 + 300 + 300 * skill_lv; diff --git a/src/map/map-server-generator.vcxproj b/src/map/map-server-generator.vcxproj index d6c13fc8fef..b4ab32b4e65 100644 --- a/src/map/map-server-generator.vcxproj +++ b/src/map/map-server-generator.vcxproj @@ -275,7 +275,9 @@ + + @@ -287,6 +289,7 @@ + @@ -548,7 +551,9 @@ + + @@ -560,6 +565,7 @@ + diff --git a/src/map/map-server-generator.vcxproj.filters b/src/map/map-server-generator.vcxproj.filters index 3d941dcbe3d..03057cec984 100644 --- a/src/map/map-server-generator.vcxproj.filters +++ b/src/map/map-server-generator.vcxproj.filters @@ -474,9 +474,15 @@ Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Archer @@ -510,6 +516,9 @@ Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Custom @@ -1151,9 +1160,15 @@ Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Archer @@ -1187,6 +1202,9 @@ Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Custom diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj index 277a27aa7ad..2d8f208d414 100644 --- a/src/map/map-server.vcxproj +++ b/src/map/map-server.vcxproj @@ -275,7 +275,9 @@ + + @@ -287,6 +289,7 @@ + @@ -548,7 +551,9 @@ + + @@ -560,6 +565,7 @@ + diff --git a/src/map/map-server.vcxproj.filters b/src/map/map-server.vcxproj.filters index 3d941dcbe3d..03057cec984 100644 --- a/src/map/map-server.vcxproj.filters +++ b/src/map/map-server.vcxproj.filters @@ -474,9 +474,15 @@ Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Archer @@ -510,6 +516,9 @@ Header Files\Skills\Archer + + Header Files\Skills\Archer + Header Files\Skills\Custom @@ -1151,9 +1160,15 @@ Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Archer @@ -1187,6 +1202,9 @@ Source Files\Skills\Archer + + Source Files\Skills\Archer + Source Files\Skills\Custom diff --git a/src/map/skill.cpp b/src/map/skill.cpp index fdb31654988..e858b090124 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -5168,11 +5168,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id, } break; -#ifndef RENEWAL - case SN_SHARPSHOOTING: - flag |= 2; // Flag for specific mob damage formula - [[fallthrough]]; -#endif case MA_SHARPSHOOTING: case NJ_KAMAITACHI: case NPC_DARKPIERCING: @@ -5192,10 +5187,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id, if (!(map_foreachindir(skill_attack_area, src->m, src->x, src->y, bl->x, bl->y, skill_get_splash(skill_id, skill_lv), skill_get_maxcount(skill_id, skill_lv), 0, splash_target(src), skill_get_type(skill_id), src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY))) { -#ifndef RENEWAL - if (skill_id == SN_SHARPSHOOTING) - flag &= ~2; // Only targets in the splash area are affected -#endif //These skills hit at least the target if the AoE doesn't hit skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); @@ -5295,9 +5286,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id, flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit [[fallthrough]]; case MA_SHOWER: -#ifdef RENEWAL - case SN_SHARPSHOOTING: -#endif case HW_NAPALMVULCAN: case NJ_HUUMA: case NPC_PULSESTRIKE: @@ -5501,11 +5489,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id, status_heal(src, heal, 0, 0); } break; -#ifdef RENEWAL - case SN_SHARPSHOOTING: - status_change_end(src, SC_CAMOUFLAGE); - break; -#endif case SJ_PROMINENCEKICK: // Trigger the 2nd hit. (100% fire damage.) skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag|8|SD_ANIMATION); break; @@ -6184,7 +6167,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id, if (rnd() % 2 == 0) break; // 50% chance [[fallthrough]]; - case SN_FALCONASSAULT: #ifndef RENEWAL case PA_PRESSURE: case CR_ACIDDEMONSTRATION: @@ -8491,7 +8473,6 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag | BCT_PARTY | 1, skill_castend_nodamage_id); break; - case SN_WINDWALK: case CASH_BLESSING: case CASH_INCAGI: case CASH_ASSUMPTIO: diff --git a/src/map/skills/archer/falconassault.cpp b/src/map/skills/archer/falconassault.cpp new file mode 100644 index 00000000000..099f60c1f1c --- /dev/null +++ b/src/map/skills/archer/falconassault.cpp @@ -0,0 +1,11 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "falconassault.hpp" + +SkillFalconAssault::SkillFalconAssault() : SkillImpl(SN_FALCONASSAULT) { +} + +void SkillFalconAssault::castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const { + skill_attack(skill_get_type(getSkillId()),src,src,target,getSkillId(),skill_lv,tick,flag); +} diff --git a/src/map/skills/archer/falconassault.hpp b/src/map/skills/archer/falconassault.hpp new file mode 100644 index 00000000000..0ced1afe707 --- /dev/null +++ b/src/map/skills/archer/falconassault.hpp @@ -0,0 +1,13 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#pragma once + +#include "../skill_impl.hpp" + +class SkillFalconAssault : public SkillImpl { +public: + SkillFalconAssault(); + + void castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override; +}; diff --git a/src/map/skills/archer/focusedarrowstrike.cpp b/src/map/skills/archer/focusedarrowstrike.cpp new file mode 100644 index 00000000000..666b284d5a5 --- /dev/null +++ b/src/map/skills/archer/focusedarrowstrike.cpp @@ -0,0 +1,56 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "focusedarrowstrike.hpp" + +#include +#include + +#include "map/status.hpp" + +SkillFocusedArrowStrike::SkillFocusedArrowStrike() : SkillImplRecursiveDamageSplash(SN_SHARPSHOOTING) { +} + +void SkillFocusedArrowStrike::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { + if (src->type == BL_MOB) { // TODO: Did these formulas change in the renewal balancing? + if (wd->miscflag & 2) // Splash damage bonus + skillratio += -100 + 140 * skill_lv; + else + skillratio += 100 + 50 * skill_lv; + return; + } +#ifdef RENEWAL + skillratio += -100 + 300 + 300 * skill_lv; + RE_LVL_DMOD(100); +#else + skillratio += 100 + 50 * skill_lv; +#endif +} + +void SkillFocusedArrowStrike::castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const { +#ifdef RENEWAL + SkillImplRecursiveDamageSplash::castendDamageId(src, target, skill_lv, tick, flag); + + if( flag&1 ) { + status_change_end(src, SC_CAMOUFLAGE); + } +#else + flag |= 2; // Flag for specific mob damage formula + skill_area_temp[1] = target->id; + if (battle_config.skill_eightpath_algorithm) { + //Use official AoE algorithm + if (!(map_foreachindir(skill_attack_area, src->m, src->x, src->y, target->x, target->y, + skill_get_splash(getSkillId(), skill_lv), skill_get_maxcount(getSkillId(), skill_lv), 0, splash_target(src), + skill_get_type(getSkillId()), src, src, getSkillId(), skill_lv, tick, flag, BCT_ENEMY))) { + flag &= ~2; // Only targets in the splash area are affected + + //These skills hit at least the target if the AoE doesn't hit + skill_attack(skill_get_type(getSkillId()), src, src, target, getSkillId(), skill_lv, tick, flag); + } + } else { + map_foreachinpath(skill_attack_area, src->m, src->x, src->y, target->x, target->y, + skill_get_splash(getSkillId(), skill_lv), skill_get_maxcount(getSkillId(), skill_lv), splash_target(src), + skill_get_type(getSkillId()), src, src, getSkillId(), skill_lv, tick, flag, BCT_ENEMY); + } +#endif +} diff --git a/src/map/skills/archer/focusedarrowstrike.hpp b/src/map/skills/archer/focusedarrowstrike.hpp new file mode 100644 index 00000000000..4b29bf94143 --- /dev/null +++ b/src/map/skills/archer/focusedarrowstrike.hpp @@ -0,0 +1,14 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#pragma once + +#include "../skill_impl.hpp" + +class SkillFocusedArrowStrike : public SkillImplRecursiveDamageSplash { +public: + SkillFocusedArrowStrike(); + + void calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const override; + void castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override; +}; diff --git a/src/map/skills/archer/skill_factory_archer.cpp b/src/map/skills/archer/skill_factory_archer.cpp index 5c11dbc5aaa..d1f2a18772b 100644 --- a/src/map/skills/archer/skill_factory_archer.cpp +++ b/src/map/skills/archer/skill_factory_archer.cpp @@ -16,7 +16,9 @@ #include "concentration.hpp" #include "detect.hpp" #include "doublestrafe.hpp" +#include "falconassault.hpp" #include "flasher.hpp" +#include "focusedarrowstrike.hpp" #include "freezingtrap.hpp" #include "landmine.hpp" #include "makingarrow.hpp" @@ -27,6 +29,7 @@ #include "skidtrap.hpp" #include "springtrap.hpp" #include "talkiebox.hpp" +#include "windwalker.hpp" std::unique_ptr SkillFactoryArcher::create(const e_skill skill_id) const { switch( skill_id ){ @@ -84,8 +87,14 @@ std::unique_ptr SkillFactoryArcher::create(const e_skill skill_ return std::make_unique(skill_id); case RA_UNLIMIT: return std::make_unique(skill_id); + case SN_FALCONASSAULT: + return std::make_unique(); + case SN_SHARPSHOOTING: + return std::make_unique(); case SN_SIGHT: return std::make_unique(skill_id); + case SN_WINDWALK: + return std::make_unique(); case TR_KVASIR_SONATA: return std::make_unique(skill_id); case TR_MYSTIC_SYMPHONY: diff --git a/src/map/skills/archer/windwalker.cpp b/src/map/skills/archer/windwalker.cpp new file mode 100644 index 00000000000..83c56e87453 --- /dev/null +++ b/src/map/skills/archer/windwalker.cpp @@ -0,0 +1,24 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "windwalker.hpp" + +#include "map/clif.hpp" +#include "map/party.hpp" +#include "map/pc.hpp" +#include "map/status.hpp" + +SkillWindWalker::SkillWindWalker() : SkillImpl(SN_WINDWALK) { +} + +void SkillWindWalker::castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const { + sc_type type = skill_get_sc(getSkillId()); + map_session_data* sd = BL_CAST( BL_PC, src ); + + if( sd == nullptr || sd->status.party_id == 0 || (flag & 1) ) + clif_skill_nodamage(target, *target, getSkillId(), skill_lv, sc_start(src,target,type,100,skill_lv,skill_get_time(getSkillId(),skill_lv))); + else if (sd) + { + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(getSkillId(), skill_lv), src, getSkillId(), skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } +} diff --git a/src/map/skills/archer/windwalker.hpp b/src/map/skills/archer/windwalker.hpp new file mode 100644 index 00000000000..abaeed74f9a --- /dev/null +++ b/src/map/skills/archer/windwalker.hpp @@ -0,0 +1,13 @@ +// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#pragma once + +#include "../skill_impl.hpp" + +class SkillWindWalker : public SkillImpl { +public: + SkillWindWalker(); + + void castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override; +};