summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/skill.c17
-rw-r--r--src/map/skill.h32
-rw-r--r--src/map/status.c25
-rw-r--r--src/map/unit.c14
5 files changed, 58 insertions, 32 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 2317801bc..68d2bbc48 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10078,7 +10078,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
if( sd->sc.option&OPTION_COSTUME )
return;
- if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) {
+ if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0 && (skill->get_inf2(sd->ud.skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0) {
if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0);
return;
diff --git a/src/map/skill.c b/src/map/skill.c
index 1527d31b2..a7ed0b8f2 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -4916,12 +4916,11 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK) )
+ if (sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd, SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
}
-
ud->skilltimer = INVALID_TIMER;
}
@@ -9946,7 +9945,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && ( pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK ) )
+ if (sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd, SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
@@ -19204,6 +19203,18 @@ void skill_validate_skillinfo(struct config_setting_t *conf, struct s_skill_db *
} else {
sk->inf2 &= ~INF2_CHORUS_SKILL;
}
+ } else if (strcmpi(type, "FreeCastNormal") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_FREE_CAST_NORMAL;
+ } else {
+ sk->inf2 &= ~INF2_FREE_CAST_NORMAL;
+ }
+ } else if (strcmpi(type, "FreeCastReduced") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_FREE_CAST_REDUCED;
+ } else {
+ sk->inf2 &= ~INF2_FREE_CAST_REDUCED;
+ }
} else if (strcmpi(type, "None") != 0) {
skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 0ad91001d..c37f9ec41 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -103,21 +103,23 @@ enum e_skill_nk {
//A skill with 3 would be no damage + splash: area of effect.
//Constants to identify a skill's inf2 value.
enum e_skill_inf2 {
- INF2_QUEST_SKILL = 0x0001,
- INF2_NPC_SKILL = 0x0002, // NPC skills are those that players can't have in their skill tree.
- INF2_WEDDING_SKILL = 0x0004,
- INF2_SPIRIT_SKILL = 0x0008,
- INF2_GUILD_SKILL = 0x0010,
- INF2_SONG_DANCE = 0x0020,
- INF2_ENSEMBLE_SKILL = 0x0040,
- INF2_TRAP = 0x0080,
- INF2_TARGET_SELF = 0x0100, // Refers to ground placed skills that will target the caster as well (like Grandcross)
- INF2_NO_TARGET_SELF = 0x0200,
- INF2_PARTY_ONLY = 0x0400,
- INF2_GUILD_ONLY = 0x0800,
- INF2_NO_ENEMY = 0x1000,
- INF2_NOLP = 0x2000, // Spells that can ignore Land Protector
- INF2_CHORUS_SKILL = 0x4000, // Chorus skill
+ INF2_QUEST_SKILL = 0x00001,
+ INF2_NPC_SKILL = 0x00002, // NPC skills are those that players can't have in their skill tree.
+ INF2_WEDDING_SKILL = 0x00004,
+ INF2_SPIRIT_SKILL = 0x00008,
+ INF2_GUILD_SKILL = 0x00010,
+ INF2_SONG_DANCE = 0x00020,
+ INF2_ENSEMBLE_SKILL = 0x00040,
+ INF2_TRAP = 0x00080,
+ INF2_TARGET_SELF = 0x00100, // Refers to ground placed skills that will target the caster as well (like Grandcross)
+ INF2_NO_TARGET_SELF = 0x00200,
+ INF2_PARTY_ONLY = 0x00400,
+ INF2_GUILD_ONLY = 0x00800,
+ INF2_NO_ENEMY = 0x01000,
+ INF2_NOLP = 0x02000, // Spells that can ignore Land Protector
+ INF2_CHORUS_SKILL = 0x04000, // Chorus skill
+ INF2_FREE_CAST_NORMAL = 0x08000,
+ INF2_FREE_CAST_REDUCED = 0x10000,
};
diff --git a/src/map/status.c b/src/map/status.c
index 3c3b15312..9a76060c5 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -3886,8 +3886,16 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
#endif
if ( st->aspd_rate != 1000 ) // absolute percentage modifier
amotion = amotion * st->aspd_rate / 1000;
- if ( sd && sd->ud.skilltimer != INVALID_TIMER && pc->checkskill(sd, SA_FREECAST) > 0 )
- amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100;
+ if (sd && sd->ud.skilltimer != INVALID_TIMER) {
+ if (pc->checkskill(sd, SA_FREECAST) > 0) {
+ amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100;
+ } else {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
+ amotion = amotion * 5 * (ud->skill_lv + 10) / 100;
+ }
+ }
+ }
#ifdef RENEWAL_ASPD
amotion += (max(0xc3 - amotion, 2) * (st->aspd_rate2 + status->calc_aspd(bl, sc, 2))) / 100;
amotion = 10 * (200 - amotion) + sd->bonus.aspd_add;
@@ -5497,19 +5505,22 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc,
unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
{
struct map_session_data *sd = BL_CAST(BL_PC, bl);
- int speed_rate;
+ int speed_rate = -1;
if( sc == NULL || ( sd && sd->state.permanent_speed ) )
return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
- if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) )
+ if (sd && sd->ud.skilltimer != INVALID_TIMER)
{
- if( sd->ud.skill_id == LG_EXEEDBREAK )
+ if (sd->ud.skill_id == LG_EXEEDBREAK) {
speed_rate = 160 - 10 * sd->ud.skill_lv;
- else
+ } else if ((skill->get_inf2(sd->ud.skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
+ speed_rate = 175 - 5 * sd->ud.skill_lv;
+ } else if (pc->checkskill(sd, SA_FREECAST) > 0) {
speed_rate = 175 - 5 * pc->checkskill(sd,SA_FREECAST);
+ }
}
- else
+ if (speed_rate == -1)
{
speed_rate = 100;
diff --git a/src/map/unit.c b/src/map/unit.c
index 3a3e56dd3..c52683444 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1053,8 +1053,10 @@ int unit_can_move(struct block_list *bl) {
if (!ud)
return 0;
- if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc->checkskill(sd, SA_FREECAST) || skill->get_inf2(ud->skill_id)&INF2_GUILD_SKILL))
+ if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK &&
+ (!sd || (!pc->checkskill(sd, SA_FREECAST) && (skill->get_inf2(ud->skill_id) & (INF2_GUILD_SKILL | INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0))) {
return 0; // prevent moving while casting
+ }
if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0)
return 0;
@@ -1629,7 +1631,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (src->id != target->id) // self-targeted skills shouldn't show different direction
unit->setdir(src, map->calc_dir(src, target->x, target->y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 );
- if( sd && (pc->checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) )
+ if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
} else
skill->castend_id(ud->skilltimer,tick,src->id,0);
@@ -1773,7 +1775,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
if( casttime > 0 ) {
unit->setdir(src, map->calc_dir(src, skill_x, skill_y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 );
- if ( (sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK ) {
+ if ((sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
}
} else {
@@ -2118,10 +2120,10 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
return 0;
}
- if( ud->skilltimer != INVALID_TIMER && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) )
+ if (ud->skilltimer != INVALID_TIMER && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0)))
return 0; // can't attack while casting
- if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) )
+ if (!battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick, tick) > 0 && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0)))
{ // attacking when under cast delay has restrictions:
if( tid == INVALID_TIMER ) { //requested attack.
if(sd) clif->skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0);
@@ -2270,7 +2272,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
ud->skilltimer = INVALID_TIMER;
- if( sd && pc->checkskill(sd,SA_FREECAST) > 0 )
+ if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
if( sd ) {