diff --git a/src/map/skill.cpp b/src/map/skill.cpp index ea9b9ec0e3..a347f05707 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -434,6 +434,50 @@ unsigned short skill_dummy2skill_id(unsigned short skill_id) { return skill_id; } +/** + * Check skill unit maxcount + * @param src: Caster to check against + * @param x: X location of skill + * @param y: Y location of skill + * @param skill_id: Skill used + * @param skill_lv: Skill level used + * @param type: Type of unit to check against for battle_config checks + * @param display_failure: Display skill failure message + * @return True on skill cast success or false on failure + */ +bool skill_pos_maxcount_check(struct block_list *src, int16 x, int16 y, uint16 skill_id, uint16 skill_lv, enum bl_type type, bool display_failure) { + if (!src) + return false; + + struct unit_data *ud = unit_bl2ud(src); + struct map_session_data *sd = map_id2sd(src->id); + int maxcount = 0; + + if (!(type&battle_config.skill_reiteration) && skill_get_unit_flag(skill_id)&UF_NOREITERATION && skill_check_unit_range(src, x, y, skill_id, skill_lv)) { + if (sd && display_failure) + clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + return false; + } + if (type&battle_config.skill_nofootset && skill_get_unit_flag(skill_id)&UF_NOFOOTSET && skill_check_unit_range2(src, x, y, skill_id, skill_lv, false)) { + if (sd && display_failure) + clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + return false; + } + if (type&battle_config.land_skill_limit && (maxcount = skill_get_maxcount(skill_id, skill_lv)) > 0) { + for (int i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount; i++) { + if (ud->skillunit[i]->skill_id == skill_id) + maxcount--; + } + if (maxcount == 0) { + if (sd && display_failure) + clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + return false; + } + } + + return true; +} + /** * Calculates heal value of skill's effect * @param src: Unit casting heal @@ -649,7 +693,7 @@ static int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_idx) { /** * Check if the skill is ok to cast and when. - * Done before check_condition_begin, requirement + * Done before skill_check_condition_castbegin, requirement * @param skill_id: Skill ID that casted * @param sd: Player who casted * @return true: Skill cannot be used, false: otherwise @@ -2106,29 +2150,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 tbl = (it.id < 0) ? src : bl; - if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { - int maxcount = 0; - if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(src,tbl->x,tbl->y,skill,autospl_skill_lv) - ) + if ((type = skill_get_casttype(skill)) == CAST_GROUND) { + if (!skill_pos_maxcount_check(src, tbl->x, tbl->y, skill, autospl_skill_lv, BL_PC, false)) continue; - if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(src,tbl->x,tbl->y,skill,autospl_skill_lv,false) - ) - continue; - if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, autospl_skill_lv)) > 0 - ) { - int v; - for(v=0;vud.skillunit[v] && maxcount;v++) { - if(sd->ud.skillunit[v]->skill_id == skill) - maxcount--; - } - if( maxcount == 0 ) - continue; - } } if (battle_config.autospell_check_range && !battle_check_range(bl, tbl, skill_get_range2(src, skill, autospl_skill_lv, true))) @@ -2233,27 +2257,9 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 else tbl = bl; - if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { - int maxcount = 0; - if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(&sd->bl,tbl->x,tbl->y,skill,skill_lv) ) + if ((type = skill_get_casttype(skill)) == CAST_GROUND) { + if (!skill_pos_maxcount_check(&sd->bl, tbl->x, tbl->y, skill_id, skill_lv, BL_PC, false)) continue; - if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(&sd->bl,tbl->x,tbl->y,skill,skill_lv,false) ) - continue; - if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, skill_lv)) > 0 ) - { - int v; - for(v=0;vud.skillunit[v] && maxcount;v++) { - if(sd->ud.skillunit[v]->skill_id == skill) - maxcount--; - } - if( maxcount == 0 ) - continue; - } } if (battle_config.autospell_check_range && !battle_check_range(bl, tbl, skill_get_range2(&sd->bl, skill, skill_lv, true))) @@ -2443,30 +2449,9 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * continue; tbl = (it.id < 0) ? bl : src; - if( (type = skill_get_casttype(autospl_skill_id)) == CAST_GROUND ) { - int maxcount = 0; - if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(autospl_skill_id)&UF_NOREITERATION && - skill_check_unit_range(bl,tbl->x,tbl->y,autospl_skill_id,autospl_skill_lv) - ) + if ((type = skill_get_casttype(autospl_skill_id)) == CAST_GROUND) { + if (!skill_pos_maxcount_check(bl, tbl->x, tbl->y, autospl_skill_id, autospl_skill_lv, BL_PC, false)) continue; - if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(autospl_skill_id)&UF_NOFOOTSET && - skill_check_unit_range2(bl,tbl->x,tbl->y,autospl_skill_id,autospl_skill_lv,false) - ) - continue; - if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(autospl_skill_id, autospl_skill_lv)) > 0 - ) { - int v; - for(v=0;vud.skillunit[v] && maxcount;v++) { - if(dstsd->ud.skillunit[v]->skill_id == autospl_skill_id) - maxcount--; - } - if( maxcount == 0 ) { - continue; - } - } } if (!battle_check_range(bl, tbl, skill_get_range2(src, autospl_skill_id, autospl_skill_lv, true)) && battle_config.autospell_check_range) @@ -11576,39 +11561,11 @@ TIMER_FUNC(skill_castend_pos){ ud->skilltimer = INVALID_TIMER; do { - int maxcount=0; if( status_isdead(src) ) break; - if( !(src->type&battle_config.skill_reiteration) && - skill_get_unit_flag(ud->skill_id)&UF_NOREITERATION && - skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv) - ) - { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if (!skill_pos_maxcount_check(src, ud->skillx, ud->skilly, ud->skill_id, ud->skill_lv, src->type, true)) break; - } - if( skill_get_unit_flag(ud->skill_id)&UF_NOFOOTSET && - skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,false) - ) - { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if( src->type&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(ud->skill_id, ud->skill_lv)) > 0 - ) { - int i; - for(i=0;iskillunit[i] && maxcount;i++) { - if(ud->skillunit[i]->skill_id == ud->skill_id) - maxcount--; - } - if( maxcount == 0 ) - { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - } if(tid != INVALID_TIMER) { //Avoid double checks on instant cast skills. [Skotlex] diff --git a/src/map/skill.hpp b/src/map/skill.hpp index e02669663c..4a5ac6f8d6 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -487,6 +487,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap); void skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type); struct skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); int skill_disable_check(struct status_change *sc, uint16 skill_id); +bool skill_pos_maxcount_check(struct block_list *src, int16 x, int16 y, uint16 skill_id, uint16 skill_lv, enum bl_type type, bool display_failure); int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16 *skill_lv, int range, int cast_flag); int skill_unit_move(struct block_list *bl,t_tick tick,int flag); diff --git a/src/map/unit.cpp b/src/map/unit.cpp index 93a3c15648..f35f0a032f 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -1998,6 +1998,8 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( sd ) { if( skill_isNotOk(skill_id, sd) || !skill_check_condition_castbegin(sd, skill_id, skill_lv) ) return 0; + if (skill_id == MG_FIREWALL && !skill_pos_maxcount_check(src, skill_x, skill_y, skill_id, skill_lv, BL_PC, true)) + return 0; // Special check for Firewall only } if( (skill_id >= SC_MANHOLE && skill_id <= SC_FEINTBOMB) && map_getcell(src->m, skill_x, skill_y, CELL_CHKMAELSTROM) ) {