|
@@ -1469,7 +1469,7 @@ void initChangeTables(void)
|
|
|
StatusChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN;
|
|
|
StatusChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP;
|
|
|
StatusChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN;
|
|
|
- StatusChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE;
|
|
|
+ StatusChangeFlagTable[SC_PYREXIA] |= SCB_ALL;
|
|
|
StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
|
|
|
StatusChangeFlagTable[SC_BANDING_DEFENCE] |= SCB_SPEED;
|
|
|
StatusChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK;
|
|
@@ -1694,7 +1694,7 @@ void initChangeTables(void)
|
|
|
#endif
|
|
|
StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST;
|
|
|
StatusChangeStateTable[SC_DEATHBOUND] |= SCS_NOCAST;
|
|
|
- StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST;
|
|
|
+ StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST|SCS_NOCASTCOND;
|
|
|
StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST;
|
|
|
StatusChangeStateTable[SC__SHADOWFORM] |= SCS_NOCAST;
|
|
|
StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST;
|
|
@@ -3415,7 +3415,7 @@ static int status_get_hpbonus(struct block_list *bl, enum e_status_bonus type) {
|
|
|
bonus += sc->data[SC_LUNARSTANCE]->val2;
|
|
|
|
|
|
//Decreasing
|
|
|
- if(sc->data[SC_VENOMBLEED])
|
|
|
+ if (sc->data[SC_VENOMBLEED] && sc->data[SC_VENOMBLEED]->val3 == 1)
|
|
|
bonus -= 15;
|
|
|
if(sc->data[SC_BEYONDOFWARCRY])
|
|
|
bonus -= sc->data[SC_BEYONDOFWARCRY]->val3;
|
|
@@ -4682,6 +4682,8 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
|
|
|
sd->subele[ELE_GHOST] += sc->data[SC_SYMPHONYOFLOVER]->val1 * 3;
|
|
|
sd->subele[ELE_HOLY] += sc->data[SC_SYMPHONYOFLOVER]->val1 * 3;
|
|
|
}
|
|
|
+ if (sc->data[SC_PYREXIA] && sc->data[SC_PYREXIA]->val3 == 0)
|
|
|
+ sd->bonus.crit_atk_rate += sc->data[SC_PYREXIA]->val2;
|
|
|
}
|
|
|
status_cpy(&sd->battle_status, base_status);
|
|
|
|
|
@@ -5098,7 +5100,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|
|
|
|| sc->data[SC_BERSERK]
|
|
|
|| sc->data[SC_TRICKDEAD]
|
|
|
|| sc->data[SC_BLEEDING]
|
|
|
- || sc->data[SC_MAGICMUSHROOM]
|
|
|
+ || (sc->data[SC_MAGICMUSHROOM] && sc->data[SC_MAGICMUSHROOM]->val3 == 1)
|
|
|
|| sc->data[SC_SATURDAYNIGHTFEVER]
|
|
|
|| sc->data[SC_REBOUND])
|
|
|
regen->flag = RGN_NONE;
|
|
@@ -5115,7 +5117,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|
|
|
(bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
|
|
|
sc->data[SC_EXTREMITYFIST] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)) ||
|
|
|
#endif
|
|
|
- sc->data[SC_OBLIVIONCURSE] || sc->data[SC_VITALITYACTIVATION])
|
|
|
+ (sc->data[SC_OBLIVIONCURSE] && sc->data[SC_OBLIVIONCURSE]->val3 == 1) || sc->data[SC_VITALITYACTIVATION])
|
|
|
regen->flag &= ~RGN_SP;
|
|
|
|
|
|
if (sc->data[SC_TENSIONRELAX]) {
|
|
@@ -5233,6 +5235,8 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, enum sc
|
|
|
if( flag&SCS_NOCAST ) {
|
|
|
if( !(flag&SCS_NOCASTCOND) )
|
|
|
sc->cant.cast += ( start ? 1 : -1 );
|
|
|
+ else if (sc->data[SC_OBLIVIONCURSE] && sc->data[SC_OBLIVIONCURSE]->val3 == 1)
|
|
|
+ sc->cant.cast += (start ? 1 : -1);
|
|
|
}
|
|
|
|
|
|
// Can't chat
|
|
@@ -6931,7 +6935,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
|
|
|
flee -= flee * 25/100;
|
|
|
if(sc->data[SC_FEAR])
|
|
|
flee -= flee * 20 / 100;
|
|
|
- if(sc->data[SC_PARALYSE])
|
|
|
+ if(sc->data[SC_PARALYSE] && sc->data[SC_PARALYSE]->val3 == 1)
|
|
|
flee -= flee * 10 / 100;
|
|
|
if(sc->data[SC_INFRAREDSCAN])
|
|
|
flee -= flee * 30 / 100;
|
|
@@ -7409,6 +7413,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
|
|
|
val = max( val, 75 );
|
|
|
if( sc->data[SC_CLOAKINGEXCEED] )
|
|
|
val = max( val, sc->data[SC_CLOAKINGEXCEED]->val3);
|
|
|
+ if (sc->data[SC_PARALYSE] && sc->data[SC_PARALYSE]->val3 == 0)
|
|
|
+ val = max(val, 50);
|
|
|
if( sc->data[SC_HOVERING] )
|
|
|
val = max( val, 10 );
|
|
|
if( sc->data[SC_GN_CARTBOOST] )
|
|
@@ -7441,7 +7447,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
|
|
|
// GetSpeed()
|
|
|
if( sd && pc_iscarton(sd) )
|
|
|
speed += speed * (50 - 5 * pc_checkskill(sd,MC_PUSHCART)) / 100;
|
|
|
- if( sc->data[SC_PARALYSE] )
|
|
|
+ if( sc->data[SC_PARALYSE] && sc->data[SC_PARALYSE]->val3 == 1 )
|
|
|
speed += speed * 50 / 100;
|
|
|
if( speed_rate != 100 )
|
|
|
speed = speed * speed_rate / 100;
|
|
@@ -7542,7 +7548,7 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, b
|
|
|
bonus -= 30;
|
|
|
if (sc->data[SC_HALLUCINATIONWALK_POSTDELAY])
|
|
|
bonus -= 50;
|
|
|
- if (sc->data[SC_PARALYSE])
|
|
|
+ if (sc->data[SC_PARALYSE] && sc->data[SC_PARALYSE]->val3 == 1)
|
|
|
bonus -= 10;
|
|
|
if (sc->data[SC__BODYPAINT])
|
|
|
bonus -= 5 * sc->data[SC__BODYPAINT]->val1;
|
|
@@ -7742,7 +7748,7 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
|
|
|
aspd_rate += 300;
|
|
|
if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] )
|
|
|
aspd_rate += 500;
|
|
|
- if( sc->data[SC_PARALYSE] )
|
|
|
+ if( sc->data[SC_PARALYSE] && sc->data[SC_PARALYSE]->val3 == 1 )
|
|
|
aspd_rate += 100;
|
|
|
if( sc->data[SC__BODYPAINT] )
|
|
|
aspd_rate += 50 * sc->data[SC__BODYPAINT]->val1;
|
|
@@ -8549,8 +8555,9 @@ static int status_get_sc_interval(enum sc_type type)
|
|
|
{
|
|
|
switch (type) {
|
|
|
case SC_POISON:
|
|
|
- case SC_DPOISON:
|
|
|
case SC_LEECHESEND:
|
|
|
+ case SC_DPOISON:
|
|
|
+ case SC_DEATHHURT:
|
|
|
return 1000;
|
|
|
case SC_BURNING:
|
|
|
case SC_PYREXIA:
|
|
@@ -8765,10 +8772,11 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
|
|
|
tick_def2 = (status->vit + status->dex)*50;
|
|
|
break;
|
|
|
case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT)
|
|
|
- sc_def = status->int_*80;
|
|
|
+ sc_def = status->int_ * 80;
|
|
|
sc_def = max(sc_def, 500); // minimum of 5% resist
|
|
|
tick_def = 0;
|
|
|
- //Fall through
|
|
|
+ tick_def2 = (status->vit + status->luk) * 500;
|
|
|
+ break;
|
|
|
case SC_TOXIN:
|
|
|
case SC_PARALYSE:
|
|
|
case SC_VENOMBLEED:
|
|
@@ -8853,6 +8861,19 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
|
|
|
#endif
|
|
|
else if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 2)
|
|
|
sc_def += sc->data[SC_SHIELDSPELL_REF]->val3*100;
|
|
|
+ else if (sc->data[SC_LEECHESEND] && sc->data[SC_LEECHESEND]->val3 == 0) {
|
|
|
+ switch (type) {
|
|
|
+ case SC_BLIND:
|
|
|
+ case SC_STUN:
|
|
|
+ return 0; // Immune
|
|
|
+ }
|
|
|
+ } else if (sc->data[SC_OBLIVIONCURSE] && sc->data[SC_OBLIVIONCURSE]->val3 == 0) {
|
|
|
+ switch (type) {
|
|
|
+ case SC_SILENCE:
|
|
|
+ case SC_CURSE:
|
|
|
+ return 0; // Immune
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// When tick def not set, reduction is the same for both.
|
|
@@ -9497,12 +9518,13 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
case SC_PYREXIA:
|
|
|
case SC_OBLIVIONCURSE:
|
|
|
case SC_LEECHESEND:
|
|
|
- { // It doesn't stack or even renew
|
|
|
- int i = SC_TOXIN;
|
|
|
- for(; i<= SC_LEECHESEND; i++)
|
|
|
- if(sc->data[i]) return 0;
|
|
|
+ for (int32 i = SC_TOXIN; i <= SC_LEECHESEND; i++) {
|
|
|
+ if (sc->data[i] && sc->data[i]->val3 == 1) // It doesn't stack or even renew on the target
|
|
|
+ return 0;
|
|
|
+ else if (sc->data[i] && sc->data[i]->val3 == 0)
|
|
|
+ status_change_end(bl, static_cast<sc_type>(i), INVALID_TIMER); // End the bonus part on the caster
|
|
|
}
|
|
|
- break;
|
|
|
+ break;
|
|
|
case SC_SATURDAYNIGHTFEVER:
|
|
|
if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION])
|
|
|
return 0;
|
|
@@ -10248,8 +10270,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
#ifndef RENEWAL
|
|
|
val3 = 50*(val1+1); // Damage increase (+50 +50*lv%)
|
|
|
#endif
|
|
|
- if( sd )// [Ind] - iROwiki says each level increases its duration by 3 seconds
|
|
|
- tick += pc_checkskill(sd,GC_RESEARCHNEWPOISON)*3000;
|
|
|
+ if (sd) {
|
|
|
+ uint16 poison_level = pc_checkskill(sd, GC_RESEARCHNEWPOISON);
|
|
|
+
|
|
|
+ if (poison_level > 0) {
|
|
|
+ tick += 30000; // Base of 30 seconds
|
|
|
+ tick += poison_level * 15 * 1000; // Additional 15 seconds per level
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
case SC_POISONREACT:
|
|
|
val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex]
|
|
@@ -10522,18 +10550,46 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
case SC_POISON:
|
|
|
case SC_BLEEDING:
|
|
|
case SC_BURNING:
|
|
|
+ tick_time = status_get_sc_interval(type);
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
+ break;
|
|
|
case SC_TOXIN:
|
|
|
- case SC_MAGICMUSHROOM:
|
|
|
+ if (val3 == 1) // Target
|
|
|
+ tick_time = status_get_sc_interval(type);
|
|
|
+ else // Caster
|
|
|
+ tick_time = 1000;
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
+ break;
|
|
|
+ case SC_DEATHHURT:
|
|
|
+ if (val3 == 1)
|
|
|
+ break;
|
|
|
+ tick_time = status_get_sc_interval(type);
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
case SC_LEECHESEND:
|
|
|
+ if (val3 == 0)
|
|
|
+ break;
|
|
|
tick_time = status_get_sc_interval(type);
|
|
|
- val4 = tick-tick_time; // Remaining time
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
break;
|
|
|
-
|
|
|
case SC_PYREXIA:
|
|
|
- //Causes blind for duration of pyrexia, unreducable and unavoidable, but can be healed with e.g. green potion
|
|
|
- status_change_start(src,bl,SC_BLIND,10000,val1,0,0,0,tick,SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
|
|
|
- tick_time = status_get_sc_interval(type);
|
|
|
- val4 = tick-tick_time; // Remaining time
|
|
|
+ if (val3 == 1) { // Target
|
|
|
+ // Causes blind for duration of pyrexia, unreducable and unavoidable, but can be healed with e.g. green potion
|
|
|
+ status_change_start(src, bl, SC_BLIND, 10000, val1, 0, 0, 0, tick, SCSTART_NOAVOID | SCSTART_NOTICKDEF | SCSTART_NORATEDEF);
|
|
|
+ tick_time = status_get_sc_interval(type);
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
+ } else // Caster
|
|
|
+ val2 = 15; // CRIT % and ATK % increase
|
|
|
+ break;
|
|
|
+ case SC_VENOMBLEED:
|
|
|
+ if (val3 == 0) // Caster
|
|
|
+ val2 = 30; // Reflect damage % reduction
|
|
|
+ break;
|
|
|
+ case SC_MAGICMUSHROOM:
|
|
|
+ if (val3 == 1) { // Target
|
|
|
+ tick_time = status_get_sc_interval(type);
|
|
|
+ val4 = tick - tick_time; // Remaining time
|
|
|
+ } else // Caster
|
|
|
+ val2 = 10; // After-cast delay % reduction
|
|
|
break;
|
|
|
|
|
|
case SC_CONFUSION:
|
|
@@ -11175,6 +11231,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
tick_time = 5000; // [GodLesZ] tick time
|
|
|
break;
|
|
|
case SC_OBLIVIONCURSE:
|
|
|
+ if (val3 == 0)
|
|
|
+ break;
|
|
|
val4 = tick / 3000;
|
|
|
tick_time = 3000; // [GodLesZ] tick time
|
|
|
break;
|
|
@@ -11759,7 +11817,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
val2 = 20 * val1 + 20; // atk bonus
|
|
|
break;
|
|
|
case SC_DARKCROW:
|
|
|
- val2 = 30 * val1;
|
|
|
+ val2 = 30 * val1; // ATK bonus
|
|
|
break;
|
|
|
case SC_UNLIMIT:
|
|
|
val2 = 50 * val1;
|
|
@@ -12098,11 +12156,21 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|
|
case SC_BLEEDING:
|
|
|
case SC_BURNING:
|
|
|
case SC_TOXIN:
|
|
|
+ tick_time = tick;
|
|
|
+ tick = tick_time + max(val4, 0);
|
|
|
+ break;
|
|
|
+ case SC_DEATHHURT:
|
|
|
+ if (val3 == 1)
|
|
|
+ break;
|
|
|
+ tick_time = tick;
|
|
|
+ tick = tick_time + max(val4, 0);
|
|
|
case SC_MAGICMUSHROOM:
|
|
|
case SC_PYREXIA:
|
|
|
case SC_LEECHESEND:
|
|
|
+ if (val3 == 0)
|
|
|
+ break;
|
|
|
tick_time = tick;
|
|
|
- tick = tick_time + max(val4,0);
|
|
|
+ tick = tick_time + max(val4, 0);
|
|
|
break;
|
|
|
case SC_SWORDCLAN:
|
|
|
case SC_ARCWANDCLAN:
|
|
@@ -13861,12 +13929,19 @@ TIMER_FUNC(status_change_timer){
|
|
|
status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, 0, 1, damage, 1, DMG_NORMAL, 0, false),0);
|
|
|
}
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
case SC_TOXIN:
|
|
|
if (sce->val4 >= 0) { // Damage is every 10 seconds including 3%sp drain.
|
|
|
- map_freeblock_lock();
|
|
|
- dounlock = true;
|
|
|
- status_damage(bl, bl, 1, status->max_sp * 3 / 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 1, 1, DMG_NORMAL, 0, false), 0, 0);
|
|
|
+ if (sce->val3 == 1) { // Target
|
|
|
+ map_freeblock_lock();
|
|
|
+ dounlock = true;
|
|
|
+ status_damage(bl, bl, 1, status->max_sp * 3 / 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 1, 1, DMG_NORMAL, 0, false), 0, 0);
|
|
|
+ } else { // Caster
|
|
|
+ interval = 1000; // Assign here since status_get_sc_internval() contains the target interval.
|
|
|
+
|
|
|
+ if (status->sp < status->max_sp)
|
|
|
+ status_heal(bl, 0, (int)status->max_sp * 1 / 100, 1);
|
|
|
+ }
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -13914,7 +13989,7 @@ TIMER_FUNC(status_change_timer){
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
case SC_PYREXIA:
|
|
|
if (sce->val4 >= 0) {
|
|
|
map_freeblock_lock();
|
|
@@ -13922,7 +13997,7 @@ TIMER_FUNC(status_change_timer){
|
|
|
status_fix_damage(bl, bl, 100, clif_damage(bl, bl, tick, status->amotion, status->dmotion + 500, 100, 1, DMG_NORMAL, 0, false),0);
|
|
|
}
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
case SC_LEECHESEND:
|
|
|
if (sce->val4 >= 0) {
|
|
|
int64 damage = status->vit * (sce->val1 - 3) + (int)status->max_hp / 100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100)
|
|
@@ -13933,6 +14008,13 @@ TIMER_FUNC(status_change_timer){
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case SC_DEATHHURT:
|
|
|
+ if (sce->val4 >= 0) {
|
|
|
+ if (status->hp < status->max_hp)
|
|
|
+ status_heal(bl, (int)status->max_hp * 1 / 100, 0, 1);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
case SC_TENSIONRELAX:
|
|
|
if(status->max_hp > status->hp && --(sce->val3) >= 0) {
|
|
|
sc_timer_next(10000 + tick);
|
|
@@ -14116,7 +14198,7 @@ TIMER_FUNC(status_change_timer){
|
|
|
sc_timer_next(10000+tick);
|
|
|
}
|
|
|
break;
|
|
|
-
|
|
|
+
|
|
|
case SC_OBLIVIONCURSE:
|
|
|
if( --(sce->val4) >= 0 ) {
|
|
|
clif_emotion(bl,ET_QUESTION);
|