diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 2a5340d5aac..2c3e0b159f4 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -3314,14 +3314,6 @@ static bool is_attack_hitting(struct Damage* wd, block_list *src, block_list *ta
case ML_PIERCE:
hitrate += hitrate * 5 * skill_lv / 100;
break;
- case AS_SONICBLOW:
- if(sd && pc_checkskill(sd,AS_SONICACCEL) > 0)
-#ifdef RENEWAL
- hitrate += hitrate * 90 / 100;
-#else
- hitrate += hitrate * 50 / 100;
-#endif
- break;
case RK_SONICWAVE:
hitrate += hitrate * 3 * skill_lv / 100; // !TODO: Confirm the hitrate bonus
break;
@@ -4753,20 +4745,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
case MS_BOWLINGBASH:
skillratio += 40 * skill_lv;
break;
- case AS_GRIMTOOTH:
- skillratio += 20 * skill_lv;
- break;
- case AS_SONICBLOW:
-#ifdef RENEWAL
- skillratio += 100 + 100 * skill_lv;
- if (tstatus->hp < (tstatus->max_hp / 2))
- skillratio += skillratio / 2;
-#else
- skillratio += 200 + 50 * skill_lv;
- if (sd && pc_checkskill(sd, AS_SONICACCEL) > 0)
- skillratio += skillratio / 10;
-#endif
- break;
case NPC_PIERCINGATT:
skillratio += -25; //75% base damage
break;
@@ -4961,15 +4939,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
skillratio += 100 + 100 * skill_lv;
#endif
break;
- case AS_SPLASHER:
-#ifdef RENEWAL
- skillratio += -100 + 400 + 100 * skill_lv;
-#else
- skillratio += 400 + 50 * skill_lv;
-#endif
- if(sd)
- skillratio += 20 * pc_checkskill(sd,AS_POISONREACT);
- break;
case ASC_BREAKER:
#ifdef RENEWAL
skillratio += -100 + 150 * skill_lv + sstatus->str + sstatus->int_; // !TODO: Confirm stat modifier
@@ -5053,9 +5022,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
case KN_CHARGEATK:
skillratio += 600;
break;
- case AS_VENOMKNIFE:
- skillratio += 400;
- break;
#else
case KN_CHARGEATK: { // +100% every 3 cells of distance but hard-limited to 500%
int32 k = (wd->miscflag-1)/3;
diff --git a/src/map/map-server-generator.vcxproj b/src/map/map-server-generator.vcxproj
index 430404129a4..23d178723a7 100644
--- a/src/map/map-server-generator.vcxproj
+++ b/src/map/map-server-generator.vcxproj
@@ -396,14 +396,17 @@
+
+
+
@@ -412,8 +415,12 @@
+
+
+
+
@@ -618,14 +625,17 @@
+
+
+
@@ -634,8 +644,12 @@
+
+
+
+
diff --git a/src/map/map-server-generator.vcxproj.filters b/src/map/map-server-generator.vcxproj.filters
index b7a1849bbc1..a9809d2191b 100644
--- a/src/map/map-server-generator.vcxproj.filters
+++ b/src/map/map-server-generator.vcxproj.filters
@@ -837,6 +837,9 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
@@ -855,12 +858,18 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
@@ -885,12 +894,24 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
+
+ Header Files\Skills\Thief
+
+
+ Header Files\Skills\Thief
+
Header Files\Skills
@@ -1361,6 +1382,9 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
@@ -1379,12 +1403,18 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
@@ -1409,12 +1439,24 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
+
+ Source Files\Skills\Thief
+
+
+ Source Files\Skills\Thief
+
Source Files\Skills
diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj
index d6760d3723c..83197a0f239 100644
--- a/src/map/map-server.vcxproj
+++ b/src/map/map-server.vcxproj
@@ -396,14 +396,17 @@
+
+
+
@@ -412,8 +415,12 @@
+
+
+
+
@@ -618,14 +625,17 @@
+
+
+
@@ -634,8 +644,12 @@
+
+
+
+
diff --git a/src/map/map-server.vcxproj.filters b/src/map/map-server.vcxproj.filters
index b7a1849bbc1..a9809d2191b 100644
--- a/src/map/map-server.vcxproj.filters
+++ b/src/map/map-server.vcxproj.filters
@@ -837,6 +837,9 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
@@ -855,12 +858,18 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
@@ -885,12 +894,24 @@
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
Header Files\Skills\Thief
Header Files\Skills\Thief
+
+ Header Files\Skills\Thief
+
+
+ Header Files\Skills\Thief
+
+
+ Header Files\Skills\Thief
+
Header Files\Skills
@@ -1361,6 +1382,9 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
@@ -1379,12 +1403,18 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
@@ -1409,12 +1439,24 @@
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
Source Files\Skills\Thief
Source Files\Skills\Thief
+
+ Source Files\Skills\Thief
+
+
+ Source Files\Skills\Thief
+
+
+ Source Files\Skills\Thief
+
Source Files\Skills
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index 64e717d6ef7..50332438945 100755
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -1408,22 +1408,8 @@ int32 skill_additional_effect( block_list* src, block_list *bl, uint16 skill_id,
sc_start(src,bl,SC_STUN,(6*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
break;
- case AS_VENOMKNIFE:
- case AS_SPLASHER:
- sc_start2(src, bl, SC_POISON, 100, skill_lv, src->id, skill_get_time2(skill_id, skill_lv));
- break;
-
- case AS_SONICBLOW:
case HN_MEGA_SONIC_BLOW:
- if (!map_flag_gvg2(bl->m) && !map_getmapflag(bl->m, MF_BATTLEGROUND) && sc && sc->getSCE(SC_SPIRIT) && sc->getSCE(SC_SPIRIT)->val2 == SL_ASSASIN)
- sc_start(src, bl, SC_STUN, (4 * skill_lv + 20), skill_lv, skill_get_time2(skill_id, skill_lv)); //Link gives double stun chance outside GVG/BG
- else
- sc_start(src, bl, SC_STUN, (2 * skill_lv + 10), skill_lv, skill_get_time2(skill_id, skill_lv));
- break;
-
- case AS_GRIMTOOTH:
- if (dstmd && !status_has_mode(tstatus,MD_STATUSIMMUNE))
- sc_start(src,bl,SC_QUAGMIRE,100,0,skill_get_time2(skill_id,skill_lv));
+ sc_start(src, bl, SC_STUN, (2 * skill_lv + 10), skill_lv, skill_get_time2(skill_id, skill_lv));
break;
case NPC_STORMGUST2:
@@ -5361,11 +5347,9 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id,
break;
//Splash attack skills.
- case AS_GRIMTOOTH:
case NPC_SPLASHATTACK:
flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
[[fallthrough]];
- case AS_SPLASHER:
case MA_SHOWER:
#ifdef RENEWAL
case SN_SHARPSHOOTING:
@@ -5830,7 +5814,7 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id,
//SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets
//special case: Venom Splasher uses a different range for searching than for splashing
if (flag&SD_LEVEL || skill_get_nk(skill_id, NK_SPLASHSPLIT)) {
- skill_area_temp[0] = map_foreachinallrange(skill_area_sub, bl, (skill_id == AS_SPLASHER)?1:splash_size, BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count);
+ skill_area_temp[0] = map_foreachinallrange(skill_area_sub, bl, splash_size, BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count);
// If there are no characters in the area, then it always counts as if there was one target
// This happens when targetting skill units such as icewall
skill_area_temp[0] = std::max(1, skill_area_temp[0]);
@@ -5841,10 +5825,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id,
if (skill_id == RA_ARROWSTORM)
status_change_end(src, SC_CAMOUFLAGE);
- if( skill_id == AS_SPLASHER ) {
- // Don't consume a second gemstone.
- return 0;
- }
}
break;
case NW_THE_VIGILANTE_AT_NIGHT:
@@ -8122,18 +8102,6 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i
break;
*/
- case AS_ENCHANTPOISON:
- if( sc_start( src, bl, type, 100, skill_lv, skill_get_time( skill_id, skill_lv ) ) ){
- clif_skill_nodamage(src, *bl, skill_id, skill_lv);
- }else{
- clif_skill_nodamage(src, *bl, skill_id, skill_lv, false );
-
- if( sd != nullptr ){
- clif_skill_fail( *sd, skill_id );
- }
- }
- 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),
@@ -8715,7 +8683,6 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i
clif_skill_nodamage(src,*bl,skill_id,-1,sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
break;
- case AS_CLOAKING:
case GC_CLOAKINGEXCEED:
case LG_FORCEOFVANGUARD:
case SC_REPRODUCE:
@@ -9490,22 +9457,6 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i
unit_skilluse_id(src, src->id, sd->skill_id_song, sd->skill_lv_song);
break;
- case AS_SPLASHER:
- if( status_has_mode(tstatus,MD_STATUSIMMUNE)
- // Renewal dropped the 3/4 hp requirement
-#ifndef RENEWAL
- || tstatus-> hp > tstatus->max_hp*3/4
-#endif
- ) {
- if (sd) {
- clif_skill_fail( *sd, skill_id );
- }
- return 1;
- }
- clif_skill_nodamage(src,*bl,skill_id,skill_lv,
- sc_start4(src,bl,type,100,skill_lv,skill_id,src->id,skill_get_time(skill_id,skill_lv),1000));
- break;
-
case PF_MINDBREAKER:
{
if(status_has_mode(tstatus,MD_STATUSIMMUNE) || battle_check_undead(tstatus->race,tstatus->def_ele)) {
@@ -13273,7 +13224,6 @@ int32 skill_castend_pos2(block_list* src, int32 x, int32 y, uint16 skill_id, uin
case MA_LANDMINE:
case MA_SANDMAN:
case MA_FREEZINGTRAP:
- case AS_VENOMDUST:
case PF_FOGWALL:
case PF_SPIDERWEB:
case WE_CALLPARTNER:
diff --git a/src/map/skills/thief/cloaking.cpp b/src/map/skills/thief/cloaking.cpp
new file mode 100644
index 00000000000..2129bad9e28
--- /dev/null
+++ b/src/map/skills/thief/cloaking.cpp
@@ -0,0 +1,33 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "cloaking.hpp"
+
+#include "map/clif.hpp"
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillCloaking::SkillCloaking() : SkillImpl(AS_CLOAKING) {
+}
+
+void SkillCloaking::castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ map_session_data* sd = BL_CAST( BL_PC, src );
+ sc_type type = skill_get_sc(getSkillId());
+ status_change *tsc = status_get_sc(target);
+ status_change_entry *tsce = (tsc && type != SC_NONE)?tsc->getSCE(type):nullptr;
+ int32 i = 0;
+
+ if (tsce) {
+ i = status_change_end(target, type);
+ if( i )
+ clif_skill_nodamage(src,*target,getSkillId(),-1,i);
+ else if( sd )
+ clif_skill_fail( *sd, getSkillId() );
+ return;
+ }
+ i = sc_start(src,target,type,100,skill_lv,skill_get_time(getSkillId(),skill_lv));
+ if( i )
+ clif_skill_nodamage(src,*target,getSkillId(),-1,i);
+ else if( sd )
+ clif_skill_fail( *sd, getSkillId(), USESKILL_FAIL_LEVEL );
+}
diff --git a/src/map/skills/thief/cloaking.hpp b/src/map/skills/thief/cloaking.hpp
new file mode 100644
index 00000000000..b79d12c5ee6
--- /dev/null
+++ b/src/map/skills/thief/cloaking.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 SkillCloaking : public SkillImpl {
+public:
+ SkillCloaking();
+
+ void castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/thief/enchantpoison.cpp b/src/map/skills/thief/enchantpoison.cpp
new file mode 100644
index 00000000000..9ed8c9c0133
--- /dev/null
+++ b/src/map/skills/thief/enchantpoison.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "enchantpoison.hpp"
+
+#include "map/clif.hpp"
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillEnchantPoison::SkillEnchantPoison() : SkillImpl(AS_ENCHANTPOISON) {
+}
+
+void SkillEnchantPoison::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( sc_start( src, target, type, 100, skill_lv, skill_get_time( getSkillId(), skill_lv ) ) ){
+ clif_skill_nodamage(src, *target, getSkillId(), skill_lv);
+ }else{
+ clif_skill_nodamage(src, *target, getSkillId(), skill_lv, false );
+
+ if( sd != nullptr ){
+ clif_skill_fail( *sd, getSkillId() );
+ }
+ }
+}
diff --git a/src/map/skills/thief/enchantpoison.hpp b/src/map/skills/thief/enchantpoison.hpp
new file mode 100644
index 00000000000..1f696165e85
--- /dev/null
+++ b/src/map/skills/thief/enchantpoison.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 SkillEnchantPoison : public SkillImpl {
+public:
+ SkillEnchantPoison();
+
+ void castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/thief/grimtooth.cpp b/src/map/skills/thief/grimtooth.cpp
new file mode 100644
index 00000000000..8ccd898d2de
--- /dev/null
+++ b/src/map/skills/thief/grimtooth.cpp
@@ -0,0 +1,28 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "grimtooth.hpp"
+
+#include "map/mob.hpp"
+#include "map/status.hpp"
+
+SkillGrimtooth::SkillGrimtooth() : SkillImplRecursiveDamageSplash(AS_GRIMTOOTH) {
+}
+
+void SkillGrimtooth::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+ base_skillratio += 20 * skill_lv;
+}
+
+void SkillGrimtooth::castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
+
+ SkillImplRecursiveDamageSplash::castendDamageId(src, target, skill_lv, tick, flag);
+}
+
+void SkillGrimtooth::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);
+ mob_data* dstmd = BL_CAST(BL_MOB, target);
+
+ if (dstmd && !status_has_mode(tstatus,MD_STATUSIMMUNE))
+ sc_start(src,target,SC_QUAGMIRE,100,0,skill_get_time2(getSkillId(),skill_lv));
+}
diff --git a/src/map/skills/thief/grimtooth.hpp b/src/map/skills/thief/grimtooth.hpp
new file mode 100644
index 00000000000..af499e3a06e
--- /dev/null
+++ b/src/map/skills/thief/grimtooth.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 "../skill_impl.hpp"
+
+class SkillGrimtooth : public SkillImplRecursiveDamageSplash {
+public:
+ SkillGrimtooth();
+
+ 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;
+ void castendDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/thief/skill_factory_thief.cpp b/src/map/skills/thief/skill_factory_thief.cpp
index 14d3faabb22..7b3e64e7d4a 100644
--- a/src/map/skills/thief/skill_factory_thief.cpp
+++ b/src/map/skills/thief/skill_factory_thief.cpp
@@ -8,14 +8,17 @@
#include "backslide.hpp"
#include "backstab.hpp"
+#include "cloaking.hpp"
#include "closeconfine.hpp"
#include "detoxify.hpp"
#include "divestarmor.hpp"
#include "divesthelm.hpp"
#include "divestshield.hpp"
#include "divestweapon.hpp"
+#include "enchantpoison.hpp"
#include "envenom.hpp"
#include "findstone.hpp"
+#include "grimtooth.hpp"
#include "hiding.hpp"
#include "mug.hpp"
#include "remover.hpp"
@@ -23,8 +26,12 @@
#include "scribble.hpp"
#include "sightlessmind.hpp"
#include "snatch.hpp"
+#include "sonicblow.hpp"
#include "steal.hpp"
#include "stonefling.hpp"
+#include "throwvenomknife.hpp"
+#include "venomdust.hpp"
+#include "venomsplasher.hpp"
std::unique_ptr SkillFactoryThief::create(const e_skill skill_id) const {
switch (skill_id) {
@@ -32,12 +39,22 @@ std::unique_ptr SkillFactoryThief::create(const e_skill skill_i
return std::make_unique(skill_id);
case ABC_CHAIN_REACTION_SHOT_ATK:
return std::make_unique(skill_id);
+ case AS_CLOAKING:
+ return std::make_unique();
+ case AS_ENCHANTPOISON:
+ return std::make_unique();
+ case AS_GRIMTOOTH:
+ return std::make_unique();
case AS_POISONREACT:
return std::make_unique(skill_id);
case AS_SONICBLOW:
- return std::make_unique(skill_id);
+ return std::make_unique();
+ case AS_SPLASHER:
+ return std::make_unique();
+ case AS_VENOMDUST:
+ return std::make_unique();
case AS_VENOMKNIFE:
- return std::make_unique(skill_id);
+ return std::make_unique();
case ASC_BREAKER:
return std::make_unique(skill_id);
case GC_VENOMIMPRESS:
diff --git a/src/map/skills/thief/sonicblow.cpp b/src/map/skills/thief/sonicblow.cpp
new file mode 100644
index 00000000000..7c0029b53c2
--- /dev/null
+++ b/src/map/skills/thief/sonicblow.cpp
@@ -0,0 +1,48 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "sonicblow.hpp"
+
+#include
+
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillSonicBlow::SkillSonicBlow() : WeaponSkillImpl(AS_SONICBLOW) {
+}
+
+void SkillSonicBlow::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+#ifdef RENEWAL
+ const status_data* tstatus = status_get_status_data(*target);
+
+ base_skillratio += 100 + 100 * skill_lv;
+ if (tstatus->hp < (tstatus->max_hp / 2))
+ base_skillratio += base_skillratio / 2;
+#else
+ const map_session_data* sd = BL_CAST( BL_PC, src );
+
+ base_skillratio += 200 + 50 * skill_lv;
+ if (sd && pc_checkskill(sd, AS_SONICACCEL) > 0)
+ base_skillratio += base_skillratio / 10;
+#endif
+}
+
+void SkillSonicBlow::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ status_change *sc = status_get_sc(src);
+
+ if (!map_flag_gvg2(target->m) && !map_getmapflag(target->m, MF_BATTLEGROUND) && sc && sc->getSCE(SC_SPIRIT) && sc->getSCE(SC_SPIRIT)->val2 == SL_ASSASIN)
+ sc_start(src, target, SC_STUN, (4 * skill_lv + 20), skill_lv, skill_get_time2(getSkillId(), skill_lv)); //Link gives doutargete stun chance outside GVG/BG
+ else
+ sc_start(src, target, SC_STUN, (2 * skill_lv + 10), skill_lv, skill_get_time2(getSkillId(), skill_lv));
+}
+
+void SkillSonicBlow::modifyHitRate(int16& hit_rate, const block_list* src, const block_list* target, uint16 skill_lv) const {
+ const map_session_data* sd = BL_CAST( BL_PC, src );
+
+ if(sd && pc_checkskill(sd,AS_SONICACCEL) > 0)
+#ifdef RENEWAL
+ hit_rate += hit_rate * 90 / 100;
+#else
+ hit_rate += hit_rate * 50 / 100;
+#endif
+}
diff --git a/src/map/skills/thief/sonicblow.hpp b/src/map/skills/thief/sonicblow.hpp
new file mode 100644
index 00000000000..01b765ab077
--- /dev/null
+++ b/src/map/skills/thief/sonicblow.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 SkillSonicBlow : public WeaponSkillImpl {
+public:
+ SkillSonicBlow();
+
+ 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;
+ void modifyHitRate(int16& hit_rate, const block_list* src, const block_list* target, uint16 skill_lv) const override;
+};
diff --git a/src/map/skills/thief/throwvenomknife.cpp b/src/map/skills/thief/throwvenomknife.cpp
new file mode 100644
index 00000000000..a08acfae937
--- /dev/null
+++ b/src/map/skills/thief/throwvenomknife.cpp
@@ -0,0 +1,21 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "throwvenomknife.hpp"
+
+#include
+
+#include "map/status.hpp"
+
+SkillThrowVenomKnife::SkillThrowVenomKnife() : WeaponSkillImpl(AS_VENOMKNIFE) {
+}
+
+void SkillThrowVenomKnife::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+#ifdef RENEWAL
+ base_skillratio += 400;
+#endif
+}
+
+void SkillThrowVenomKnife::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ sc_start2(src, target, SC_POISON, 100, skill_lv, src->id, skill_get_time2(getSkillId(), skill_lv));
+}
diff --git a/src/map/skills/thief/throwvenomknife.hpp b/src/map/skills/thief/throwvenomknife.hpp
new file mode 100644
index 00000000000..00346103368
--- /dev/null
+++ b/src/map/skills/thief/throwvenomknife.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 SkillThrowVenomKnife : public WeaponSkillImpl {
+public:
+ SkillThrowVenomKnife();
+
+ 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/thief/venomdust.cpp b/src/map/skills/thief/venomdust.cpp
new file mode 100644
index 00000000000..2813941e7e1
--- /dev/null
+++ b/src/map/skills/thief/venomdust.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "venomdust.hpp"
+
+
+SkillVenomDust::SkillVenomDust() : SkillImpl(AS_VENOMDUST) {
+}
+
+void SkillVenomDust::castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const {
+ flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/thief/venomdust.hpp b/src/map/skills/thief/venomdust.hpp
new file mode 100644
index 00000000000..55fea57bfa0
--- /dev/null
+++ b/src/map/skills/thief/venomdust.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 SkillVenomDust : public SkillImpl {
+public:
+ SkillVenomDust();
+
+ void castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/thief/venomsplasher.cpp b/src/map/skills/thief/venomsplasher.cpp
new file mode 100644
index 00000000000..53396461bfd
--- /dev/null
+++ b/src/map/skills/thief/venomsplasher.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "venomsplasher.hpp"
+
+#include
+
+#include "map/clif.hpp"
+#include "map/pc.hpp"
+#include "map/status.hpp"
+
+SkillVenomSplasher::SkillVenomSplasher() : SkillImplRecursiveDamageSplash(AS_SPLASHER) {
+}
+
+void SkillVenomSplasher::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const {
+ const map_session_data* sd = BL_CAST( BL_PC, src );
+
+#ifdef RENEWAL
+ base_skillratio += -100 + 400 + 100 * skill_lv;
+#else
+ base_skillratio += 400 + 50 * skill_lv;
+#endif
+ if(sd)
+ base_skillratio += 20 * pc_checkskill(sd,AS_POISONREACT);
+}
+
+void SkillVenomSplasher::castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ status_data* tstatus = status_get_status_data(*target);
+ sc_type type = skill_get_sc(getSkillId());
+ map_session_data* sd = BL_CAST( BL_PC, src );
+
+ if( status_has_mode(tstatus,MD_STATUSIMMUNE)
+ // Renewal dropped the 3/4 hp requirement
+#ifndef RENEWAL
+ || tstatus-> hp > tstatus->max_hp*3/4
+#endif
+ ) {
+ if (sd) {
+ clif_skill_fail( *sd, getSkillId() );
+ }
+ return;
+ }
+ clif_skill_nodamage(src,*target,getSkillId(),skill_lv,
+ sc_start4(src,target,type,100,skill_lv,getSkillId(),src->id,skill_get_time(getSkillId(),skill_lv),1000));
+}
+
+void SkillVenomSplasher::castendDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ SkillImplRecursiveDamageSplash::castendDamageId(src, target, skill_lv, tick, flag);
+
+ if (!(flag & 1)) {
+ // Don't consume a second gemstone.
+ flag |= SKILL_NOCONSUME_REQ;
+ }
+}
+
+int16 SkillVenomSplasher::getSearchSize(uint16 skill_lv) const {
+ // Venom Splasher uses a different range for searching than for splashing
+ return 1;
+}
+
+void SkillVenomSplasher::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ sc_start2(src, target, SC_POISON, 100, skill_lv, src->id, skill_get_time2(getSkillId(), skill_lv));
+}
diff --git a/src/map/skills/thief/venomsplasher.hpp b/src/map/skills/thief/venomsplasher.hpp
new file mode 100644
index 00000000000..bb56b8fa0be
--- /dev/null
+++ b/src/map/skills/thief/venomsplasher.hpp
@@ -0,0 +1,17 @@
+// 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 SkillVenomSplasher : public SkillImplRecursiveDamageSplash {
+public:
+ SkillVenomSplasher();
+
+ 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;
+ void castendNoDamageId(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+ void castendDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+ int16 getSearchSize(uint16 skill_lv) const override;
+};