From 934896a004b84b8988791ba1f4d0c93a35efa9f3 Mon Sep 17 00:00:00 2001 From: Atemo Date: Thu, 15 Jan 2026 21:58:39 +0100 Subject: [PATCH] Split up Assassin skills (#9741) --- src/map/battle.cpp | 34 ----------- src/map/map-server-generator.vcxproj | 14 +++++ src/map/map-server-generator.vcxproj.filters | 42 +++++++++++++ src/map/map-server.vcxproj | 14 +++++ src/map/map-server.vcxproj.filters | 42 +++++++++++++ src/map/skill.cpp | 54 +---------------- src/map/skills/thief/cloaking.cpp | 33 ++++++++++ src/map/skills/thief/cloaking.hpp | 13 ++++ src/map/skills/thief/enchantpoison.cpp | 26 ++++++++ src/map/skills/thief/enchantpoison.hpp | 13 ++++ src/map/skills/thief/grimtooth.cpp | 28 +++++++++ src/map/skills/thief/grimtooth.hpp | 15 +++++ src/map/skills/thief/skill_factory_thief.cpp | 21 ++++++- src/map/skills/thief/sonicblow.cpp | 48 +++++++++++++++ src/map/skills/thief/sonicblow.hpp | 15 +++++ src/map/skills/thief/throwvenomknife.cpp | 21 +++++++ src/map/skills/thief/throwvenomknife.hpp | 14 +++++ src/map/skills/thief/venomdust.cpp | 13 ++++ src/map/skills/thief/venomdust.hpp | 13 ++++ src/map/skills/thief/venomsplasher.cpp | 63 ++++++++++++++++++++ src/map/skills/thief/venomsplasher.hpp | 17 ++++++ 21 files changed, 465 insertions(+), 88 deletions(-) create mode 100644 src/map/skills/thief/cloaking.cpp create mode 100644 src/map/skills/thief/cloaking.hpp create mode 100644 src/map/skills/thief/enchantpoison.cpp create mode 100644 src/map/skills/thief/enchantpoison.hpp create mode 100644 src/map/skills/thief/grimtooth.cpp create mode 100644 src/map/skills/thief/grimtooth.hpp create mode 100644 src/map/skills/thief/sonicblow.cpp create mode 100644 src/map/skills/thief/sonicblow.hpp create mode 100644 src/map/skills/thief/throwvenomknife.cpp create mode 100644 src/map/skills/thief/throwvenomknife.hpp create mode 100644 src/map/skills/thief/venomdust.cpp create mode 100644 src/map/skills/thief/venomdust.hpp create mode 100644 src/map/skills/thief/venomsplasher.cpp create mode 100644 src/map/skills/thief/venomsplasher.hpp 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; +};