summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2020-02-10 01:34:04 +0100
committerGitHub <noreply@github.com>2020-02-10 01:34:04 +0100
commitd762e0255b63def0a20db15d386c332d5fb93dd1 (patch)
tree3be31ba3a73295bd3d655d27643a248e9abe60a6 /src/map
parente164b55dbb908c0006f0ca4e2e74e9995f318d57 (diff)
parentcaae14cae60f27594a2dbf4c41076330be1afd5e (diff)
downloadhercules-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.c34
-rw-r--r--src/map/itemdb.h2
-rw-r--r--src/map/packets_struct.h12
-rw-r--r--src/map/pc.c35
-rw-r--r--src/map/pc.h14
-rw-r--r--src/map/script.c58
-rw-r--r--src/map/script.h10
-rw-r--r--src/map/skill.c76
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/unit.c46
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 ) {