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;
+};