From 8af3ac4acc92f12cd3cb38b9fe9c844d6693eaec Mon Sep 17 00:00:00 2001 From: Atemo Date: Mon, 9 Mar 2026 14:42:31 +0100 Subject: [PATCH 1/2] Add impl for skill_counter_additional_effect (#9908) Co-authored-by: Lemongrass3110 --- src/map/skill.cpp | 41 +------------------ src/map/skills/gunslinger/fullbuster.cpp | 6 +++ src/map/skills/gunslinger/fullbuster.hpp | 1 + .../skills/homunculus/homunculus_sbr44.cpp | 13 ++++++ .../skills/homunculus/homunculus_sbr44.hpp | 1 + src/map/skills/skill_impl.cpp | 4 ++ src/map/skills/skill_impl.hpp | 7 +++- src/map/skills/swordman/grandcross.cpp | 8 ++++ src/map/skills/swordman/grandcross.hpp | 1 + src/map/skills/swordman/hesperuslit.cpp | 18 ++++++++ src/map/skills/swordman/hesperuslit.hpp | 1 + src/map/skills/taekwon/esha.cpp | 4 ++ src/map/skills/taekwon/esha.hpp | 1 + src/map/skills/taekwon/espa.cpp | 4 ++ src/map/skills/taekwon/espa.hpp | 1 + src/map/skills/taekwon/eswhoo.cpp | 4 ++ src/map/skills/taekwon/eswhoo.hpp | 1 + 17 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 8c55dff880c..ffd62cde09e 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1735,45 +1735,8 @@ int32 skill_counter_additional_effect (block_list* src, block_list *bl, uint16 s } } - switch(skill_id) { - case GS_FULLBUSTER: - sc_start(src,src,SC_BLIND,2*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case HFLI_SBR44: //[orn] - if(src->type == BL_HOM){ - homun_data& hd = reinterpret_cast( *src ); - - hd.homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION); - - clif_send_homdata( hd, SP_INTIMATE ); - } - break; - case CR_GRANDCROSS: - if (src == bl) { - // Grand Cross on self specifically only triggers "When hit by physical attack" autospells and ignores everything else - attack_type |= BF_WEAPON; - attack_type &= ~BF_MAGIC; - } - break; - case LG_HESPERUSLIT: - { - status_change *sc = status_get_sc(src); - - if( sc && sc->getSCE(SC_FORCEOFVANGUARD)) { - for(int32 i = 0; i < sc->getSCE(SC_FORCEOFVANGUARD)->val3; i++ ) - pc_addspiritball(sd, skill_get_time(LG_FORCEOFVANGUARD,1),sc->getSCE(SC_FORCEOFVANGUARD)->val3); - } - } - break; - case SP_SPA: - sc_start(src, src, SC_USE_SKILL_SP_SPA, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case SP_SHA: - sc_start(src, src, SC_USE_SKILL_SP_SHA, 100, skill_lv, skill_get_time2(skill_id, skill_lv)); - break; - case SP_SWHOO: - sc_start(src, src, SC_USE_SKILL_SP_SHA, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - break; + if (std::shared_ptr skill = skill_db.find(skill_id); skill != nullptr && skill->impl != nullptr) { + skill->impl->applyCounterAdditionalEffects(src, bl, skill_lv, tick, attack_type); } if(sd && (sd->class_&MAPID_SECONDMASK) == MAPID_STAR_GLADIATOR && diff --git a/src/map/skills/gunslinger/fullbuster.cpp b/src/map/skills/gunslinger/fullbuster.cpp index 66c63921e0d..87a3193916c 100644 --- a/src/map/skills/gunslinger/fullbuster.cpp +++ b/src/map/skills/gunslinger/fullbuster.cpp @@ -3,9 +3,15 @@ #include "fullbuster.hpp" +#include "map/status.hpp" + SkillFullBuster::SkillFullBuster() : WeaponSkillImpl(GS_FULLBUSTER) { } +void SkillFullBuster::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + sc_start(src, src, SC_BLIND, 2 * skill_lv, skill_lv, skill_get_time2(getSkillId(), skill_lv)); +} + void SkillFullBuster::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const { base_skillratio += 100 * (skill_lv + 2); } diff --git a/src/map/skills/gunslinger/fullbuster.hpp b/src/map/skills/gunslinger/fullbuster.hpp index a65e7d5247c..2be3b7eb1e5 100644 --- a/src/map/skills/gunslinger/fullbuster.hpp +++ b/src/map/skills/gunslinger/fullbuster.hpp @@ -11,5 +11,6 @@ class SkillFullBuster : public WeaponSkillImpl { public: SkillFullBuster(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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; }; diff --git a/src/map/skills/homunculus/homunculus_sbr44.cpp b/src/map/skills/homunculus/homunculus_sbr44.cpp index 2d1c4b40500..d0606894f46 100644 --- a/src/map/skills/homunculus/homunculus_sbr44.cpp +++ b/src/map/skills/homunculus/homunculus_sbr44.cpp @@ -3,9 +3,22 @@ #include "homunculus_sbr44.hpp" +#include "map/clif.hpp" +#include "map/homunculus.hpp" + SkillSBR44::SkillSBR44() : WeaponSkillImpl(HFLI_SBR44) { } +void SkillSBR44::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + if (src->type == BL_HOM) { + homun_data& hd = reinterpret_cast(*src); + + hd.homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION); + + clif_send_homdata(hd, SP_INTIMATE); + } +} + void SkillSBR44::calculateSkillRatio(const Damage* wd, const block_list* src, const block_list* target, uint16 skill_lv, int32& base_skillratio, int32 mflag) const { base_skillratio += 100 * (skill_lv - 1); } diff --git a/src/map/skills/homunculus/homunculus_sbr44.hpp b/src/map/skills/homunculus/homunculus_sbr44.hpp index 5b58ba5164c..f41c0ac5aa9 100644 --- a/src/map/skills/homunculus/homunculus_sbr44.hpp +++ b/src/map/skills/homunculus/homunculus_sbr44.hpp @@ -9,5 +9,6 @@ class SkillSBR44 : public WeaponSkillImpl { public: SkillSBR44(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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; }; diff --git a/src/map/skills/skill_impl.cpp b/src/map/skills/skill_impl.cpp index 5ad14b632aa..ca968651d5e 100644 --- a/src/map/skills/skill_impl.cpp +++ b/src/map/skills/skill_impl.cpp @@ -38,6 +38,10 @@ void SkillImpl::applyAdditionalEffects(block_list*, block_list*, uint16, t_tick, // no-op } +void SkillImpl::applyCounterAdditionalEffects(block_list*, block_list*, uint16, t_tick, int32&) const { + // no-op +} + StatusSkillImpl::StatusSkillImpl(e_skill skillId, bool end_if_running) : SkillImpl(skillId) { this->end_if_running = end_if_running; }; diff --git a/src/map/skills/skill_impl.hpp b/src/map/skills/skill_impl.hpp index 8be264978bc..21c56da943d 100644 --- a/src/map/skills/skill_impl.hpp +++ b/src/map/skills/skill_impl.hpp @@ -38,10 +38,15 @@ class SkillImpl { virtual void modifyHitRate(int16& hit_rate, const block_list* src, const block_list* target, uint16 skill_lv) const; /** - * Apply additional effects after damage - called from skill_additional_effect + * Apply additional effects on the target after damage - called from skill_additional_effect */ virtual void applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const; + /** + * Apply additional effects on the caster after damage - called from skill_counter_additional_effect + */ + virtual void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const; + protected: e_skill skill_id_; }; diff --git a/src/map/skills/swordman/grandcross.cpp b/src/map/skills/swordman/grandcross.cpp index 3bc8488dc81..5e13d59ef5c 100644 --- a/src/map/skills/swordman/grandcross.cpp +++ b/src/map/skills/swordman/grandcross.cpp @@ -9,6 +9,14 @@ SkillGrandCross::SkillGrandCross() : SkillImpl(CR_GRANDCROSS) { } +void SkillGrandCross::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + if (src == target) { + // Grand Cross on self specifically only triggers "When hit by physical attack" autospells and ignores everything else + attack_type |= BF_WEAPON; + attack_type &= ~BF_MAGIC; + } +} + void SkillGrandCross::castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const { //Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). flag|=1; diff --git a/src/map/skills/swordman/grandcross.hpp b/src/map/skills/swordman/grandcross.hpp index 00cf0678f76..5b05eeca9e1 100644 --- a/src/map/skills/swordman/grandcross.hpp +++ b/src/map/skills/swordman/grandcross.hpp @@ -9,6 +9,7 @@ class SkillGrandCross : public SkillImpl { public: SkillGrandCross(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const override; void castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const override; void applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const override; }; diff --git a/src/map/skills/swordman/hesperuslit.cpp b/src/map/skills/swordman/hesperuslit.cpp index 6427217ff5e..54f2bc35ec2 100644 --- a/src/map/skills/swordman/hesperuslit.cpp +++ b/src/map/skills/swordman/hesperuslit.cpp @@ -13,6 +13,24 @@ SkillHesperusLit::SkillHesperusLit() : WeaponSkillImpl(LG_HESPERUSLIT) { } +void SkillHesperusLit::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + map_session_data* sd = BL_CAST(BL_PC, src); + + if (sd == nullptr) { + return; + } + + status_change_entry* sce = sd->sc.getSCE(SC_FORCEOFVANGUARD); + + if (sce == nullptr) { + return; + } + + for (int32 i = 0; i < sce->val3; i++) { + pc_addspiritball(sd, skill_get_time(LG_FORCEOFVANGUARD, 1), sce->val3); + } +} + void SkillHesperusLit::calculateSkillRatio(const Damage* wd, const block_list* src, const block_list* target, uint16 skill_lv, int32& skillratio, int32 mflag) const { const status_change* sc = status_get_sc(src); const status_data* sstatus = status_get_status_data(*src); diff --git a/src/map/skills/swordman/hesperuslit.hpp b/src/map/skills/swordman/hesperuslit.hpp index b76f25781f2..f706d92f8b8 100644 --- a/src/map/skills/swordman/hesperuslit.hpp +++ b/src/map/skills/swordman/hesperuslit.hpp @@ -9,6 +9,7 @@ class SkillHesperusLit : public WeaponSkillImpl { public: SkillHesperusLit(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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 applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const override; }; diff --git a/src/map/skills/taekwon/esha.cpp b/src/map/skills/taekwon/esha.cpp index 7c03b6a14a8..dbd650986f4 100644 --- a/src/map/skills/taekwon/esha.cpp +++ b/src/map/skills/taekwon/esha.cpp @@ -15,6 +15,10 @@ void SkillEsha::applyAdditionalEffects(block_list *src, block_list *target, uint sc_start(src, target, SC_SP_SHA, 100, skill_lv, skill_get_time(getSkillId(), skill_lv)); } +void SkillEsha::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + sc_start(src, src, SC_USE_SKILL_SP_SHA, 100, skill_lv, skill_get_time2(getSkillId(), skill_lv)); +} + void SkillEsha::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &base_skillratio, int32 mflag) const { base_skillratio += -100 + 5 * skill_lv; } diff --git a/src/map/skills/taekwon/esha.hpp b/src/map/skills/taekwon/esha.hpp index 0343666c1b1..103feb2c8bb 100644 --- a/src/map/skills/taekwon/esha.hpp +++ b/src/map/skills/taekwon/esha.hpp @@ -10,6 +10,7 @@ class SkillEsha : public SkillImplRecursiveDamageSplash { SkillEsha(); 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 applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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 splashSearch(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 flag) const override; int64 splashDamage(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 flag) const override; diff --git a/src/map/skills/taekwon/espa.cpp b/src/map/skills/taekwon/espa.cpp index f46743f9a26..23987c8622a 100644 --- a/src/map/skills/taekwon/espa.cpp +++ b/src/map/skills/taekwon/espa.cpp @@ -13,6 +13,10 @@ SkillEspa::SkillEspa() : SkillImpl(SP_SPA) { } +void SkillEspa::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + sc_start(src, src, SC_USE_SKILL_SP_SPA, 100, skill_lv, skill_get_time(getSkillId(), skill_lv)); +} + void SkillEspa::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { skillratio += 400 + 250 * skill_lv; RE_LVL_DMOD(100); diff --git a/src/map/skills/taekwon/espa.hpp b/src/map/skills/taekwon/espa.hpp index 126484797f1..fe90b202faa 100644 --- a/src/map/skills/taekwon/espa.hpp +++ b/src/map/skills/taekwon/espa.hpp @@ -9,6 +9,7 @@ class SkillEspa : public SkillImpl { public: SkillEspa(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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/taekwon/eswhoo.cpp b/src/map/skills/taekwon/eswhoo.cpp index c32eece6a48..08778f4ae89 100644 --- a/src/map/skills/taekwon/eswhoo.cpp +++ b/src/map/skills/taekwon/eswhoo.cpp @@ -13,6 +13,10 @@ SkillEswhoo::SkillEswhoo() : SkillImplRecursiveDamageSplash(SP_SWHOO) { } +void SkillEswhoo::applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) const { + sc_start(src, src, SC_USE_SKILL_SP_SHA, 100, skill_lv, skill_get_time(getSkillId(), skill_lv)); +} + void SkillEswhoo::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const { skillratio += 1000 + 200 * skill_lv; RE_LVL_DMOD(100); diff --git a/src/map/skills/taekwon/eswhoo.hpp b/src/map/skills/taekwon/eswhoo.hpp index 40587f20329..6be12326a99 100644 --- a/src/map/skills/taekwon/eswhoo.hpp +++ b/src/map/skills/taekwon/eswhoo.hpp @@ -9,6 +9,7 @@ class SkillEswhoo : public SkillImplRecursiveDamageSplash { public: SkillEswhoo(); + void applyCounterAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& attack_type) 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 splashSearch(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 flag) const override; int64 splashDamage(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 flag) const override; From b8a07a165e807fe9e250c31696ea586ed776c706 Mon Sep 17 00:00:00 2001 From: idk-whoami <60462533+idk-whoami@users.noreply.github.com> Date: Mon, 9 Mar 2026 21:43:43 +0700 Subject: [PATCH 2/2] Added new middle headgear items (Mermaid Headphones) (#9909) --- db/re/item_db_equip.yml | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/db/re/item_db_equip.yml b/db/re/item_db_equip.yml index b2bbd816af1..6a5aa5bf698 100644 --- a/db/re/item_db_equip.yml +++ b/db/re/item_db_equip.yml @@ -184855,6 +184855,81 @@ Body: Costume_Head_Mid: true ArmorLevel: 1 View: 2817 + - Id: 410587 + AegisName: aegis_410587 + Name: Mermaid Headphones (Global Cooldown) # !todo check english name + Type: Armor + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bDelayrate,-8; + bonus bBaseAtk,20; + bonus bMatk,20; + - Id: 410588 + AegisName: aegis_410588 + Name: Mermaid Headphones (Variable Casting) # !todo check english name + Type: Armor + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bVariableCastrate,-8; + bonus bBaseAtk,20; + bonus bMatk,20; + - Id: 410589 + AegisName: aegis_410589 + Name: Mermaid Headphones (MAXHP) # !todo check english name + Type: Armor + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bMaxHPrate,8; + bonus bBaseAtk,20; + bonus bMatk,20; + - Id: 410590 + AegisName: 26_3_MidHat1_ + Name: Mermaid Headphones (Global Cooldown) # !todo check english name + Type: Armor + Slots: 1 + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bDelayrate,-4; + bonus bBaseAtk,10; + bonus bMatk,10; + - Id: 410591 + AegisName: 26_3_MidHat2_ + Name: Mermaid Headphones (Variable Casting) # !todo check english name + Type: Armor + Slots: 1 + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bVariableCastrate,-4; + bonus bBaseAtk,10; + bonus bMatk,10; + - Id: 410592 + AegisName: 26_3_MidHat3_ + Name: Mermaid Headphones (MAXHP) # !todo check english name + Type: Armor + Slots: 1 + Locations: + Head_Mid: true + ArmorLevel: 1 + View: 1254 + Script: | + bonus bMaxHPrate,4; + bonus bBaseAtk,10; + bonus bMatk,10; - Id: 420000 AegisName: Isabella_Carrot Name: Isabella Carrot