diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 4e5e2ed2990..44fbb23a7da 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -4862,22 +4862,7 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
skillratio += 100 + 100 * skill_lv;
#endif
break;
- case LK_HEADCRUSH:
- skillratio += 40 * skill_lv;
- break;
- case LK_JOINTBEAT:
- skillratio += 10 * skill_lv - 50;
- if (wd->miscflag & BREAK_NECK || (tsc && tsc->getSCE(SC_JOINTBEAT) && tsc->getSCE(SC_JOINTBEAT)->val2 & BREAK_NECK)) // The 2x damage is only for the BREAK_NECK ailment.
- skillratio *= 2;
- break;
#ifdef RENEWAL
- // Renewal: skill ratio applies to entire damage [helvetica]
- case LK_SPIRALPIERCE:
- skillratio += 50 + 50 * skill_lv;
- RE_LVL_DMOD(100);
- if (sc && sc->getSCE(SC_CHARGINGPIERCE_COUNT) && sc->getSCE(SC_CHARGINGPIERCE_COUNT)->val1 >= 10)
- skillratio *= 2;
- break;
case ML_SPIRALPIERCE:
skillratio += 50 + 50 * skill_lv;
RE_LVL_DMOD(100);
diff --git a/src/map/map-server-generator.vcxproj b/src/map/map-server-generator.vcxproj
index 4ae7d0f04e1..d6c13fc8fef 100644
--- a/src/map/map-server-generator.vcxproj
+++ b/src/map/map-server-generator.vcxproj
@@ -382,6 +382,7 @@
+
@@ -391,6 +392,9 @@
+
+
+
@@ -651,6 +655,7 @@
+
@@ -660,6 +665,9 @@
+
+
+
diff --git a/src/map/map-server-generator.vcxproj.filters b/src/map/map-server-generator.vcxproj.filters
index 969354b7a90..3d941dcbe3d 100644
--- a/src/map/map-server-generator.vcxproj.filters
+++ b/src/map/map-server-generator.vcxproj.filters
@@ -795,6 +795,9 @@
Header Files\Skills\Swordman
+
+ Header Files\Skills\Swordman
+
Header Files\Skills\Swordman
@@ -822,6 +825,15 @@
Header Files\Skills\Swordman
+
+ Header Files\Skills\Swordman
+
+
+ Header Files\Skills\Swordman
+
+
+ Header Files\Skills\Swordman
+
Header Files\Skills\Taekwon
@@ -1460,6 +1472,9 @@
Source Files\Skills\Swordman
+
+ Source Files\Skills\Swordman
+
Source Files\Skills\Swordman
@@ -1487,6 +1502,15 @@
Source Files\Skills\Swordman
+
+ Source Files\Skills\Swordman
+
+
+ Source Files\Skills\Swordman
+
+
+ Source Files\Skills\Swordman
+
Source Files\Skills\Taekwon
diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj
index ce700fa94ca..277a27aa7ad 100644
--- a/src/map/map-server.vcxproj
+++ b/src/map/map-server.vcxproj
@@ -382,6 +382,7 @@
+
@@ -391,6 +392,9 @@
+
+
+
@@ -651,6 +655,7 @@
+
@@ -660,6 +665,9 @@
+
+
+
diff --git a/src/map/map-server.vcxproj.filters b/src/map/map-server.vcxproj.filters
index 969354b7a90..3d941dcbe3d 100644
--- a/src/map/map-server.vcxproj.filters
+++ b/src/map/map-server.vcxproj.filters
@@ -795,6 +795,9 @@
Header Files\Skills\Swordman
+
+ Header Files\Skills\Swordman
+
Header Files\Skills\Swordman
@@ -822,6 +825,15 @@
Header Files\Skills\Swordman
+
+ Header Files\Skills\Swordman
+
+
+ Header Files\Skills\Swordman
+
+
+ Header Files\Skills\Swordman
+
Header Files\Skills\Taekwon
@@ -1460,6 +1472,9 @@
Source Files\Skills\Swordman
+
+ Source Files\Skills\Swordman
+
Source Files\Skills\Swordman
@@ -1487,6 +1502,15 @@
Source Files\Skills\Swordman
+
+ Source Files\Skills\Swordman
+
+
+ Source Files\Skills\Swordman
+
+
+ Source Files\Skills\Swordman
+
Source Files\Skills\Taekwon
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index fcfd420a55b..fdb31654988 100755
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -1572,7 +1572,6 @@ int32 skill_additional_effect( block_list* src, block_list *bl, uint16 skill_id,
}
break;
- case LK_SPIRALPIERCE:
case ML_SPIRALPIERCE:
case HN_SPIRAL_PIERCE_MAX:
if( dstsd || ( dstmd && !status_bl_has_mode(bl,MD_STATUSIMMUNE) ) ) //Does not work on status immune
@@ -1584,11 +1583,6 @@ int32 skill_additional_effect( block_list* src, block_list *bl, uint16 skill_id,
sc_start(src,bl,SC_BLIND,100,skill_lv,skill_get_time2(skill_id,skill_lv));
break;
- case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element
- if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON))
- sc_start2(src,bl, SC_BLEEDING,50, skill_lv, src->id, skill_get_time2(skill_id,skill_lv));
- break;
-
case HW_NAPALMVULCAN:
case HN_NAPALM_VULCAN_STRIKE:
sc_start(src,bl,SC_CURSE,5*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv));
@@ -5120,23 +5114,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id,
skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION);
break;
- case LK_HEADCRUSH:
- if (status_get_class_(bl) == CLASS_BOSS) {
- if (sd)
- clif_skill_fail( *sd, skill_id );
- break;
- }
- skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
- break;
-
- case LK_JOINTBEAT:
- flag = 1 << rnd() % 6;
- if (flag != BREAK_NECK && tsc && tsc->getSCE(SC_JOINTBEAT) && tsc->getSCE(SC_JOINTBEAT)->val2 & BREAK_NECK)
- flag = BREAK_NECK; // Target should always receive double damage if neck is already broken
- if (skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag))
- status_change_start(src, bl, SC_JOINTBEAT, (50 * (skill_lv + 1) - (270 * tstatus->str) / 100) * 10, skill_lv, flag & BREAK_FLAGS, src->id, 0, skill_get_time2(skill_id, skill_lv), SCSTART_NONE);
- break;
-
case MO_COMBOFINISH:
if (!(flag&1) && sc && sc->getSCE(SC_SPIRIT) && sc->getSCE(SC_SPIRIT)->val2 == SL_MONK)
{ //Becomes a splash attack when Soul Linked.
@@ -8040,12 +8017,6 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i
break;
*/
- case LK_TENSIONRELAX:
- clif_skill_nodamage(src,*bl,skill_id,skill_lv,
- sc_start4(src,bl,type,100,skill_lv,0,0,skill_get_time2(skill_id,skill_lv),
- skill_get_time(skill_id,skill_lv)));
- break;
-
case MER_PROVOKE:
if( status_has_mode(tstatus,MD_STATUSIMMUNE) || battle_check_undead(tstatus->race,tstatus->def_ele) ) {
return 1;
diff --git a/src/map/skills/swordman/relax.cpp b/src/map/skills/swordman/relax.cpp
new file mode 100644
index 00000000000..efab2545fde
--- /dev/null
+++ b/src/map/skills/swordman/relax.cpp
@@ -0,0 +1,18 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "relax.hpp"
+
+#include "map/clif.hpp"
+#include "map/status.hpp"
+
+SkillRelax::SkillRelax() : SkillImpl(LK_TENSIONRELAX) {
+}
+
+void SkillRelax::castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ sc_type type = skill_get_sc(getSkillId());
+
+ clif_skill_nodamage(src,*target,getSkillId(),skill_lv,
+ sc_start4(src,target,type,100,skill_lv,0,0,skill_get_time2(getSkillId(),skill_lv),
+ skill_get_time(getSkillId(),skill_lv)));
+}
diff --git a/src/map/skills/swordman/relax.hpp b/src/map/skills/swordman/relax.hpp
new file mode 100644
index 00000000000..e0edd3869c3
--- /dev/null
+++ b/src/map/skills/swordman/relax.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 SkillRelax : public SkillImpl {
+public:
+ SkillRelax();
+
+ void castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/swordman/skill_factory_swordman.cpp b/src/map/skills/swordman/skill_factory_swordman.cpp
index 7ae68c084a0..e901f59c271 100644
--- a/src/map/skills/swordman/skill_factory_swordman.cpp
+++ b/src/map/skills/swordman/skill_factory_swordman.cpp
@@ -16,6 +16,7 @@
#include "magnum.hpp"
#include "pierce.hpp"
#include "provoke.hpp"
+#include "relax.hpp"
#include "resistantsouls.hpp"
#include "sacrifice.hpp"
#include "selfprovoke.hpp"
@@ -24,6 +25,9 @@
#include "smite.hpp"
#include "spearboomerang.hpp"
#include "spearstab.hpp"
+#include "spiralpierce.hpp"
+#include "traumaticblow.hpp"
+#include "vitalstrike.hpp"
std::unique_ptr SkillFactorySwordman::create(const e_skill skill_id) const {
switch( skill_id ){
@@ -99,10 +103,16 @@ std::unique_ptr SkillFactorySwordman::create(const e_skill skil
return std::make_unique(skill_id);
case LK_CONCENTRATION:
return std::make_unique(skill_id);
+ case LK_HEADCRUSH:
+ return std::make_unique();
+ case LK_JOINTBEAT:
+ return std::make_unique();
case LK_PARRYING:
return std::make_unique(skill_id);
case LK_SPIRALPIERCE:
- return std::make_unique(skill_id);
+ return std::make_unique();
+ case LK_TENSIONRELAX:
+ return std::make_unique();
case PA_SACRIFICE:
return std::make_unique(skill_id);
case PA_SHIELDCHAIN:
diff --git a/src/map/skills/swordman/spiralpierce.cpp b/src/map/skills/swordman/spiralpierce.cpp
new file mode 100644
index 00000000000..d7c69f0ee40
--- /dev/null
+++ b/src/map/skills/swordman/spiralpierce.cpp
@@ -0,0 +1,33 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "spiralpierce.hpp"
+
+#include
+#include
+
+#include "map/mob.hpp"
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillSpiralPierce::SkillSpiralPierce() : WeaponSkillImpl(LK_SPIRALPIERCE) {
+}
+
+void SkillSpiralPierce::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const {
+#ifdef RENEWAL
+ const status_change *sc = status_get_sc(src);
+
+ skillratio += 50 + 50 * skill_lv;
+ RE_LVL_DMOD(100);
+ if (sc && sc->getSCE(SC_CHARGINGPIERCE_COUNT) && sc->getSCE(SC_CHARGINGPIERCE_COUNT)->val1 >= 10)
+ skillratio *= 2;
+#endif
+}
+
+void SkillSpiralPierce::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ map_session_data *dstsd = BL_CAST(BL_PC, target);
+ mob_data* dstmd = BL_CAST(BL_MOB, target);
+
+ if( dstsd || ( dstmd && !status_bl_has_mode(target,MD_STATUSIMMUNE) ) ) //Does not work on status immune
+ sc_start(src,target,SC_ANKLE,100,0,skill_get_time2(getSkillId(),skill_lv));
+}
diff --git a/src/map/skills/swordman/spiralpierce.hpp b/src/map/skills/swordman/spiralpierce.hpp
new file mode 100644
index 00000000000..dafb0bdb19a
--- /dev/null
+++ b/src/map/skills/swordman/spiralpierce.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 "../weapon_skill_impl.hpp"
+
+class SkillSpiralPierce : public WeaponSkillImpl {
+public:
+ SkillSpiralPierce();
+
+ void applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const override;
+ void calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const override;
+};
diff --git a/src/map/skills/swordman/traumaticblow.cpp b/src/map/skills/swordman/traumaticblow.cpp
new file mode 100644
index 00000000000..6d1e1c0ecc4
--- /dev/null
+++ b/src/map/skills/swordman/traumaticblow.cpp
@@ -0,0 +1,35 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "traumaticblow.hpp"
+
+#include "map/clif.hpp"
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillTraumaticBlow::SkillTraumaticBlow() : WeaponSkillImpl(LK_HEADCRUSH) {
+}
+
+void SkillTraumaticBlow::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+ base_skillratio += 40 * skill_lv;
+}
+
+void SkillTraumaticBlow::castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ map_session_data* sd = BL_CAST( BL_PC, src );
+
+ if (status_get_class_(target) == CLASS_BOSS) {
+ if (sd)
+ clif_skill_fail( *sd, getSkillId() );
+ return;
+ }
+
+ WeaponSkillImpl::castendDamageId(src, target, skill_lv, tick, flag);
+}
+
+void SkillTraumaticBlow::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ status_data* tstatus = status_get_status_data(*target);
+
+ // Headcrush has chance of causing Bleeding status, except on demon and undead element
+ if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON))
+ sc_start2(src,target, SC_BLEEDING,50, skill_lv, src->id, skill_get_time2(getSkillId(),skill_lv));
+}
diff --git a/src/map/skills/swordman/traumaticblow.hpp b/src/map/skills/swordman/traumaticblow.hpp
new file mode 100644
index 00000000000..3f153346ab7
--- /dev/null
+++ b/src/map/skills/swordman/traumaticblow.hpp
@@ -0,0 +1,15 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#pragma once
+
+#include "../weapon_skill_impl.hpp"
+
+class SkillTraumaticBlow : public WeaponSkillImpl {
+public:
+ SkillTraumaticBlow();
+
+ void applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const override;
+ void calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_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/swordman/vitalstrike.cpp b/src/map/skills/swordman/vitalstrike.cpp
new file mode 100644
index 00000000000..93f67e1886d
--- /dev/null
+++ b/src/map/skills/swordman/vitalstrike.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "vitalstrike.hpp"
+
+#include "map/status.hpp"
+
+SkillVitalStrike::SkillVitalStrike() : SkillImpl(LK_JOINTBEAT) {
+}
+
+void SkillVitalStrike::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+ const status_change *tsc = status_get_sc(target);
+
+ base_skillratio += 10 * skill_lv - 50;
+
+ // The 2x damage is only for the BREAK_NECK ailment.
+ if (wd->miscflag & BREAK_NECK || (tsc && tsc->getSCE(SC_JOINTBEAT) && tsc->getSCE(SC_JOINTBEAT)->val2 & BREAK_NECK))
+ base_skillratio *= 2;
+}
+
+void SkillVitalStrike::castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ status_data* tstatus = status_get_status_data(*target);
+ status_change *tsc = status_get_sc(target);
+
+ flag = 1 << rnd() % 6;
+ if (flag != BREAK_NECK && tsc && tsc->getSCE(SC_JOINTBEAT) && tsc->getSCE(SC_JOINTBEAT)->val2 & BREAK_NECK)
+ flag = BREAK_NECK; // Target should always receive double damage if neck is already broken
+ if (skill_attack(BF_WEAPON, src, src, target, getSkillId(), skill_lv, tick, flag))
+ status_change_start(src, target, SC_JOINTBEAT, (50 * (skill_lv + 1) - (270 * tstatus->str) / 100) * 10, skill_lv, flag & BREAK_FLAGS, src->id, 0, skill_get_time2(getSkillId(), skill_lv), SCSTART_NONE);
+}
diff --git a/src/map/skills/swordman/vitalstrike.hpp b/src/map/skills/swordman/vitalstrike.hpp
new file mode 100644
index 00000000000..ab7d0761d33
--- /dev/null
+++ b/src/map/skills/swordman/vitalstrike.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 SkillVitalStrike : public SkillImpl {
+public:
+ SkillVitalStrike();
+
+ void calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const override;
+ void castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};