diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index b170a4d0be4..d707198bbc3 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -8234,14 +8234,6 @@ struct Damage battle_calc_magic_attack(block_list *src,block_list *target,uint16
if (sd && ad.div_ > 0)
ad.div_ *= -1; //For players, damage is divided by number of hits
break;
- case HW_NAPALMVULCAN:
-#ifdef RENEWAL
- skillratio += -100 + 70 * skill_lv;
- RE_LVL_DMOD(100);
-#else
- skillratio += 25;
-#endif
- break;
case NJ_KOUENKA:
skillratio -= 10;
if(sd && sd->spiritcharm_type == CHARM_TYPE_FIRE && sd->spiritcharm > 0)
diff --git a/src/map/map-server-generator.vcxproj b/src/map/map-server-generator.vcxproj
index b4ab32b4e65..98691c10e13 100644
--- a/src/map/map-server-generator.vcxproj
+++ b/src/map/map-server-generator.vcxproj
@@ -316,6 +316,8 @@
+
+
@@ -323,6 +325,7 @@
+
@@ -592,6 +595,8 @@
+
+
@@ -599,6 +604,7 @@
+
diff --git a/src/map/map-server-generator.vcxproj.filters b/src/map/map-server-generator.vcxproj.filters
index 03057cec984..c02c0791e28 100644
--- a/src/map/map-server-generator.vcxproj.filters
+++ b/src/map/map-server-generator.vcxproj.filters
@@ -597,6 +597,12 @@
Header Files\Skills\Mage
+
+ Header Files\Skills\Mage
+
+
+ Header Files\Skills\Mage
+
Header Files\Skills\Mage
@@ -618,6 +624,9 @@
Header Files\Skills\Mage
+
+ Header Files\Skills\Mage
+
Header Files\Skills\Mage
@@ -1283,6 +1292,12 @@
Source Files\Skills\Mage
+
+ Source Files\Skills\Mage
+
+
+ Source Files\Skills\Mage
+
Source Files\Skills\Mage
@@ -1304,6 +1319,9 @@
Source Files\Skills\Mage
+
+ Source Files\Skills\Mage
+
Source Files\Skills\Mage
diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj
index 2d8f208d414..cf56751fbbb 100644
--- a/src/map/map-server.vcxproj
+++ b/src/map/map-server.vcxproj
@@ -316,6 +316,8 @@
+
+
@@ -323,6 +325,7 @@
+
@@ -592,6 +595,8 @@
+
+
@@ -599,6 +604,7 @@
+
diff --git a/src/map/map-server.vcxproj.filters b/src/map/map-server.vcxproj.filters
index 03057cec984..c02c0791e28 100644
--- a/src/map/map-server.vcxproj.filters
+++ b/src/map/map-server.vcxproj.filters
@@ -597,6 +597,12 @@
Header Files\Skills\Mage
+
+ Header Files\Skills\Mage
+
+
+ Header Files\Skills\Mage
+
Header Files\Skills\Mage
@@ -618,6 +624,9 @@
Header Files\Skills\Mage
+
+ Header Files\Skills\Mage
+
Header Files\Skills\Mage
@@ -1283,6 +1292,12 @@
Source Files\Skills\Mage
+
+ Source Files\Skills\Mage
+
+
+ Source Files\Skills\Mage
+
Source Files\Skills\Mage
@@ -1304,6 +1319,9 @@
Source Files\Skills\Mage
+
+ Source Files\Skills\Mage
+
Source Files\Skills\Mage
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index e858b090124..6293103a553 100755
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -1448,9 +1448,7 @@ int32 skill_additional_effect( block_list* src, block_list *bl, uint16 skill_id,
#ifndef RENEWAL
case PA_PRESSURE:
status_percent_damage(src, bl, 0, 15+5*skill_lv, false);
- [[fallthrough]];
- case HW_GRAVITATION:
- //Pressure and Gravitation can trigger physical autospells
+ //Pressure can trigger physical autospells
attack_type |= BF_NORMAL;
attack_type |= BF_WEAPON;
break;
@@ -1583,7 +1581,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 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));
break;
@@ -5286,7 +5283,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:
- case HW_NAPALMVULCAN:
case NJ_HUUMA:
case NPC_PULSESTRIKE:
case NPC_PULSESTRIKE2:
@@ -13044,9 +13040,6 @@ int32 skill_castend_pos2(block_list* src, int32 x, int32 y, uint16 skill_id, uin
case NJ_HYOUSYOURAKU:
case NJ_RAIGEKISAI:
case NJ_KAMAITACHI:
-#ifdef RENEWAL
- case HW_GRAVITATION:
-#endif
case NPC_EVILLAND:
case NPC_VENOMFOG:
case NPC_COMET:
@@ -13305,26 +13298,6 @@ int32 skill_castend_pos2(block_list* src, int32 x, int32 y, uint16 skill_id, uin
}
break;
- case HW_GANBANTEIN:
- if (rnd()%100 < 80) {
- int32 dummy = 1;
- clif_skill_poseffect( *src, skill_id, skill_lv, x, y, tick );
- i = skill_get_splash(skill_id, skill_lv);
- map_foreachinallarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src);
- } else {
- if (sd) clif_skill_fail( *sd, skill_id );
- return 1;
- }
- break;
-
-#ifndef RENEWAL
- case HW_GRAVITATION:
- if ((sg = skill_unitsetting(src,skill_id,skill_lv,x,y,0)))
- sc_start4(src,src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill_get_time(skill_id,skill_lv));
- flag|=1;
- break;
-#endif
-
// Plant Cultivation [Celest]
case CR_CULTIVATION:
if (sd) {
diff --git a/src/map/skills/mage/ganbantein.cpp b/src/map/skills/mage/ganbantein.cpp
new file mode 100644
index 00000000000..9c457375454
--- /dev/null
+++ b/src/map/skills/mage/ganbantein.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "ganbantein.hpp"
+
+#include "map/clif.hpp"
+#include "map/pc.hpp"
+
+SkillGanbantein::SkillGanbantein() : SkillImpl(HW_GANBANTEIN) {
+}
+
+void SkillGanbantein::castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const {
+ map_session_data* sd = BL_CAST( BL_PC, src );
+
+ if (rnd()%100 < 80) {
+ int32 dummy = 1;
+ clif_skill_poseffect( *src, getSkillId(), skill_lv, x, y, tick );
+ bool i = skill_get_splash(getSkillId(), skill_lv);
+ map_foreachinallarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, getSkillId(), &dummy, src);
+ } else {
+ if (sd) clif_skill_fail( *sd, getSkillId() );
+
+ flag |= SKILL_NOCONSUME_REQ;
+ return;
+ }
+}
diff --git a/src/map/skills/mage/ganbantein.hpp b/src/map/skills/mage/ganbantein.hpp
new file mode 100644
index 00000000000..b91fc80d7a4
--- /dev/null
+++ b/src/map/skills/mage/ganbantein.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 SkillGanbantein : public SkillImpl {
+public:
+ SkillGanbantein();
+
+ 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/mage/gravitationfield.cpp b/src/map/skills/mage/gravitationfield.cpp
new file mode 100644
index 00000000000..ca3d6ab4f08
--- /dev/null
+++ b/src/map/skills/mage/gravitationfield.cpp
@@ -0,0 +1,41 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "gravitationfield.hpp"
+
+#include
+#include
+
+#include "map/status.hpp"
+
+SkillGravitationField::SkillGravitationField() : SkillImpl(HW_GRAVITATION) {
+}
+
+void SkillGravitationField::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const {
+#ifdef RENEWAL
+ skillratio += -100 + 100 * skill_lv;
+ RE_LVL_DMOD(100);
+#endif
+}
+
+void SkillGravitationField::castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const {
+#ifdef RENEWAL
+ 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);
+#else
+ std::shared_ptr sg;
+ sc_type type = skill_get_sc(getSkillId());
+
+ if ((sg = skill_unitsetting(src,getSkillId(),skill_lv,x,y,0)))
+ sc_start4(src,src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill_get_time(getSkillId(),skill_lv));
+ flag|=1;
+#endif
+}
+
+void SkillGravitationField::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+#ifndef RENEWAL
+ // Gravitation can trigger physical autospells
+ attack_type |= BF_NORMAL;
+ attack_type |= BF_WEAPON;
+#endif
+}
diff --git a/src/map/skills/mage/gravitationfield.hpp b/src/map/skills/mage/gravitationfield.hpp
new file mode 100644
index 00000000000..a6d282d6267
--- /dev/null
+++ b/src/map/skills/mage/gravitationfield.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 SkillGravitationField : public SkillImpl {
+public:
+ SkillGravitationField();
+
+ 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 castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/mage/napalmvulcan.cpp b/src/map/skills/mage/napalmvulcan.cpp
new file mode 100644
index 00000000000..6acf275b8a2
--- /dev/null
+++ b/src/map/skills/mage/napalmvulcan.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "napalmvulcan.hpp"
+
+#include
+#include
+
+#include "map/status.hpp"
+
+SkillNapalmVulcan::SkillNapalmVulcan() : SkillImplRecursiveDamageSplash(HW_NAPALMVULCAN) {
+}
+
+void SkillNapalmVulcan::calculateSkillRatio(const Damage *wd, const block_list *src, const block_list *target, uint16 skill_lv, int32 &skillratio, int32 mflag) const {
+#ifdef RENEWAL
+ skillratio += -100 + 70 * skill_lv;
+ RE_LVL_DMOD(100);
+#else
+ skillratio += 25;
+#endif
+}
+
+void SkillNapalmVulcan::applyAdditionalEffects(block_list *src, block_list *target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ sc_start(src,target,SC_CURSE,5*skill_lv,skill_lv,skill_get_time2(getSkillId(),skill_lv));
+}
diff --git a/src/map/skills/mage/napalmvulcan.hpp b/src/map/skills/mage/napalmvulcan.hpp
new file mode 100644
index 00000000000..474fa0d2568
--- /dev/null
+++ b/src/map/skills/mage/napalmvulcan.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 SkillNapalmVulcan : public SkillImplRecursiveDamageSplash {
+public:
+ SkillNapalmVulcan();
+
+ 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/mage/skill_factory_mage.cpp b/src/map/skills/mage/skill_factory_mage.cpp
index 7c0be1ac923..f9420380442 100644
--- a/src/map/skills/mage/skill_factory_mage.cpp
+++ b/src/map/skills/mage/skill_factory_mage.cpp
@@ -15,13 +15,16 @@
#include "firewall.hpp"
#include "frostdiver.hpp"
#include "frostnova.hpp"
+#include "ganbantein.hpp"
+#include "gravitationfield.hpp"
#include "heavensdrive.hpp"
#include "icewall.hpp"
#include "jupitelthunder.hpp"
+#include "lightningbolt.hpp"
#include "lordofvermilion.hpp"
#include "meteorstorm.hpp"
#include "napalmbeat.hpp"
-#include "lightningbolt.hpp"
+#include "napalmvulcan.hpp"
#include "quagmire.hpp"
#include "safetywall.hpp"
#include "sense.hpp"
@@ -40,10 +43,16 @@ std::unique_ptr SkillFactoryMage::create(const e_skill skill_id
return std::make_unique(skill_id);
case EM_SPELL_ENCHANTING:
return std::make_unique(skill_id);
+ case HW_GANBANTEIN:
+ return std::make_unique();
+ case HW_GRAVITATION:
+ return std::make_unique();
case HW_MAGICCRASHER:
return std::make_unique(skill_id);
case HW_MAGICPOWER:
return std::make_unique(skill_id);
+ case HW_NAPALMVULCAN:
+ return std::make_unique();
case MG_SAFETYWALL:
return std::make_unique();
case MG_SIGHT: