From db5874d677a668702349c5ee8b3ce709b247eed3 Mon Sep 17 00:00:00 2001 From: Atemo Date: Fri, 7 Apr 2023 01:09:44 +0200 Subject: [PATCH] Updated unitskilluseid and unitskillusepos script commands (#7684) * Added the parameter 'ignore_range' to ignore the skill range defined in skill_db.yml --- doc/script_commands.txt | 11 +++++++---- src/map/script.cpp | 14 ++++++++------ src/map/unit.cpp | 29 +++++++++++++++-------------- src/map/unit.hpp | 4 ++-- 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 62b70f04e6..b4153f7000 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -8490,10 +8490,10 @@ flag: Specify target --------------------------------------- -*unitskilluseid ,,{,,,,}; -*unitskilluseid ,"",{,,,,}; -*unitskillusepos ,,,,{,,,}; -*unitskillusepos ,"",,,{,,,}; +*unitskilluseid ,,{,,,,,}; +*unitskilluseid ,"",{,,,,,}; +*unitskillusepos ,,,,{,,,,}; +*unitskillusepos ,"",,,{,,,,}; This is the replacement of the older commands, these use the same values for GID as the other unit* commands (See 'GID'). @@ -8509,6 +8509,9 @@ CastCancel from skill_db.yml is the default value of . If is defined (positive number, default 0) the monster will say the message from 'Line_ID' in mob_chat_db.yml when casting the skill. +If is true, the unit will ignore the skill range defined by the database. The default value is false. +Attention! this setting does not work for all skills. + --------------------------------------- *unitexists ; diff --git a/src/map/script.cpp b/src/map/script.cpp index 69a8d606cb..6a53afaac2 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -19920,6 +19920,7 @@ BUILDIN_FUNC(unitskilluseid) casttime = ( script_hasdata(st,6) ? script_getnum(st,6) : 0 ); bool cancel = ( script_hasdata(st,7) ? script_getnum(st,7) > 0 : skill_get_castcancel(skill_id) ); int msg_id = (script_hasdata(st, 8) ? script_getnum(st, 8) : 0); + bool ignore_range = (script_hasdata(st, 9) ? script_getnum(st, 9) > 0 : false); if(script_rid2bl(2,bl)){ if (msg_id > 0) { @@ -19937,7 +19938,7 @@ BUILDIN_FUNC(unitskilluseid) else status_calc_npc(((TBL_NPC*)bl), SCO_NONE); } - unit_skilluse_id2(bl, target_id, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel); + unit_skilluse_id2(bl, target_id, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel, ignore_range); } return SCRIPT_CMD_SUCCESS; @@ -19974,6 +19975,7 @@ BUILDIN_FUNC(unitskillusepos) casttime = ( script_hasdata(st,7) ? script_getnum(st,7) : 0 ); bool cancel = ( script_hasdata(st,8) ? script_getnum(st,8) > 0 : skill_get_castcancel(skill_id) ); int msg_id = (script_hasdata(st, 9) ? script_getnum(st, 9) : 0); + bool ignore_range = (script_hasdata(st, 10) ? script_getnum(st, 10) > 0 : false); if(script_rid2bl(2,bl)){ if (msg_id > 0) { @@ -19991,7 +19993,7 @@ BUILDIN_FUNC(unitskillusepos) else status_calc_npc(((TBL_NPC*)bl), SCO_NONE); } - unit_skilluse_pos2(bl, skill_x, skill_y, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel); + unit_skilluse_pos2(bl, skill_x, skill_y, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel, ignore_range); } return SCRIPT_CMD_SUCCESS; @@ -22890,9 +22892,9 @@ BUILDIN_FUNC(npcskill) status_calc_npc(nd, SCO_NONE); if (skill_get_inf(skill_id)&INF_GROUND_SKILL) - unit_skilluse_pos2(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level,0,0); + unit_skilluse_pos2(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level,0,0,true); else - unit_skilluse_id2(&nd->bl, sd->bl.id, skill_id, skill_level,0,0); + unit_skilluse_id2(&nd->bl, sd->bl.id, skill_id, skill_level,0,0,true); return SCRIPT_CMD_SUCCESS; } @@ -27385,8 +27387,8 @@ struct script_function buildin_func[] = { BUILDIN_DEF(unitstopattack,"i"), BUILDIN_DEF(unitstopwalk,"i?"), BUILDIN_DEF(unittalk,"is?"), - BUILDIN_DEF(unitskilluseid,"ivi????"), // originally by Qamera [Celest] - BUILDIN_DEF(unitskillusepos,"iviii???"), // [Celest] + BUILDIN_DEF(unitskilluseid,"ivi?????"), // originally by Qamera [Celest] + BUILDIN_DEF(unitskillusepos,"iviii????"), // [Celest] // <--- [zBuffer] List of unit control commands BUILDIN_DEF(sleep,"i"), BUILDIN_DEF(sleep2,"i"), diff --git a/src/map/unit.cpp b/src/map/unit.cpp index 3f181d420e..b5c0995151 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -1602,7 +1602,7 @@ int unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int typ * @param castcancel: Whether or not the skill can be cancelled by interruption (hit) * @return Success(1); Fail(0); */ -int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) +int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel, bool ignore_range) { struct unit_data *ud; struct status_data *tstatus; @@ -1747,7 +1747,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui return 0; // Fail if the targetted skill is near NPC [Cydh] - if(skill->inf2[INF2_DISABLENEARNPC] && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) { + if(skill->inf2[INF2_DISABLENEARNPC] && !ignore_range && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) { if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -1864,7 +1864,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if(ud->stepaction || ud->steptimer != INVALID_TIMER) unit_stop_stepaction(src); // Remember the skill request from the client while walking to the next cell - if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle_check_range(src, target, range-1)) { + if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && (!battle_check_range(src, target, range-1) || ignore_range)) { ud->stepaction = true; ud->target_to = target_id; ud->stepskill_id = skill_id; @@ -1874,7 +1874,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui // Check range when not using skill on yourself or is a combo-skill during attack // (these are supposed to always have the same range as your attack) - if( src->type != BL_NPC && src->id != target_id && (!combo || ud->attacktimer == INVALID_TIMER) ) { + if( src->type != BL_NPC && !ignore_range && src->id != target_id && (!combo || ud->attacktimer == INVALID_TIMER) ) { if( skill_get_state(ud->skill_id) == ST_MOVE_ENABLE ) { if( !unit_can_reach_bl(src, target, range + 1, 1, NULL, NULL) ) return 0; // Walk-path check failed. @@ -2010,7 +2010,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui mobskill_event(md, src, tick, -1); // Cast targetted skill event. - if ((status_has_mode(tstatus,MD_CASTSENSORIDLE) || status_has_mode(tstatus,MD_CASTSENSORCHASE)) && battle_check_target(target, src, BCT_ENEMY) > 0) { + if ((status_has_mode(tstatus,MD_CASTSENSORIDLE) || status_has_mode(tstatus,MD_CASTSENSORCHASE)) && battle_check_target(target, src, BCT_ENEMY) > 0 && !ignore_range) { switch (md->state.skillstate) { case MSS_RUSH: case MSS_FOLLOW: @@ -2117,7 +2117,7 @@ int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint * @param castcancel: Whether or not the skill can be cancelled by interuption (hit) * @return Success(1); Fail(0); */ -int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) +int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel, bool ignore_range) { map_session_data *sd = NULL; struct unit_data *ud = NULL; @@ -2170,7 +2170,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui return 0; // Fail if the targetted skill is near NPC [Cydh] - if(skill_get_inf2(skill_id, INF2_DISABLENEARNPC) && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) { + if(skill_get_inf2(skill_id, INF2_DISABLENEARNPC) && !ignore_range && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) { if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -2192,7 +2192,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if(ud->stepaction || ud->steptimer != INVALID_TIMER) unit_stop_stepaction(src); // Remember the skill request from the client while walking to the next cell - if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle_check_range(src, &bl, range-1)) { + if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && (!battle_check_range(src, &bl, range-1) || ignore_range)) { struct map_data *md = &map[src->m]; // Convert coordinates to target_to so we can use it as target later ud->stepaction = true; @@ -2202,12 +2202,13 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui return 0; // Attacking will be handled by unit_walktoxy_timer in this case } - if( skill_get_state(ud->skill_id) == ST_MOVE_ENABLE ) { - if( !unit_can_reach_bl(src, &bl, range + 1, 1, NULL, NULL) ) - return 0; // Walk-path check failed. - }else if( !battle_check_range(src, &bl, range) ) - return 0; // Arrow-path check failed. - + if (!ignore_range) { + if( skill_get_state(ud->skill_id) == ST_MOVE_ENABLE ) { + if( !unit_can_reach_bl(src, &bl, range + 1, 1, NULL, NULL) ) + return 0; // Walk-path check failed. + }else if( !battle_check_range(src, &bl, range) ) + return 0; // Arrow-path check failed. + } unit_stop_attack(src); // Moved here to prevent Suffragium from ending if skill fails diff --git a/src/map/unit.hpp b/src/map/unit.hpp index dabba0fd5f..cfd9326156 100644 --- a/src/map/unit.hpp +++ b/src/map/unit.hpp @@ -146,8 +146,8 @@ bool unit_can_attack(struct block_list *bl, int target_id); // Cast on a unit int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv); int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv); -int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel); -int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel); +int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel, bool ignore_range = false); +int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel, bool ignore_range = false); // Step timer used for delayed attack and skill use TIMER_FUNC(unit_step_timer);