diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index f73b7e12f24..522d3713824 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -4712,9 +4712,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
else
skillratio += 10 * skill_lv; //Outer 5x5 circle takes 100%+10%*level damage [Playtester]
break;
- case HT_POWER:
- skillratio += -50 + 8 * sstatus->str;
- break;
case MA_DOUBLE:
skillratio += 10 * (skill_lv - 1);
break;
@@ -5082,13 +5079,6 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, block_list *src,b
}
break;
#endif
- case HT_PHANTASMIC:
-#ifdef RENEWAL
- skillratio += 400;
-#else
- skillratio += 50;
-#endif
- break;
case MO_BALKYOUNG:
#ifdef RENEWAL
skillratio += 700;
diff --git a/src/map/map-server-generator.vcxproj b/src/map/map-server-generator.vcxproj
index 71bfdebca23..d4abc2a9bc2 100644
--- a/src/map/map-server-generator.vcxproj
+++ b/src/map/map-server-generator.vcxproj
@@ -265,12 +265,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -455,12 +471,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/map/map-server-generator.vcxproj.filters b/src/map/map-server-generator.vcxproj.filters
index af5528e1d9e..3c55ace6d37 100644
--- a/src/map/map-server-generator.vcxproj.filters
+++ b/src/map/map-server-generator.vcxproj.filters
@@ -444,24 +444,72 @@
Header Files\Skills\Acolyte
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Custom
@@ -872,24 +920,72 @@
Source Files\Skills\Acolyte
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Custom
diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj
index 746165e2efe..91ce78ef0c2 100644
--- a/src/map/map-server.vcxproj
+++ b/src/map/map-server.vcxproj
@@ -265,12 +265,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -455,12 +471,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/map/map-server.vcxproj.filters b/src/map/map-server.vcxproj.filters
index af5528e1d9e..3c55ace6d37 100644
--- a/src/map/map-server.vcxproj.filters
+++ b/src/map/map-server.vcxproj.filters
@@ -444,24 +444,72 @@
Header Files\Skills\Acolyte
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Archer
+
+ Header Files\Skills\Archer
+
+
+ Header Files\Skills\Archer
+
Header Files\Skills\Custom
@@ -872,24 +920,72 @@
Source Files\Skills\Acolyte
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Archer
+
+ Source Files\Skills\Archer
+
+
+ Source Files\Skills\Archer
+
Source Files\Skills\Custom
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index 352f00f4c74..c97fbde8291 100755
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -1439,25 +1439,14 @@ int32 skill_additional_effect( block_list* src, block_list *bl, uint16 skill_id,
sc_start(src,bl,SC_STUN,3*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv));
break;
- case HT_FREEZINGTRAP:
case MA_FREEZINGTRAP:
sc_start(src, bl, SC_FREEZE, 100, skill_lv, skill_get_time2(skill_id, skill_lv), sstatus->amotion + 100);
break;
- case HT_FLASHER:
- sc_start(src, bl, SC_BLIND, 100, skill_lv, skill_get_time2(skill_id, skill_lv), 1000);
- break;
-
- case HT_LANDMINE:
case MA_LANDMINE:
sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time2(skill_id, skill_lv), 1000);
break;
- case HT_SHOCKWAVE:
- status_percent_damage(src, bl, 0, -(15*skill_lv+5), false);
- break;
-
- case HT_SANDMAN:
case MA_SANDMAN:
sc_start(src, bl, SC_SLEEP, (10 * skill_lv + 40), skill_lv, skill_get_time2(skill_id, skill_lv), 1000);
break;
@@ -5376,11 +5365,6 @@ int32 skill_castend_damage_id (block_list* src, block_list *bl, uint16 skill_id,
}
break;
- case HT_POWER:
- if( tstatus->race == RC_BRUTE || tstatus->race == RC_PLAYER_DORAM || tstatus->race == RC_INSECT )
- skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- break;
-
case SU_PICKYPECK:
clif_skill_nodamage(src, *bl, skill_id, skill_lv);
[[fallthrough]];
@@ -5400,7 +5384,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 AS_SPLASHER:
- case HT_BLITZBEAT:
case MA_SHOWER:
#ifdef RENEWAL
case SN_SHARPSHOOTING:
@@ -9688,86 +9671,18 @@ int32 skill_castend_nodamage_id (block_list *src, block_list *bl, uint16 skill_i
break;
case MA_REMOVETRAP:
- case HT_REMOVETRAP:
{
skill_unit* su = BL_CAST(BL_SKILL, bl);
std::shared_ptr sg;
std::shared_ptr skill_group;
// Mercenaries can remove any trap
- // Players can only remove their own traps or traps on Vs maps.
- if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && ( skill_group = skill_db.find(sg->skill_id) ) && skill_group->inf2[INF2_ISTRAP] )
+ if( su && (sg = su->group) && ( skill_group = skill_db.find(sg->skill_id) ) && skill_group->inf2[INF2_ISTRAP] )
{
clif_skill_nodamage(src, *bl, skill_id, skill_lv);
- if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
- { // prevent picking up expired traps
- if( battle_config.skill_removetrap_type )
- { // get back all items used to deploy the trap
- for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ )
- {
- if( skill_group->require.itemid[i] > 0 )
- {
- int32 flag2;
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = skill_group->require.itemid[i];
- item_tmp.identify = 1;
- item_tmp.amount = skill_group->require.amount[i];
- if( item_tmp.nameid && (flag2=pc_additem(sd,&item_tmp,item_tmp.amount,LOG_TYPE_OTHER)) ){
- clif_additem(sd,0,0,flag2);
- if (battle_config.skill_drop_items_full)
- map_addflooritem(&item_tmp,item_tmp.amount,sd->m,sd->x,sd->y,0,0,0,4,0);
- }
- }
- }
- }
- else
- { // get back 1 trap
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP;
- item_tmp.identify = 1;
- if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) )
- {
- clif_additem(sd,0,0,flag);
- if (battle_config.skill_drop_items_full)
- map_addflooritem(&item_tmp,1,sd->m,sd->x,sd->y,0,0,0,4,0);
- }
- }
- }
skill_delunit(su);
- }else if(sd)
- clif_skill_fail( *sd, skill_id );
-
- }
- break;
- case HT_SPRINGTRAP:
- clif_skill_nodamage(src,*bl,skill_id,skill_lv);
- {
- skill_unit *su=nullptr;
- if((bl->type==BL_SKILL) && (su=(skill_unit *)bl) && (su->group) ){
- switch(su->group->unit_id){
- case UNT_ANKLESNARE: // ankle snare
- if (su->group->val2 != 0)
- // if it is already trapping something don't spring it,
- // remove trap should be used instead
- break;
- [[fallthrough]];
- case UNT_BLASTMINE:
- case UNT_SKIDTRAP:
- case UNT_LANDMINE:
- case UNT_SHOCKWAVE:
- case UNT_SANDMAN:
- case UNT_FLASHER:
- case UNT_FREEZINGTRAP:
- case UNT_CLAYMORETRAP:
- case UNT_TALKIEBOX:
- su->group->unit_id = UNT_USED_TRAPS;
- clif_changetraplook(bl, UNT_USED_TRAPS);
- su->group->limit=DIFF_TICK(tick+1500,su->group->tick);
- su->limit=DIFF_TICK(tick+1500,su->group->tick);
- }
}
+
}
break;
case BD_ENCORE:
@@ -13546,14 +13461,6 @@ int32 skill_castend_pos2(block_list* src, int32 x, int32 y, uint16 skill_id, uin
switch(skill_id)
{
- case HT_DETECTING:
- i = skill_get_splash(skill_id, skill_lv);
- map_foreachinallarea( status_change_timer_sub,
- src->m, x-i, y-i, x+i,y+i,BL_CHAR,
- src,nullptr,SC_SIGHT,tick);
- skill_reveal_trap_inarea(src, i, x, y);
- break;
-
case SR_RIDEINLIGHTNING:
case NW_BASIC_GRENADE:
i = skill_get_splash(skill_id, skill_lv);
@@ -13590,24 +13497,14 @@ int32 skill_castend_pos2(block_list* src, int32 x, int32 y, uint16 skill_id, uin
case NPC_GROUNDDRIVE:
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
- case HT_SKIDTRAP:
case MA_SKIDTRAP:
- case HT_LANDMINE:
case MA_LANDMINE:
- case HT_ANKLESNARE:
- case HT_SHOCKWAVE:
- case HT_SANDMAN:
case MA_SANDMAN:
- case HT_FLASHER:
- case HT_FREEZINGTRAP:
case MA_FREEZINGTRAP:
- case HT_BLASTMINE:
- case HT_CLAYMORETRAP:
case AS_VENOMDUST:
case AM_DEMONSTRATION:
case PF_FOGWALL:
case PF_SPIDERWEB:
- case HT_TALKIEBOX:
case WE_CALLPARTNER:
case WE_CALLPARENT:
case WE_CALLBABY:
diff --git a/src/map/skills/archer/anklesnare.cpp b/src/map/skills/archer/anklesnare.cpp
new file mode 100644
index 00000000000..7d3e7e352c1
--- /dev/null
+++ b/src/map/skills/archer/anklesnare.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "anklesnare.hpp"
+
+SkillAnkleSnare::SkillAnkleSnare() : SkillImpl(HT_ANKLESNARE) {
+}
+
+void SkillAnkleSnare::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/archer/anklesnare.hpp b/src/map/skills/archer/anklesnare.hpp
new file mode 100644
index 00000000000..9cddf5513c4
--- /dev/null
+++ b/src/map/skills/archer/anklesnare.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 SkillAnkleSnare : public SkillImpl {
+public:
+ SkillAnkleSnare();
+
+ 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/archer/beaststrafing.cpp b/src/map/skills/archer/beaststrafing.cpp
new file mode 100644
index 00000000000..d248cbfe0de
--- /dev/null
+++ b/src/map/skills/archer/beaststrafing.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "beaststrafing.hpp"
+
+#include "map/status.hpp"
+
+SkillBeastStrafing::SkillBeastStrafing() : SkillImpl(HT_POWER) {
+}
+
+void SkillBeastStrafing::castendDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ status_data* tstatus = status_get_status_data(*target);
+
+ if( tstatus->race == RC_BRUTE || tstatus->race == RC_PLAYER_DORAM || tstatus->race == RC_INSECT )
+ skill_attack(BF_WEAPON,src,src,target,getSkillId(),skill_lv,tick,flag);
+}
+
+void SkillBeastStrafing::calculateSkillRatio(const Damage* wd, const block_list* src, const block_list* target, uint16 skill_lv, int32& base_skillratio, int32 mflag) const {
+ const status_data* sstatus = status_get_status_data(*src);
+
+ base_skillratio += -50 + 8 * sstatus->str;
+}
diff --git a/src/map/skills/archer/beaststrafing.hpp b/src/map/skills/archer/beaststrafing.hpp
new file mode 100644
index 00000000000..da69be5ee53
--- /dev/null
+++ b/src/map/skills/archer/beaststrafing.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 SkillBeastStrafing : public SkillImpl {
+public:
+ SkillBeastStrafing();
+
+ void castendDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) 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/archer/blastmine.cpp b/src/map/skills/archer/blastmine.cpp
new file mode 100644
index 00000000000..ae53ae0fe16
--- /dev/null
+++ b/src/map/skills/archer/blastmine.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "blastmine.hpp"
+
+SkillBlastMine::SkillBlastMine() : SkillImpl(HT_BLASTMINE) {
+}
+
+void SkillBlastMine::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/archer/blastmine.hpp b/src/map/skills/archer/blastmine.hpp
new file mode 100644
index 00000000000..705bee0f8bd
--- /dev/null
+++ b/src/map/skills/archer/blastmine.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 SkillBlastMine : public SkillImpl {
+public:
+ SkillBlastMine();
+
+ 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/archer/blitzbeat.cpp b/src/map/skills/archer/blitzbeat.cpp
new file mode 100644
index 00000000000..672ee9f2b06
--- /dev/null
+++ b/src/map/skills/archer/blitzbeat.cpp
@@ -0,0 +1,7 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "blitzbeat.hpp"
+
+SkillBlitzBeat::SkillBlitzBeat() : SkillImplRecursiveDamageSplash(HT_BLITZBEAT) {
+}
diff --git a/src/map/skills/archer/blitzbeat.hpp b/src/map/skills/archer/blitzbeat.hpp
new file mode 100644
index 00000000000..0795232697f
--- /dev/null
+++ b/src/map/skills/archer/blitzbeat.hpp
@@ -0,0 +1,11 @@
+// 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 SkillBlitzBeat : public SkillImplRecursiveDamageSplash {
+public:
+ SkillBlitzBeat();
+};
diff --git a/src/map/skills/archer/claymoretrap.cpp b/src/map/skills/archer/claymoretrap.cpp
new file mode 100644
index 00000000000..7d8014445b1
--- /dev/null
+++ b/src/map/skills/archer/claymoretrap.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "claymoretrap.hpp"
+
+SkillClaymoreTrap::SkillClaymoreTrap() : SkillImpl(HT_CLAYMORETRAP) {
+}
+
+void SkillClaymoreTrap::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/archer/claymoretrap.hpp b/src/map/skills/archer/claymoretrap.hpp
new file mode 100644
index 00000000000..2b3ef24eb47
--- /dev/null
+++ b/src/map/skills/archer/claymoretrap.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 SkillClaymoreTrap : public SkillImpl {
+public:
+ SkillClaymoreTrap();
+
+ 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/archer/detect.cpp b/src/map/skills/archer/detect.cpp
new file mode 100644
index 00000000000..8524622718c
--- /dev/null
+++ b/src/map/skills/archer/detect.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "detect.hpp"
+
+#include "map/status.hpp"
+
+SkillDetect::SkillDetect() : SkillImpl(HT_DETECTING) {
+}
+
+void SkillDetect::castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const {
+ int32 i = skill_get_splash(getSkillId(), skill_lv);
+ map_foreachinallarea( status_change_timer_sub,
+ src->m, x-i, y-i, x+i,y+i,BL_CHAR,
+ src,nullptr,SC_SIGHT,tick);
+ skill_reveal_trap_inarea(src, i, x, y);
+}
diff --git a/src/map/skills/archer/detect.hpp b/src/map/skills/archer/detect.hpp
new file mode 100644
index 00000000000..f1b4c638936
--- /dev/null
+++ b/src/map/skills/archer/detect.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 SkillDetect : public SkillImpl {
+public:
+ SkillDetect();
+
+ 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/archer/flasher.cpp b/src/map/skills/archer/flasher.cpp
new file mode 100644
index 00000000000..0996222e388
--- /dev/null
+++ b/src/map/skills/archer/flasher.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "flasher.hpp"
+
+#include "map/status.hpp"
+
+SkillFlasher::SkillFlasher() : SkillImpl(HT_FLASHER) {
+}
+
+void SkillFlasher::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
+
+void SkillFlasher::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_BLIND, 100, skill_lv, skill_get_time2(getSkillId(), skill_lv), 1000);
+}
diff --git a/src/map/skills/archer/flasher.hpp b/src/map/skills/archer/flasher.hpp
new file mode 100644
index 00000000000..b267f0d12d7
--- /dev/null
+++ b/src/map/skills/archer/flasher.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 SkillFlasher : public SkillImpl {
+public:
+ SkillFlasher();
+
+ 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/archer/freezingtrap.cpp b/src/map/skills/archer/freezingtrap.cpp
new file mode 100644
index 00000000000..8481ade87ee
--- /dev/null
+++ b/src/map/skills/archer/freezingtrap.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "freezingtrap.hpp"
+
+#include "map/status.hpp"
+
+SkillFreezingTrap::SkillFreezingTrap() : SkillImpl(HT_FREEZINGTRAP) {
+}
+
+void SkillFreezingTrap::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
+
+void SkillFreezingTrap::applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ status_data* sstatus = status_get_status_data(*src);
+
+ sc_start(src, target, SC_FREEZE, 100, skill_lv, skill_get_time2(getSkillId(), skill_lv), sstatus->amotion + 100);
+}
diff --git a/src/map/skills/archer/freezingtrap.hpp b/src/map/skills/archer/freezingtrap.hpp
new file mode 100644
index 00000000000..01b7a19d6af
--- /dev/null
+++ b/src/map/skills/archer/freezingtrap.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 SkillFreezingTrap : public SkillImpl {
+public:
+ SkillFreezingTrap();
+
+ 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/archer/landmine.cpp b/src/map/skills/archer/landmine.cpp
new file mode 100644
index 00000000000..ab091964a43
--- /dev/null
+++ b/src/map/skills/archer/landmine.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "landmine.hpp"
+
+#include "map/status.hpp"
+
+SkillLandMine::SkillLandMine() : SkillImpl(HT_LANDMINE) {
+}
+
+void SkillLandMine::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
+
+void SkillLandMine::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_STUN, 10, skill_lv, skill_get_time2(getSkillId(), skill_lv), 1000);
+}
diff --git a/src/map/skills/archer/landmine.hpp b/src/map/skills/archer/landmine.hpp
new file mode 100644
index 00000000000..268569bf9d7
--- /dev/null
+++ b/src/map/skills/archer/landmine.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 SkillLandMine : public SkillImpl {
+public:
+ SkillLandMine();
+
+ 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/archer/phantasmicarrow.cpp b/src/map/skills/archer/phantasmicarrow.cpp
new file mode 100644
index 00000000000..f909dbfdd49
--- /dev/null
+++ b/src/map/skills/archer/phantasmicarrow.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "phantasmicarrow.hpp"
+
+#include
+
+SkillPhantasmicArrow::SkillPhantasmicArrow() : WeaponSkillImpl(HT_PHANTASMIC) {
+}
+
+void SkillPhantasmicArrow::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;
+#else
+ base_skillratio += 50;
+#endif
+}
diff --git a/src/map/skills/archer/phantasmicarrow.hpp b/src/map/skills/archer/phantasmicarrow.hpp
new file mode 100644
index 00000000000..9a7bbe61b06
--- /dev/null
+++ b/src/map/skills/archer/phantasmicarrow.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 "../weapon_skill_impl.hpp"
+
+class SkillPhantasmicArrow : public WeaponSkillImpl {
+public:
+ SkillPhantasmicArrow();
+
+ 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/archer/removetrap.cpp b/src/map/skills/archer/removetrap.cpp
new file mode 100644
index 00000000000..663ea2986b2
--- /dev/null
+++ b/src/map/skills/archer/removetrap.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "removetrap.hpp"
+
+#include "map/clif.hpp"
+#include "map/log.hpp"
+#include "map/pc.hpp"
+
+SkillRemoveTrap::SkillRemoveTrap() : SkillImpl(HT_REMOVETRAP) {
+}
+
+void SkillRemoveTrap::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);
+
+ if( sd == nullptr ){
+ return;
+ }
+
+ skill_unit* su = BL_CAST(BL_SKILL, target);
+ std::shared_ptr sg;
+ std::shared_ptr skill_group;
+
+ // Players can only remove their own traps or traps on Vs maps.
+ if( su && (sg = su->group) && (sg->src_id == src->id || map_flag_vs(target->m)) && ( skill_group = skill_db.find(sg->skill_id) ) && skill_group->inf2[INF2_ISTRAP] )
+ {
+ clif_skill_nodamage(src, *target, getSkillId(), skill_lv);
+ if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
+ { // prevent picking up expired traps
+ if( battle_config.skill_removetrap_type )
+ { // get back all items used to deploy the trap
+ for( int32 i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ )
+ {
+ if( skill_group->require.itemid[i] > 0 )
+ {
+ int32 flag2;
+ struct item item_tmp;
+ memset(&item_tmp,0,sizeof(item_tmp));
+ item_tmp.nameid = skill_group->require.itemid[i];
+ item_tmp.identify = 1;
+ item_tmp.amount = skill_group->require.amount[i];
+ if( item_tmp.nameid && (flag2=pc_additem(sd,&item_tmp,item_tmp.amount,LOG_TYPE_OTHER)) ){
+ clif_additem(sd,0,0,flag2);
+ if (battle_config.skill_drop_items_full)
+ map_addflooritem(&item_tmp,item_tmp.amount,sd->m,sd->x,sd->y,0,0,0,4,0);
+ }
+ }
+ }
+ }
+ else
+ { // get back 1 trap
+ struct item item_tmp;
+ memset(&item_tmp,0,sizeof(item_tmp));
+ item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP;
+ item_tmp.identify = 1;
+ if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) )
+ {
+ clif_additem(sd,0,0,flag);
+ if (battle_config.skill_drop_items_full)
+ map_addflooritem(&item_tmp,1,sd->m,sd->x,sd->y,0,0,0,4,0);
+ }
+ }
+ }
+ skill_delunit(su);
+ }else
+ clif_skill_fail( *sd, getSkillId() );
+}
diff --git a/src/map/skills/archer/removetrap.hpp b/src/map/skills/archer/removetrap.hpp
new file mode 100644
index 00000000000..dca030bf392
--- /dev/null
+++ b/src/map/skills/archer/removetrap.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 SkillRemoveTrap : public SkillImpl {
+public:
+ SkillRemoveTrap();
+
+ void castendNoDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/archer/sandman.cpp b/src/map/skills/archer/sandman.cpp
new file mode 100644
index 00000000000..73ffffebd74
--- /dev/null
+++ b/src/map/skills/archer/sandman.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "sandman.hpp"
+
+#include "map/status.hpp"
+
+SkillSandman::SkillSandman() : SkillImpl(HT_SANDMAN) {
+}
+
+void SkillSandman::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
+
+void SkillSandman::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_SLEEP, (10 * skill_lv + 40), skill_lv, skill_get_time2(getSkillId(), skill_lv), 1000);
+}
diff --git a/src/map/skills/archer/sandman.hpp b/src/map/skills/archer/sandman.hpp
new file mode 100644
index 00000000000..fd7bf70d442
--- /dev/null
+++ b/src/map/skills/archer/sandman.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 SkillSandman : public SkillImpl {
+public:
+ SkillSandman();
+
+ 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/archer/shockwavetrap.cpp b/src/map/skills/archer/shockwavetrap.cpp
new file mode 100644
index 00000000000..a553b43b373
--- /dev/null
+++ b/src/map/skills/archer/shockwavetrap.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "shockwavetrap.hpp"
+
+#include "map/status.hpp"
+
+SkillShockwaveTrap::SkillShockwaveTrap() : SkillImpl(HT_SHOCKWAVE) {
+}
+
+void SkillShockwaveTrap::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
+
+void SkillShockwaveTrap::applyAdditionalEffects(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32 attack_type, enum damage_lv dmg_lv) const {
+ status_percent_damage(src, target, 0, -(15*skill_lv+5), false);
+}
diff --git a/src/map/skills/archer/shockwavetrap.hpp b/src/map/skills/archer/shockwavetrap.hpp
new file mode 100644
index 00000000000..727677b5b95
--- /dev/null
+++ b/src/map/skills/archer/shockwavetrap.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 SkillShockwaveTrap : public SkillImpl {
+public:
+ SkillShockwaveTrap();
+
+ 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/archer/skidtrap.cpp b/src/map/skills/archer/skidtrap.cpp
new file mode 100644
index 00000000000..9cbca9b71e9
--- /dev/null
+++ b/src/map/skills/archer/skidtrap.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "skidtrap.hpp"
+
+SkillSkidTrap::SkillSkidTrap() : SkillImpl(HT_SKIDTRAP) {
+}
+
+void SkillSkidTrap::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/archer/skidtrap.hpp b/src/map/skills/archer/skidtrap.hpp
new file mode 100644
index 00000000000..e3cb1b7ea5f
--- /dev/null
+++ b/src/map/skills/archer/skidtrap.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 SkillSkidTrap : public SkillImpl {
+public:
+ SkillSkidTrap();
+
+ 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/archer/skill_factory_archer.cpp b/src/map/skills/archer/skill_factory_archer.cpp
index 1605a8e7ba3..5c11dbc5aaa 100644
--- a/src/map/skills/archer/skill_factory_archer.cpp
+++ b/src/map/skills/archer/skill_factory_archer.cpp
@@ -6,11 +6,27 @@
#include "../status_skill_impl.hpp"
#include "../weapon_skill_impl.hpp"
+#include "anklesnare.hpp"
#include "arrowshower.hpp"
+#include "beaststrafing.hpp"
+#include "blastmine.hpp"
+#include "blitzbeat.hpp"
#include "chargearrow.hpp"
+#include "claymoretrap.hpp"
#include "concentration.hpp"
+#include "detect.hpp"
#include "doublestrafe.hpp"
+#include "flasher.hpp"
+#include "freezingtrap.hpp"
+#include "landmine.hpp"
#include "makingarrow.hpp"
+#include "phantasmicarrow.hpp"
+#include "removetrap.hpp"
+#include "sandman.hpp"
+#include "shockwavetrap.hpp"
+#include "skidtrap.hpp"
+#include "springtrap.hpp"
+#include "talkiebox.hpp"
std::unique_ptr SkillFactoryArcher::create(const e_skill skill_id) const {
switch( skill_id ){
@@ -32,8 +48,38 @@ std::unique_ptr SkillFactoryArcher::create(const e_skill skill_
return std::make_unique(skill_id);
case DC_THROWARROW:
return std::make_unique(skill_id);
+ case HT_ANKLESNARE:
+ return std::make_unique();
+ case HT_BLASTMINE:
+ return std::make_unique();
+ case HT_BLITZBEAT:
+ return std::make_unique();
+ case HT_CLAYMORETRAP:
+ return std::make_unique();
+ case HT_DETECTING:
+ return std::make_unique();
+ case HT_FLASHER:
+ return std::make_unique();
+ case HT_FREEZINGTRAP:
+ return std::make_unique();
+ case HT_LANDMINE:
+ return std::make_unique();
case HT_PHANTASMIC:
- return std::make_unique(skill_id);
+ return std::make_unique();
+ case HT_POWER:
+ return std::make_unique();
+ case HT_REMOVETRAP:
+ return std::make_unique();
+ case HT_SANDMAN:
+ return std::make_unique();
+ case HT_SHOCKWAVE:
+ return std::make_unique();
+ case HT_SKIDTRAP:
+ return std::make_unique();
+ case HT_SPRINGTRAP:
+ return std::make_unique();
+ case HT_TALKIEBOX:
+ return std::make_unique();
case RA_AIMEDBOLT:
return std::make_unique(skill_id);
case RA_UNLIMIT:
diff --git a/src/map/skills/archer/springtrap.cpp b/src/map/skills/archer/springtrap.cpp
new file mode 100644
index 00000000000..f67c4d16156
--- /dev/null
+++ b/src/map/skills/archer/springtrap.cpp
@@ -0,0 +1,38 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "springtrap.hpp"
+
+#include "map/clif.hpp"
+
+SkillSpringTrap::SkillSpringTrap() : SkillImpl(HT_SPRINGTRAP) {
+}
+
+void SkillSpringTrap::castendNoDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const {
+ clif_skill_nodamage(src,*target,getSkillId(),skill_lv);
+
+ skill_unit *su=nullptr;
+ if((target->type==BL_SKILL) && (su=(skill_unit *)target) && (su->group) ){
+ switch(su->group->unit_id){
+ case UNT_ANKLESNARE: // ankle snare
+ if (su->group->val2 != 0)
+ // if it is already trapping something don't spring it,
+ // remove trap should be used instead
+ break;
+ [[fallthrough]];
+ case UNT_BLASTMINE:
+ case UNT_SKIDTRAP:
+ case UNT_LANDMINE:
+ case UNT_SHOCKWAVE:
+ case UNT_SANDMAN:
+ case UNT_FLASHER:
+ case UNT_FREEZINGTRAP:
+ case UNT_CLAYMORETRAP:
+ case UNT_TALKIEBOX:
+ su->group->unit_id = UNT_USED_TRAPS;
+ clif_changetraplook(target, UNT_USED_TRAPS);
+ su->group->limit=DIFF_TICK(tick+1500,su->group->tick);
+ su->limit=DIFF_TICK(tick+1500,su->group->tick);
+ }
+ }
+}
diff --git a/src/map/skills/archer/springtrap.hpp b/src/map/skills/archer/springtrap.hpp
new file mode 100644
index 00000000000..c6f01d3758a
--- /dev/null
+++ b/src/map/skills/archer/springtrap.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 SkillSpringTrap : public SkillImpl {
+public:
+ SkillSpringTrap();
+
+ void castendNoDamageId(block_list* src, block_list* target, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};
diff --git a/src/map/skills/archer/talkiebox.cpp b/src/map/skills/archer/talkiebox.cpp
new file mode 100644
index 00000000000..aaa21df9fe6
--- /dev/null
+++ b/src/map/skills/archer/talkiebox.cpp
@@ -0,0 +1,14 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "talkiebox.hpp"
+
+SkillTalkieBox::SkillTalkieBox() : SkillImpl(HT_TALKIEBOX) {
+}
+
+void SkillTalkieBox::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;
+
+ skill_unitsetting(src,getSkillId(),skill_lv,x,y,0);
+}
diff --git a/src/map/skills/archer/talkiebox.hpp b/src/map/skills/archer/talkiebox.hpp
new file mode 100644
index 00000000000..239c7a91c3a
--- /dev/null
+++ b/src/map/skills/archer/talkiebox.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 SkillTalkieBox : public SkillImpl {
+public:
+ SkillTalkieBox();
+
+ void castendPos2(block_list* src, int32 x, int32 y, uint16 skill_lv, t_tick tick, int32& flag) const override;
+};