Skip to content

Commit

Permalink
Minor SC_STONEWAIT fixes (#6892)
Browse files Browse the repository at this point in the history
* The SC_STONEWAIT status should not be applicable to the Undead element.
* Fixes the overall duration for SC_STONEWAIT and SC_STONE because of incorrect order of resistance application.
* Adds the delay parameter to sc_start functions since some statuses, if not most, have a delay of some sort before being applied to a target.
* Swaps the duration values for Stone Curse related skills.
Thanks to @Playtester!
  • Loading branch information
aleos89 committed Apr 27, 2022
1 parent ef6a682 commit 3b9c28a
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 107 deletions.
15 changes: 8 additions & 7 deletions db/pre-re/skill_db.yml
Expand Up @@ -796,8 +796,8 @@ Body:
Element: Earth
CastCancel: true
CastTime: 1000
Duration1: 20000
Duration2: 5000
Duration1: 5000
Duration2: 20000
Requires:
SpCost:
- Level: 1
Expand Down Expand Up @@ -5663,8 +5663,8 @@ Body:
Hit: Single
HitCount: 1
Element: Weapon
Duration1: 20000
Duration2: 100
Duration1: 100
Duration2: 20000
Status: StoneWait
- Id: 181
Name: NPC_CURSEATTACK
Expand Down Expand Up @@ -15911,8 +15911,8 @@ Body:
Area: 11
- Level: 5
Area: 14
Duration1: 20000
Duration2: 100
Duration1: 100
Duration2: 20000
Status: StoneWait
- Id: 667
Name: NPC_WIDECONFUSE
Expand Down Expand Up @@ -29647,7 +29647,8 @@ Body:
HitCount: 1
CastCancel: true
AfterCastActDelay: 1000
Duration1: 10000
Duration1: 100
Duration2: 10000
Requires:
SpCost: 30
Unit:
Expand Down
20 changes: 10 additions & 10 deletions db/re/skill_db.yml
Expand Up @@ -780,8 +780,8 @@ Body:
Element: Earth
CastCancel: true
CastTime: 800
Duration1: 17000
Duration2: 5000
Duration1: 5000
Duration2: 17000
FixedCastTime: 200
Requires:
SpCost:
Expand Down Expand Up @@ -5933,8 +5933,8 @@ Body:
Hit: Single
HitCount: 1
Element: Weapon
Duration1: 17000
Duration2: 100
Duration1: 100
Duration2: 17000
Status: StoneWait
- Id: 181
Name: NPC_CURSEATTACK
Expand Down Expand Up @@ -16310,8 +16310,8 @@ Body:
Area: 11
- Level: 5
Area: 14
Duration1: 17000
Duration2: 100
Duration1: 100
Duration2: 17000
Status: StoneWait
- Id: 667
Name: NPC_WIDECONFUSE
Expand Down Expand Up @@ -19231,7 +19231,8 @@ Body:
CastCancel: true
CastTime: 2000
AfterCastActDelay: 2000
Duration1:
Duration1: 100
Duration2:
- Level: 1
Time: 7000
- Level: 2
Expand All @@ -19242,7 +19243,6 @@ Body:
Time: 13000
- Level: 5
Time: 15000
Duration2: 100
Requires:
SpCost:
- Level: 1
Expand Down Expand Up @@ -32011,8 +32011,8 @@ Body:
HitCount: 1
CastCancel: true
AfterCastActDelay: 1000
Duration1: 10000
Duration2: 5000
Duration1: 100
Duration2: 10000
Requires:
SpCost: 30
Unit:
Expand Down
101 changes: 22 additions & 79 deletions src/map/skill.cpp
Expand Up @@ -1272,9 +1272,6 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
#endif
) {
// Trigger status effects
enum sc_type type;
unsigned int time;

for (const auto &it : sd->addeff) {
rate = it.rate;
if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG]
Expand All @@ -1299,58 +1296,24 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
continue; //Range Failed.
}

type = it.sc;
time = it.duration;

int32 val1 = 7, val2, val3;

if (type == SC_STONEWAIT) {
val2 = src->id;
val3 = skill_get_time(status_db.getSkill(type), 7);
} else {
val2 = 0;
if (type == SC_BURNING)
val3 = src->id;
else
val3 = 0;
}

if (it.flag&ATF_TARGET)
status_change_start(src,bl,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, bl, it.sc, rate, 7, it.duration, 100);

if (it.flag&ATF_SELF)
status_change_start(src,src,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, src, it.sc, rate, 7, it.duration, 100);
}
}

if( skill_id ) {
// Trigger status effects on skills
enum sc_type type;
unsigned int time;

for (const auto &it : sd->addeff_onskill) {
if (skill_id != it.skill_id || !it.rate)
continue;
type = it.sc;
time = it.duration;

int32 val1 = 7, val2, val3;

if (type == SC_STONEWAIT) {
val2 = src->id;
val3 = skill_get_time(status_db.getSkill(type), 7);
} else {
val2 = 0;
if (type == SC_BURNING)
val3 = src->id;
else
val3 = 0;
}

if (it.target&ATF_TARGET)
status_change_start(src,bl,type,it.rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, bl, it.sc, rate, 7, it.duration, 100);
if (it.target&ATF_SELF)
status_change_start(src,src,type,it.rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, src, it.sc, rate, 7, it.duration, 100);
}
//"While the damage can be blocked by Pneuma, the chance to break armor remains", irowiki. [Cydh]
if (dmg_lv == ATK_BLOCK && skill_id == AM_ACIDTERROR) {
Expand Down Expand Up @@ -1648,7 +1611,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;

case NPC_PETRIFYATTACK:
sc_start4(src,bl,SC_STONEWAIT,(20*skill_lv),skill_lv,src->id,skill_get_time(skill_id,skill_lv),0,skill_get_time2(skill_id,skill_lv));
sc_start2(src,bl,SC_STONEWAIT,(20*skill_lv),skill_lv,src->id,skill_get_time2(skill_id,skill_lv),skill_get_time(skill_id, skill_lv));
break;
case NPC_CURSEATTACK:
sc_start(src,bl,SC_CURSE,(20*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv));
Expand Down Expand Up @@ -2527,9 +2490,6 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
dstsd = BL_CAST(BL_PC, bl);

if(dstsd && attack_type&BF_WEAPON) { //Counter effects.
enum sc_type type;
unsigned int time;

for (const auto &it : dstsd->addeff_atked) {
rate = it.rate;
if (attack_type&BF_LONG)
Expand All @@ -2542,27 +2502,12 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
(it.flag&ATF_SHORT && !(attack_type&BF_SHORT)))
continue; //Range Failed.
}
type = it.sc;
time = it.duration;

int32 val1 = 7, val2, val3;

if (type == SC_STONEWAIT) {
val2 = src->id;
val3 = skill_get_time(status_db.getSkill(type), 7);
} else {
val2 = 0;
if (type == SC_BURNING)
val3 = src->id;
else
val3 = 0;
}

if (it.flag&ATF_TARGET && src != bl)
status_change_start(src,src,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, src, it.sc, rate, 7, it.duration, 100);

if (it.flag&ATF_SELF && !status_isdead(bl))
status_change_start(src,bl,type,rate,val1,val2,val3,0,time,SCSTART_NONE);
sc_start(src, bl, it.sc, rate, 7, it.duration, 100);
}
}

Expand Down Expand Up @@ -4892,7 +4837,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
int time = ((rand_eff == 0) ? skill_get_time2(skill_id, skill_lv) : skill_get_time2(status_db.getSkill(sc[rand_eff]), 1));

if (sc[rand_eff] == SC_STONEWAIT)
sc_start4(src, target, SC_STONEWAIT, 100, skill_lv, src->id, skill_get_time(status_db.getSkill(SC_STONEWAIT), 1), 0, time);
sc_start2(src, target, SC_STONEWAIT, 100, skill_lv, src->id, time, skill_get_time(status_db.getSkill(SC_STONEWAIT), 1));
else
sc_start(src, target, sc[rand_eff], 100, skill_lv, time);
break;
Expand Down Expand Up @@ -8769,10 +8714,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (sd && sd->sc.data[SC_PETROLOGY_OPTION])
brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3;

if (sc_start4(src,bl,type,(skill_lv*4+20)+brate,
skill_lv, src->id, skill_get_time(skill_id, skill_lv), 0,
skill_get_time2(skill_id,skill_lv)))
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
if (sc_start2(src, bl, type, (skill_lv * 4 + 20) + brate, skill_lv, src->id, skill_get_time2(skill_id, skill_lv), skill_get_time(skill_id, skill_lv)))
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
else if(sd) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
// Level 6-10 doesn't consume a red gem if it fails [celest]
Expand Down Expand Up @@ -10358,7 +10301,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sc_start4(src,bl,type,100,skill_lv,1000,src->id,0,skill_get_time2(skill_id,skill_lv));
break;
case SC_STONEWAIT:
sc_start4(src,bl,type,100,skill_lv,src->id,skill_get_time(skill_id, skill_lv), 0, skill_get_time2(skill_id,skill_lv));
sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv),skill_get_time(skill_id, skill_lv));
break;
default:
sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv));
Expand Down Expand Up @@ -10808,12 +10751,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( bl->id == skill_area_temp[1] )
break; // Already work on this target

status_change_start(src,bl,type,10000,skill_lv,src->id,skill_get_time(skill_id, skill_lv),0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF);
status_change_start(src,bl,type,10000,skill_lv,src->id,0,0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF, skill_get_time(skill_id, skill_lv));
} else {
int rate = 45 + 5 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4;
// IroWiki says Rate should be reduced by target stats, but currently unknown
if( rnd()%100 < rate ) { // Success on First Target
if( status_change_start(src,bl,type,10000,skill_lv,src->id,skill_get_time(skill_id, skill_lv),0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF) ) {
if( status_change_start(src,bl,type,10000,skill_lv,src->id,0,0,skill_get_time2(skill_id,skill_lv), SCSTART_NOTICKDEF, skill_get_time(skill_id, skill_lv)) ) {
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
skill_area_temp[1] = bl->id;
map_foreachinallrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
Expand Down Expand Up @@ -15912,42 +15855,42 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
case UNT_ZENKAI_WATER:
switch (rnd()%2 + 1) {
case 1:
sc_start(ss, bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start(ss, bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
case 2:
sc_start(ss, bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start(ss, bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
}
break;
case UNT_ZENKAI_LAND:
switch (rnd()%2 + 1) {
case 1:
sc_start4(ss, bl, SC_STONEWAIT, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv), 0, skill_get_time2(sg->skill_id, sg->skill_lv));
sc_start2(ss, bl, SC_STONEWAIT, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv), skill_get_time(sg->skill_id, sg->skill_lv));
break;
case 2:
sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
}
break;
case UNT_ZENKAI_FIRE:
sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 1000, ss->id, 0, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 1000, ss->id, 0, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_ZENKAI_WIND:
switch (rnd()%3 + 1) {
case 1:
sc_start(ss, bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start(ss, bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
case 2:
sc_start(ss, bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start(ss, bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
case 3:
sc_start(ss, bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
sc_start(ss, bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv));
break;
}
break;
}
} else
sc_start2(ss, bl,type,100,sg->val1,sg->val2,skill_get_time(sg->skill_id, sg->skill_lv));
sc_start2(ss, bl,type,100,sg->val1,sg->val2,skill_get_time2(sg->skill_id, sg->skill_lv));
break;

case UNT_POISON_MIST:
Expand Down
15 changes: 9 additions & 6 deletions src/map/status.cpp
Expand Up @@ -8803,7 +8803,7 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
tick_def2 = -2000;
#endif
break;
case SC_STONE:
case SC_STONEWAIT:
#ifndef RENEWAL
sc_def = status->mdef*100;
sc_def2 = status->luk*10 + status_get_lv(bl)*10 - status_get_lv(src)*10;
Expand Down Expand Up @@ -9200,11 +9200,12 @@ void status_display_remove(struct block_list *bl, enum sc_type type) {
* @param type: Status change (SC_*)
* @param rate: Initial percentage rate of affecting bl (0~10000)
* @param val1~4: Depends on type of status change
* @param tick: Initial duration that the status change affects bl
* @param duration: Initial duration that the status change affects bl
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
* @param delay: Delay in milliseconds before the SC is applied
* @return adjusted duration based on flag values
*/
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,t_tick duration,unsigned char flag) {
int status_change_start(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,t_tick duration,unsigned char flag, int32 delay) {
struct map_session_data *sd = NULL;
struct status_change* sc;
struct status_change_entry* sce;
Expand Down Expand Up @@ -9298,6 +9299,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
return 0;
break;
case SC_STONE:
case SC_STONEWAIT:
case SC_FREEZE:
// Undead are immune to Freeze/Stone
if (undead_flag && !(flag&SCSTART_NOAVOID))
Expand Down Expand Up @@ -10126,7 +10128,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;

case SC_STONEWAIT:
val3 -= tick; // Petrify time - Incubation time
val3 = max(1, tick - delay); // Petrify time
tick = delay;
break;

case SC_DPOISON:
Expand Down Expand Up @@ -13025,8 +13028,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
npc_touch_area_allnpc(sd,bl->m,bl->x,bl->y); // Trigger on-touch event.

// Needed to be here to make sure OPT1_STONEWAIT has been cleared from the target
if (type == SC_STONEWAIT && sce->val4 > -1)
sc_start2(bl, bl, SC_STONE, 100, sce->val1, sce->val2, sce->val3);
if (type == SC_STONEWAIT)
status_change_start(bl, bl, SC_STONE, 100, sce->val1, sce->val2, 0, 0, sce->val3, SCSTART_NOAVOID);

ers_free(sc_data_ers, sce);
return 1;
Expand Down

0 comments on commit 3b9c28a

Please sign in to comment.