summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2020-05-31 23:33:55 +0200
committerGitHub <noreply@github.com>2020-05-31 23:33:55 +0200
commitb3189b88eafd5a159780000845bacef79310a22c (patch)
tree6abf9ca36ce7c703c2735589e7f89cef6e5f698a
parent1cccfca3dd708354bf808068c1210ce353957f2e (diff)
parent468c81a5367c444e2e678148d556df94eaa623af (diff)
downloadhercules-b3189b88eafd5a159780000845bacef79310a22c.tar.gz
hercules-b3189b88eafd5a159780000845bacef79310a22c.tar.bz2
hercules-b3189b88eafd5a159780000845bacef79310a22c.tar.xz
hercules-b3189b88eafd5a159780000845bacef79310a22c.zip
Merge pull request #2699 from Kenpachi2k13/multi_itemskill
Enable multiple itemskill() calls per item
-rw-r--r--src/map/battle.c12
-rw-r--r--src/map/clif.c32
-rw-r--r--src/map/pc.c85
-rw-r--r--src/map/pc.h8
-rw-r--r--src/map/script.c29
-rw-r--r--src/map/skill.c143
-rw-r--r--src/map/status.c9
-rw-r--r--src/map/unit.c24
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc17
10 files changed, 226 insertions, 137 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index a8193d24a..796e0de68 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -5934,14 +5934,14 @@ static void battle_reflect_damage(struct block_list *target, struct block_list *
enum autocast_type ac_type;
if (sd != NULL) {
- ac_type = sd->autocast.type;
- sd->autocast.type = AUTOCAST_TEMP;
+ ac_type = sd->auto_cast_current.type;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
}
map->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,delay,wd->dmotion,rdamage,status_get_race(target));
if (sd != NULL)
- sd->autocast.type = ac_type;
+ sd->auto_cast_current.type = ac_type;
delay += 150;/* gradual increase so the numbers don't clip in the client */
@@ -6131,7 +6131,7 @@ static int battle_damage_area(struct block_list *bl, va_list ap)
else
status_fix_damage(src,bl,damage,0);
clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0);
- if (src->type != BL_PC || BL_UCCAST(BL_PC, src)->autocast.type != AUTOCAST_TEMP)
+ if (src->type != BL_PC || BL_UCCAST(BL_PC, src)->auto_cast_current.type != AUTOCAST_TEMP)
skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
map->freeblock_unlock();
}
@@ -6455,10 +6455,10 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_
}
}
- sd->autocast.type = AUTOCAST_TEMP;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,r_skill,r_lv,3);
skill->castend_type(type, src, target, r_skill, r_lv, tick, flag);
- sd->autocast.type = AUTOCAST_NONE;
+ sd->auto_cast_current.type = AUTOCAST_NONE;
sd->ud.canact_tick = tick + skill->delay_fix(src, r_skill, r_lv);
clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1);
}
diff --git a/src/map/clif.c b/src/map/clif.c
index a0ec1fdf6..477894805 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -6766,7 +6766,7 @@ static void clif_item_skill(struct map_session_data *sd, uint16 skill_id, uint16
struct PACKET_ZC_AUTORUN_SKILL *p = WFIFOP(fd, 0);
int type = skill->get_inf(skill_id);
- if (sd->autocast.itemskill_cast_on_self && sd->autocast.type == AUTOCAST_ITEM)
+ if (sd->auto_cast_current.itemskill_cast_on_self && sd->auto_cast_current.type == AUTOCAST_ITEM)
type = INF_SELF_SKILL;
p->packetType = HEADER_ZC_AUTORUN_SKILL;
@@ -12797,13 +12797,15 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
{
int64 tick = timer->gettick();
+ pc->autocast_set_current(sd, skill_id);
+
/**
* According to Skotlex' comment below, the client sometimes passes 0 for the skill level.
* Even though this seems to only affect guild skills, sd->autocast.skill_lv is used
* for the auto-cast data validation if skill_lv is 0.
*
**/
- skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->auto_cast_current.skill_lv : skill_lv);
if (skill_lv < 1)
skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
@@ -12855,10 +12857,10 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
target_id = sd->bl.id;
if (sd->ud.skilltimer != INVALID_TIMER) {
- if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST)
+ if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST && sd->auto_cast_current.type == AUTOCAST_NONE)
return;
} else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
- if (sd->autocast.type == AUTOCAST_NONE) {
+ if (sd->auto_cast_current.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -12876,9 +12878,9 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
} else if (sd->menuskill_id != SA_AUTOSPELL)
return; //Can't use skills while a menu is open.
}
- if (sd->autocast.type != AUTOCAST_NONE) {
- if (skill_lv != sd->autocast.skill_lv)
- skill_lv = sd->autocast.skill_lv;
+ if (sd->auto_cast_current.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->auto_cast_current.skill_lv)
+ skill_lv = sd->auto_cast_current.skill_lv;
if (!(tmp&INF_SELF_SKILL))
pc->delinvincibletimer(sd); // Target skills through items cancel invincibility. [Inkfish]
unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
@@ -12946,6 +12948,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
int64 tick = timer->gettick();
nullpo_retv(sd);
+
+ pc->autocast_set_current(sd, skill_id);
/**
* When using clif_item_skill() to initiate the execution of ground skills,
@@ -12954,7 +12958,7 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
* since clif_item_skill() is only used for auto-cast skills.
*
**/
- skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->auto_cast_current.skill_lv : skill_lv);
if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) )
return; //Using a target skill on the ground? WRONG.
@@ -12992,11 +12996,11 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
safestrncpy(sd->message, RFIFOP(fd, skillmoreinfo), TALKBOX_MESSAGE_SIZE);
}
- if( sd->ud.skilltimer != INVALID_TIMER )
+ if (sd->ud.skilltimer != INVALID_TIMER && sd->auto_cast_current.type == AUTOCAST_NONE)
return;
if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
- if (sd->autocast.type == AUTOCAST_NONE) {
+ if (sd->auto_cast_current.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -13017,9 +13021,9 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
pc->delinvincibletimer(sd);
- if (sd->autocast.type != AUTOCAST_NONE) {
- if (skill_lv != sd->autocast.skill_lv)
- skill_lv = sd->autocast.skill_lv;
+ if (sd->auto_cast_current.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->auto_cast_current.skill_lv)
+ skill_lv = sd->auto_cast_current.skill_lv;
unit->skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
} else {
int lv;
@@ -13093,6 +13097,8 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd)
clif_menuskill_clear(sd);
return;
}
+
+ pc->autocast_set_current(sd, skill_id);
/**
* Since no skill level was passed use 0 to notify skill_validate_autocast_data() of this special case.
diff --git a/src/map/pc.c b/src/map/pc.c
index 5faadf76a..4497ef54f 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1279,6 +1279,7 @@ static bool pc_authok(struct map_session_data *sd, int login_id2, time_t expirat
sd->bg_queue.client_has_bg_data = 0;
sd->bg_queue.type = 0;
+ VECTOR_INIT(sd->auto_cast); // Initialize auto-cast vector.
VECTOR_INIT(sd->channels);
VECTOR_INIT(sd->script_queues);
VECTOR_INIT(sd->achievement); // Achievements [Smokexyz/Hercules]
@@ -5333,24 +5334,79 @@ static int pc_useitem(struct map_session_data *sd, int n)
}
/**
+ * Unsets a character's currently processed auto-cast skill data.
+ *
+ * @param sd The character.
+ *
+ **/
+static void pc_autocast_clear_current(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ sd->auto_cast_current.type = AUTOCAST_NONE;
+ sd->auto_cast_current.skill_id = 0;
+ sd->auto_cast_current.skill_lv = 0;
+ sd->auto_cast_current.itemskill_conditions_checked = false;
+ sd->auto_cast_current.itemskill_check_conditions = true;
+ sd->auto_cast_current.itemskill_instant_cast = false;
+ sd->auto_cast_current.itemskill_cast_on_self = false;
+}
+
+/**
* Unsets a character's auto-cast related data.
*
- * @param sd The character's session data.
- * @return 0 if parameter sd is NULL, otherwise 1.
- */
-static int pc_autocast_clear(struct map_session_data *sd)
+ * @param sd The character.
+ *
+ **/
+static void pc_autocast_clear(struct map_session_data *sd)
{
- nullpo_ret(sd);
+ nullpo_retv(sd);
- sd->autocast.type = AUTOCAST_NONE;
- sd->autocast.skill_id = 0;
- sd->autocast.skill_lv = 0;
- sd->autocast.itemskill_conditions_checked = false;
- sd->autocast.itemskill_check_conditions = false;
- sd->autocast.itemskill_instant_cast = false;
- sd->autocast.itemskill_cast_on_self = false;
+ pc->autocast_clear_current(sd);
+ VECTOR_TRUNCATE(sd->auto_cast); // Truncate auto-cast vector.
+}
- return 1;
+/**
+ * Sets a character's currently processed auto-cast skill data by comparing the skill ID.
+ *
+ * @param sd The character.
+ * @param skill_id The skill ID to compare.
+ *
+ **/
+static void pc_autocast_set_current(struct map_session_data *sd, int skill_id)
+{
+ nullpo_retv(sd);
+
+ pc->autocast_clear_current(sd);
+
+ for (int i = 0; i < VECTOR_LENGTH(sd->auto_cast); i++) {
+ if (VECTOR_INDEX(sd->auto_cast, i).skill_id == skill_id) {
+ sd->auto_cast_current = VECTOR_INDEX(sd->auto_cast, i);
+ break;
+ }
+ }
+}
+
+/**
+ * Removes a specific entry from a character's auto-cast vector.
+ *
+ * @param sd The character.
+ * @param type The entry's auto-cast type.
+ * @param skill_id The entry's skill ID.
+ * @param skill_lv The entry's skill level.
+ *
+ **/
+static void pc_autocast_remove(struct map_session_data *sd, enum autocast_type type, int skill_id, int skill_lv)
+{
+ nullpo_retv(sd);
+
+ for (int i = 0; i < VECTOR_LENGTH(sd->auto_cast); i++) {
+ if (VECTOR_INDEX(sd->auto_cast, i).type == type && VECTOR_INDEX(sd->auto_cast, i).skill_id == skill_id
+ && VECTOR_INDEX(sd->auto_cast, i).skill_lv == skill_lv) {
+ VECTOR_ERASE(sd->auto_cast, i);
+ break;
+ }
+ }
}
/*==========================================
@@ -12883,7 +12939,10 @@ void pc_defaults(void)
pc->unequipitem_pos = pc_unequipitem_pos;
pc->checkitem = pc_checkitem;
pc->useitem = pc_useitem;
+ pc->autocast_clear_current = pc_autocast_clear_current;
pc->autocast_clear = pc_autocast_clear;
+ pc->autocast_set_current = pc_autocast_set_current;
+ pc->autocast_remove = pc_autocast_remove;
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 8d1cd0ca4..dfc1f886e 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -192,7 +192,8 @@ struct map_session_data {
struct status_change sc;
struct regen_data regen;
struct regen_data_sub sregen, ssregen;
- struct autocast_data autocast;
+ struct autocast_data auto_cast_current; // Currently processed auto-cast skill.
+ VECTOR_DECL(struct autocast_data) auto_cast; // Auto-cast vector.
//NOTE: When deciding to add a flag to state or special_state, take into consideration that state is preserved in
//status_calc_pc, while special_state is recalculated in each call. [Skotlex]
struct {
@@ -1028,7 +1029,10 @@ 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 (*autocast_clear) (struct map_session_data *sd);
+ void (*autocast_clear_current) (struct map_session_data *sd);
+ void (*autocast_clear) (struct map_session_data *sd);
+ void (*autocast_set_current) (struct map_session_data *sd, int skill_id);
+ void (*autocast_remove) (struct map_session_data *sd, enum autocast_type type, int skill_id, int skill_lv);
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 e4a57194d..069b98eef 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -11287,32 +11287,33 @@ static BUILDIN(itemskill)
{
struct map_session_data *sd = script->rid2sd(st);
- if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER)
+ if (sd == NULL)
return true;
- pc->autocast_clear(sd);
- sd->autocast.type = AUTOCAST_ITEM;
- sd->autocast.skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
- sd->autocast.skill_lv = script_getnum(st, 3);
+ sd->auto_cast_current.type = AUTOCAST_ITEM;
+ sd->auto_cast_current.skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
+ sd->auto_cast_current.skill_lv = script_getnum(st, 3);
int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE;
- sd->autocast.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS);
+ sd->auto_cast_current.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS);
- if (sd->autocast.itemskill_check_conditions) {
- if (skill->check_condition_castbegin(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0
- || skill->check_condition_castend(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0) {
- pc->autocast_clear(sd);
+ if (sd->auto_cast_current.itemskill_check_conditions) {
+ if (skill->check_condition_castbegin(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv) == 0
+ || skill->check_condition_castend(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv) == 0) {
return true;
}
- sd->autocast.itemskill_conditions_checked = true;
+ sd->auto_cast_current.itemskill_conditions_checked = true;
}
- sd->autocast.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST);
- sd->autocast.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF);
+ sd->auto_cast_current.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST);
+ sd->auto_cast_current.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF);
+
+ VECTOR_ENSURE(sd->auto_cast, 1, 1);
+ VECTOR_PUSH(sd->auto_cast, sd->auto_cast_current);
- clif->item_skill(sd, sd->autocast.skill_id, sd->autocast.skill_lv);
+ clif->item_skill(sd, sd->auto_cast_current.skill_id, sd->auto_cast_current.skill_lv);
return true;
}
diff --git a/src/map/skill.c b/src/map/skill.c
index e3fa6b0a1..8c83e57a3 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1029,14 +1029,14 @@ static int skillnotok(uint16 skill_id, struct map_session_data *sd)
if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOSKILL))
return 1; // block usage on 'noskill' cells [Wolfie]
- if (skill_id == AL_TELEPORT && sd->autocast.type == AUTOCAST_ITEM && sd->autocast.skill_lv > 2)
+ if (skill_id == AL_TELEPORT && sd->auto_cast_current.type == AUTOCAST_ITEM && sd->auto_cast_current.skill_lv > 2)
return 0; // Teleport level 3 and higher bypasses this check if cast by itemskill() script commands.
// Epoque:
// This code will compare the player's attack motion value which is influenced by ASPD before
// allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as
// AC_DOUBLE which do not have a skill delay and are not regarded in terms of attack motion.
- if (sd->autocast.type == AUTOCAST_NONE && sd->canskill_tick != 0 &&
+ if (sd->auto_cast_current.type == AUTOCAST_NONE && sd->canskill_tick != 0 &&
DIFF_TICK(timer->gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (battle_config.skill_amotion_leniency) / 100) )
{// attempted to cast a skill before the attack motion has finished
return 1;
@@ -1051,7 +1051,7 @@ static int skillnotok(uint16 skill_id, struct map_session_data *sd)
* It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions below
* Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map
**/
- if (sd->autocast.type == AUTOCAST_ITEM)
+ if (sd->auto_cast_current.type == AUTOCAST_ITEM)
return 0;
if( sd->sc.data[SC_ALL_RIDING] )
@@ -1211,14 +1211,16 @@ static void skill_validate_autocast_data(struct map_session_data *sd, int skill_
// Determine if called by clif_parse_UseSkillMap().
bool use_skill_map = (skill_lv == 0 && (skill_id == AL_WARP || skill_id == AL_TELEPORT));
- if (sd->autocast.type == AUTOCAST_NONE)
+ struct autocast_data *auto_cast = &sd->auto_cast_current;
+
+ if (auto_cast->type == AUTOCAST_NONE)
pc->autocast_clear(sd); // No auto-cast type set. Preventively unset all auto-cast related data.
- else if (sd->autocast.type == AUTOCAST_TEMP)
+ else if (auto_cast->type == AUTOCAST_TEMP)
pc->autocast_clear(sd); // AUTOCAST_TEMP should have been unset straight after usage.
- else if (sd->autocast.skill_id == 0 || skill_id == 0 || sd->autocast.skill_id != skill_id)
- pc->autocast_clear(sd); // Implausible skill ID.
- else if (sd->autocast.skill_lv == 0 || (!use_skill_map && (skill_lv == 0 || sd->autocast.skill_lv != skill_lv)))
- pc->autocast_clear(sd); // Implausible skill level.
+ else if (auto_cast->skill_id == 0 || skill_id == 0 || auto_cast->skill_id != skill_id)
+ pc->autocast_remove(sd, auto_cast->type, auto_cast->skill_id, auto_cast->skill_lv); // Implausible skill ID.
+ else if (auto_cast->skill_lv == 0 || (!use_skill_map && (skill_lv == 0 || auto_cast->skill_lv != skill_lv)))
+ pc->autocast_remove(sd, auto_cast->type, auto_cast->skill_id, auto_cast->skill_lv); // Implausible skill level.
}
static struct s_skill_unit_layout *skill_get_unit_layout(uint16 skill_id, uint16 skill_lv, struct block_list *src, int x, int y)
@@ -2109,9 +2111,9 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
temp = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id;
- sd->autocast.type = AUTOCAST_TEMP;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->autocast.type = AUTOCAST_NONE;
+ sd->auto_cast_current.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2162,11 +2164,11 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
else if (temp == PF_SPIDERWEB) //Special case, due to its nature of coding.
type = CAST_GROUND;
- sd->autocast.type = AUTOCAST_TEMP;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,auto_skill_lv,1);
skill->toggle_magicpower(src, temp);
skill->castend_type(type, src, tbl, temp, auto_skill_lv, tick, 0);
- sd->autocast.type = AUTOCAST_NONE;
+ sd->auto_cast_current.type = AUTOCAST_NONE;
//Set canact delay. [Skotlex]
ud = unit->bl2ud(src);
@@ -2237,7 +2239,7 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
return 0;
// Preserve auto-cast type if bAutoSpellOnSkill was triggered by a skill which was cast by Abracadabra, Improvised Song or an item.
- enum autocast_type ac_type = sd->autocast.type;
+ enum autocast_type ac_type = sd->auto_cast_current.type;
for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ ) {
if( sd->autospell3[i].flag != skill_id )
@@ -2248,9 +2250,9 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
temp = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id;
- sd->autocast.type = AUTOCAST_TEMP;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->autocast.type = AUTOCAST_NONE;
+ sd->auto_cast_current.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2297,14 +2299,14 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
continue;
sd->autospell3[i].lock = true;
- sd->autocast.type = AUTOCAST_TEMP;
+ sd->auto_cast_current.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,skill_lv,1);
skill->castend_type(type, &sd->bl, tbl, temp, skill_lv, tick, 0);
- sd->autocast.type = AUTOCAST_NONE;
+ sd->auto_cast_current.type = AUTOCAST_NONE;
sd->autospell3[i].lock = false;
}
- sd->autocast.type = ac_type;
+ sd->auto_cast_current.type = ac_type;
if (sd->autobonus3[0].rate) {
for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) {
@@ -2453,7 +2455,7 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
int i, auto_skill_id, auto_skill_lv, type, notok;
// Preserve auto-cast type if bAutoSpellWhenHit was triggered during cast of a skill which was cast by Abracadabra, Improvised Song or an item.
- enum autocast_type ac_type = dstsd->autocast.type;
+ enum autocast_type ac_type = dstsd->auto_cast_current.type;
for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) {
@@ -2470,9 +2472,9 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
if (attack_type&BF_LONG)
rate>>=1;
- dstsd->autocast.type = AUTOCAST_TEMP;
+ dstsd->auto_cast_current.type = AUTOCAST_TEMP;
notok = skill->not_ok(auto_skill_id, dstsd);
- dstsd->autocast.type = AUTOCAST_NONE;
+ dstsd->auto_cast_current.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2513,10 +2515,10 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
if( !battle->check_range(src, tbl, skill->get_range2(src, auto_skill_id,auto_skill_lv) + (auto_skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
continue;
- dstsd->autocast.type = AUTOCAST_TEMP;
+ dstsd->auto_cast_current.type = AUTOCAST_TEMP;
skill->consume_requirement(dstsd,auto_skill_id,auto_skill_lv,1);
skill->castend_type(type, bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
- dstsd->autocast.type = AUTOCAST_NONE;
+ dstsd->auto_cast_current.type = AUTOCAST_NONE;
// Set canact delay. [Skotlex]
ud = unit->bl2ud(bl);
@@ -2530,7 +2532,7 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
}
}
- dstsd->autocast.type = ac_type;
+ dstsd->auto_cast_current.type = ac_type;
}
//Autobonus when attacked
@@ -5843,7 +5845,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH)
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.skill_id != ud->skill_id || skill->get_delay(ud->skill_id, ud->skill_lv) != 0)
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); // Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish]
if (sd) { // Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
@@ -5911,8 +5913,10 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
skill->blockpc_start(sd,BD_ADAPTATION,3000);
}
- if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish]
- pc->autocast_clear(sd);
+ if (sd != NULL && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL
+ && ud->skill_id == sd->auto_cast_current.skill_id) { // they just set the data so leave it as it is.[Inkfish]
+ pc->autocast_remove(sd, sd->auto_cast_current.type, ud->skill_id, ud->skill_lv);
+ }
if (ud->skilltimer == INVALID_TIMER) {
if(md) md->skill_idx = -1;
@@ -5961,16 +5965,20 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
}
}
- if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.skill_id != ud->skill_id || skill->get_delay(ud->skill_id, ud->skill_lv) != 0)
ud->canact_tick = tick;
- ud->skill_id = ud->skill_lv = ud->skilltarget = 0;
//You can't place a skill failed packet here because it would be
//sent in ALL cases, even cases where skill_check_condition fails
//which would lead to double 'skill failed' messages u.u [Skotlex]
- if(sd)
- pc->autocast_clear(sd);
+ if (sd != NULL && ud->skill_id == sd->auto_cast_current.skill_id)
+ pc->autocast_remove(sd, sd->auto_cast_current.type, ud->skill_id, ud->skill_lv);
else if(md)
md->skill_idx = -1;
+
+ ud->skill_id = 0;
+ ud->skill_lv = 0;
+ ud->skilltarget = 0;
+
return 0;
}
@@ -6350,9 +6358,12 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if (sd) {
// player-casted
- sd->autocast.type = AUTOCAST_ABRA;
- sd->autocast.skill_id = abra_skill_id;
- sd->autocast.skill_lv = abra_skill_lv;
+ pc->autocast_clear(sd);
+ sd->auto_cast_current.type = AUTOCAST_ABRA;
+ sd->auto_cast_current.skill_id = abra_skill_id;
+ sd->auto_cast_current.skill_lv = abra_skill_lv;
+ VECTOR_ENSURE(sd->auto_cast, 1, 1);
+ VECTOR_PUSH(sd->auto_cast, sd->auto_cast_current);
clif->item_skill(sd, abra_skill_id, abra_skill_lv);
} else {
// mob-casted
@@ -7481,7 +7492,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
map->freeblock_unlock();
return 1;
}
- if (sd->autocast.type == AUTOCAST_NONE)
+ if (sd->auto_cast_current.type == AUTOCAST_NONE)
status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded
}
break;
@@ -7518,7 +7529,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
break;
}
- if (sd->autocast.type == AUTOCAST_TEMP || ((sd->autocast.skill_id == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1) || skill_lv == 3)
+ if (sd->auto_cast_current.type == AUTOCAST_TEMP || ((sd->auto_cast_current.skill_id == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1) || skill_lv == 3)
{
if( skill_lv == 1 )
pc->randomwarp(sd,CLR_TELEPORT);
@@ -10092,9 +10103,12 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
if (sd != NULL) {
- sd->autocast.type = AUTOCAST_IMPROVISE;
- sd->autocast.skill_id = improv_skill_id;
- sd->autocast.skill_lv = improv_skill_lv;
+ pc->autocast_clear(sd);
+ sd->auto_cast_current.type = AUTOCAST_IMPROVISE;
+ sd->auto_cast_current.skill_id = improv_skill_id;
+ sd->auto_cast_current.skill_lv = improv_skill_lv;
+ VECTOR_ENSURE(sd->auto_cast, 1, 1);
+ VECTOR_PUSH(sd->auto_cast, sd->auto_cast_current);
clif->item_skill(sd, improv_skill_id, improv_skill_lv);
} else {
struct unit_data *ud = unit->bl2ud(src);
@@ -10863,7 +10877,7 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
if (ud->walktimer != INVALID_TIMER)
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.skill_id != ud->skill_id || skill->get_delay(ud->skill_id, ud->skill_lv) != 0)
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv);
if (sd) { //Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
@@ -10892,8 +10906,8 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
map->freeblock_lock();
skill->castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0);
- if (sd != NULL && sd->autocast.skill_id != AL_WARP) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
- pc->autocast_clear(sd);
+ if (sd != NULL && ud->skill_id != AL_WARP && ud->skill_id == sd->auto_cast_current.skill_id) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
+ pc->autocast_remove(sd, sd->auto_cast_current.type, ud->skill_id, ud->skill_lv);
unit->set_dir(src, map->calc_dir(src, ud->skillx, ud->skilly));
@@ -10907,13 +10921,17 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
return 1;
} while(0);
- if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.skill_id != ud->skill_id || skill->get_delay(ud->skill_id, ud->skill_lv) != 0)
ud->canact_tick = tick;
- ud->skill_id = ud->skill_lv = 0;
- if(sd)
- pc->autocast_clear(sd);
+
+ if (sd != NULL && ud->skill_id == sd->auto_cast_current.skill_id)
+ pc->autocast_remove(sd, sd->auto_cast_current.type, ud->skill_id, ud->skill_lv);
else if(md)
md->skill_idx = -1;
+
+ ud->skill_id = 0;
+ ud->skill_lv = 0;
+
return 0;
}
@@ -11072,7 +11090,7 @@ static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const
}
}
- lv = (sd->autocast.type > AUTOCAST_TEMP) ? sd->autocast.skill_lv : pc->checkskill(sd, skill_id);
+ lv = (sd->auto_cast_current.type > AUTOCAST_TEMP) ? sd->auto_cast_current.skill_lv : pc->checkskill(sd, skill_id);
wx = sd->menuskill_val>>16;
wy = sd->menuskill_val&0xffff;
@@ -11095,7 +11113,10 @@ static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const
}
skill->consume_requirement(sd,sd->menuskill_id,lv,2);
- pc->autocast_clear(sd); // Clear data which was skipped in skill_castend_pos().
+
+ // Clear data which was skipped in skill_castend_pos().
+ pc->autocast_remove(sd, sd->auto_cast_current.type, sd->auto_cast_current.skill_id,
+ sd->auto_cast_current.skill_lv);
if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) {
skill_failed(sd);
@@ -14108,12 +14129,12 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s
if (sd->chat_id != 0)
return 0;
- if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
- && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ if (((sd->auto_cast_current.itemskill_conditions_checked || !sd->auto_cast_current.itemskill_check_conditions)
+ && sd->auto_cast_current.type == AUTOCAST_ITEM) || sd->auto_cast_current.type == AUTOCAST_IMPROVISE) {
return 1;
}
- if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->auto_cast_current.type != AUTOCAST_ITEM) {
// GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
@@ -14145,7 +14166,7 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s
if( !sc->count )
sc = NULL;
- if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
+ if (pc_is90overweight(sd) && sd->auto_cast_current.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -15016,7 +15037,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 && sd->autocast.type == AUTOCAST_NONE) { // Auto-cast skills don't consume SP.
+ if (require.sp > 0 && st->sp < (unsigned int)require.sp && sd->auto_cast_current.type == AUTOCAST_NONE) { // Auto-cast skills don't consume SP.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0);
return 0;
}
@@ -15074,12 +15095,12 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski
if (sd->chat_id != 0)
return 0;
- if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
- && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ if (((sd->auto_cast_current.itemskill_conditions_checked || !sd->auto_cast_current.itemskill_check_conditions)
+ && sd->auto_cast_current.type == AUTOCAST_ITEM) || sd->auto_cast_current.type == AUTOCAST_IMPROVISE) {
return 1;
}
- if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->auto_cast_current.type != AUTOCAST_ITEM) {
// GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
@@ -15107,7 +15128,7 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski
break;
}
- if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
+ if (pc_is90overweight(sd) && sd->auto_cast_current.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -15278,8 +15299,8 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i
nullpo_ret(sd);
- if ((!sd->autocast.itemskill_check_conditions && sd->autocast.type == AUTOCAST_ITEM)
- || sd->autocast.type == AUTOCAST_IMPROVISE) {
+ if ((!sd->auto_cast_current.itemskill_check_conditions && sd->auto_cast_current.type == AUTOCAST_ITEM)
+ || sd->auto_cast_current.type == AUTOCAST_IMPROVISE) {
return 1;
}
@@ -15297,7 +15318,7 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i
break;
default:
- if (sd->autocast.type != AUTOCAST_NONE) // Auto-cast skills don't consume SP.
+ if (sd->auto_cast_current.type != AUTOCAST_NONE) // Auto-cast skills don't consume SP.
req.sp = 0;
break;
diff --git a/src/map/status.c b/src/map/status.c
index b0cb07d11..a6e6b24c0 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1596,7 +1596,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
}
if( skill_id ) {
- if (src != NULL && (sd == NULL || sd->autocast.type != AUTOCAST_ITEM)) {
+ if (src != NULL && (sd == NULL || sd->auto_cast_current.type != AUTOCAST_ITEM)) {
// Items that cast skills using 'itemskill' will not be handled by map_zone_db.
int i;
@@ -1640,7 +1640,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
if (src != NULL
&& map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR)
&& !(st->mode&MD_BOSS)
- && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM))
+ && (src->type != BL_PC || sd->auto_cast_current.type != AUTOCAST_ITEM))
return 0;
break;
default:
@@ -1719,7 +1719,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
}
- if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM)) {
+ if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->auto_cast_current.type != AUTOCAST_ITEM)) {
//Skills blocked through status changes...
if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
sc->data[SC_SILENCE] ||
@@ -1737,6 +1737,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
(sc->data[SC_MARIONETTE] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another
(sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) ||
(sc->data[SC_KG_KAGEHUMI] && skill->block_check(src, SC_KG_KAGEHUMI, skill_id))
+ || sc->data[SC_ALL_RIDING] != NULL // New mounts can't attack nor use skills in the client; this check makes it cheat-safe. [Ind]
))
return 0;
@@ -1785,8 +1786,6 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
} else if ( skill_id != ST_CHASEWALK )
return 0;
}
- if( sc->data[SC_ALL_RIDING] )
- return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind]
}
if (target == NULL || target == src) //No further checking needed.
diff --git a/src/map/unit.c b/src/map/unit.c
index 19f09f83c..53e517045 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1156,10 +1156,9 @@ static int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_
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 && ret == 0)
- pc->autocast_clear(sd); // Error in unit_skilluse_id2().
- else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
- skill->validate_autocast_data(sd, skill_id, skill_lv);
+ if (sd != NULL)
+ pc->autocast_remove(sd, sd->auto_cast_current.type, sd->auto_cast_current.skill_id,
+ sd->auto_cast_current.skill_lv);
return ret;
}
@@ -1718,7 +1717,7 @@ 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->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
+ if (sd != NULL && sd->auto_cast_current.itemskill_instant_cast && sd->auto_cast_current.type == AUTOCAST_ITEM)
casttime = 0;
// in official this is triggered even if no cast time.
@@ -1756,7 +1755,7 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill
if( casttime <= 0 )
ud->state.skillcastcancel = 0;
- if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
if( sd )
{
@@ -1795,10 +1794,9 @@ static int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_
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 && ret == 0)
- pc->autocast_clear(sd); // Error in unit_skilluse_pos2().
- else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
- skill->validate_autocast_data(sd, skill_id, skill_lv);
+ if (sd != NULL)
+ pc->autocast_remove(sd, sd->auto_cast_current.type, sd->auto_cast_current.skill_id,
+ sd->auto_cast_current.skill_lv);
return ret;
}
@@ -1895,7 +1893,7 @@ static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill
}
ud->state.skillcastcancel = castcancel&&casttime>0?1:0;
- if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
+ if (sd == NULL || sd->auto_cast_current.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
#if 0
if (sd) {
@@ -1926,7 +1924,7 @@ 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->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
+ if (sd != NULL && sd->auto_cast_current.itemskill_instant_cast && sd->auto_cast_current.type == AUTOCAST_ITEM)
casttime = 0;
// in official this is triggered even if no cast time.
@@ -2889,6 +2887,8 @@ static int unit_free(struct block_list *bl, enum clr_type clrtype)
aFree(sd->instance);
sd->instance = NULL;
}
+
+ VECTOR_CLEAR(sd->auto_cast); // Clear auto-cast vector.
VECTOR_CLEAR(sd->channels);
VECTOR_CLEAR(sd->script_queues);
VECTOR_CLEAR(sd->achievement); // Achievement [Smokexyz/Hercules]
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index 363727d46..107d0cc33 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -6216,8 +6216,8 @@ typedef int (*HPMHOOK_pre_pc_checkitem) (struct map_session_data **sd);
typedef int (*HPMHOOK_post_pc_checkitem) (int retVal___, struct map_session_data *sd);
typedef int (*HPMHOOK_pre_pc_useitem) (struct map_session_data **sd, int *n);
typedef int (*HPMHOOK_post_pc_useitem) (int retVal___, struct map_session_data *sd, int n);
-typedef int (*HPMHOOK_pre_pc_autocast_clear) (struct map_session_data **sd);
-typedef int (*HPMHOOK_post_pc_autocast_clear) (int retVal___, struct map_session_data *sd);
+typedef void (*HPMHOOK_pre_pc_autocast_clear) (struct map_session_data **sd);
+typedef void (*HPMHOOK_post_pc_autocast_clear) (struct map_session_data *sd);
typedef int (*HPMHOOK_pre_pc_skillatk_bonus) (struct map_session_data **sd, uint16 *skill_id);
typedef int (*HPMHOOK_post_pc_skillatk_bonus) (int retVal___, struct map_session_data *sd, uint16 skill_id);
typedef int (*HPMHOOK_pre_pc_skillheal_bonus) (struct map_session_data **sd, uint16 *skill_id);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index c1ee157af..97997f7b8 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -63781,32 +63781,31 @@ int HP_pc_useitem(struct map_session_data *sd, int n) {
}
return retVal___;
}
-int HP_pc_autocast_clear(struct map_session_data *sd) {
+void HP_pc_autocast_clear(struct map_session_data *sd) {
int hIndex = 0;
- int retVal___ = 0;
if (HPMHooks.count.HP_pc_autocast_clear_pre > 0) {
- int (*preHookFunc) (struct map_session_data **sd);
+ void (*preHookFunc) (struct map_session_data **sd);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_autocast_clear_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_pc_autocast_clear_pre[hIndex].func;
- retVal___ = preHookFunc(&sd);
+ preHookFunc(&sd);
}
if (*HPMforce_return) {
*HPMforce_return = false;
- return retVal___;
+ return;
}
}
{
- retVal___ = HPMHooks.source.pc.autocast_clear(sd);
+ HPMHooks.source.pc.autocast_clear(sd);
}
if (HPMHooks.count.HP_pc_autocast_clear_post > 0) {
- int (*postHookFunc) (int retVal___, struct map_session_data *sd);
+ void (*postHookFunc) (struct map_session_data *sd);
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_autocast_clear_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_pc_autocast_clear_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, sd);
+ postHookFunc(sd);
}
}
- return retVal___;
+ return;
}
int HP_pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id) {
int hIndex = 0;