summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/clif.c6
-rw-r--r--src/map/skill.c168
-rw-r--r--src/map/skill.h10
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc12
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc36
6 files changed, 142 insertions, 92 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 796e0de68..236ed70b7 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6340,7 +6340,7 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_
skill_id = AB_DUPLELIGHT_MELEE;
else
skill_id = AB_DUPLELIGHT_MAGIC;
- skill->attack(skill->get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL);
+ skill->attack(skill->get_type(skill_id, sc->data[SC_DUPLELIGHT]->val1), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL);
}
}
diff --git a/src/map/clif.c b/src/map/clif.c
index 477894805..5b0122401 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -19927,9 +19927,9 @@ static int clif_autoshadowspell_list(struct map_session_data *sd)
WFIFOHEAD(fd, 2 * 6 + 4);
WFIFOW(fd,0) = 0x442;
for (i = 0, c = 0; i < MAX_SKILL_DB; i++)
- if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 &&
- sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id) == BF_MAGIC )
- { // Can't auto cast both Extended class and 3rd class skills.
+ if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && sd->status.skill[i].id < GS_GLITTERING
+ && skill->get_type(sd->status.skill[i].id, sd->status.skill[i].lv) == BF_MAGIC) {
+ // Can't auto cast both Extended class and 3rd class skills.
WFIFOW(fd,8+c*2) = sd->status.skill[i].id;
c++;
}
diff --git a/src/map/skill.c b/src/map/skill.c
index d24d7ea89..8be97842e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -624,14 +624,26 @@ static int skill_get_delaynodex(int skill_id, int skill_lv)
return skill->dbs->db[idx].delaynodex[skill_get_lvl_idx(skill_lv)];
}
-static int skill_get_type(int skill_id)
+/**
+ * Gets a skill's attack type by its ID and level.
+ *
+ * @param skill_id The skill's ID.
+ * @param skill_lv The skill's level.
+ * @return The skill's attack type corresponding to the passed level. Defaults to BF_NONE (0) in case of error.
+ *
+ **/
+static int skill_get_type(int skill_id, int skill_lv)
{
- int idx;
if (skill_id == 0)
return BF_NONE;
- idx = skill->get_index(skill_id);
+
+ Assert_retr(BF_NONE, skill_lv > 0);
+
+ int idx = skill->get_index(skill_id);
+
Assert_retr(BF_NONE, idx != 0);
- return skill->dbs->db[idx].skill_type;
+
+ return skill->dbs->db[idx].skill_type[skill_get_lvl_idx(skill_lv)];
}
static int skill_get_unit_id(int skill_id, int flag)
@@ -2178,7 +2190,7 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
sd->auto_cast_current.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,auto_skill_lv,1);
- skill->toggle_magicpower(src, temp);
+ skill->toggle_magicpower(src, temp, auto_skill_lv);
skill->castend_type(type, src, tbl, temp, auto_skill_lv, tick, 0);
sd->auto_cast_current.type = AUTOCAST_NONE;
@@ -3964,7 +3976,7 @@ static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
clif->skill_nodamage(src,target,skl->skill_id,skl->skill_lv,1);
break;
case WZ_WATERBALL:
- skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify
+ skill->toggle_magicpower(src, skl->skill_id, skl->skill_lv); // only the first hit will be amplify
if (!status->isdead(target))
skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
if (skl->type>1 && !status->isdead(target) && !status->isdead(src)) {
@@ -3984,7 +3996,7 @@ static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
**/
case WL_CHAINLIGHTNING_ATK:
skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, (9-skl->type)); // Hit a Lightning on the current Target
- skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify
+ skill->toggle_magicpower(src, skl->skill_id, skl->skill_lv); // only the first hit will be amplify
if (skl->type < (4 + skl->skill_lv - 1) && skl->x < 3) {
// Remaining Chains Hit
@@ -4004,7 +4016,7 @@ static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
case WL_TETRAVORTEX_GROUND:
clif->skill_nodamage(src, target, skl->skill_id, skl->skill_lv, 1);
skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
- skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify
+ skill->toggle_magicpower(src, skl->skill_id, skl->skill_lv); // only the first hit will be amplify
if( skl->type == 4 ){
const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used.
int rate = skl->y, index = skl->x-1;
@@ -4013,7 +4025,7 @@ static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
break;
case WM_REVERBERATION_MELEE:
case WM_REVERBERATION_MAGIC:
- skill->attack(skill->get_type(skl->skill_id),src, src, target, skl->skill_id, skl->skill_lv, 0, SD_LEVEL);
+ skill->attack(skill->get_type(skl->skill_id, skl->skill_lv), src, src, target, skl->skill_id, skl->skill_lv, 0, SD_LEVEL);
break;
case SC_FATALMENACE:
if( src == target ) // Casters Part
@@ -4118,7 +4130,7 @@ static int skill_timerskill(int tid, int64 tick, int id, intptr_t data)
case LG_OVERBRAND_BRANDISH:
skill->area_temp[1] = 0;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,skl->x,skl->y,4,2,BL_CHAR,
- skill->get_type(skl->skill_id),src,src,skl->skill_id,skl->skill_lv,tick,skl->flag,BCT_ENEMY);
+ skill->get_type(skl->skill_id, skl->skill_lv), src, src, skl->skill_id, skl->skill_lv, tick, skl->flag, BCT_ENEMY);
break;
default:
skill->timerskill_notarget_unknown(tid, tick, src, ud, skl);
@@ -4295,7 +4307,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if (status->isdead(bl))
return 1;
- if (skill_id && skill->get_type(skill_id) == BF_MAGIC && status->isimmune(bl) == 100) {
+ if (skill_id != 0 && skill->get_type(skill_id, skill_lv) == BF_MAGIC && status->isimmune(bl) == 100) {
//GTB makes all targeted magic display miss with a single bolt.
sc_type sct = status->skill2sc(skill_id);
if(sct != SC_NONE)
@@ -4508,7 +4520,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
- skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->get_type(skill_id, skill_lv), src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
case NPC_ACIDBREATH:
@@ -4519,7 +4531,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
- skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->get_type(skill_id, skill_lv), src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
case MO_INVESTIGATE:
@@ -4691,7 +4703,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if ( tsc && tsc->data[SC_HOVERING] && ( skill_id == SR_WINDMILL || skill_id == LG_MOONSLASHER ) )
break;
- heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag);
+ heal = skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, sflag);
if (skill_id == NPC_VAMPIRE_GIFT && heal > 0) {
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
@@ -4766,7 +4778,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case MS_MAGNUM:
if( flag&1 ) {
//Damage depends on distance, so add it to flag if it is > 1
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION|distance_bl(src, bl));
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION|distance_bl(src, bl));
}
break;
@@ -4774,9 +4786,9 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case ML_BRANDISH:
//Coded apart for it needs the flag passed to the damage calculation.
if (skill->area_temp[1] != bl->id)
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION);
else
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
break;
case KN_BOWLINGBASH:
@@ -5171,7 +5183,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
break;
case WL_DRAINLIFE:
{
- int heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ int heal = skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
int rate = 70 + 5 * skill_lv;
heal = heal * (5 + 5 * skill_lv) / 100;
@@ -5217,7 +5229,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if (sd) {
int i;
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- skill->toggle_magicpower(src, skill_id);
+ skill->toggle_magicpower(src, skill_id, skill_lv);
// Priority is to release SpellBook
if (sc && sc->data[SC_READING_SB]) {
// SpellBook
@@ -5461,7 +5473,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
{
struct status_change *tsc = status->get_sc(bl);
if( tsc && tsc->data[SC_POISON] ) {
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
status_change_end(bl, SC_POISON, INVALID_TIMER);
} else if( sd )
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
@@ -5483,7 +5495,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case EL_HURRICANE:
case EL_TYPOON_MIS:
if( flag&1 )
- skill->attack(skill->get_type(skill_id+1),src,src,bl,skill_id+1,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id + 1, skill_lv), src, src, bl, skill_id + 1, skill_lv, tick, flag);
else {
int i = skill->get_splash(skill_id,skill_lv);
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
@@ -5491,7 +5503,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if( rnd()%100 < 30 )
map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
else
- skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
}
break;
@@ -5506,7 +5518,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case EL_STONE_RAIN:
if( flag&1 )
- skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
else {
int i = skill->get_splash(skill_id,skill_lv);
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
@@ -5514,7 +5526,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if( rnd()%100 < 30 )
map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
else
- skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
}
break;
@@ -5524,7 +5536,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case EL_STONE_HAMMER:
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
- skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
break;
case EL_TIDAL_WEAPON:
@@ -5541,7 +5553,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
elemental->clean_single_effect(ele, skill_id);
}
if( rnd()%100 < 50 )
- skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
else {
sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
sc_start(src, battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv));
@@ -5554,7 +5566,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case MH_MAGMA_FLOW:
case MH_HEILIGE_STANGE:
if(flag & 1)
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
else {
map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
}
@@ -5578,7 +5590,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
break;
case SU_SV_STEMSPEAR:
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(skill->get_type(skill_id, skill_lv), src, src, bl, skill_id, skill_lv, tick, flag);
if (status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance.
skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, (skill_id == SU_SV_STEMSPEAR) ? BF_MAGIC : BF_WEAPON, flag);
break;
@@ -5900,7 +5912,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
map->freeblock_lock();
// SC_MAGICPOWER needs to switch states before any damage is actually dealt
- skill->toggle_magicpower(src, ud->skill_id);
+ skill->toggle_magicpower(src, ud->skill_id, ud->skill_lv);
#if 0 // On aegis damage skills are also increase by camouflage. Need confirmation on kRO.
if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses
@@ -11189,7 +11201,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
}
// SC_MAGICPOWER needs to switch states before any damage is actually dealt
- skill->toggle_magicpower(src, skill_id);
+ skill->toggle_magicpower(src, skill_id, skill_lv);
switch(skill_id) {
case PR_BENEDICTIO:
@@ -11807,7 +11819,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
case LG_OVERBRAND:
skill->area_temp[1] = 0;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,x,y,1,5,BL_CHAR,
- skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->get_type(skill_id, skill_lv), src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
skill->addtimerskill(src,timer->gettick() + status_get_amotion(src), 0, x, y, LG_OVERBRAND_BRANDISH, skill_lv, 0, flag);
break;
@@ -12616,7 +12628,7 @@ static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int
nullpo_ret(sg=src->group);
nullpo_ret(ss=map->id2bl(sg->src_id));
- if (skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(src->bl.m, &src->bl, src->bl.x, src->bl.y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR)
+ if (skill->get_type(sg->skill_id, sg->skill_lv) == BF_MAGIC && map->getcell(src->bl.m, &src->bl, src->bl.x, src->bl.y, CELL_CHKLANDPROTECTOR) != 0 && sg->skill_id != SA_LANDPROTECTOR)
return 0; //AoE skills are ineffective. [Skotlex]
sc = status->get_sc(bl);
@@ -12815,7 +12827,7 @@ static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int
if( status_get_mode(bl)&MD_BOSS )
break; // iRO Wiki says that this skill don't affect to Boss monsters.
if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle->check_target(&src->bl,bl, BCT_ENEMY) == 1 )
- skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
case UNT_REVERBERATION:
@@ -13051,7 +13063,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you.
if (tsc)
tsc->sg_counter++; //SG hit counter.
- if (skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc)
+ if (skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) <= 0 && tsc != NULL)
tsc->sg_counter=0; //Attack absorbed.
break;
#endif
@@ -13060,7 +13072,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
default:
- skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
}
break;
@@ -13381,7 +13393,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
case UNT_PSYCHIC_WAVE:
case UNT_MAGMA_ERUPTION:
case UNT_MAKIBISHI:
- skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
case UNT_GROUNDDRIFT_WIND:
@@ -13482,7 +13494,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
sec = 3000; // Couldn't trap it?
sg->limit = DIFF_TICK32(tick, sg->tick) + sec;
} else if( tsc->data[SC_THORNS_TRAP] && bl->id == sg->val2 )
- skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
+ skill->attack(skill->get_type(GN_THORNS_TRAP, sg->skill_lv), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
}
break;
@@ -13494,11 +13506,11 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
default:
sc_start4(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0,
skill->get_time2(sg->skill_id, sg->skill_lv));
- skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl,
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl,
sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0);
break;
case 3:
- skill->attack(skill->get_type(CR_ACIDDEMONSTRATION), ss, &src->bl, bl,
+ skill->attack(skill->get_type(CR_ACIDDEMONSTRATION, sg->skill_lv), ss, &src->bl, bl,
CR_ACIDDEMONSTRATION, sd ? pc->checkskill(sd, CR_ACIDDEMONSTRATION) : sg->skill_lv, tick, 0);
break;
@@ -13516,7 +13528,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
case UNT_HELLS_PLANT:
if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 )
- skill->attack(skill->get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
+ skill->attack(skill->get_type(GN_HELLS_PLANT_ATK, sg->skill_lv), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them
sg->limit = DIFF_TICK32(tick, sg->tick) + 100;
break;
@@ -13524,7 +13536,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
case UNT_CLOUD_KILL:
if(tsc && !tsc->data[type])
status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_FIXEDRATE);
- skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
case UNT_WARMER:
@@ -13649,7 +13661,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
}
sg->limit = DIFF_TICK32(tick, sg->tick) + sec;
} else if (tsc->data[type] && bl->id == sg->val2) {
- skill->attack(skill->get_type(SU_SV_ROOTTWIST_ATK), ss, &src->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
+ skill->attack(skill->get_type(SU_SV_ROOTTWIST_ATK, sg->skill_lv), ss, &src->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
}
}
break;
@@ -14103,16 +14115,16 @@ static int skill_check_condition_mob_master_sub(struct block_list *bl, va_list a
* Determines if a given skill should be made to consume ammo
* when used by the player. [Skotlex]
*------------------------------------------*/
-static int skill_isammotype(struct map_session_data *sd, int skill_id)
+static int skill_isammotype(struct map_session_data *sd, int skill_id, int skill_lv)
{
nullpo_ret(sd);
return (
battle_config.arrow_decrement==2 &&
(sd->weapontype == W_BOW || (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE)) &&
skill_id != HT_PHANTASMIC &&
- skill->get_type(skill_id) == BF_WEAPON &&
+ skill->get_type(skill_id, skill_lv) == BF_WEAPON &&
!(skill->get_nk(skill_id)&NK_NO_DAMAGE) &&
- !skill->get_spiritball(skill_id,1) //Assume spirit spheres are used as ammo instead.
+ !skill->get_spiritball(skill_id, skill_lv) //Assume spirit spheres are used as ammo instead.
);
}
@@ -15512,7 +15524,7 @@ static struct skill_condition skill_get_requirement(struct map_session_data *sd,
if (req.ammo_qty)
req.ammo = skill->dbs->db[idx].ammo;
- if (!req.ammo && skill_id && skill->isammotype(sd, skill_id)) {
+ if (req.ammo == 0 && skill_id != 0 && skill->isammotype(sd, skill_id, skill_lv)) {
//Assume this skill is using the weapon, therefore it requires arrows.
req.ammo = 0xFFFFFFFF; //Enable use on all ammo types.
req.ammo_qty = 1;
@@ -17036,7 +17048,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
}
/* Fall through */
default:
- skill->attack(skill->get_type(sg->skill_id), ss, src, bl, sg->skill_id, sg->skill_lv, tick, enemy_count);
+ skill->attack(skill->get_type(sg->skill_id, sg->skill_lv), ss, src, bl, sg->skill_id, sg->skill_lv, tick, enemy_count);
break;
}
return 1;
@@ -18847,12 +18859,12 @@ static int skill_poisoningweapon(struct map_session_data *sd, int nameid)
return 0;
}
-static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id)
+static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id, int skill_lv)
{
struct status_change *sc = status->get_sc(bl);
// non-offensive and non-magic skills do not affect the status
- if (skill->get_nk(skill_id)&NK_NO_DAMAGE || !(skill->get_type(skill_id)&BF_MAGIC))
+ if ((skill->get_nk(skill_id) & NK_NO_DAMAGE) != 0 || (skill->get_type(skill_id, skill_lv) & BF_MAGIC) == 0)
return;
if (sc && sc->count && sc->data[SC_MAGICPOWER]) {
@@ -18986,14 +18998,20 @@ static int skill_select_menu(struct map_session_data *sd, uint16 skill_id)
idx = skill->get_index(skill_id);
- if( skill_id >= GS_GLITTERING || skill->get_type(skill_id) != BF_MAGIC ||
- (id = sd->status.skill[idx].id) == 0 || sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED ) {
+ if (skill_id >= GS_GLITTERING || (id = sd->status.skill[idx].id) == 0
+ || sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED) {
clif->skill_fail(sd, SC_AUTOSHADOWSPELL, 0, 0, 0);
return 0;
}
lv = (aslvl + 1) / 2; // The level the skill will be autocasted
- lv = min(lv,sd->status.skill[idx].lv);
+ lv = min(lv, sd->status.skill[idx].lv);
+
+ if (skill->get_type(skill_id, lv) != BF_MAGIC) {
+ clif->skill_fail(sd, SC_AUTOSHADOWSPELL, 0, 0, 0);
+ return 0;
+ }
+
prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15.
sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl));
return 0;
@@ -20622,20 +20640,50 @@ static void skill_validate_attacktype(struct config_setting_t *conf, struct s_sk
nullpo_retv(conf);
nullpo_retv(sk);
- sk->skill_type = BF_NONE;
+ skill->level_set_value(sk->skill_type, BF_NONE);
+
+ struct config_setting_t *t = libconfig->setting_get_member(conf, "AttackType");
+
+ if (t != NULL && config_setting_is_group(t)) {
+ for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
+ char lv[6]; // Big enough to contain "Lv999" in case of custom MAX_SKILL_LEVEL.
+ safesnprintf(lv, sizeof(lv), "Lv%d", i + 1);
+ const char *attack_type;
+
+ if (libconfig->setting_lookup_string(t, lv, &attack_type) == CONFIG_TRUE) {
+ if (strcmpi(attack_type, "Weapon") == 0)
+ sk->skill_type[i] = BF_WEAPON;
+ else if (strcmpi(attack_type, "Magic") == 0)
+ sk->skill_type[i] = BF_MAGIC;
+ else if (strcmpi(attack_type, "Misc") == 0)
+ sk->skill_type[i] = BF_MISC;
+ else if (strcmpi(attack_type, "None") != 0)
+ ShowWarning("%s: Invalid attack type %s specified in level %d for skill ID %d in %s! Defaulting to None...\n",
+ __func__, attack_type, i + 1, sk->nameid, conf->file);
+ }
+ }
+
+ return;
+ }
const char *attack_type;
if (libconfig->setting_lookup_string(conf, "AttackType", &attack_type) == CONFIG_TRUE) {
- if (strcmpi(attack_type, "Weapon") == 0)
- sk->skill_type = BF_WEAPON;
- else if (strcmpi(attack_type, "Magic") == 0)
- sk->skill_type = BF_MAGIC;
- else if (strcmpi(attack_type, "Misc") == 0)
- sk->skill_type = BF_MISC;
- else if (strcmpi(attack_type, "None") != 0)
+ int attack = BF_NONE;
+
+ if (strcmpi(attack_type, "Weapon") == 0) {
+ attack = BF_WEAPON;
+ } else if (strcmpi(attack_type, "Magic") == 0) {
+ attack = BF_MAGIC;
+ } else if (strcmpi(attack_type, "Misc") == 0) {
+ attack = BF_MISC;
+ } else if (strcmpi(attack_type, "None") != 0) {
ShowWarning("%s: Invalid attack type %s specified for skill ID %d in %s! Defaulting to None...\n",
__func__, attack_type, sk->nameid, conf->file);
+ return;
+ }
+
+ skill->level_set_value(sk->skill_type, attack);
}
}
diff --git a/src/map/skill.h b/src/map/skill.h
index c8ec04a98..af8f3774b 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1765,7 +1765,9 @@ struct s_skill_db {
#endif
int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL];
int castcancel,cast_def_rate;
- int inf2,maxcount[MAX_SKILL_LEVEL],skill_type;
+ int inf2;
+ int maxcount[MAX_SKILL_LEVEL];
+ int skill_type[MAX_SKILL_LEVEL];
int blewcount[MAX_SKILL_LEVEL];
int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL];
int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL];
@@ -1962,7 +1964,7 @@ struct skill_interface {
int unit_group_newid;
/* accesssors */
int (*get_index) (int skill_id);
- int (*get_type) (int skill_id);
+ int (*get_type) (int skill_id, int skill_lv);
int (*get_hit) (int skill_id, int skill_lv);
int (*get_inf) (int skill_id);
int (*get_ele) (int skill_id, int skill_lv);
@@ -2013,7 +2015,7 @@ struct skill_interface {
int (*get_casttype2) (int index);
bool (*is_combo) (int skill_id);
int (*name2id) (const char* name);
- int (*isammotype) (struct map_session_data *sd, int skill_id);
+ int (*isammotype) (struct map_session_data *sd, int skill_id, int skill_lv);
int (*castend_id) (int tid, int64 tick, int id, intptr_t data);
int (*castend_pos) (int tid, int64 tick, int id, intptr_t data);
int (*castend_map) ( struct map_session_data *sd,uint16 skill_id, const char *mapname);
@@ -2083,7 +2085,7 @@ struct skill_interface {
int (*check_unit_range_sub) (struct block_list *bl, va_list ap);
int (*check_unit_range2) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
int (*check_unit_range2_sub) (struct block_list *bl, va_list ap);
- void (*toggle_magicpower) (struct block_list *bl, uint16 skill_id);
+ void (*toggle_magicpower) (struct block_list *bl, uint16 skill_id, int skill_lv);
int (*magic_reflect) (struct block_list* src, struct block_list* bl, int type);
int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick);
int (*cell_overlap) (struct block_list *bl, va_list ap);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index 4f7c82092..5f789a9b1 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -7230,8 +7230,8 @@ typedef void (*HPMHOOK_pre_skill_read_db) (bool *minimal);
typedef void (*HPMHOOK_post_skill_read_db) (bool minimal);
typedef int (*HPMHOOK_pre_skill_get_index) (int *skill_id);
typedef int (*HPMHOOK_post_skill_get_index) (int retVal___, int skill_id);
-typedef int (*HPMHOOK_pre_skill_get_type) (int *skill_id);
-typedef int (*HPMHOOK_post_skill_get_type) (int retVal___, int skill_id);
+typedef int (*HPMHOOK_pre_skill_get_type) (int *skill_id, int *skill_lv);
+typedef int (*HPMHOOK_post_skill_get_type) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_hit) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_hit) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_get_inf) (int *skill_id);
@@ -7330,8 +7330,8 @@ typedef bool (*HPMHOOK_pre_skill_is_combo) (int *skill_id);
typedef bool (*HPMHOOK_post_skill_is_combo) (bool retVal___, int skill_id);
typedef int (*HPMHOOK_pre_skill_name2id) (const char **name);
typedef int (*HPMHOOK_post_skill_name2id) (int retVal___, const char *name);
-typedef int (*HPMHOOK_pre_skill_isammotype) (struct map_session_data **sd, int *skill_id);
-typedef int (*HPMHOOK_post_skill_isammotype) (int retVal___, struct map_session_data *sd, int skill_id);
+typedef int (*HPMHOOK_pre_skill_isammotype) (struct map_session_data **sd, int *skill_id, int *skill_lv);
+typedef int (*HPMHOOK_post_skill_isammotype) (int retVal___, struct map_session_data *sd, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_castend_id) (int *tid, int64 *tick, int *id, intptr_t *data);
typedef int (*HPMHOOK_post_skill_castend_id) (int retVal___, int tid, int64 tick, int id, intptr_t data);
typedef int (*HPMHOOK_pre_skill_castend_pos) (int *tid, int64 *tick, int *id, intptr_t *data);
@@ -7470,8 +7470,8 @@ typedef int (*HPMHOOK_pre_skill_check_unit_range2) (struct block_list **bl, int
typedef int (*HPMHOOK_post_skill_check_unit_range2) (int retVal___, struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
typedef int (*HPMHOOK_pre_skill_check_unit_range2_sub) (struct block_list **bl, va_list ap);
typedef int (*HPMHOOK_post_skill_check_unit_range2_sub) (int retVal___, struct block_list *bl, va_list ap);
-typedef void (*HPMHOOK_pre_skill_toggle_magicpower) (struct block_list **bl, uint16 *skill_id);
-typedef void (*HPMHOOK_post_skill_toggle_magicpower) (struct block_list *bl, uint16 skill_id);
+typedef void (*HPMHOOK_pre_skill_toggle_magicpower) (struct block_list **bl, uint16 *skill_id, int *skill_lv);
+typedef void (*HPMHOOK_post_skill_toggle_magicpower) (struct block_list *bl, uint16 skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_magic_reflect) (struct block_list **src, struct block_list **bl, int *type);
typedef int (*HPMHOOK_post_skill_magic_reflect) (int retVal___, struct block_list *src, struct block_list *bl, int type);
typedef int (*HPMHOOK_pre_skill_onskillusage) (struct map_session_data **sd, struct block_list **bl, uint16 *skill_id, int64 *tick);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 268051ec8..2f38a5a3d 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -76769,15 +76769,15 @@ int HP_skill_get_index(int skill_id) {
}
return retVal___;
}
-int HP_skill_get_type(int skill_id) {
+int HP_skill_get_type(int skill_id, int skill_lv) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_get_type_pre > 0) {
- int (*preHookFunc) (int *skill_id);
+ int (*preHookFunc) (int *skill_id, int *skill_lv);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_type_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_get_type_pre[hIndex].func;
- retVal___ = preHookFunc(&skill_id);
+ retVal___ = preHookFunc(&skill_id, &skill_lv);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -76785,13 +76785,13 @@ int HP_skill_get_type(int skill_id) {
}
}
{
- retVal___ = HPMHooks.source.skill.get_type(skill_id);
+ retVal___ = HPMHooks.source.skill.get_type(skill_id, skill_lv);
}
if (HPMHooks.count.HP_skill_get_type_post > 0) {
- int (*postHookFunc) (int retVal___, int skill_id);
+ int (*postHookFunc) (int retVal___, int skill_id, int skill_lv);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_type_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_get_type_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, skill_id);
+ retVal___ = postHookFunc(retVal___, skill_id, skill_lv);
}
}
return retVal___;
@@ -78119,15 +78119,15 @@ int HP_skill_name2id(const char *name) {
}
return retVal___;
}
-int HP_skill_isammotype(struct map_session_data *sd, int skill_id) {
+int HP_skill_isammotype(struct map_session_data *sd, int skill_id, int skill_lv) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_isammotype_pre > 0) {
- int (*preHookFunc) (struct map_session_data **sd, int *skill_id);
+ int (*preHookFunc) (struct map_session_data **sd, int *skill_id, int *skill_lv);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_isammotype_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_isammotype_pre[hIndex].func;
- retVal___ = preHookFunc(&sd, &skill_id);
+ retVal___ = preHookFunc(&sd, &skill_id, &skill_lv);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -78135,13 +78135,13 @@ int HP_skill_isammotype(struct map_session_data *sd, int skill_id) {
}
}
{
- retVal___ = HPMHooks.source.skill.isammotype(sd, skill_id);
+ retVal___ = HPMHooks.source.skill.isammotype(sd, skill_id, skill_lv);
}
if (HPMHooks.count.HP_skill_isammotype_post > 0) {
- int (*postHookFunc) (int retVal___, struct map_session_data *sd, int skill_id);
+ int (*postHookFunc) (int retVal___, struct map_session_data *sd, int skill_id, int skill_lv);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_isammotype_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_isammotype_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, sd, skill_id);
+ retVal___ = postHookFunc(retVal___, sd, skill_id, skill_lv);
}
}
return retVal___;
@@ -80039,14 +80039,14 @@ int HP_skill_check_unit_range2_sub(struct block_list *bl, va_list ap) {
}
return retVal___;
}
-void HP_skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
+void HP_skill_toggle_magicpower(struct block_list *bl, uint16 skill_id, int skill_lv) {
int hIndex = 0;
if (HPMHooks.count.HP_skill_toggle_magicpower_pre > 0) {
- void (*preHookFunc) (struct block_list **bl, uint16 *skill_id);
+ void (*preHookFunc) (struct block_list **bl, uint16 *skill_id, int *skill_lv);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_toggle_magicpower_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_toggle_magicpower_pre[hIndex].func;
- preHookFunc(&bl, &skill_id);
+ preHookFunc(&bl, &skill_id, &skill_lv);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -80054,13 +80054,13 @@ void HP_skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
}
}
{
- HPMHooks.source.skill.toggle_magicpower(bl, skill_id);
+ HPMHooks.source.skill.toggle_magicpower(bl, skill_id, skill_lv);
}
if (HPMHooks.count.HP_skill_toggle_magicpower_post > 0) {
- void (*postHookFunc) (struct block_list *bl, uint16 skill_id);
+ void (*postHookFunc) (struct block_list *bl, uint16 skill_id, int skill_lv);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_toggle_magicpower_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_toggle_magicpower_post[hIndex].func;
- postHookFunc(bl, skill_id);
+ postHookFunc(bl, skill_id, skill_lv);
}
}
return;