diff options
-rw-r--r-- | src/map/battle.c | 2 | ||||
-rw-r--r-- | src/map/clif.c | 6 | ||||
-rw-r--r-- | src/map/skill.c | 168 | ||||
-rw-r--r-- | src/map/skill.h | 10 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking.Defs.inc | 12 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 36 |
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; |