Skip to content

Commit

Permalink
Merge pull request #2657 from Kenpachi2k13/autocast_clean_up
Browse files Browse the repository at this point in the history
Clean up auto-cast related code
  • Loading branch information
MishimaHaruna authored Apr 5, 2020
2 parents 02a84aa + 876cfa6 commit 024c9c4
Show file tree
Hide file tree
Showing 14 changed files with 221 additions and 226 deletions.
2 changes: 2 additions & 0 deletions src/map/atcommand.c
Original file line number Diff line number Diff line change
Expand Up @@ -5671,6 +5671,8 @@ ACMD(useskill)
return false;
}

pc->autocast_clear(sd);

if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL
&& sd->hd && homun_alive(sd->hd)) // (If used with @useskill, put the homunc as dest)
bl = &sd->hd->bl;
Expand Down
20 changes: 10 additions & 10 deletions src/map/battle.c
Original file line number Diff line number Diff line change
Expand Up @@ -5928,21 +5928,21 @@ static void battle_reflect_damage(struct block_list *target, struct block_list *
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
if( sc->data[SC_LG_REFLECTDAMAGE] && rnd()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) {
bool change = false;

NORMALIZE_RDAMAGE(damage * sc->data[SC_LG_REFLECTDAMAGE]->val2 / 100);

trdamage -= rdamage;/* wont count towards total */

if( sd && !sd->state.autocast ) {
change = true;
sd->state.autocast = 1;
enum autocast_type ac_type;

if (sd != NULL) {
ac_type = sd->autocast.type;
sd->autocast.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( change )
sd->state.autocast = 0;
if (sd != NULL)
sd->autocast.type = ac_type;

delay += 150;/* gradual increase so the numbers don't clip in the client */

Expand Down Expand Up @@ -6132,7 +6132,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)->state.autocast)
if (src->type != BL_PC || BL_UCCAST(BL_PC, src)->autocast.type != AUTOCAST_TEMP)
skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
map->freeblock_unlock();
}
Expand Down Expand Up @@ -6456,10 +6456,10 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_
}
}

sd->state.autocast = 1;
sd->autocast.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->state.autocast = 0;
sd->autocast.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);
}
Expand Down
48 changes: 36 additions & 12 deletions src/map/clif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->state.itemskill_castonself == 1 && skill->is_item_skill(sd, skill_id, skill_lv))
if (sd->autocast.itemskill_cast_on_self && sd->autocast.type == AUTOCAST_ITEM)
type = INF_SELF_SKILL;

p->packetType = HEADER_ZC_AUTORUN_SKILL;
Expand Down Expand Up @@ -12707,6 +12707,14 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
{
int64 tick = timer->gettick();

/**
* 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);

if (skill_lv < 1)
skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]

Expand Down Expand Up @@ -12760,7 +12768,7 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST)
return;
} else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
if (sd->skillitem != skill_id) {
if (sd->autocast.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
Expand All @@ -12778,16 +12786,16 @@ 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->skillitem == skill_id) {
if (skill_lv != sd->skillitemlv)
skill_lv = sd->skillitemlv;
if (sd->autocast.type != AUTOCAST_NONE) {
if (skill_lv != sd->autocast.skill_lv)
skill_lv = sd->autocast.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);
return;
}

sd->skillitem = sd->skillitemlv = 0;
pc->autocast_clear(sd);

if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) {
if (sd->state.gmaster_flag)
Expand Down Expand Up @@ -12848,6 +12856,16 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
int64 tick = timer->gettick();

nullpo_retv(sd);

/**
* When using clif_item_skill() to initiate the execution of ground skills,
* the client sometimes passes 0 for the skill level in packet 0x0af4.
* In that case sd->autocast.skill_lv is used for the auto-cast data validation,
* 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);

if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) )
return; //Using a target skill on the ground? WRONG.

Expand Down Expand Up @@ -12888,7 +12906,7 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
return;

if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
if( sd->skillitem != skill_id ) {
if (sd->autocast.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
Expand All @@ -12909,13 +12927,13 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin

pc->delinvincibletimer(sd);

if( sd->skillitem == skill_id ) {
if( skill_lv != sd->skillitemlv )
skill_lv = sd->skillitemlv;
if (sd->autocast.type != AUTOCAST_NONE) {
if (skill_lv != sd->autocast.skill_lv)
skill_lv = sd->autocast.skill_lv;
unit->skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
} else {
int lv;
sd->skillitem = sd->skillitemlv = 0;
pc->autocast_clear(sd);
if( (lv = pc->checkskill(sd, skill_id)) > 0 ) {
if( skill_lv > lv )
skill_lv = lv;
Expand Down Expand Up @@ -12986,9 +13004,15 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd)
return;
}

/**
* Since no skill level was passed use 0 to notify skill_validate_autocast_data() of this special case.
*
**/
skill->validate_autocast_data(sd, skill_id, 0);

pc->delinvincibletimer(sd);
skill->castend_map(sd,skill_id,map_name);
pc->itemskill_clear(sd);
pc->autocast_clear(sd);
}

static void clif_parse_RequestMemo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
Expand Down
29 changes: 13 additions & 16 deletions src/map/pc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5295,10 +5295,6 @@ static int pc_useitem(struct map_session_data *sd, int n)
if(sd->catch_target_class != -1) //Abort pet catching.
sd->catch_target_class = -1;

// Removes abracadabra/randomize spell flag for delayed consume items or item doesn't get consumed
if (sd->inventory_data[n]->flag.delay_consume)
sd->state.abra_flag = 0;

amount = sd->status.inventory[n].amount;
//Check if the item is to be consumed immediately [Skotlex]
if (sd->inventory_data[n]->flag.delay_consume || sd->inventory_data[n]->flag.keepafteruse)
Expand Down Expand Up @@ -5337,21 +5333,22 @@ static int pc_useitem(struct map_session_data *sd, int n)
}

/**
* Sets state flags and helper variables, used by itemskill() script command, to 0.
* 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_itemskill_clear(struct map_session_data *sd)
static int pc_autocast_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_check_conditions = 0;
sd->state.itemskill_no_casttime = 0;
sd->state.itemskill_castonself = 0;
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;

return 1;
}
Expand Down Expand Up @@ -8122,9 +8119,9 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)

clif->party_dead_notification(sd);

//Reset menu skills/item skills
if (sd->skillitem)
sd->skillitem = sd->skillitemlv = 0;
pc->autocast_clear(sd); // Unset auto-cast data.

// Reset menu skills.
if (sd->menuskill_id)
sd->menuskill_id = sd->menuskill_val = 0;
//Reset ticks.
Expand Down Expand Up @@ -12730,7 +12727,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->autocast_clear = pc_autocast_clear;

pc->skillatk_bonus = pc_skillatk_bonus;
pc->skillheal_bonus = pc_skillheal_bonus;
Expand Down
30 changes: 13 additions & 17 deletions src/map/pc.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ struct pc_combos {
int id; /* this combo id */
};

/** Auto-cast related data. **/
struct autocast_data {
enum autocast_type type; // The auto-cast type.
int skill_id; // The auto-cast skill ID.
int skill_lv; // The auto-cast skill level.
bool itemskill_conditions_checked; // Used by itemskill() script command, to prevent second check of conditions after target was selected.
bool itemskill_check_conditions; // Used by itemskill() script command, to check skill conditions and consume them.
bool itemskill_instant_cast; // Used by itemskill() script command, to cast skill instantaneously.
bool itemskill_cast_on_self; // Used by itemskill() script command, to forcefully cast skill on invoking character.
};

struct map_session_data {
struct block_list bl;
struct unit_data ud;
Expand All @@ -181,6 +192,7 @@ struct map_session_data {
struct status_change sc;
struct regen_data regen;
struct regen_data_sub sregen, ssregen;
struct autocast_data autocast;
//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 {
Expand All @@ -194,8 +206,6 @@ struct map_session_data {
unsigned int rest : 1;
unsigned int storage_flag : 2; // @see enum storage_flag
unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
unsigned int autocast : 1; // Autospell flag [Inkfish]
unsigned int autotrade : 2; //By Fantik
unsigned int showdelay :1;
unsigned int showexp :1;
Expand Down Expand Up @@ -240,10 +250,6 @@ 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_check_conditions : 1; // Used by itemskill() script command, to check skill conditions and 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;
Expand Down Expand Up @@ -298,7 +304,6 @@ struct map_session_data {
int followtimer; // [MouseJstr]
int followtarget;
time_t emotionlasttime; // to limit flood with emotion packets
int skillitem,skillitemlv;
uint16 skill_id_old,skill_lv_old;
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
Expand Down Expand Up @@ -647,15 +652,6 @@ 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
Expand Down Expand Up @@ -1034,7 +1030,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 (*autocast_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);
Expand Down
36 changes: 19 additions & 17 deletions src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -11001,33 +11001,29 @@ static BUILDIN(itemskill)
if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER)
return true;

pc->itemskill_clear(sd);
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.
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);

int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE;

sd->state.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS) ? 1 : 0; // Unset in pc_itemskill_clear().
sd->autocast.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS);

if (sd->state.itemskill_check_conditions == 1) {
if (skill->check_condition_castbegin(sd, sd->skillitem, sd->skillitemlv) == 0
|| skill->check_condition_castend(sd, sd->skillitem, sd->skillitemlv) == 0) {
pc->itemskill_clear(sd);
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);
return true;
}

sd->state.itemskill_conditions_checked = 1; // Unset in pc_itemskill_clear().
sd->autocast.itemskill_conditions_checked = true;
}

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().
sd->autocast.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST);
sd->autocast.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF);

// 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);
clif->item_skill(sd, sd->autocast.skill_id, sd->autocast.skill_lv);

return true;
}
Expand Down Expand Up @@ -21429,7 +21425,10 @@ static BUILDIN(unitskilluseid)
} else {
status_calc_npc(nd, SCO_NONE);
}
} else if (bl->type == BL_PC) {
pc->autocast_clear(BL_UCAST(BL_PC, bl));
}

unit->skilluse_id(bl, target_id, skill_id, skill_lv);
}

Expand Down Expand Up @@ -21465,7 +21464,10 @@ static BUILDIN(unitskillusepos)
} else {
status_calc_npc(nd, SCO_NONE);
}
} else if (bl->type == BL_PC) {
pc->autocast_clear(BL_UCAST(BL_PC, bl));
}

unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
}

Expand Down
Loading

0 comments on commit 024c9c4

Please sign in to comment.