diff options
author | Haru <haru@dotalux.com> | 2020-02-10 01:34:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-10 01:34:04 +0100 |
commit | d762e0255b63def0a20db15d386c332d5fb93dd1 (patch) | |
tree | 3be31ba3a73295bd3d655d27643a248e9abe60a6 /src/map | |
parent | e164b55dbb908c0006f0ca4e2e74e9995f318d57 (diff) | |
parent | caae14cae60f27594a2dbf4c41076330be1afd5e (diff) | |
download | hercules-d762e0255b63def0a20db15d386c332d5fb93dd1.tar.gz hercules-d762e0255b63def0a20db15d386c332d5fb93dd1.tar.bz2 hercules-d762e0255b63def0a20db15d386c332d5fb93dd1.tar.xz hercules-d762e0255b63def0a20db15d386c332d5fb93dd1.zip |
Merge pull request #2616 from Kenpachi2k13/issue#819
Modified itemskill() script command to be usable like AEGIS' SkillToMe command.
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/clif.c | 34 | ||||
-rw-r--r-- | src/map/itemdb.h | 2 | ||||
-rw-r--r-- | src/map/packets_struct.h | 12 | ||||
-rw-r--r-- | src/map/pc.c | 35 | ||||
-rw-r--r-- | src/map/pc.h | 14 | ||||
-rw-r--r-- | src/map/script.c | 58 | ||||
-rw-r--r-- | src/map/script.h | 10 | ||||
-rw-r--r-- | src/map/skill.c | 76 | ||||
-rw-r--r-- | src/map/skill.h | 1 | ||||
-rw-r--r-- | src/map/unit.c | 46 |
10 files changed, 214 insertions, 74 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 868117a96..660c516d7 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -6754,21 +6754,28 @@ static void clif_item_refine_list(struct map_session_data *sd) /// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B static void clif_item_skill(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) { - int fd; - nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x147)); - WFIFOW(fd, 0)=0x147; - WFIFOW(fd, 2)=skill_id; - WFIFOL(fd, 4)=skill->get_inf(skill_id); - WFIFOW(fd, 8)=skill_lv; - WFIFOW(fd,10)=skill->get_sp(skill_id,skill_lv); - WFIFOW(fd,12)=skill->get_range2(&sd->bl, skill_id,skill_lv); - safestrncpy(WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); - WFIFOB(fd,38)=0; - WFIFOSET(fd,packet_len(0x147)); + int fd = sd->fd; + + WFIFOHEAD(fd, sizeof(struct PACKET_ZC_AUTORUN_SKILL)); + + struct PACKET_ZC_AUTORUN_SKILL *p = WFIFOP(fd, 0); + int type = skill->get_inf(skill_id); + + if (sd->state.itemskill_castonself == 1 && skill->is_item_skill(sd, skill_id, skill_lv)) + type = INF_SELF_SKILL; + + p->packetType = HEADER_ZC_AUTORUN_SKILL; + p->skill_id = skill_id; + p->skill_type = type; + p->skill_lv = skill_lv; + p->skill_sp = skill->get_sp(skill_id, skill_lv); + p->skill_range = skill->get_range2(&sd->bl, skill_id, skill_lv); + safestrncpy(p->skill_name, skill->get_name(skill_id), NAME_LENGTH); + p->up_flag = 0; + + WFIFOSET(fd, sizeof(struct PACKET_ZC_AUTORUN_SKILL)); } /// Adds an item to character's cart. @@ -12926,6 +12933,7 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) pc->delinvincibletimer(sd); skill->castend_map(sd,skill_id,map_name); + pc->itemskill_clear(sd); } static void clif_parse_RequestMemo(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); diff --git a/src/map/itemdb.h b/src/map/itemdb.h index d2592af4e..5f0790b10 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -95,6 +95,8 @@ enum item_itemid { ITEMID_ALOEBERA = 606, ITEMID_SPECTACLES = 611, ITEMID_POISON_BOTTLE = 678, + ITEMID_EARTH_SCROLL_1_3 = 686, + ITEMID_EARTH_SCROLL_1_5 = 687, ITEMID_EMPTY_BOTTLE = 713, ITEMID_EMPERIUM = 714, ITEMID_YELLOW_GEMSTONE = 715, diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 31b28e831..b604c77b8 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -3873,6 +3873,18 @@ struct PACKET_ZC_STATE_CHANGE { DEFINE_PACKET_HEADER(ZC_STATE_CHANGE, 0x0119); #endif +struct PACKET_ZC_AUTORUN_SKILL { + int16 packetType; + uint16 skill_id; + uint32 skill_type; + uint16 skill_lv; + uint16 skill_sp; + uint16 skill_range; + char skill_name[NAME_LENGTH]; + char up_flag; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_AUTORUN_SKILL, 0x0147); + #if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #pragma pack(pop) #endif // not NetBSD < 6 / Solaris diff --git a/src/map/pc.c b/src/map/pc.c index f6edb5e3c..c96e957c7 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5257,6 +5257,14 @@ static int pc_useitem(struct map_session_data *sd, int n) #endif if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) { clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true); + + // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, there is a chance to don't consume the scroll. [Kenpachi] + if ((nameid == ITEMID_EARTH_SCROLL_1_3 || nameid == ITEMID_EARTH_SCROLL_1_5) + && sd->sc.count > 0 && sd->sc.data[SC_EARTHSCROLL] != NULL + && rnd() % 100 > sd->sc.data[SC_EARTHSCROLL]->val2) { + return 0; + } + pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); } return 0; @@ -5302,11 +5310,37 @@ static int pc_useitem(struct map_session_data *sd, int n) script->run_use_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id); script->potion_flag = 0; + // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, there is a chance to don't consume the scroll. [Kenpachi] + if ((nameid == ITEMID_EARTH_SCROLL_1_3 || nameid == ITEMID_EARTH_SCROLL_1_5) && sd->sc.count > 0 + && sd->sc.data[SC_EARTHSCROLL] != NULL && rnd() % 100 > sd->sc.data[SC_EARTHSCROLL]->val2) { + removeItem = false; + } + if (removeItem) pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); return 1; } +/** + * Sets state flags and helper variables, used by itemskill() script command, to 0. + * + * @param sd The character's session data. + * @return 0 if parameter sd is NULL, otherwise 1. + */ +static int pc_itemskill_clear(struct map_session_data *sd) +{ + nullpo_ret(sd); + + sd->itemskill_id = 0; + sd->itemskill_lv = 0; + sd->state.itemskill_conditions_checked = 0; + sd->state.itemskill_no_conditions = 0; + sd->state.itemskill_no_casttime = 0; + sd->state.itemskill_castonself = 0; + + return 1; +} + /*========================================== * Add item on cart for given index. * Return: @@ -12648,6 +12682,7 @@ void pc_defaults(void) pc->unequipitem_pos = pc_unequipitem_pos; pc->checkitem = pc_checkitem; pc->useitem = pc_useitem; + pc->itemskill_clear = pc_itemskill_clear; pc->skillatk_bonus = pc_skillatk_bonus; pc->skillheal_bonus = pc_skillheal_bonus; diff --git a/src/map/pc.h b/src/map/pc.h index a3a3ee48d..e940c3310 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -240,6 +240,10 @@ struct map_session_data { unsigned int refine_ui : 1; unsigned int npc_unloaded : 1; ///< The player is talking with an unloaded NPCs (respawned tombstones) unsigned int lapine_ui : 1; + unsigned int itemskill_conditions_checked : 1; // Used by itemskill() script command, to prevent second check of conditions after target was selected. + unsigned int itemskill_no_conditions : 1; // Used by itemskill() script command, to ignore skill conditions and don't consume them. + unsigned int itemskill_no_casttime : 1; // Used by itemskill() script command, to cast skill instantaneously. + unsigned int itemskill_castonself : 1; // Used by itemskill() script command, to forcefully cast skill on invoking character. } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -643,6 +647,15 @@ END_ZEROED_BLOCK; bool achievements_received; // Title VECTOR_DECL(int) title_ids; + + /* + * itemskill_conditions_checked/itemskill_no_conditions/itemskill_no_casttime/itemskill_castonself abuse prevention. + * If a skill, casted by itemskill() script command, is aborted while target selection, + * the map server gets no notification where these states could be unset. + * Thus we need this helper variables to prevent abusing these states for next skill cast. + */ + int itemskill_id; + int itemskill_lv; }; #define EQP_WEAPON EQP_HAND_R @@ -1021,6 +1034,7 @@ END_ZEROED_BLOCK; /* End */ void (*unequipitem_pos) (struct map_session_data *sd, int n, int pos); int (*checkitem) (struct map_session_data *sd); int (*useitem) (struct map_session_data *sd,int n); + int (*itemskill_clear) (struct map_session_data *sd); int (*skillatk_bonus) (struct map_session_data *sd, uint16 skill_id); int (*skillheal_bonus) (struct map_session_data *sd, uint16 skill_id); diff --git a/src/map/script.c b/src/map/script.c index b77e6a376..c1eb2e8b7 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10985,33 +10985,51 @@ static BUILDIN(guildopenstorage) return true; } -/*========================================== - * Make player use a skill trought item usage - *------------------------------------------*/ -/// itemskill <skill id>,<level>{,flag -/// itemskill "<skill name>",<level>{,flag +/** + * Makes the attached character use a skill by using an item. + * + * @code{.herc} + * itemskill(<skill id>, <skill level>{, <flag>}); + * itemskill("<skill name>", <skill level>{, <flag>}); + * @endcode + * + */ static BUILDIN(itemskill) { - int id; - int lv; struct map_session_data *sd = script->rid2sd(st); + if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER) return true; - id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); - lv = script_getnum(st,3); -/* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ -#if 0 - if( !script_hasdata(st, 4) ) { - if( !skill->check_condition_castbegin(sd,id,lv) || !skill->check_condition_castend(sd,id,lv) ) + sd->skillitem = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2); + sd->skillitemlv = script_getnum(st, 3); + sd->state.itemskill_conditions_checked = 0; // Skill casting items will check the conditions prior to the target selection in AEGIS. Thus we need a flag to prevent checking them twice. + + int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE; + + sd->state.itemskill_no_conditions = ((flag & ISF_IGNORECONDITIONS) == ISF_IGNORECONDITIONS) ? 1 : 0; // Unset in pc_itemskill_clear(). + + if (sd->state.itemskill_no_conditions == 0) { + if (skill->check_condition_castbegin(sd, sd->skillitem, sd->skillitemlv) == 0 + || skill->check_condition_castend(sd, sd->skillitem, sd->skillitemlv) == 0) { return true; + } + + sd->state.itemskill_conditions_checked = 1; // Unset in pc_itemskill_clear(). } -#endif - sd->skillitem=id; - sd->skillitemlv=lv; - clif->item_skill(sd,id,lv); + + sd->state.itemskill_no_casttime = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST) ? 1 : 0; // Unset in pc_itemskill_clear(). + sd->state.itemskill_castonself = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF) ? 1 : 0; // Unset in pc_itemskill_clear(). + + // itemskill_conditions_checked/itemskill_no_conditions/itemskill_no_casttime/itemskill_castonself abuse prevention. Unset in pc_itemskill_clear(). + sd->itemskill_id = sd->skillitem; + sd->itemskill_lv = sd->skillitemlv; + + clif->item_skill(sd, sd->skillitem, sd->skillitemlv); + return true; } + /*========================================== * Attempt to create an item *------------------------------------------*/ @@ -27838,6 +27856,12 @@ static void script_hardcoded_constants(void) script->set_constant("MADO_ROBOT", MADO_ROBOT, false, false); script->set_constant("MADO_SUITE", MADO_SUITE, false, false); + script->constdb_comment("itemskill option flags"); + script->set_constant("ISF_NONE", ISF_NONE, false, false); + script->set_constant("ISF_IGNORECONDITIONS", ISF_IGNORECONDITIONS, false, false); + script->set_constant("ISF_INSTANTCAST", ISF_INSTANTCAST, false, false); + script->set_constant("ISF_CASTONSELF", ISF_CASTONSELF, false, false); + script->constdb_comment("Renewal"); #ifdef RENEWAL script->set_constant("RENEWAL", 1, false, false); diff --git a/src/map/script.h b/src/map/script.h index 8d7669d68..857d22c61 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -565,6 +565,16 @@ enum mado_type { }; /** + * Option flags for itemskill() script command. + **/ +enum itemskill_flag { + ISF_NONE = 0x00, + ISF_IGNORECONDITIONS = 0x01, // Ignore skill conditions and don't consume them. + ISF_INSTANTCAST = 0x02, // Cast skill instantaneously. + ISF_CASTONSELF = 0x04, // Forcefully cast skill on invoking character without showing the target selection cursor. +}; + +/** * Structures **/ diff --git a/src/map/skill.c b/src/map/skill.c index 0f0a72dce..a8dbefbd7 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4190,6 +4190,11 @@ static void skill_castend_type(int type, struct block_list *src, struct block_li skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag); break; } + + struct map_session_data *sd = BL_CAST(BL_PC, src); + + if (sd != NULL) + pc->itemskill_clear(sd); } /*========================================== @@ -13989,6 +13994,22 @@ static bool skill_is_combo(int skill_id) return false; } +/** + * Checks if a skill is casted by an item (itemskill() script command). + * + * @param sd The charcater's session data. + * @param skill_id The skill's ID. + * @param skill_lv The skill's level. + * @return true if skill is casted by an item, otherwise false. + */ +static bool skill_is_item_skill(struct map_session_data *sd, int skill_id, int skill_lv) +{ + nullpo_retr(false, sd); + + return (sd->skillitem == skill_id && sd->skillitemlv == skill_lv + && sd->itemskill_id == skill_id && sd->itemskill_lv == skill_lv); +} + static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) { struct status_data *st; @@ -13997,9 +14018,17 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s nullpo_ret(sd); + if (skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL) + return 0; + if (sd->chat_id != 0) return 0; + if ((sd->state.itemskill_conditions_checked == 1 || sd->state.itemskill_no_conditions == 1) + && skill->is_item_skill(sd, skill_id, skill_lv)) { + return 1; + } + if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check. @@ -14041,24 +14070,21 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s if( (i = sd->itemindex) == -1 || sd->status.inventory[i].nameid != sd->itemid || sd->inventory_data[i] == NULL || - !sd->inventory_data[i]->flag.delay_consume || sd->status.inventory[i].amount < 1 ) { //Something went wrong, item exploit? sd->itemid = sd->itemindex = -1; return 0; } + //Consume sd->itemid = sd->itemindex = -1; - if( skill_id == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007] - ; //Do not consume item. - else if( sd->status.inventory[i].expire_time == 0 ) // Rental usable items are not consumed until expiration + if (sd->status.inventory[i].expire_time == 0 && sd->inventory_data[i]->flag.delay_consume == 1) // Rental usable items are not consumed until expiration pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); } - return 1; } - if( pc_is90overweight(sd) ) { + if (pc_is90overweight(sd) && sd->skillitem != skill_id) { /// Skill casting items ignore the overweight restriction. [Kenpachi] clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0); return 0; } @@ -14182,9 +14208,6 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s } } - if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) - return 0; - require = skill->get_requirement(sd,skill_id,skill_lv); //Can only update state when weapon/arrow info is checked. @@ -14932,7 +14955,7 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s return 0; } - if( require.sp > 0 && st->sp < (unsigned int)require.sp) { + if (require.sp > 0 && st->sp < (unsigned int)require.sp && sd->skillitem != skill_id) { /// Skill casting items and Hocus-Pocus skills don't consume SP. [Kenpachi] clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0); return 0; } @@ -14990,6 +15013,11 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski if (sd->chat_id != 0) return 0; + if ((sd->state.itemskill_conditions_checked == 1 || sd->state.itemskill_no_conditions == 1) + && skill->is_item_skill(sd, skill_id, skill_lv)) { + return 1; + } + if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check. @@ -15017,14 +15045,8 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski return 0; break; } - /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ -#if 0 - if( sd->state.abra_flag ) // Casting finished (Hocus-Pocus) - return 1; -#endif - if( sd->skillitem == skill_id ) - return 1; - if( pc_is90overweight(sd) ) { + + if (pc_is90overweight(sd) && sd->skillitem != skill_id) { /// Skill casting items ignore the overweight restriction. [Kenpachi] clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0); return 0; } @@ -15197,6 +15219,9 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i nullpo_ret(sd); + if (sd->state.itemskill_no_conditions == 1 && skill->is_item_skill(sd, skill_id, skill_lv)) + return 1; + req = skill->get_requirement(sd,skill_id,skill_lv); if (type&1) { @@ -15205,9 +15230,15 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i case MC_IDENTIFY: req.sp = 0; break; + case WZ_EARTHSPIKE: + if (sd->sc.count > 0 && sd->sc.data[SC_EARTHSCROLL] != NULL) // If Earth Spike Scroll is used while SC_EARTHSCROLL is active, 10 SP are consumed. [Kenpachi] + req.sp = 10; + + break; default: - if( sd->state.autocast ) + if (sd->state.autocast == 1 || sd->skillitem == skill_id) /// Skill casting items and Hocus-Pocus skills don't consume SP. [Kenpachi] req.sp = 0; + break; } @@ -15285,12 +15316,6 @@ static struct skill_condition skill_get_requirement(struct map_session_data *sd, if( !sd ) return req; -#if 0 /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ - if( sd->state.abra_flag ) -#else // not 0 - if( sd->skillitem == skill_id ) -#endif // 0 - return req; // Hocus-Pocus don't have requirements. sc = &sd->sc; if( !sc->count ) @@ -21602,6 +21627,7 @@ void skill_defaults(void) skill->cast_fix_sc = skill_castfix_sc; skill->vf_cast_fix = skill_vfcastfix; skill->delay_fix = skill_delay_fix; + skill->is_item_skill = skill_is_item_skill; skill->check_condition_castbegin = skill_check_condition_castbegin; skill->check_condition_castend = skill_check_condition_castend; skill->consume_requirement = skill_consume_requirement; diff --git a/src/map/skill.h b/src/map/skill.h index 188a1c927..eff9ed7fc 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -2019,6 +2019,7 @@ struct skill_interface { int (*cast_fix_sc) ( struct block_list *bl, int time); int (*vf_cast_fix) ( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv); int (*delay_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv); + bool (*is_item_skill) (struct map_session_data *sd, int skill_id, int skill_lv); int (*check_condition_castbegin) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); int (*check_condition_castend) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); int (*consume_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type); diff --git a/src/map/unit.c b/src/map/unit.c index 482440978..29a01aea7 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1041,11 +1041,15 @@ static int unit_stop_walking(struct block_list *bl, int flag) static int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv) { - return unit->skilluse_id2( - src, target_id, skill_id, skill_lv, - skill->cast_fix(src, skill_id, skill_lv), - skill->get_castcancel(skill_id) - ); + int casttime = skill->cast_fix(src, skill_id, skill_lv); + int castcancel = skill->get_castcancel(skill_id); + int ret = unit->skilluse_id2(src, target_id, skill_id, skill_lv, casttime, castcancel); + struct map_session_data *sd = BL_CAST(BL_PC, src); + + if (sd != NULL) + pc->itemskill_clear(sd); + + return ret; } static int unit_is_walking(struct block_list *bl) @@ -1418,15 +1422,8 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill } } - if (sd) { - /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ -#if 0 - if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) -#else - if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) -#endif - return 0; - } + if (sd != NULL && skill->check_condition_castbegin(sd, skill_id, skill_lv) == 0) + return 0; if (src->type == BL_MOB) { const struct mob_data *src_md = BL_UCCAST(BL_MOB, src); @@ -1609,6 +1606,9 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill if (!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);// even though this is not how official works but this will do the trick. bugreport:6829 + if (sd != NULL && sd->state.itemskill_no_casttime == 1 && skill->is_item_skill(sd, skill_id, skill_lv)) + casttime = 0; + // in official this is triggered even if no cast time. clif->useskill(src, src->id, target_id, 0,0, skill_id, skill_lv, casttime); if( casttime > 0 || temp ) @@ -1678,11 +1678,15 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill static int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv) { - return unit->skilluse_pos2( - src, skill_x, skill_y, skill_id, skill_lv, - skill->cast_fix(src, skill_id, skill_lv), - skill->get_castcancel(skill_id) - ); + int casttime = skill->cast_fix(src, skill_id, skill_lv); + int castcancel = skill->get_castcancel(skill_id); + int ret = unit->skilluse_pos2(src, skill_x, skill_y, skill_id, skill_lv, casttime, castcancel); + struct map_session_data *sd = BL_CAST(BL_PC, src); + + if (sd != NULL) + pc->itemskill_clear(sd); + + return ret; } static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) @@ -1807,6 +1811,10 @@ static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill } unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); + + if (sd != NULL && sd->state.itemskill_no_casttime == 1 && skill->is_item_skill(sd, skill_id, skill_lv)) + casttime = 0; + // in official this is triggered even if no cast time. clif->useskill(src, src->id, 0, skill_x, skill_y, skill_id, skill_lv, casttime); if( casttime > 0 ) { |