summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/map/atcommand.c8
-rw-r--r--src/map/battle.c684
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/clif.c18
-rw-r--r--src/map/itemdb.h4
-rw-r--r--src/map/map.c3
-rw-r--r--src/map/map.h3
-rw-r--r--src/map/mob.c7
-rw-r--r--src/map/party.c17
-rw-r--r--src/map/party.h1
-rw-r--r--src/map/pc.c19
-rw-r--r--src/map/skill.c1201
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c867
-rw-r--r--src/map/status.h94
-rw-r--r--src/map/unit.c17
16 files changed, 1750 insertions, 1196 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 2849ada0b..d39004c74 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -6072,7 +6072,7 @@ ACMD(npctalk)
unsigned int color = 0;
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -6121,7 +6121,7 @@ ACMD(pettalk)
}
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -6912,7 +6912,7 @@ ACMD(homtalk)
}
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -7287,7 +7287,7 @@ ACMD(me)
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
diff --git a/src/map/battle.c b/src/map/battle.c
index 1a04aeff9..fac8c791c 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -366,8 +366,6 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
}
if( tsc->data[SC_THORNS_TRAP])
status_change_end(target, SC_THORNS_TRAP, INVALID_TIMER);
- if( tsc->data[SC_FIRE_CLOAK_OPTION])
- damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
if( tsc->data[SC_COLD] && target->type != BL_MOB)
status_change_end(target, SC_COLD, INVALID_TIMER);
if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
@@ -377,7 +375,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
break;
case ELE_POISON:
- if( tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
+ if( tsc->data[SC_VENOMIMPRESS] && atk_elem == ELE_POISON ) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
break;
case ELE_WIND:
if( tsc->data[SC_COLD] && target->type != BL_MOB) damage += damage/2;
@@ -446,8 +444,8 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
eatk += 200;
#ifdef RENEWAL_EDP
if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ){
- eatk = eatk * sc->data[SC_EDP]->val4 / 100;
- damage += damage * sc->data[SC_EDP]->val3 / 100;
+ eatk = eatk * (sc->data[SC_EDP]->val4 / 100 - 1);
+ damage = damage * (sc->data[SC_EDP]->val4 / 100);
}
#endif
}
@@ -611,7 +609,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
if( (skill_lv = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (st->def_ele == ELE_FIRE || st->def_ele == ELE_EARTH) )
damage += (skill_lv * 10);
if( pc_ismadogear(sd) )
- damage += 20 + 20 * pc->checkskill(sd, NC_MADOLICENCE);
+ damage += 15 * pc->checkskill(sd, NC_MADOLICENCE);
#ifdef RENEWAL
if( (skill_lv = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0 )
damage += (skill_lv * 2);
@@ -788,6 +786,8 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
// general skill masteries
#ifdef RENEWAL
+ if( div < 0 ) // div fix
+ div = 1;
if( skill_id == MO_FINGEROFFENSIVE )//The finger offensive spheres on moment of attack do count. [Skotlex]
damage += div * sd->spiritball_old * 3;
else
@@ -849,6 +849,10 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint
damage=battle->attr_fix(src, target, damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element
damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
+ if( skill_id == NC_ARMSCANNON )
+ damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
+ if( skill_id == GN_CARTCANNON )
+ damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage.
damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
}
@@ -1364,6 +1368,22 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
return damage;
}
+// Minstrel/Wanderer number check for chorus skills.
+int battle_calc_chorusbonus(struct map_session_data *sd) {
+ int members = 0;
+
+ if (!sd || !sd->status.party_id)
+ return 0;
+
+ members = party->foreachsamemap(party->sub_count_chorus, sd, 0);
+
+ if (members < 3)
+ return 0; // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
+ if (members > 7)
+ return 5; // Maximum effect possiable from 7 or more Minstrel's/Wanderer's
+ return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible
+}
+
int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){
int i;
struct status_change *sc, *tsc;
@@ -1500,25 +1520,24 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
* Arch Bishop
**/
case AB_JUDEX:
- skillratio += 180 + 20 * skill_lv;
- if (skill_lv > 4) skillratio += 20;
+ skillratio = 300 + 20 * skill_lv;
RE_LVL_DMOD(100);
break;
case AB_ADORAMUS:
- skillratio += 400 + 100 * skill_lv;
+ skillratio = 500 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case AB_DUPLELIGHT_MAGIC:
- skillratio += 100 + 20 * skill_lv;
+ skillratio = 200 + 20 * skill_lv;
break;
/**
* Warlock
**/
- case WL_SOULEXPANSION: // MATK [{( Skill Level + 4 ) x 100 ) + ( Caster?s INT )} x ( Caster?s Base Level / 100 )] %
- skillratio += 300 + 100 * skill_lv + status_get_int(src);
+ case WL_SOULEXPANSION: // MATK [{( Skill Level + 4 ) x 100 ) + ( Caster's INT )} x ( Caster's Base Level / 100 )] %
+ skillratio = 100 * (skill_lv + 4) + st->int_;
RE_LVL_DMOD(100);
break;
- case WL_FROSTMISTY: // MATK [{( Skill Level x 100 ) + 200 } x ( Caster?s Base Level / 100 )] %
+ case WL_FROSTMISTY: // MATK [{( Skill Level x 100 ) + 200 } x ( Caster's Base Level / 100 )] %
skillratio += 100 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
@@ -1566,7 +1585,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
c = 0;
memset (p_sd, 0, sizeof(p_sd));
party->foreachsamemap(skill->check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id);
- c = ( c > 1 ? rand()%c : 0 );
+ c = ( c > 1 ? rnd()%c : 0 );
if( (psd = map->id2sd(p_sd[c])) && pc->checkskill(psd,WL_COMET) > 0 ){
skillratio = skill_lv * 400; //MATK [{( Skill Level x 400 ) x ( Caster's Base Level / 120 )} + 2500 ] %
@@ -1583,7 +1602,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 * flag;
break;
case WL_EARTHSTRAIN:
- skillratio += 1900 + 100 * skill_lv;
+ skillratio = 2000 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case WL_TETRAVORTEX_FIRE:
@@ -1596,7 +1615,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case WL_SUMMON_ATK_WATER:
case WL_SUMMON_ATK_WIND:
case WL_SUMMON_ATK_GROUND:
- skillratio = skill_lv * (status->get_lv(src) + ( sd ? sd->status.job_level : 50 ));// This is close to official, but lacking a little info to finalize. [Rytech]
+ skillratio = (1 + skill_lv) / 2 * (status->get_lv(src) + (sd ? sd->status.job_level : 50));
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
@@ -1607,82 +1626,68 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
bandingBonus = 200 * (sd ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0) : 1);
skillratio = ((300 * skill_lv) + bandingBonus) * (sd ? sd->status.job_level : 1) / 25;
}
- break;
- case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] %
- if( sd ) {
- skillratio = status->get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2;
- } else
- skillratio += 1900; //2000%
break;
- case WM_METALICSOUND:
- skillratio += 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 ) - 100;
+ case LG_SHIELDSPELL:
+ if ( sd && skill_lv == 2 ) // [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] %
+ skillratio = 4 * status->get_lv(src) + 100 * sd->bonus.shieldmdef + 2 * st->int_;
+ else
+ skillratio = 0;
break;
- /*case WM_SEVERE_RAINSTORM:
- skillratio += 50 * skill_lv;
+ case WM_METALICSOUND:
+ skillratio = 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 );
+ RE_LVL_DMOD(100);
break;
-
- WM_SEVERE_RAINSTORM just set a unit place,
- refer to WM_SEVERE_RAINSTORM_MELEE to set the formula.
- */
case WM_REVERBERATION_MAGIC:
- // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] %
- skillratio += 100 * (sd ? pc->checkskill(sd, WM_REVERBERATION) : 1);
+ skillratio = 100 * skill_lv + 100;
RE_LVL_DMOD(100);
break;
case SO_FIREWALK:
- skillratio = 300;
+ skillratio = 60 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_HEATER_OPTION] )
- skillratio += sc->data[SC_HEATER_OPTION]->val3;
+ skillratio += sc->data[SC_HEATER_OPTION]->val3 / 2;
break;
case SO_ELECTRICWALK:
- skillratio = 300;
+ skillratio = 60 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level / 2 : 0;
+ skillratio += sc->data[SC_BLAST_OPTION]->val2 / 2;
break;
case SO_EARTHGRAVE:
- skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_SEISMICWEAPON) : 10 ) + status_get_int(src) * skill_lv );
+ skillratio = st->int_ * skill_lv + 200 * (sd ? pc->checkskill(sd,SA_SEISMICWEAPON) : 1);
RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3 * 5;
break;
case SO_DIAMONDDUST:
- skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 10 ) + status_get_int(src) * skill_lv );
- RE_LVL_DMOD(100);
+ skillratio = (st->int_ * skill_lv + 200 * (sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 1)) * status->get_lv(src) / 100;
if( sc && sc->data[SC_COOLER_OPTION] )
- skillratio += sc->data[SC_COOLER_OPTION]->val3;
+ skillratio += sc->data[SC_COOLER_OPTION]->val3 * 5;
break;
case SO_POISON_BUSTER:
- skillratio += 1100 + 300 * skill_lv;
+ skillratio += 900 + 300 * skill_lv;
+ RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3 * 5;
break;
case SO_PSYCHIC_WAVE:
- skillratio += -100 + skill_lv * 70 + (status_get_int(src) * 3);
+ skillratio = 70 * skill_lv + 3 * st->int_;
RE_LVL_DMOD(100);
- if( sc ){
- if( sc->data[SC_HEATER_OPTION] )
- skillratio += sc->data[SC_HEATER_OPTION]->val3;
- else if(sc->data[SC_COOLER_OPTION] )
- skillratio += sc->data[SC_COOLER_OPTION]->val3;
- else if(sc->data[SC_BLAST_OPTION] )
- skillratio += sc->data[SC_BLAST_OPTION]->val2;
- else if(sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3;
- }
+ if( sc && ( sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION]
+ || sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ) )
+ skillratio += skillratio * 20 / 100;
break;
- case SO_VARETYR_SPEAR: //MATK [{( Endow Tornado skill level x 50 ) + ( Caster INT x Varetyr Spear Skill level )} x Caster Base Level / 100 ] %
+ case SO_VARETYR_SPEAR:
skillratio = status_get_int(src) * skill_lv + ( sd ? pc->checkskill(sd, SA_LIGHTNINGLOADER) * 50 : 0 );
RE_LVL_DMOD(100);
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level * 5 : 0;
+ skillratio += sc->data[SC_BLAST_OPTION]->val2 * 5;
break;
case SO_CLOUD_KILL:
- skillratio += -100 + skill_lv * 40;
+ skillratio = 40 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3;
break;
case GN_DEMONIC_FIRE:
if( skill_lv > 20)
@@ -2073,7 +2078,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += ((skill_lv-1)%5+1) * 100;
break;
case RK_SONICWAVE:
- skillratio += -100 + 100 * (skill_lv + 5);
+ skillratio = (skill_lv + 5) * 100;
skillratio = skillratio * (100 + (status->get_lv(src)-100) / 2) / 100;
break;
case RK_HUNDREDSPEAR:
@@ -2087,20 +2092,20 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
}
break;
case RK_WINDCUTTER:
- skillratio += -100 + 50 * (skill_lv + 2);
+ skillratio = (skill_lv + 2) * 50;
RE_LVL_DMOD(100);
break;
case RK_IGNITIONBREAK:
- i = distance_bl(src,target);
- if( i < 2 )
- skillratio += 300 * skill_lv;
- else if( i < 4 )
- skillratio += 250 * skill_lv;
- else
- skillratio += 200 * skill_lv;
- skillratio = (skillratio - 100) * (100 + (status->get_lv(src)-100)) / 100;
- if( st->rhw.ele == ELE_FIRE )
- skillratio += 100 * skill_lv;
+ i = distance_bl(src,target);
+ if( i < 2 )
+ skillratio = 300 * skill_lv;
+ else if( i < 4 )
+ skillratio = 250 * skill_lv;
+ else
+ skillratio = 200 * skill_lv;
+ skillratio = skillratio * status->get_lv(src) / 100;
+ if( st->rhw.ele == ELE_FIRE )
+ skillratio += 100 * skill_lv;
break;
case RK_CRUSHSTRIKE:
if( sd )
@@ -2112,10 +2117,10 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
}
break;
case RK_STORMBLAST:
- skillratio += -100 + 100 *(sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + status_get_int(src) / 8;
+ skillratio = ((sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + status_get_int(src) / 8) * 100;
break;
case RK_PHANTOMTHRUST:
- skillratio += -100 + 50 * skill_lv + 10 * ( sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10);
+ skillratio = 50 * skill_lv + 10 * (sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10);
RE_LVL_DMOD(150);
break;
/**
@@ -2134,7 +2139,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(120);
break;
case GC_ROLLINGCUTTER:
- skillratio += -50 + 50 * skill_lv;
+ skillratio = 50 + 50 * skill_lv;
RE_LVL_DMOD(100);
break;
case GC_CROSSRIPPERSLASHER:
@@ -2167,88 +2172,99 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 + 100 * skill_lv;
break;
case RA_WUGDASH:// ATK 300%
- skillratio += 200;
+ skillratio = 300;
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ skillratio += 10 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd));
break;
case RA_WUGSTRIKE:
- skillratio += -100 + 200 * skill_lv;
+ skillratio = 200 * skill_lv;
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ skillratio += 10 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd));
break;
case RA_WUGBITE:
skillratio += 300 + 200 * skill_lv;
if ( skill_lv == 5 ) skillratio += 100;
break;
case RA_SENSITIVEKEEN:
- skillratio += 50 * skill_lv;
+ skillratio = 150 * skill_lv;
break;
/**
* Mechanic
**/
case NC_BOOSTKNUCKLE:
- skillratio += 100 + 100 * skill_lv + status_get_dex(src);
- RE_LVL_DMOD(100);
+ skillratio = skill_lv * 100 + 200 + st->dex;
+ RE_LVL_DMOD(120);
break;
case NC_PILEBUNKER:
- skillratio += 200 + 100 * skill_lv + status_get_str(src);
+ skillratio = skill_lv*100 + 300 + status_get_str(src);
RE_LVL_DMOD(100);
break;
case NC_VULCANARM:
- skillratio += -100 + 70 * skill_lv + status_get_dex(src);
+ skillratio = 70 * skill_lv + status_get_dex(src);
RE_LVL_DMOD(100);
break;
case NC_FLAMELAUNCHER:
case NC_COLDSLOWER:
- skillratio += 200 + 300 * skill_lv;
+ skillratio += 200 + 100 * skill_lv + status_get_str(src);
RE_LVL_DMOD(100);
break;
case NC_ARMSCANNON:
switch( tst->size ) {
- case SZ_MEDIUM: skillratio += 100 + 500 * skill_lv; break;// Medium
- case SZ_SMALL: skillratio += 100 + 400 * skill_lv; break;// Small
- case SZ_BIG: skillratio += 100 + 300 * skill_lv; break;// Large
+ case SZ_MEDIUM: skillratio = 300 + 350 * skill_lv; break; // Medium
+ case SZ_SMALL: skillratio = 300 + 400 * skill_lv; break; // Small
+ case SZ_BIG: skillratio = 300 + 300 * skill_lv; break; // Large
}
- RE_LVL_DMOD(100);
- //NOTE: Their's some other factors that affects damage, but not sure how exactly. Will recheck one day. [Rytech]
+ RE_LVL_DMOD(120);
break;
case NC_AXEBOOMERANG:
- skillratio += 60 + 40 * skill_lv;
+ skillratio = 250 + 50 * skill_lv;
if( sd ) {
short index = sd->equip_index[EQI_HAND_R];
if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
- skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actural weight. [Rytech]
+ skillratio += sd->inventory_data[index]->weight / 10;
}
RE_LVL_DMOD(100);
break;
case NC_POWERSWING:
- skillratio += 80 + 20 * skill_lv + status_get_str(src) + status_get_dex(src);
- RE_LVL_DMOD(100);
+ skillratio = 300 + 100*skill_lv + ( status_get_str(src)+status_get_dex(src) ) * status->get_lv(src) / 100;
break;
case NC_AXETORNADO:
- skillratio += 100 + 100 * skill_lv + status_get_vit(src);
+ skillratio = 200 + 100 * skill_lv + st->vit;
RE_LVL_DMOD(100);
+ if( st->rhw.ele == ELE_WIND )
+ skillratio = skillratio * 125 / 100;
+ if ( distance_bl(src, target) > 2 ) // Will deal 75% damage outside of 5x5 area.
+ skillratio = skillratio * 75 / 100;
break;
case SC_FATALMENACE:
- skillratio += 100 * skill_lv;
+ skillratio = 100 * (skill_lv+1) * status->get_lv(src) / 100;
break;
case SC_TRIANGLESHOT:
- skillratio += 270 + 30 * skill_lv;
+ skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 ) * status->get_lv(src) / 120;
break;
case SC_FEINTBOMB:
- skillratio += 100 + 100 * skill_lv;
+ skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10 * status->get_lv(src) / 120;
break;
case LG_CANNONSPEAR:
- skillratio += -100 + (50 + status_get_str(src)) * skill_lv;
+ skillratio = (50 + st->str) * skill_lv;
RE_LVL_DMOD(100);
break;
case LG_BANISHINGPOINT:
- skillratio += -100 + ((50 * skill_lv) + (30 * ((sd)?pc->checkskill(sd,SM_BASH):1)));
+ skillratio = 50 * skill_lv + 30 * (sd ? pc->checkskill(sd,SM_BASH) : 10);
RE_LVL_DMOD(100);
break;
case LG_SHIELDPRESS:
- skillratio += 60 + 43 * skill_lv;
+ skillratio = 150 * skill_lv + st->str;
+ if( sd ) {
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ skillratio += sd->inventory_data[index]->weight / 10;
+ }
RE_LVL_DMOD(100);
break;
case LG_PINPOINTATTACK:
- skillratio += -100 + ((100 * skill_lv) + (10 * status_get_agi(src)) );
- RE_LVL_DMOD(100);
+ skillratio = 100 * skill_lv + 5 * st->agi;
+ RE_LVL_DMOD(120);
break;
case LG_RAGEBURST:
if( sc ){
@@ -2257,17 +2273,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
}
RE_LVL_DMOD(100);
break;
- case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] %
- if( sd ) {
+ case LG_SHIELDSPELL:
+ if ( sd && skill_lv == 1 ) {
struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
- skillratio += -100 + status->get_lv(src) * 4 + status_get_vit(src) * 2;
if( shield_data )
- skillratio += shield_data->def * 10;
- } else
- skillratio += 2400; //2500%
+ skillratio = 4 * status->get_lv(src) + 10 * shield_data->def + 2 * st->vit;
+ }
+ else
+ skillratio = 0; // Prevents ATK damage from being done on LV 2 usage since LV 2 us MATK. [Rytech]
break;
case LG_MOONSLASHER:
- skillratio += -100 + (120 * skill_lv + ((sd) ? pc->checkskill(sd,LG_OVERBRAND) : 5) * 80);
+ skillratio = 120 * skill_lv + 80 * (sd ? pc->checkskill(sd,LG_OVERBRAND) : 5);
RE_LVL_DMOD(100);
break;
case LG_OVERBRAND:
@@ -2283,11 +2299,15 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
- skillratio += 200 + 300 * skill_lv;
+ skillratio = 300 + 300 * skill_lv;
RE_LVL_DMOD(100);
break;
case LG_EARTHDRIVE:
- skillratio = (skillratio + 100) * skill_lv;
+ if( sd ) {
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ skillratio = (1 + skill_lv) * sd->inventory_data[index]->weight / 10;
+ }
RE_LVL_DMOD(100);
break;
case LG_HESPERUSLIT:
@@ -2341,8 +2361,9 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
}
break;
case SR_KNUCKLEARROW:
- if( flag&4 ){ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %
- skillratio += -100 + 150 * skill_lv + status->get_lv(target) * 5 * (status->get_lv(src) / 100) ;
+ if ( flag&4 || map->list[src->m].flag.gvg_castle || tst->mode&MD_BOSS ) {
+ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %
+ skillratio = 150 * skill_lv + status->get_lv(target) * 5 * (status->get_lv(src) / 100) ;
if( tsd && tsd->weight )
skillratio += 100 * (tsd->weight / tsd->max_weight);
}else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] %
@@ -2350,7 +2371,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] %
- skillratio += -100 + status->get_lv(src) + status_get_dex(src);
+ skillratio = status->get_lv(src) + status_get_dex(src);
RE_LVL_DMOD(100);
break;
case SR_GATEOFHELL:
@@ -2376,40 +2397,36 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case WM_REVERBERATION_MELEE:
- // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100]
- skillratio += 200 + 100 * pc->checkskill(sd, WM_REVERBERATION);
+ skillratio += 200 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case WM_SEVERE_RAINSTORM_MELEE:
- //ATK [{(Caster DEX + AGI) x (Skill Level / 5)} x Caster Base Level / 100] %
- skillratio += -100 + (status_get_dex(src) + status_get_agi(src)) * (skill_lv * 2);
+ skillratio = (st->agi + st->dex) * skill_lv / 5;
RE_LVL_DMOD(100);
- skillratio /= 10;
break;
case WM_GREAT_ECHO:
- skillratio += 800 + 100 * skill_lv;
- if( sd ) { // Still need official value [pakpil]
- uint16 lv = skill_lv;
- skillratio += 100 * skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0);
- }
- break;
- case WM_SOUND_OF_DESTRUCTION:
- skillratio += 400;
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ skillratio += 300 + 200 * skill_lv;
+ //Chorus bonus dont count the first 2 Minstrel's/Wanderer's and only increases when their's 3 or more. [Rytech]
+ if (chorusbonus >= 1 && chorusbonus <= 5)
+ skillratio += 100<<(chorusbonus-1); // 1->100; 2->200; 3->400; 4->800; 5->1600
+ RE_LVL_DMOD(100);
+ }
break;
case GN_CART_TORNADO:
- // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] %
- skillratio += -100 + 50 * skill_lv;
- if( sd && sd->cart_weight)
- skillratio += sd->cart_weight/10 / max(150-status_get_str(src),1) + pc->checkskill(sd, GN_REMODELING_CART) * 50;
+ {
+ int strbonus = st->str; // FIXME Supposed to take only base STR, but current code wont allow that. So well just take STR for now. [Rytech]
+ if ( strbonus > 130 ) // Max base stat limit on official is 130. So well allow no higher then 125 STR here. This limit prevents
+ strbonus = 130; // the division from going any lower then 30 so the server wont divide by 0 if someone has 150 STR.
+ skillratio = 50 * skill_lv + (sd ? sd->cart_weight : battle_config.max_cart_weight) / 10 / (150 - strbonus) + 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5);
+ }
break;
case GN_CARTCANNON:
- // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] %
- skillratio += -100 + 60 * skill_lv;
- if( sd ) skillratio += pc->checkskill(sd, GN_REMODELING_CART) * 50 * (status_get_int(src) / 40);
+ skillratio = 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40) + 60 * skill_lv;
break;
case GN_SPORE_EXPLOSION:
- skillratio += 200 + 100 * skill_lv;
- break;
+ skillratio = 100 * skill_lv + (200 + st->int_) * status->get_lv(src) / 100;
case GN_CRAZYWEED_ATK:
skillratio += 400 + 100 * skill_lv;
break;
@@ -2417,25 +2434,32 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
if( sd ) {
switch( sd->itemid ) {
case ITEMID_APPLE_BOMB:
- case ITEMID_COCONUT_BOMB:
+ skillratio = st->str + st->dex + 300;
+ break;
case ITEMID_MELON_BOMB:
+ skillratio = st->str + st->dex + 500;
+ break;
+ case ITEMID_COCONUT_BOMB:
case ITEMID_PINEAPPLE_BOMB:
- skillratio += 400; // Unconfirmed
+ case ITEMID_BANANA_BOMB:
+ skillratio = st->str + st->dex + 800;
break;
- case ITEMID_BANANA_BOMB: // 2000%
- skillratio += 1900;
+ case ITEMID_BLACK_LUMP:
+ skillratio = (st->str + st->agi + st->dex) / 3; // Black Lump
+ break;
+ case ITEMID_BLACK_HARD_LUMP:
+ skillratio = (st->str + st->agi + st->dex) / 2; // Hard Black Lump
+ break;
+ case ITEMID_VERY_HARD_LUMP:
+ skillratio = st->str + st->agi + st->dex; // Extremely Hard Black Lump
break;
- case ITEMID_BLACK_LUMP: skillratio -= 75; break; // 25%
- case ITEMID_BLACK_HARD_LUMP: skillratio -= 25; break; // 75%
- case ITEMID_VERY_HARD_LUMP: skillratio += 100; break; // 200%
}
- } else
- skillratio += 300; // Bombs
+ }
break;
case SO_VARETYR_SPEAR://ATK [{( Striking Level x 50 ) + ( Varetyr Spear Skill Level x 50 )} x Caster Base Level / 100 ] %
skillratio += -100 + 50 * skill_lv + ( sd ? pc->checkskill(sd, SO_STRIKING) * 50 : 0 );
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level * 5 : 0;
+ skillratio += (sd ? sd->status.job_level * 5 : 0);
break;
// Physical Elemantal Spirits Attack Skills
case EL_CIRCLE_OF_FIRE:
@@ -2510,7 +2534,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += sc->data[SC_OVERTHRUST]->val3;
if(sc->data[SC_OVERTHRUSTMAX])
skillratio += sc->data[SC_OVERTHRUSTMAX]->val2;
- if(sc->data[SC_BERSERK] || sc->data[SC_SATURDAY_NIGHT_FEVER])
+ if(sc->data[SC_BERSERK])
#ifndef RENEWAL
skillratio += 100;
#else
@@ -2535,7 +2559,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
*------------------------------------------*/
int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv) {
struct map_session_data *sd = NULL;
- struct status_change *sc;
+ struct status_change *sc, *tsc;
struct status_change_entry *sce;
int div_ = d->div_, flag = d->flag;
@@ -2545,9 +2569,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
if( battle_config.ksprotection && mob->ksprotected(src, bl) )
return 0;
- if( map->getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) && skill->get_type(skill_id) != BF_MISC
- && skill->get_casttype(skill_id) == CAST_GROUND )
- return 0;
if (bl->type == BL_PC) {
sd=(struct map_session_data *)bl;
//Special no damage states
@@ -2564,6 +2585,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
}
sc = status->get_sc(bl);
+ tsc = status->get_sc(src);
if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
return 1;
@@ -2608,9 +2630,20 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if (group) {
d->dmg_lv = ATK_BLOCK;
if(src_skill_id == MH_STEINWAND){
- if (--group->val2<=0)
- skill->del_unitgroup(group,ALC_MARK);
- return 0;
+ if (--group->val2<=0)
+ skill->del_unitgroup(group,ALC_MARK);
+ if( (group->val3 - damage) > 0 )
+ group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+ else
+ skill->del_unitgroup(group,ALC_MARK);
+ return 0;
+ }
+ if( skill_id == SO_ELEMENTAL_SHIELD ) {
+ if ( ( group->val2 - damage) > 0 ) {
+ group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
+ } else
+ skill->del_unitgroup(group,ALC_MARK);
+ return 0;
}
/**
* in RE, SW possesses a lifetime equal to 3 times the caster's health
@@ -2633,6 +2666,17 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
d->dmg_lv = ATK_BLOCK;
return 0;
}
+ if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG && skill_id != CR_ACIDDEMONSTRATION ) {
+ d->dmg_lv = ATK_BLOCK;
+ return 0;
+ }
+ if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) {
+ // {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2
+ int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + sd->status.job_level / 5) / 2;
+ status->heal(bl, 0, sp, 3);
+ d->dmg_lv = ATK_BLOCK;
+ return 0;
+ }
if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 )
{
clif->skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1);
@@ -2640,6 +2684,10 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
sc_start2(bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000);
return 0;
}
+ if( sc->data[SC_HOVERING] && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL || skill_id == SR_WINDMILL) ) {
+ d->dmg_lv = ATK_BLOCK;
+ return 0;
+ }
if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 )
{
int delay;
@@ -2692,17 +2740,12 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}
- if(sc->data[SC_HERMODE] && flag&BF_MAGIC)
+ if((sc->data[SC_HERMODE] || sc->data[SC_HOVERING]) && flag&BF_MAGIC)
return 0;
if(sc->data[SC_NJ_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
return 0;
- if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) {
- d->dmg_lv = ATK_MISS;
- return 0;
- }
-
if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2)
{ //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
clif->specialeffect(bl, 462, AREA);
@@ -2810,7 +2853,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
(flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
damage -= damage * 20 / 100;
- if(sc->data[SC_FOGWALL] && skill_id != RK_DRAGONBREATH && skill_id != RK_DRAGONBREATH_WATER) {
+ if(sc->data[SC_FOGWALL]) {
if(flag&BF_SKILL) //25% reduction
damage -= damage * 25 / 100;
else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
@@ -2838,11 +2881,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
sce->val3&flag && sce->val4&flag)
damage -= damage * sc->data[SC_ARMOR]->val2 / 100;
+ if( sc->data[SC_ENERGYCOAT] && (skill_id == GN_HELLS_PLANT_ATK ||
#ifdef RENEWAL
- if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION)
+ ((flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION)
#else
- if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION))
+ (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION)
#endif
+ ) )
{
struct status_data *sstatus = status->get_status_data(bl);
int per = 100*sstatus->sp / sstatus->max_sp -1; //100% should be counted as the 80~99% interval
@@ -2863,6 +2908,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,timer->gettick(),0);
}
+ if( sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
+ damage += damage * sc->data[SC_DARKCROW]->val2 / 100;
+
if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&(BF_SHORT|BF_WEAPON) && damage > 0 ) {
sce->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
if( src->type == BL_PC ) {
@@ -2942,7 +2990,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if (hd) homun->addspiritball(hd, 10); //add a sphere
}
- if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
+ if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
status->change_spread(bl, src); // Deadly infect attacked side
}
@@ -2973,10 +3021,19 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
break;
}
}
- if( sc->data[SC_POISONINGWEAPON] && skill_id != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 )
- sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1));
- if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
+ if( tsc->data[SC_POISONINGWEAPON] ) {
+ short rate = 100;
+ struct status_data *tstatus = status->get_status_data(bl);
+ if ( !(flag&BF_SKILL) && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < tsc->data[SC_POISONINGWEAPON]->val3 ) {
+ if ( tsc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5;
+ sc_start(bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ }
+ }
+ if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
status->change_spread(src, bl);
+ if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0)
+ skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY );
if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
if (hd) homun->addspiritball(hd, 10);
@@ -3104,6 +3161,7 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
case HW_GRAVITATION:
case NJ_ZENYNAGE:
case KO_MUCHANAGE:
+ case NC_SELFDESTRUCTION:
break;
default:
/* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka]
@@ -3264,11 +3322,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Skill Range Criteria
ad.flag |= battle->range_type(src, target, skill_id, skill_lv);
flag.infdef=(tstatus->mode&MD_PLANT?1:0);
- if( target->type == BL_SKILL){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- flag.infdef = 1;
- }
+ if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION )
+ flag.infdef = 1; // Reberberation takes 1 damage
switch(skill_id) {
case MG_FIREWALL:
@@ -3317,11 +3372,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
case AL_HEAL:
case PR_BENEDICTIO:
case PR_SANCTUARY:
+ ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false);
+ break;
/**
* Arch Bishop
**/
case AB_HIGHNESSHEAL:
- ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false);
+ ad.damage = skill->calc_heal(src, target, AL_HEAL, 10, false) * ( 17 + 3 * skill_lv ) / 10;
break;
case PR_ASPERSIO:
ad.damage = 40;
@@ -3336,7 +3393,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = tstatus->hp;
else {
#ifdef RENEWAL
- MATK_ADD(status->get_matk(src, 2));
+ MATK_ADD(status->get_matk(src, 2));
#else
ad.damage = status->get_lv(src) + sstatus->int_ + skill_lv * 10;
#endif
@@ -3350,9 +3407,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
**/
case AB_RENOVATIO:
//Damage calculation from iRO wiki. [Jobbie]
- ad.damage = (int)((15 * status->get_lv(src)) + (1.5 * sstatus->int_));
+ ad.damage = status->get_lv(src) * 10 + sstatus->int_;
break;
- default: {
+ default: {
MATK_ADD( status->get_matk(src, 2) );
if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill
@@ -3364,14 +3421,14 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (sc){
if( sc->data[SC_TELEKINESIS_INTENSE] && s_ele == ELE_GHOST )
- skillratio += sc->data[SC_TELEKINESIS_INTENSE]->val3;
+ ad.damage += sc->data[SC_TELEKINESIS_INTENSE]->val3;
}
switch(skill_id){
case MG_FIREBOLT:
case MG_COLDBOLT:
case MG_LIGHTNINGBOLT:
if ( sc && sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) {
- skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
+ skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax]
ad.flag = BF_WEAPON|BF_SHORT;
ad.type = 0;
@@ -3741,7 +3798,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
case RK_DRAGONBREATH_WATER:
md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
RE_LVL_MDMOD(150);
- if (sd) md.damage = md.damage * (100 + 5 * (pc->checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100;
+ if (sd) md.damage = md.damage * (95 + 5 * pc->checkskill(sd,RK_DRAGONTRAINING)) / 100;
md.flag |= BF_LONG|BF_WEAPON;
break;
/**
@@ -3763,6 +3820,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100);
break;
+ case WM_SOUND_OF_DESTRUCTION:
+ md.damage = 1000 * skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10);
+ md.damage += md.damage * 10 * battle->calc_chorusbonus(sd) / 100;
+ break;
/**
* Mechanic
**/
@@ -3785,8 +3846,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 100 + 200 * skill_lv + sstatus->int_;
break;
case GN_HELLS_PLANT_ATK:
- //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level ))
- md.damage = ( skill_lv * status->get_lv(src) * 10 ) + ( sstatus->int_ * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - (sd?pc->checkskill(sd,AM_CANNIBALIZE):0)) );
+ md.damage = skill_lv * status->get_lv(src) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
+ md.damage = md.damage*(1000 + tstatus->mdef) / (1000 + tstatus->mdef * 10) - tstatus->mdef2;
break;
case KO_HAPPOKUNAI:
{
@@ -3906,10 +3967,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
default:
md.damage = 1;
}
- }else if( target->type == BL_SKILL ){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- md.damage = 1;
}
if(!(nk&NK_NO_ELEFIX))
@@ -3992,11 +4049,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
&& skill_id != HT_FREEZINGTRAP
#endif
?1:0);
- if( target->type == BL_SKILL){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- flag.infdef = 1;
- }
+ if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION )
+ flag.infdef = 1; // Reberberation takes 1 damage
//Initial Values
wd.type=0; //Normal attack
@@ -4180,7 +4234,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW
&& (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){
- int chance = rand()%100;
+ int chance = rnd()%100;
wd.type = 0x08;
switch(sc->data[SC_FEARBREEZE]->val1){
case 5:
@@ -4364,6 +4418,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case GC_VENOMPRESSURE:
hitrate += 10 + 4 * skill_lv;
break;
+ case SC_FATALMENACE:
+ hitrate -= 35 - 5 * skill_lv;
+ break;
case LG_BANISHINGPOINT:
hitrate += 3 * skill_lv;
break;
@@ -4486,16 +4543,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
case CR_SHIELDBOOMERANG:
case PA_SHIELDCHAIN:
- case LG_SHIELDPRESS:
- case LG_EARTHDRIVE:
wd.damage = sstatus->batk;
if (sd) {
+ int damagevalue = 0;
short index = sd->equip_index[EQI_HAND_L];
- if (index >= 0 &&
- sd->inventory_data[index] &&
- sd->inventory_data[index]->type == IT_ARMOR)
- ATK_ADD(sd->inventory_data[index]->weight/10);
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ damagevalue = sd->inventory_data[index]->weight/10;
+ ATK_ADD(damagevalue);
} else
ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
break;
@@ -4568,14 +4623,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
} //End default case
} //End switch(skill_id)
- if( sc && skill_id != PA_SACRIFICE ){
- if( sc->data[SC_UNLIMIT] && wd.flag&BF_LONG )
- ATK_ADD( 50 * sc->data[SC_UNLIMIT]->val1 );
- }
-
- if( tsc && skill_id != PA_SACRIFICE ){
- if( tsc->data[SC_DARKCROW] && wd.flag&BF_SHORT )
- ATK_ADD( 30 * tsc->data[SC_DARKCROW]->val1 );
+ if( sc && skill_id != PA_SACRIFICE && sc->data[SC_UNLIMIT] && (wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) {
+ switch(skill_id) {
+ case RA_WUGDASH:
+ case RA_WUGSTRIKE:
+ case RA_WUGBITE:
+ break;
+ default:
+ ATK_ADD( 50 * sc->data[SC_UNLIMIT]->val1 );
+ }
}
if ( sc && !skill_id && sc->data[SC_EXEEDBREAK] ) {
@@ -4654,12 +4710,40 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case GC_COUNTERSLASH:
ATK_ADD( status_get_agi(src) * 2 + (sd?sd->status.job_level:0) * 4 );
break;
- case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40)
+ case RA_WUGDASH:
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ ATK_ADD(2 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd)));
+ break;
+ case SR_TIGERCANNON:
ATK_ADD( skill_lv * 240 + status->get_lv(target) * 40 );
if( sc && sc->data[SC_COMBOATTACK]
- && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40)
+ && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE )
ATK_ADD( skill_lv * 500 + status->get_lv(target) * 40 );
break;
+ case RA_WUGSTRIKE:
+ case RA_WUGBITE:
+ if(sd)
+ ATK_ADD(30*pc->checkskill(sd, RA_TOOTHOFWUG));
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ ATK_ADD(2 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd)));
+ break;
+ case LG_SHIELDPRESS:
+ if( sd ) {
+ int damagevalue = 0;
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ damagevalue = sstatus->vit * sd->status.inventory[index].refine;
+ ATK_ADD(damagevalue);
+ }
+ break;
+ case SR_GATEOFHELL:
+ ATK_ADD (sstatus->max_hp - status_get_hp(src));
+ if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE) {
+ ATK_ADD( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status->get_lv(src) );
+ } else {
+ ATK_ADD( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status->get_lv(src) );
+ }
+ break;
case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)]
ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str);
if( tsd && tsd->weight ){
@@ -4688,12 +4772,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sc->data[SC_TRUESIGHT] )
ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
#endif
- if( sc->data[SC_GLOOMYDAY_SK] &&
- ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR ||
- skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ||
- skill_id == LG_SHIELDPRESS || skill_id == RK_HUNDREDSPEAR ||
- skill_id == CR_SHIELDCHARGE ) )
- ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2);
#ifndef RENEWAL_EDP
if( sc->data[SC_EDP] ){
@@ -4728,10 +4806,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
sc->data[SC_SOULLINK]->val2 == SL_CRUSADER)
ATK_ADDRATE(100);
break;
- case NC_AXETORNADO:
- if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND )
- ATK_ADDRATE(50);
- break;
}
if( skill_id ){
uint16 rskill;/* redirect skill id */
@@ -5033,6 +5107,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(!flag.lh && wd.damage2)
wd.damage2=0;
+ if( sc && sc->data[SC_GLOOMYDAY] ) {
+ switch( skill_id ) {
+ case KN_BRANDISHSPEAR:
+ case LK_SPIRALPIERCE:
+ case CR_SHIELDCHARGE:
+ case CR_SHIELDBOOMERANG:
+ case PA_SHIELDCHAIN:
+ case RK_HUNDREDSPEAR:
+ case LG_SHIELDPRESS:
+ wd.damage += wd.damage * sc->data[SC_GLOOMYDAY]->val2 / 100;
+ }
+ }
+
if( sc ) {
//SG_FUSION hp penalty [Komurka]
if (sc->data[SC_FUSION]) {
@@ -5055,14 +5142,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage += md.damage;
break;
}
- case SR_GATEOFHELL:
- ATK_ADD (sstatus->max_hp - status_get_hp(src));
- if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE){
- ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status->get_lv(src) );
- }else{
- ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status->get_lv(src) );
- }
- break;
}
if( wd.damage + wd.damage2 ) { //There is a total damage value
@@ -5194,30 +5273,31 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
int64 damage = wd->damage + wd->damage2, rdamage = 0, trdamage = 0;
struct map_session_data *sd, *tsd;
struct status_change *sc;
+ struct status_change *ssc;
int64 tick = timer->gettick();
int delay = 50, rdelay = 0;
#ifdef RENEWAL
int max_reflect_damage;
-
+
max_reflect_damage = max(status_get_max_hp(target), status_get_max_hp(target) * status->get_lv(target) / 100);
#endif
-
+
sd = BL_CAST(BL_PC, src);
-
+
tsd = BL_CAST(BL_PC, target);
sc = status->get_sc(target);
-
+
#ifdef RENEWAL
- #define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, min(max_reflect_damage, (d))) )
+#define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, min(max_reflect_damage, (d))) )
#else
- #define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, (d)) )
+#define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, (d)) )
#endif
-
+
if( sc && !sc->count )
sc = NULL;
-
+
if( sc ) {
-
+
if( sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){
//ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}]
int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status->get_lv(target) / 125;
@@ -5225,31 +5305,31 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
rdamage = rdamage * ratio / 100 + (damage) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10;
skill->blown(target, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit->getdir(src), 0);
clif->skill_damage(target, src, tick, status_get_amotion(src), 0, rdamage,
- 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
+ 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, 0);
status->damage(src, target, status->damage(target, src, rdamage, 0, 0, 1)/10, 0, 0, 1);
status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER);
/* shouldn't this trigger skill->additional_effect? */
return; // Just put here to minimize redundancy
}
-
+
if( wd->flag & BF_SHORT ) {
if( !is_boss(src) ) {
if( sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION ) {
uint8 dir = map->calc_dir(target,src->x,src->y),
- t_dir = unit->getdir(target);
-
+ t_dir = unit->getdir(target);
+
if( !map->check_dir(dir,t_dir) ) {
int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
-
+
trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended.
rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6);
skill->blown(target, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit->getdir(src), 0);
-
+
if( tsd ) /* is this right? rdamage as both left and right? */
battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-
+
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
wd->damage = wd->damage + wd->damage2;
@@ -5258,85 +5338,103 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
}
}
}
-
+
if( sc->data[SC_KYOMU] ){
// Nullify reflecting ability of the conditions onwards
return;
}
-
+
}
-
+
if( wd->flag & BF_SHORT ) {
if ( tsd && tsd->bonus.short_weapon_damage_return ) {
NORMALIZE_RDAMAGE(damage * tsd->bonus.short_weapon_damage_return / 100);
rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
-
+
/* is this right? rdamage as both left and right? */
battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-
+
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
-
- if( sc && wd->dmg_lv >= ATK_BLOCK ) {/* yes block still applies, somehow gravity thinks it makes sense. */
- if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
- NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
-
+
+ if( wd->dmg_lv >= ATK_BLOCK ) {/* yes block still applies, somehow gravity thinks it makes sense. */
+ if( sc ) {
+ if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
+
#ifndef RENEWAL
- rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
#else
- rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4);
+ rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4);
#endif
- /* is this right? rdamage as both left and right? */
- if( tsd )
- battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
- battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-
- delay += 100;/* gradual increase so the numbers don't clip in the client */
- }
- if( sc->data[SC_LG_REFLECTDAMAGE] && rand()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) {
- bool change = false;
+ /* is this right? rdamage as both left and right? */
+ if( tsd )
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
- 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;
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
+ if( sc->data[SC_LG_REFLECTDAMAGE] && rand()%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;
+ }
+
+ 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;
+
+ delay += 150;/* gradual increase so the numbers don't clip in the client */
+
+ if( (--sc->data[SC_LG_REFLECTDAMAGE]->val3) <= 0 )
+ status_change_end(target, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ }
+ if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100);
+
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+
+ /* is this right? rdamage as both left and right? */
+ if( tsd )
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
}
-
- 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;
-
- delay += 150;/* gradual increase so the numbers don't clip in the client */
}
- if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){
- NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100);
-
- rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+ if( ( ssc = status->get_sc(src) ) ) {
+ if( ssc->data[SC_INSPIRATION] ) {
+ NORMALIZE_RDAMAGE(damage / 100);
+
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
- /* is this right? rdamage as both left and right? */
- if( tsd )
+ /* is this right? rdamage as both left and right? */
battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
- battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-
- delay += 100;/* gradual increase so the numbers don't clip in the client */
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
}
}
} else {/* long */
if ( tsd && tsd->bonus.long_weapon_damage_return ) {
NORMALIZE_RDAMAGE(damage * tsd->bonus.long_weapon_damage_return / 100);
-
+
rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
-
+
/* is this right? rdamage as both left and right? */
battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-
+
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
}
@@ -5345,12 +5443,12 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
// Tell Clang's static analyzer that we want to += it even the value is currently unused (it'd be used if we added new checks)
(void)delay;
#endif // __clang_analyzer
-
+
/* something caused reflect */
if( trdamage ) {
skill->additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
}
-
+
return;
#undef NORMALIZE_RDAMAGE
}
@@ -5958,12 +6056,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case MS_MAGNUM:
case RA_DETONATOR:
case RA_SENSITIVEKEEN:
- case GN_CRAZYWEED_ATK:
case RK_STORMBLAST:
- case RK_PHANTOMTHRUST:
case SR_RAMPAGEBLASTER:
case NC_COLDSLOWER:
- case NC_SELFDESTRUCTION:
#ifdef RENEWAL
case KN_BOWLINGBASH:
case KN_SPEARSTAB:
@@ -5985,14 +6080,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
strip_enemy = 0;
break;
default:
- if(su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD){
- state |= BCT_ENEMY;
- strip_enemy = 0;
- }else
- return 0;
+ return 0;
}
} else if (su->group->skill_id==WZ_ICEWALL ||
- su->group->skill_id == GN_WALLOFTHORN) {
+ su->group->skill_id == GN_WALLOFTHORN) {
state |= BCT_ENEMY;
strip_enemy = 0;
} else //Excepting traps and icewall, you should not be able to target skills.
@@ -6957,6 +7048,7 @@ void battle_defaults(void) {
battle->calc_cardfix = battle_calc_cardfix;
battle->calc_elefix = battle_calc_elefix;
battle->calc_masteryfix = battle_calc_masteryfix;
+ battle->calc_chorusbonus = battle_calc_chorusbonus;
battle->calc_skillratio = battle_calc_skillratio;
battle->calc_sizefix = battle_calc_sizefix;
battle->calc_weapon_damage = battle_calc_weapon_damage;
diff --git a/src/map/battle.h b/src/map/battle.h
index 0fcef7292..b57476cb4 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -540,6 +540,8 @@ struct battle_interface {
int64 (*calc_elefix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag);
/* applies mastery modifiers */
int64 (*calc_masteryfix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon);
+ /* calculates chorus bonus */
+ int (*calc_chorusbonus) (struct map_session_data *sd);
/* applies skill modifiers */
int (*calc_skillratio) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag);
/* applies size modifiers */
diff --git a/src/map/clif.c b/src/map/clif.c
index 83a3c37bd..b00e99f78 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9753,7 +9753,7 @@ void clif_disconnect_ack(struct map_session_data* sd, short result)
void clif_parse_QuitGame(int fd, struct map_session_data *sd)
{
/* Rovert's prevent logout option fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] &&
+ if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
(!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{
set_eof(fd);
@@ -9832,7 +9832,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay ) { //[Skotlex]
@@ -10081,6 +10081,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
(sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_AUTOCOUNTER] ||
sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_DEEP_SLEEP] ||
sd->sc.data[SC__MANHOLE] ||
sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
sd->sc.data[SC_CURSEDCIRCLE_TARGET] ))
@@ -10102,7 +10103,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST) )
return;
- if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] )
+ if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ||
+ (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) )
return;
if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) {
@@ -10307,7 +10309,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
break;
case 0x01:
/* Rovert's Prevent logout option - Fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] &&
+ if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
(!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{ //Send to char-server for character selection.
chrif->charselectreq(sd, session[fd]->client_addr);
@@ -10336,7 +10338,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if ( atcommand->exec(fd, sd, message, true) )
return;
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))
+ if (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))
return;
if (battle_config.min_chat_delay) { //[Skotlex]
@@ -12157,7 +12159,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay )
@@ -13221,7 +13223,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay )
@@ -16211,7 +16213,7 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd)
if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay ) {
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index c399a0442..eebcd5d4d 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -70,6 +70,7 @@ enum item_itemid {
ITEMID_PHRACON = 1010,
ITEMID_EMVERETARCON = 1011,
ITEMID_TRAP = 1065,
+ ITEMID_PILEBUNCKER = 1549,
ITEMID_ANGRA_MANYU = 1599,
ITEMID_STRANGE_EMBRYO = 6415,
ITEMID_FACE_PAINT = 6120,
@@ -108,6 +109,9 @@ enum item_itemid {
ITEMID_BULGING_HEAD = 12309,
ITEMID_THICK_MANUAL50 = 12312,
ITEMID_ANCILLA = 12333,
+ ITEMID_REPAIR_A = 12392,
+ ITEMID_REPAIR_B = 12393,
+ ITEMID_REPAIR_C = 12394,
ITEMID_BLACK_THING = 12435,
ITEMID_REINS_OF_MOUNT = 12622,
ITEMID_NOBLE_NAMEPLATE = 12705,
diff --git a/src/map/map.c b/src/map/map.c
index 96595caae..4bc272035 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2563,8 +2563,6 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
return (cell.novending);
case CELL_CHKNOCHAT:
return (cell.nochat);
- case CELL_CHKMAELSTROM:
- return (cell.maelstrom);
case CELL_CHKICEWALL:
return (cell.icewall);
@@ -2625,7 +2623,6 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
case CELL_LANDPROTECTOR: map->list[m].cell[j].landprotector = flag; break;
case CELL_NOVENDING: map->list[m].cell[j].novending = flag; break;
case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break;
- case CELL_MAELSTROM: map->list[m].cell[j].maelstrom = flag; break;
case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break;
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
diff --git a/src/map/map.h b/src/map/map.h
index a4e9499b3..438027917 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -443,7 +443,6 @@ typedef enum {
CELL_LANDPROTECTOR,
CELL_NOVENDING,
CELL_NOCHAT,
- CELL_MAELSTROM,
CELL_ICEWALL,
} cell_t;
@@ -467,7 +466,6 @@ typedef enum {
CELL_CHKLANDPROTECTOR,
CELL_CHKNOVENDING,
CELL_CHKNOCHAT,
- CELL_CHKMAELSTROM,
CELL_CHKICEWALL,
} cell_chk;
@@ -486,7 +484,6 @@ struct mapcell {
landprotector : 1,
novending : 1,
nochat : 1,
- maelstrom : 1,
icewall : 1;
#ifdef CELL_NOSTACK
diff --git a/src/map/mob.c b/src/map/mob.c
index 30658051c..7195d3edd 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -1412,7 +1412,8 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
// Abnormalities
if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
- || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets.
+ || md->sc.data[SC_DEEP_SLEEP] || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {
+ //Should reset targets.
md->target_id = md->attacked_id = 0;
return false;
}
@@ -1465,7 +1466,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
}
}
else
- if( (abl = map->id2bl(md->attacked_id)) && (!tbl || mob->can_changetarget(md, abl, mode)) ) {
+ if( (abl = map->id2bl(md->attacked_id)) && (!tbl || mob->can_changetarget(md, abl, mode) || (md->sc.count && md->sc.data[SC__CHAOS]))) {
int dist;
if( md->bl.m != abl->m || abl->prev == NULL
|| (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area
@@ -1528,7 +1529,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) {
map->foreachinrange (mob->ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode);
- } else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) {
+ } else if ((mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) || (md->sc.count && md->sc.data[SC__CHAOS])) {
int search_size;
search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range;
map->foreachinrange (mob->ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl);
diff --git a/src/map/party.c b/src/map/party.c
index 9f144297d..a299c540e 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -1108,6 +1108,22 @@ int party_vforeachsamemap(int (*func)(struct block_list*,va_list), struct map_se
return total;
}
+// Special check for Minstrel's and Wanderer's chorus skills.
+int party_sub_count_chorus(struct block_list *bl, va_list ap) {
+ struct map_session_data *sd = (TBL_PC *)bl;
+
+ if (sd->state.autotrade)
+ return 0;
+
+ if (battle_config.idle_no_share && pc_isidle(sd))
+ return 0;
+
+ if ( (sd->class_&MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER )
+ return 0;
+
+ return 1;
+}
+
/**
* Executes 'func' for each party member on the same map and within a 'range' cells area
* @param func Function to execute
@@ -1393,6 +1409,7 @@ void party_defaults(void) {
party->share_loot = party_share_loot;
party->send_dot_remove = party_send_dot_remove;
party->sub_count = party_sub_count;
+ party->sub_count_chorus = party_sub_count_chorus;
party->booking_register = party_booking_register;
party->booking_update = party_booking_update;
party->booking_search = party_booking_search;
diff --git a/src/map/party.h b/src/map/party.h
index 05b5309e6..ed8289af6 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -115,6 +115,7 @@ struct party_interface {
int (*share_loot) (struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid);
int (*send_dot_remove) (struct map_session_data *sd);
int (*sub_count) (struct block_list *bl, va_list ap);
+ int (*sub_count_chorus) (struct block_list *bl, va_list ap);
/*==========================================
* Party Booking in KRO [Spiria]
*------------------------------------------*/
diff --git a/src/map/pc.c b/src/map/pc.c
index 3c0fca33a..e3b5a2586 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1450,7 +1450,6 @@ int pc_calc_skilltree(struct map_session_data *sd)
case WL_SUMMON_ATK_GROUND:
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND_PLUSATK:
- case WM_SEVERE_RAINSTORM_MELEE:
continue;
default:
break;
@@ -4265,7 +4264,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
case ITEMID_M_BERSERK_POTION:
if( sd->md == NULL || sd->md->db == NULL )
return 0;
- if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAY_NIGHT_FEVER])
+ if (sd->md->sc.data[SC_BERSERK])
return 0;
if( nameid == ITEMID_M_AWAKENING_POTION && sd->md->db->lv < 40 )
return 0;
@@ -4389,9 +4388,12 @@ int pc_useitem(struct map_session_data *sd,int n) {
sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_HIDING] ||
sd->sc.data[SC__SHADOWFORM] ||
+ sd->sc.data[SC__INVISIBILITY] ||
sd->sc.data[SC__MANHOLE] ||
sd->sc.data[SC_KG_KAGEHUMI] ||
sd->sc.data[SC_WHITEIMPRISON] ||
+ sd->sc.data[SC_DEEP_SLEEP] ||
+ sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
))
return 0;
@@ -4945,6 +4947,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);//Will later check if this is needed. [Rytech]
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD, INVALID_TIMER);
if (sd->sc.data[SC_KNOWLEDGE]) {
struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
if (sce->timer != INVALID_TIMER)
@@ -7549,6 +7555,11 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
}
+ if( sd->sc.data[SC_VITALITYACTIVATION] ){
+ hp += hp / 2; // 1.5 times
+ sp -= sp / 2;
+ }
+
if ( sd->sc.data[SC_DEATHHURT] ) {
hp -= hp * 20 / 100;
sp -= sp * 20 / 100;
@@ -8629,7 +8640,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
return 0;
}
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER])
+ if (sd->sc.data[SC_BERSERK])
{
clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
@@ -8833,7 +8844,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
}
// if player is berserk then cannot unequip
- if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER]))
+ if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK]))
{
clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
diff --git a/src/map/skill.c b/src/map/skill.c
index 2c2ed0d6c..5491e6268 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -374,6 +374,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
if( tsd && (skill2_lv = pc->skillheal2_bonus(tsd, skill_id)) )
hp += hp*skill2_lv/100;
+ sc = status->get_sc(src);
+ if( sc && sc->count && sc->data[SC_OFFERTORIUM] ) {
+ if( skill_id == AB_HIGHNESSHEAL || skill_id == AB_CHEAL || skill_id == PR_SANCTUARY || skill_id == AL_HEAL )
+ hp += hp * sc->data[SC_OFFERTORIUM]->val2 / 100;
+ }
sc = status->get_sc(target);
if( sc && sc->count ) {
if( sc->data[SC_CRITICALWOUND] && heal ) // Critical Wound has no effect on offensive heal. [Inkfish]
@@ -384,8 +389,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
hp += hp * sc->data[SC_HEALPLUS]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
hp += hp / 10;
- if( sc->data[SC_OFFERTORIUM] && (skill_id == AB_HIGHNESSHEAL || skill_id == AB_CHEAL || skill_id == PR_SANCTUARY || skill_id == AL_HEAL) )
- hp += hp * sc->data[SC_OFFERTORIUM]->val2 / 100;
+ if ( sc && sc->data[SC_VITALITYACTIVATION] )
+ hp = hp * 150 / 100;
}
#ifdef RENEWAL
@@ -426,7 +431,7 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
return 0;
// Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie]
- if( !(sd->sc.data[SC__REPRODUCE]) && (skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) )
+ if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) || (skill_id >= KO_YAMIKUMO && skill_id <= OB_AKAITSUKI)))
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] )
@@ -554,11 +559,10 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
}
break;
- case WM_SIRCLEOFNATURE:
- case WM_SOUND_OF_DESTRUCTION:
case SC_MANHOLE:
- case WM_LULLABY_DEEPSLEEP:
+ case WM_SOUND_OF_DESTRUCTION:
case WM_SATURDAY_NIGHT_FEVER:
+ case WM_LULLABY_DEEPSLEEP:
if( !map_flag_vs(m) ) {
clif->skill_mapinfomessage(sd,2); // This skill uses this msg instead of skill fails.
return 1;
@@ -1113,25 +1117,18 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case NPC_CRITICALWOUND:
sc_start(bl,SC_CRITICALWOUND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case RK_HUNDREDSPEAR:
- if( !sd || pc->checkskill(sd,KN_SPEARBOOMERANG) == 0 )
- break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang.
- rate = 10 + 3 * skill_lv;
- if( rnd()%100 < rate )
- skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0);
- break;
case RK_WINDCUTTER:
sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case RK_DRAGONBREATH:
- sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
+ sc_start4(bl,SC_BURNING,15,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv));
break;
case RK_DRAGONBREATH_WATER:
- sc_start(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start4(bl,SC_FROSTMISTY,15,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv));
break;
case AB_ADORAMUS:
if( tsc && !tsc->data[SC_DEC_AGI] ) //Prevent duplicate agi-down effect.
- sc_start(bl, SC_ADORAMUS, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(bl, SC_ADORAMUS, skill_lv * 4 + (sd? sd->status.job_level:50)/2, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case WL_CRIMSONROCK:
sc_start(bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv));
@@ -1141,10 +1138,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case WL_EARTHSTRAIN:
{
- // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett]
- const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC };
- skill->strip_equip(bl, pos[skill_lv-1], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10,
- skill_lv, skill->get_time2(skill_id,skill_lv));
+ int i;
+ const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC };
+
+ for( i = 0; i < skill_lv; i++ )
+ skill->strip_equip(bl,pos[i], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10,
+ skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
case WL_JACKFROST:
@@ -1154,35 +1153,54 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
sc_start(bl,SC_FROSTMISTY,25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case RA_WUGBITE:
- sc_start(bl, SC_WUGBITE, (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill->get_time(skill_id,skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) );
+ rate = 50 + 10 * skill_lv + 2 * (sd ? pc->checkskill(sd,RA_TOOTHOFWUG) : 0) - tstatus->agi / 4;
+ if ( rate < 50 )
+ rate = 50;
+ sc_start(bl,SC_WUGBITE, rate, skill_lv, skill->get_time(skill_id, skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG) * 500 : 0));
break;
case RA_SENSITIVEKEEN:
if( rnd()%100 < 8 * skill_lv )
skill->castend_damage_id(src, bl, RA_WUGBITE, sd ? pc->checkskill(sd, RA_WUGBITE):skill_lv, tick, SD_ANIMATION);
break;
+ case RA_MAGENTATRAP:
+ case RA_COBALTTRAP:
+ case RA_MAIZETRAP:
+ case RA_VERDURETRAP:
+ if( dstmd && !(dstmd->status.mode&MD_BOSS) )
+ sc_start2(bl,SC_ARMOR_PROPERTY,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time2(skill_id,skill_lv));
+ break;
case RA_FIRINGTRAP:
case RA_ICEBOUNDTRAP:
- sc_start4(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FROSTMISTY, 40 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
+ sc_start4(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FROSTMISTY, 50 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
break;
case NC_PILEBUNKER:
- if( rnd()%100 < 5 + 15*skill_lv )
- { //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield
+ if( rnd()%100 < 25 + 15 *skill_lv ) {
+ //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
- status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER);
- status_change_end(bl, SC_STEELBODY, INVALID_TIMER);
status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ status_change_end(bl, SC_STEELBODY, INVALID_TIMER);
+ status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
+ status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
+ status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER);
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ status_change_end(bl, SC_DEFENDER, INVALID_TIMER);
+ status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ status_change_end(bl, SC_PRESTIGE, INVALID_TIMER);
+ status_change_end(bl, SC_BANDING, INVALID_TIMER);
status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER);
}
break;
case NC_FLAMELAUNCHER:
- sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
+ sc_start4(bl, SC_BURNING, 20 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
break;
case NC_COLDSLOWER:
sc_start(bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
- sc_start(bl, SC_FROSTMISTY, 20 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ if ( tsc && !tsc->data[SC_FREEZE] )
+ sc_start(bl, SC_FROSTMISTY, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
break;
case NC_POWERSWING:
- sc_start(bl, SC_STUN, 5*skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ // Use flag=2, the stun duration is not vit-reduced.
+ status->change_start(bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 2);
if( rnd()%100 < 5*skill_lv )
skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc->checkskill(sd, NC_AXEBOOMERANG), tick, 1);
break;
@@ -1194,23 +1212,29 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
skill->castend_nodamage_id(src,bl,skill_id,skill_lv,tick,BCT_ENEMY);
break;
case GC_DARKCROW:
- sc_start(bl, SC_DARKCROW, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(bl, SC_DARKCROW, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case LG_SHIELDPRESS:
- sc_start(bl, SC_STUN, 30 + 8 * skill_lv, skill_lv, skill->get_time(skill_id,skill_lv));
+ rate = 30 + 8 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level:0) / 4;
+ sc_start(bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
break;
case LG_PINPOINTATTACK:
- rate = 30 + (((5 * (sd?pc->checkskill(sd,LG_PINPOINTATTACK):skill_lv)) + (sstatus->agi + status->get_lv(src))) / 10);
+ rate = 30 + 5 * (sd ? pc->checkskill(sd,LG_PINPOINTATTACK) : 1) + (sstatus->agi + status->get_lv(src)) / 10;
switch( skill_lv ) {
case 1:
- sc_start2(bl,SC_BLOODING,rate,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
+ sc_start(bl,SC_BLOODING,rate,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case 2:
- if( dstsd && dstsd->spiritball && rnd()%100 < rate )
- pc->delspiritball(dstsd, dstsd->spiritball, 0);
+ skill->break_equip(bl, EQP_HELM, rate*100, BCT_ENEMY);
break;
- default:
- skill->break_equip(bl,(skill_lv == 3) ? EQP_SHIELD : (skill_lv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY);
+ case 3:
+ skill->break_equip(bl, EQP_SHIELD, rate*100, BCT_ENEMY);
+ break;
+ case 4:
+ skill->break_equip(bl, EQP_ARMOR, rate*100, BCT_ENEMY);
+ break;
+ case 5:
+ skill->break_equip(bl, EQP_WEAPON, rate*100, BCT_ENEMY);
break;
}
break;
@@ -1226,7 +1250,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
sc_start(bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv));
break;
case LG_EARTHDRIVE:
- skill->break_equip(src, EQP_SHIELD, 500, BCT_SELF);
+ skill->break_equip(src, EQP_SHIELD, 100 * skill_lv, BCT_SELF);
sc_start(bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SR_DRAGONCOMBO:
@@ -1250,71 +1274,39 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case SR_HOWLINGOFLION:
sc_start(bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
- case WM_SOUND_OF_DESTRUCTION:
- if( rnd()%100 < 5 + 5 * skill_lv ) { // Temporarly Check Until We Get the Official Formula
- status_change_end(bl, SC_DANCING, INVALID_TIMER);
- status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER);
- status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER);
- status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER);
- status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER);
- status_change_end(bl, SC_INTOABYSS, INVALID_TIMER);
- status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER);
- status_change_end(bl, SC_WHISTLE, INVALID_TIMER);
- status_change_end(bl, SC_ASSNCROS, INVALID_TIMER);
- status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER);
- status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER);
- status_change_end(bl, SC_HUMMING, INVALID_TIMER);
- status_change_end(bl, SC_FORTUNE, INVALID_TIMER);
- status_change_end(bl, SC_SERVICEFORYOU, INVALID_TIMER);
- status_change_end(bl, SC_LONGING, INVALID_TIMER);
- status_change_end(bl, SC_SWING, INVALID_TIMER);
- status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
- status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
- status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
- status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
- status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
- status_change_end(bl, SC_DC_WINKCHARM, INVALID_TIMER);
- status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
- status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
- status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
- status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
- status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- }
- break;
case SO_EARTHGRAVE:
sc_start2(bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
break;
case SO_DIAMONDDUST:
rate = 5 + 5 * skill_lv;
if( sc && sc->data[SC_COOLER_OPTION] )
- rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100;
+ rate += sc->data[SC_COOLER_OPTION]->val3 / 5;
sc_start(bl, SC_COLD, rate, skill_lv, skill->get_time2(skill_id, skill_lv));
break;
case SO_VARETYR_SPEAR:
- sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
+ sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case GN_SLINGITEM_RANGEMELEEATK:
if( sd ) {
switch( sd->itemid ) { // Starting SCs here instead of do it in skill->additional_effect to simplify the code.
case ITEMID_COCONUT_BOMB:
- sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(GN_SLINGITEM, skill_lv));
- sc_start2(bl, SC_BLOODING, 100, skill_lv, src->id, skill->get_time2(GN_SLINGITEM, skill_lv));
+ sc_start(bl, SC_STUN, 100, skill_lv, 5000); // 5 seconds until I get official
+ sc_start(bl, SC_BLOODING, 100, skill_lv, 10000);
break;
case ITEMID_MELON_BOMB:
- sc_start(bl, SC_MELON_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces ASPD and moviment speed
+ sc_start(bl, SC_MELON_BOMB, 100, skill_lv, 60000); // Reduces ASPD and moviment speed
break;
case ITEMID_BANANA_BOMB:
- sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE?
- sc_start(bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, 75, skill_lv, skill->get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds.
+ sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, 60000); // Reduces LUK? Needed confirm it, may be it's bugged in kRORE?
+ sc_start(bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, (sd? sd->status.job_level:0) + sstatus->dex / 6 + tstatus->agi / 4 - tstatus->luk / 5 - status->get_lv(bl) + status->get_lv(src), skill_lv, 1000); // Sitdown for 3 seconds.
break;
}
sd->itemid = -1;
}
break;
case GN_HELLS_PLANT_ATK:
- sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
- sc_start2(bl, SC_BLOODING, 20 + 10 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv));
+ sc_start(bl, SC_STUN, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
+ sc_start2(bl, SC_BLOODING, 5 + 5 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv));
break;
case EL_WIND_SLASH: // Non confirmed rate.
sc_start2(bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
@@ -2044,7 +2036,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
break;
case BL_SKILL:
su = (struct skill_unit *)target;
- if( su && su->group && su->group->unit_id == UNT_ANKLESNARE )
+ if( su && su->group && (su->group->unit_id == UNT_ANKLESNARE || su->group->unit_id == UNT_REVERBERATION))
return 0; // ankle snare cannot be knocked back
break;
}
@@ -2428,18 +2420,23 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case EL_HURRICANE:
case EL_HURRICANE_ATK:
case KO_BAKURETSU:
- case GN_CRAZYWEED_ATK:
case NC_MAGMA_ERUPTION:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
break;
case GN_SLINGITEM_RANGEMELEEATK:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6);
break;
+ case SC_FEINTBOMB:
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,5);
+ break;
+ case GN_CRAZYWEED_ATK:
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id, -2, 6);
+ break;
case EL_STONE_RAIN:
dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5);
break;
case WM_SEVERE_RAINSTORM_MELEE:
- dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skill_lv,5);
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6);
break;
case WM_REVERBERATION_MELEE:
case WM_REVERBERATION_MAGIC:
@@ -2514,6 +2511,9 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case GN_HELLS_PLANT_ATK:
copy_skill = GN_HELLS_PLANT;
break;
+ case GN_SLINGITEM_RANGEMELEEATK:
+ copy_skill = GN_SLINGITEM;
+ break;
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND_PLUSATK:
copy_skill = LG_OVERBRAND;
@@ -2614,7 +2614,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
break;
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
- dir = rand()%8;
+ dir = rnd()%8;
break;
case WL_CRIMSONROCK:
dir = map->calc_dir(bl,skill->area_temp[4],skill->area_temp[5]);
@@ -2641,11 +2641,6 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
skill->addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
}
break;
- case GN_WALLOFTHORN:
- unit->stop_walking(bl,1);
- skill->blown(dsrc,bl,dmg.blewcount,dir, 0x2 );
- clif->fixpos(bl);
- break;
default:
skill->blown(dsrc,bl,dmg.blewcount,dir, 0x0 );
if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){
@@ -2729,8 +2724,11 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
{
struct status_change *ssc = status->get_sc(src);
if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) {
- sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1));
- status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER);
+ short rate = 100;
+ if ( ssc->data[SC_POISONINGWEAPON]->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5;
+ sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,rate,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ status_change_end(src,SC_POISONINGWEAPON,-1);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
}
@@ -2815,7 +2813,8 @@ int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
case MG_SAFETYWALL:
case AL_PNEUMA:
case SC_MAELSTROM:
- if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM)
+ case SO_ELEMENTAL_SHIELD:
+ if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM && g_skill_id != SO_ELEMENTAL_SHIELD)
return 0;
break;
case AL_WARP:
@@ -2844,6 +2843,8 @@ int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
case RA_ICEBOUNDTRAP:
case SC_DIMENSIONDOOR:
case SC_BLOODYLUST:
+ case SC_CHAOSPANIC:
+ case GN_HELLS_PLANT:
//Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set)
if (skill_id != g_skill_id && !(skill->get_inf2(g_skill_id)&INF2_TRAP) && g_skill_id != AS_VENOMDUST && g_skill_id != MH_POISON_MIST)
return 0;
@@ -2896,6 +2897,12 @@ int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_i
case WZ_ICEWALL:
range = 2;
break;
+ case SC_MANHOLE:
+ range = 0;
+ break;
+ case GN_HELLS_PLANT:
+ range = 0;
+ break;
default: {
int layout_type = skill->get_unit_layout_type(skill_id,skill_lv);
if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
@@ -3162,15 +3169,15 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
break;
case WM_REVERBERATION_MELEE:
case WM_REVERBERATION_MAGIC:
- skill->castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets
+ skill->attack(skill->get_type(skl->skill_id),src, src, target, skl->skill_id, skl->skill_lv, 0, SD_LEVEL);
break;
case SC_FATALMENACE:
if( src == target ) // Casters Part
- unit->warp(src, -1, skl->x, skl->y, 3);
+ unit->warp(src, -1, skl->x, skl->y, CLR_TELEPORT);
else { // Target's Part
short x = skl->x, y = skl->y;
map->search_freecell(NULL, target->m, &x, &y, 2, 2, 1);
- unit->warp(target,-1,x,y,3);
+ unit->warp(target,-1,x,y,CLR_TELEPORT);
}
break;
case LG_MOONSLASHER:
@@ -3200,6 +3207,9 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
const enum e_skill combos[] = {SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW};
if( (sd = ((TBL_PC*)src)) ){
uint16 cid = combos[skl->skill_id-SR_FLASHCOMBO_ATK_STEP1];
+ if( distance_xy(src->x, src->y, target->x, target->y) >= 3 )
+ break;
+ skill->consume_requirement(sd,cid,pc->checkskill(sd, cid),1);
skill->castend_damage_id(src, target, cid, pc->checkskill(sd, cid), tick, 0);
}
}
@@ -3211,6 +3221,14 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
skill->addtimerskill(src,tick+80,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type+1,0);
}
break;
+ case RK_HUNDREDSPEAR:
+ if(src->type == BL_PC) {
+ int skill_lv = pc->checkskill((TBL_PC *)src, KN_SPEARBOOMERANG);
+ if(skill_lv > 0)
+ skill->attack(BF_WEAPON, src, src, target, KN_SPEARBOOMERANG, skill_lv, tick, skl->flag);
+ } else
+ skill->attack(BF_WEAPON, src, src, target, KN_SPEARBOOMERANG, 1, tick, skl->flag);
+ break;
case CH_PALMSTRIKE:
{
struct status_change* tsc = status->get_sc(target);
@@ -3241,11 +3259,6 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag);
break;
- case GN_CRAZYWEED_ATK:
- {
- int dummy = 1, i = skill->get_unit_range(skl->skill_id,skl->skill_lv);
- map->foreachinarea(skill->cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src);
- }
// fall through ...
case WL_EARTHSTRAIN:
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag);
@@ -3262,6 +3275,14 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
map->foreachinarea(skill->area_sub, src->m, x, y, x2, y2, BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, skl->flag|BCT_ENEMY|SD_ANIMATION|1,skill->castend_damage_id);
}
break;
+ case GN_CRAZYWEED:
+ if( skl->type >= 0 ) {
+ int x = skl->type>>16, y = skl->type&0xFFFF;
+ if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ skill->castend_pos2(src, x, y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
+ } else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ skill->castend_pos2(src, skl->x, skl->y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
+ break;
}
}
} while (0);
@@ -3330,14 +3351,16 @@ int skill_cleartimerskill (struct block_list *src)
}
return 1;
}
-int skill_activate_reverbetion( struct block_list *bl, va_list ap) {
+int skill_activate_reverberation(struct block_list *bl, va_list ap) {
struct skill_unit *su = (TBL_SKILL*)bl;
struct skill_unit_group *sg;
if( bl->type != BL_SKILL )
return 0;
- if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) {
- map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, timer->gettick());
- su->limit=DIFF_TICK32(timer->gettick(),sg->tick);
+ if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) {
+ int64 tick = timer->gettick();
+ clif->changetraplook(bl,UNT_USED_TRAPS);
+ map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, tick);
+ su->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
}
return 0;
@@ -3486,7 +3509,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NPC_CRITICALWOUND:
case NPC_HELLPOWER:
case RK_SONICWAVE:
- case RK_HUNDREDSPEAR:
case RK_STORMBLAST:
case RK_CRUSHSTRIKE:
case AB_DUPLELIGHT_MELEE:
@@ -3508,6 +3530,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SR_GENTLETOUCH_QUIET:
case WM_SEVERE_RAINSTORM_MELEE:
case WM_GREAT_ECHO:
+ case GN_CRAZYWEED_ATK:
case GN_SLINGITEM_RANGEMELEEATK:
case KO_JYUMONJIKIRI:
case KO_SETSUDAN:
@@ -3522,9 +3545,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
**/
case NC_BOOSTKNUCKLE:
case NC_PILEBUNKER:
- case NC_VULCANARM:
case NC_COLDSLOWER:
- case NC_ARMSCANNON:
if (sd) pc->overheat(sd,1);
case RK_WINDCUTTER:
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION);
@@ -3720,6 +3741,8 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case WL_JACKFROST:
case RA_ARROWSTORM:
case RA_WUGDASH:
+ case NC_VULCANARM:
+ case NC_ARMSCANNON:
case NC_SELFDESTRUCTION:
case NC_AXETORNADO:
case GC_ROLLINGCUTTER:
@@ -3731,9 +3754,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SR_SKYNETBLOW:
case SR_WINDMILL:
case SR_RIDEINLIGHTNING:
- case WM_SOUND_OF_DESTRUCTION:
- case WM_REVERBERATION_MELEE:
- case WM_REVERBERATION_MAGIC:
+ case WM_REVERBERATION:
case SO_VARETYR_SPEAR:
case GN_CART_TORNADO:
case GN_CARTCANNON:
@@ -3784,8 +3805,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->area_temp[4] = bl->x;
skill->area_temp[5] = bl->y;
}
- if( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )
- skill->area_temp[1] = 0;
+
+ if( skill_id == NC_VULCANARM )
+ if (sd) pc->overheat(sd,1);
+
// if skill damage should be split among targets, count them
//SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets
//special case: Venom Splasher uses a different range for searching than for splashing
@@ -3793,7 +3816,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
// recursive invocation of skill->castend_damage_id() with flag|1
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), ( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
}
break;
@@ -4006,7 +4029,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if( (tsc = status->get_sc(bl)) && (tsc->data[SC_HIDING] )) {
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
} else
- skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
}
break;
case NPC_SELFDESTRUCTION: {
@@ -4065,13 +4088,28 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(src, SC_HIDING, INVALID_TIMER);
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
+ case RK_HUNDREDSPEAR:
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ if(rnd()%100 < (10 + 3*skill_lv)) {
+ if( !sd || pc->checkskill(sd,KN_SPEARBOOMERANG) == 0 )
+ break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang.
+ skill->blown(src,bl,6,-1,0);
+ skill->addtimerskill(src,tick+800,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
+ skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0);
+ }
+ break;
case RK_PHANTOMTHRUST:
+ {
+ struct map_session_data *tsd = BL_CAST(BL_PC, bl);
unit->setdir(src,map->calc_dir(src, bl->x, bl->y));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
skill->blown(src,bl,distance_bl(src,bl)-1,unit->getdir(src),0);
- if( battle->check_target(src,bl,BCT_ENEMY) > 0 )
+ if( sd && tsd && sd->status.party_id && sd->status.party_id && sd->status.party_id == tsd->status.party_id ) // Don't damage party members.
+ ; // No damage to Members
+ else
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ }
break;
case GC_DARKILLUSION:
@@ -4155,7 +4193,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
types[x][1] = 25; // 25% each for equal sharing
if( x == 3 ){
x = 0;
- sc_index = types[rand()%4][0];
+ sc_index = types[rnd()%4][0];
for(; x < 4; x++)
if(types[x][0] == sc_index)
rate += types[x][1];
@@ -4185,7 +4223,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if ( s == 0 )
break;
- i = spell[s==1?0:rand()%s];// Random select of spell to be released.
+ i = spell[s==1?0:rnd()%s];// Random select of spell to be released.
if( s && sc->data[i] ){// Now extract the data from the preserved spell
spell_skill_id = sc->data[i]->val1;
spell_skill_lv = sc->data[i]->val2;
@@ -4217,7 +4255,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
sd->ud.canact_tick = tick + skill->delay_fix(src, spell_skill_id, spell_skill_lv);
clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0);
- cooldown = skill_get_cooldown(spell_skill_id, spell_skill_lv);
+ cooldown = skill->get_cooldown(spell_skill_id, spell_skill_lv);
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) {
if (sd->skillcooldown[i].id == spell_skill_id){
cooldown += sd->skillcooldown[i].val;
@@ -4297,8 +4335,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NC_INFRAREDSCAN:
if( flag&1 ) {
//TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie]
- if( rnd()%100 < 50 )
- sc_start(bl, SC_INFRAREDSCAN, 10000, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(bl, SC_INFRAREDSCAN, 10000, skill_lv, skill->get_time(skill_id, skill_lv));
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it.
@@ -4333,8 +4370,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
break;
case LG_SHIELDSPELL:
- // flag&1: Phisycal Attack, flag&2: Magic Attack.
- skill->attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
+ if ( skill_lv == 1 )
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ else if ( skill_lv == 2 )
+ skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
break;
case SR_DRAGONCOMBO:
@@ -4360,9 +4399,13 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
- status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
+ status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
@@ -4381,6 +4424,39 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
}
break;
+ case WM_SOUND_OF_DESTRUCTION:
+ {
+ struct status_change *tsc = status->get_sc(bl);
+ if( tsc && tsc->count && ( tsc->data[SC_SWING] || tsc->data[SC_SYMPHONY_LOVE] || tsc->data[SC_MOONLIT_SERENADE] ||
+ tsc->data[SC_RUSH_WINDMILL] || tsc->data[SC_ECHOSONG] || tsc->data[SC_HARMONIZE] ||
+ tsc->data[SC_SIREN] || tsc->data[SC_DEEP_SLEEP] || tsc->data[SC_SIRCLEOFNATURE] ||
+ tsc->data[SC_GLOOMYDAY] || tsc->data[SC_SONG_OF_MANA] ||
+ tsc->data[SC_DANCE_WITH_WUG] || tsc->data[SC_SATURDAY_NIGHT_FEVER] || tsc->data[SC_LERADS_DEW] ||
+ tsc->data[SC_MELODYOFSINK] || tsc->data[SC_BEYOND_OF_WARCRY] || tsc->data[SC_UNLIMITED_HUMMING_VOICE] ) &&
+ rnd()%100 < 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 10) + 10 * battle->calc_chorusbonus(sd)) {
+ skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
+ status->change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),8);
+ status_change_end(bl, SC_SWING, INVALID_TIMER);
+ status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
+ status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
+ status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
+ status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
+ status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
+ status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
+ status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
+ status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
+ status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
+ status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
+ status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
+ }
+ }
+ break;
+
case SO_POISON_BUSTER:
{
struct status_change *tsc = status->get_sc(bl);
@@ -4394,10 +4470,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case GN_SPORE_EXPLOSION:
if( flag&1 )
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
else {
clif->skill_nodamage(src, bl, skill_id, 0, 1);
- skill->addtimerskill(src, timer->gettick() + skill->get_time(skill_id, skill_lv) - 1000, bl->id, 0, 0, skill_id, skill_lv, 0, 0);
+ skill->addtimerskill(src, timer->gettick() + skill->get_time(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, 0, 0);
}
break;
@@ -4695,6 +4771,9 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
else if (inf && battle->check_target(src, target, inf) <= 0){
if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
break;
+ } else if( ud->skill_id == RK_PHANTOMTHRUST && target->type != BL_MOB ) {
+ if( !map_flag_vs(src->m) && battle->check_target(src,target,BCT_PARTY) <= 0 )
+ break; // You can use Phantom Thurst on party members in normal maps too. [pakpil]
}
if( inf&BCT_ENEMY
@@ -4795,8 +4874,11 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
// SC_MAGICPOWER needs to switch states before any damage is actually dealt
skill->toggle_magicpower(src, ud->skill_id);
+
+ /* On aegis damage skills are also increase by camouflage. Need confirmation on kRo.
if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
+ */
if (skill->get_casttype(ud->skill_id) == CAST_NODAMAGE)
skill->castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag);
@@ -4960,6 +5042,42 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
}
break;
+ case SO_ELEMENTAL_SHIELD:
+ {
+ struct party_data *p;
+ short ret = 0;
+ int x0, y0, x1, y1, range, i;
+
+ if(sd == NULL || !sd->ed)
+ break;
+ if((p = party->search(sd->status.party_id)) == NULL)
+ break;
+
+ range = skill_get_splash(skill_id,skill_lv);
+ x0 = sd->bl.x - range;
+ y0 = sd->bl.y - range;
+ x1 = sd->bl.x + range;
+ y1 = sd->bl.y + range;
+
+ elemental->delete(sd->ed,0);
+
+ if(!skill->check_unit_range(src,src->x,src->y,skill_id,skill_lv))
+ ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag);
+ for(i = 0; i < MAX_PARTY; i++) {
+ struct map_session_data *psd = p->data[i].sd;
+ if(!psd)
+ continue;
+ if(psd->bl.m != sd->bl.m || !psd->bl.prev)
+ continue;
+ if(range && (psd->bl.x < x0 || psd->bl.y < y0 ||
+ psd->bl.x > x1 || psd->bl.y > y1))
+ continue;
+ if(!skill->check_unit_range(bl,psd->bl.x,psd->bl.y,skill_id,skill_lv))
+ ret |= skill->castend_pos2(bl,psd->bl.x,psd->bl.y,skill_id,skill_lv,tick,flag);
+ }
+ return ret;
+ }
+ break;
case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex]
return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
case MH_STEINWAND: {
@@ -5018,9 +5136,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
{
int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true);
int heal_get_jobexp;
- //Highness Heal: starts at 1.5 boost + 0.5 for each level
+ //Highness Heal: starts at 1.7 boost + 0.3 for each level
if( skill_id == AB_HIGHNESSHEAL ) {
- heal = heal * ( 15 + 5 * skill_lv ) / 10;
+ heal = heal * ( 17 + 3 * skill_lv ) / 10;
}
if( status->isimmune(bl) ||
(dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) )
@@ -5042,7 +5160,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
dstsd = sd;
}
}
- else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAY_NIGHT_FEVER])
+ else if (tsc->data[SC_BERSERK])
heal = 0; //Needed so that it actually displays 0 when healing.
}
clif->skill_nodamage (src, bl, skill_id, heal, 1);
@@ -5144,8 +5262,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case MER_DECAGI:
- clif->skill_nodamage (src, bl, skill_id, skill_lv,
- sc_start(bl, type, (40 + skill_lv * 2 + (status->get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv)));
+ if( tsc && !tsc->data[SC_ADORAMUS] ) //Prevent duplicate agi-down effect.
+ clif->skill_nodamage(src, bl, skill_id, skill_lv,
+ sc_start(bl, type, (40 + skill_lv * 2 + (status->get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv)));
break;
case AL_CRUCIS:
@@ -5521,6 +5640,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case NC_SHAPESHIFT:
case WL_RECOGNIZEDSPELL:
case GC_VENOMIMPRESS:
+ case SC_INVISIBILITY:
case SC_DEADLYINFECT:
case LG_EXEEDBREAK:
case LG_PRESTIGE:
@@ -6055,7 +6175,6 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case GC_CLOAKINGEXCEED:
case LG_FORCEOFVANGUARD:
case SC_REPRODUCE:
- case SC_INVISIBILITY:
if (tsce) {
int failure = status_change_end(bl, type, INVALID_TIMER);
if( failure )
@@ -6628,6 +6747,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
|| (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel.
+ || (dstsd && pc_ismadogear(dstsd))
|| rnd()%100 >= 50+10*skill_lv )
{
if (sd)
@@ -7065,7 +7185,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill->get_inf2(sg->skill_id)&INF2_TRAP) )
{
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) {
+ if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) && sg->unit_id != UNT_THORNS_TRAP ) {
// prevent picking up expired traps
if( battle_config.skill_removetrap_type ) {
int i;
@@ -7730,7 +7850,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case RK_ENCHANTBLADE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed
- sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status->get_lv(bl)/10*/,skill->get_time(skill_id,skill_lv)));
+ sc_start2(bl,type,100,skill_lv,(100+20*skill_lv)*status->get_lv(src)/150+sstatus->int_,skill->get_time(skill_id,skill_lv)));
break;
case RK_DRAGONHOWLING:
if( flag&1)
@@ -7760,7 +7880,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case RK_STONEHARDSKIN:
if( sd ) {
- int heal = sstatus->hp / 4; // 25% HP
+ int heal = sstatus->hp / 5; // 20% HP
if( status->charge(bl,heal,0) )
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv)));
else
@@ -7778,29 +7898,36 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case RK_MILLENNIUMSHIELD:
- {
- short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2);
- sc_start4(bl,type,100,skill_lv,shields,1000,0,skill->get_time(skill_id,skill_lv));
- clif->millenniumshield(src,shields);
+ if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 9 ) {
+ short chance = 0;
+ short num_shields = 0;
+ chance = rnd()%100 + 1;//Generates a random number between 1 - 100 which is then used to determine how many shields will generate.
+ if ( chance >= 1 && chance <= 20 )//20% chance for 4 shields.
+ num_shields = 4;
+ else if ( chance >= 21 && chance <= 50 )//30% chance for 3 shields.
+ num_shields = 3;
+ else if ( chance >= 51 && chance <= 100 )//50% chance for 2 shields.
+ num_shields = 2;
+ sc_start4(bl,type,100,skill_lv,num_shields,1000,0,skill->get_time(skill_id,skill_lv));
+ clif->millenniumshield(src,num_shields);
clif->skill_nodamage(src,bl,skill_id,1,1);
}
break;
case RK_FIGHTINGSPIRIT:
if( flag&1 ) {
+ int atkbonus = 7 * party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count);
if( src == bl )
- sc_start2(bl,type,100,skill->area_temp[5],10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
+ sc_start2(bl,type,100,atkbonus,10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
else
- sc_start(bl,type,100,skill->area_temp[5]/4,skill->get_time(skill_id,skill_lv));
- } else if( sd ) {
- if( sd->status.party_id ) {
- int members = party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count);
- skill->area_temp[5] = 7 * members; // ATK
+ sc_start(bl,type,100,atkbonus / 4,skill->get_time(skill_id,skill_lv));
+ } else if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 5 ) {
+ if( sd->status.party_id )
party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
- } else
- sc_start2(bl,type,100,7,5,skill->get_time(skill_id,skill_lv));
+ else
+ sc_start2(bl,type,100,7,10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,1,1);
}
- clif->skill_nodamage(src,bl,skill_id,1,1);
break;
case RK_LUXANIMA:
@@ -7920,15 +8047,20 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case GC_PHANTOMMENACE:
+ {
+ int r;
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ r = skill->get_splash(skill_id, skill_lv);
map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinarea( status->change_timer_sub,
+ src->m, src->x-r, src->y-r, src->x+r, src->y+r, BL_CHAR, src, NULL, SC_SIGHT, tick);
+ }
break;
-
case GC_HALLUCINATIONWALK:
{
- int heal = status_get_max_hp(bl) / 10;
+ int heal = status_get_max_hp(bl) * ( 18 - 2 * skill_lv ) / 100;
if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails.
if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
break;
@@ -7968,30 +8100,45 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case AB_PRAEFATIO:
- if( sd == NULL || sd->status.party_id == 0 || flag&1 )
- clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill->get_time(skill_id, skill_lv)));
- else if( sd )
+ if( (flag&1) || sd == NULL || sd->status.party_id == 0 ) {
+ int count = 1;
+
+ if( dstsd && dstsd->special_state.no_magic_damage )
+ break;
+
+ if ( sd && sd->status.party_id == 0 )
+ count = 1;
+ else
+ count = party->foreachsamemap(party->sub_count, sd, 0);
+
+ if (count > 0)
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv,
+ sc_start4(bl, type, 100, skill_lv, 0, 0, count, skill->get_time(skill_id, skill_lv)));
+ } else
party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
-
case AB_CHEAL:
if( sd == NULL || sd->status.party_id == 0 || flag&1 ) {
- if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) ) {
- int heal = skill->calc_heal(src, bl, AL_HEAL, pc->checkskill(sd, AL_HEAL), true);
-
- if( (dstsd && pc_ismadogear(dstsd)) || status->isimmune(bl))
- heal = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett]
+ if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) && !tsc->data[SC_BERSERK] ) {
+ int lv = pc->checkskill(sd, AL_HEAL);
+ int heal = skill_calc_heal(src, bl, AL_HEAL, lv, true);
+
+ if( sd->status.party_id ) {
+ int partycount = party->foreachsamemap(party->sub_count, sd, 0);
+ if (partycount > 1)
+ heal += ((heal / 100) * (partycount * 10) / 4);
+ }
+ if( status->isimmune(bl) || (dstsd && pc_ismadogear(dstsd)) )
+ heal = 0;
clif->skill_nodamage(bl, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, 1);
}
- }
- else if( sd )
+ } else if( sd )
party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
-
case AB_ORATIO:
if( flag&1 )
sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
@@ -8024,13 +8171,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case AB_LAUDARAMUS:
if( flag&1 || sd == NULL ) {
- if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){
+ if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE] || tsc->data[SC_DEEP_SLEEP]) ){
// Success Chance: (40 + 10 * Skill Level) %
if( rnd()%100 > 40+10*skill_lv ) break;
status_change_end(bl, SC_SLEEP, INVALID_TIMER);
status_change_end(bl, SC_STUN, INVALID_TIMER);
status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER);
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
}else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets
clif->skill_nodamage(bl, bl, skill_id, skill_lv,
sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
@@ -8109,6 +8257,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) %
else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) %
+ if( sd )
+ skill->blockpc_start(sd,skill_id,4000);
+
if( !(tsc && tsc->data[type]) ){
int failure = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,failure);
@@ -8121,11 +8272,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case WL_FROSTMISTY:
+ if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)))
+ break; // Doesn't hit/cause Freezing to invisible enemy // Really? [Rytech]
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id);
break;
case WL_JACKFROST:
+ if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)))
+ break; // Do not hit invisible enemy
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
map->foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
break;
@@ -8280,19 +8435,21 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case NC_REPAIR:
- if( sd )
- {
- int heal;
- if( dstsd && pc_ismadogear(dstsd) )
- {
- heal = dstsd->status.max_hp * (3+3*skill_lv) / 100;
- status->heal(bl,heal,0,2);
- } else {
- heal = sd->status.max_hp * (3+3*skill_lv) / 100;
- status->heal(src,heal,0,2);
+ if( sd ) {
+ int heal, hp = 0; // % of max hp regen
+ if( !dstsd || !pc_ismadogear(dstsd) ) {
+ clif->skill_fail(sd, skill_id,USESKILL_FAIL_TOTARGET,0);
+ break;
}
-
- clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ switch (cap_value(skill_lv, 1, 5)) {
+ case 1: hp = 4; break;
+ case 2: hp = 7; break;
+ case 3: hp = 13; break;
+ case 4: hp = 17; break;
+ case 5: hp = 23; break;
+ }
+ heal = tstatus->max_hp * hp / 100;
+ status->heal(bl,heal,0,2);
clif->skill_nodamage(src, bl, skill_id, skill_lv, heal);
}
break;
@@ -8331,15 +8488,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SC_BODYPAINT:
if( flag&1 ) {
if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] ||
- tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] ||
- tsc->data[SC__INVISIBILITY]) ) {
+ tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] ) ) {
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CHASEWALK, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(bl,type,20 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
}
} else {
@@ -8351,34 +8506,44 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SC_ENERVATION:
case SC_GROOMY:
+ case SC_IGNORANCE:
case SC_LAZINESS:
case SC_UNLUCKY:
case SC_WEAKNESS:
if( !(tsc && tsc->data[type]) ) {
- //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3))
- int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status->get_lv(src)/10
- - status->get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3);
- rate = cap_value(rate, skill_lv+sstatus->dex/20, 100);
+ int joblvbonus = 0;
+ int rate = 0;
+ if (is_boss(bl)) break;
+ joblvbonus = ( sd ? sd->status.job_level : 50 );
+ //First we set the success chance based on the caster's build which increases the chance.
+ rate = 10 * skill_lv + rnd_value( sstatus->dex / 12, sstatus->dex / 4 ) + joblvbonus + status->get_lv(src) / 10;
+ // We then reduce the success chance based on the target's build.
+ rate -= rnd_value( tstatus->agi / 6, tstatus->agi / 3 ) - tstatus->luk / 10 - ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0 ) - status->get_lv(bl) / 10;
+ //Finally we set the minimum success chance cap based on the caster's skill level and DEX.
+ rate = cap_value( rate, skill_lv + sstatus->dex / 20, 100);
clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)));
- } else if( sd )
- clif->skill_fail(sd,skill_id,0,0);
- break;
-
- case SC_IGNORANCE:
- if( !(tsc && tsc->data[type]) ) {
- int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0)
- + status->get_lv(src)/10 - status->get_lv(bl)/10 - tstatus->luk/10
- - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3);
- rate = cap_value(rate, skill_lv+sstatus->dex/20, 100);
- if (clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)))) {
- int sp = 200 * skill_lv;
+ if ( tsc && tsc->data[SC__IGNORANCE] && skill_id == SC_IGNORANCE) {
+ //If the target was successfully inflected with the Ignorance status, drain some of the targets SP.
+ int sp = 100 * skill_lv;
if( dstmd ) sp = dstmd->level * 2;
if( status_zap(bl,0,sp) )
- status->heal(src,0,sp/2,3);
- } else if( sd )
- clif->skill_fail(sd,skill_id,0,0);
+ status->heal(src,0,sp/2,3);//What does flag 3 do? [Rytech]
+ }
+ if ( tsc && tsc->data[SC__UNLUCKY] && skill_id == SC_UNLUCKY) {
+ //If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's.
+ switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's reguardless of resistance.
+ case 0:
+ status->change_start(bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ break;
+ case 1:
+ status->change_start(bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ break;
+ case 2:
+ status->change_start(bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ }
+ }
} else if( sd )
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
case LG_TRAMPLE:
@@ -8396,108 +8561,90 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case LG_SHIELDSPELL:
if( flag&1 ) {
- int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000;
- sc_start(bl,SC_SILENCE,100,skill_lv,duration);
+ sc_start(bl,SC_SILENCE,100,skill_lv,sd->bonus.shieldmdef * 30000);
} else if( sd ) {
- int opt = skill_lv;
- int rate = rnd()%100;
- int val, brate;
+ int opt = 0, val = 0, splashrange = 0;
+ struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
+ if( !shield_data || shield_data->type != IT_ARMOR ) {
+ //Skill will first check if a shield is equipped. If none is found on the caster the skill will fail.
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
+ }
+ //Generates a number between 1 - 3. The number generated will determine which effect will be triggered.
+ opt = rnd()%3 + 1;
switch( skill_lv ) {
case 1:
- {
- struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
- if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield?
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
- break;
- }
- brate = shield_data->def * 10;
- if( rate < 50 )
- opt = 1;
- else if( rate < 75 )
- opt = 2;
+ if ( shield_data->def >= 0 && shield_data->def <= 40)
+ splashrange = 1;
+ else if ( shield_data->def >= 41 && shield_data->def <= 80)
+ splashrange = 2;
else
- opt = 3;
-
+ splashrange = 3;
switch( opt ) {
case 1:
- sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1);
+ sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,INVALID_TIMER); //Splash AoE ATK
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER);
break;
case 2:
- val = shield_data->def / 10; // % Reflected damage.
- sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000);
+ val = shield_data->def/10; //Damage Reflecting Increase.
+ sc_start2(bl,SC_SHIELDSPELL_DEF,100,opt,val,shield_data->def * 1000);
break;
case 3:
- val = shield_data->def; // Attack increase.
- sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000);
+ //Weapon Attack Increase.
+ val = shield_data->def;
+ sc_start2(bl,SC_SHIELDSPELL_DEF,100,opt,val,shield_data->def * 3000);
break;
}
- }
break;
case 2:
- brate = sd->bonus.shieldmdef * 20;
- if( rate < 30 )
- opt = 1;
- else if( rate < 60 )
- opt = 2;
+ if ( sd->bonus.shieldmdef >= 1 && sd->bonus.shieldmdef <= 3 )
+ splashrange = 1;
+ else if ( sd->bonus.shieldmdef >= 4 && sd->bonus.shieldmdef <= 5 )
+ splashrange = 2;
else
- opt = 3;
+ splashrange = 3;
switch( opt ) {
case 1:
- sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
+ sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,INVALID_TIMER); //Splash AoE MATK
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER);
break;
case 2:
- sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
- clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
+ sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 2000); //Splash AoE Lex Divina
+ clif->skill_damage(src,bl,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
break;
case 3:
- if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) )
+ if( sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 30000) ) //Magnificat
clif->skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv,
- sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000));
+ sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000));
break;
}
break;
-
case 3:
{
- struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
- if( !it ) { // No shield?
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- break;
- }
- brate = it->refine * 5;
- if( rate < 25 )
- opt = 1;
- else if( rate < 50 )
- opt = 2;
- else
- opt = 3;
+ struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
+ int rate = 0;
switch( opt ) {
case 1:
- val = 105 * it->refine / 10;
- sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill->get_time(skill_id,skill_lv));
+ sc_start(bl,SC_SHIELDSPELL_REF,100,opt,shield->refine * 30000); //Now breaks Armor at 100% rate
break;
case 2:
- case 3:
- if( rate < brate ) {
- val = sstatus->max_hp * (11 + it->refine) / 100;
- status->heal(bl, val, 0, 3);
- }
+ val = shield->refine * 10 * status->get_lv(src) / 100; //DEF Increase
+ rate = (shield->refine * 2) + (status_get_luk(src) / 10); //Status Resistance Rate
+ if( sc_start2(bl,SC_SHIELDSPELL_REF,100,opt,val,shield->refine * 20000))
+ clif->skill_nodamage(src,bl,SC_SCRESIST,skill_lv,
+ sc_start(bl,SC_SCRESIST,100,rate,shield->refine * 30000));
break;
-#if 0 // TODO: I need confirm what effect should be here. Moved to case 2 to until we got it.
case 3:
- // Full protection.
+ sc_start(bl,SC_SHIELDSPELL_REF,100,opt,INVALID_TIMER); //HP Recovery
+ val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100;
+ status->heal(bl, val, 0, 2);
+ status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER);
break;
-#endif // 0
}
}
break;
@@ -8530,9 +8677,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SC_BLOODING: case SC_CURSE:
case SC_CONFUSION: case SC_ILLUSION:
case SC_SILENCE: case SC_BURNING:
- case SC_COLD: case SC_FROSTMISTY:
+ case SC_COLD: case SC_FROSTMISTY:
case SC_DEEP_SLEEP: case SC_FEAR:
- case SC_MANDRAGORA:
+ case SC_MANDRAGORA: case SC__CHAOS:
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
}
@@ -8653,34 +8800,25 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int i;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
for(i = SR_FLASHCOMBO_ATK_STEP1; i <= SR_FLASHCOMBO_ATK_STEP4; i++)
- skill->addtimerskill(src, tick + 500 * (i - SR_FLASHCOMBO_ATK_STEP1), bl->id, 0, 0, i, skill_lv, BF_WEAPON, flag|SD_LEVEL);
+ skill->addtimerskill(src, tick + 400 * (i - SR_FLASHCOMBO_ATK_STEP1), bl->id, 0, 0, i, skill_lv, BF_WEAPON, flag|SD_LEVEL);
}
break;
case WA_SWING_DANCE:
- case WA_MOONLIT_SERENADE:
- if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- else if( sd ) { // Only shows effects on caster.
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
- }
- break;
-
case WA_SYMPHONY_OF_LOVER:
+ case WA_MOONLIT_SERENADE:
case MI_RUSH_WINDMILL:
case MI_ECHOSONG:
- if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
- sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill->get_time(skill_id,skill_lv));
- else if( sd ) { // Only shows effects on caster.
+ if( flag&1 )
+ sc_start2(bl,type,100,skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ sc_start2(bl,type,100,skill_lv,pc->checkskill(sd,WM_LESSON),skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
}
break;
case MI_HARMONIZE:
- if( src != bl )
- clif->skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill->get_time(skill_id,skill_lv)));
- clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,(sd?pc->checkskill(sd,WM_LESSON):1),skill->get_time(skill_id,skill_lv)));
break;
case WM_DEADHILLHERE:
@@ -8689,99 +8827,107 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
if( rnd()%100 < 88 + 2 * skill_lv ) {
- int heal = tstatus->sp;
- if( heal <= 0 )
+ int heal = 0;
+ status_zap(bl, 0, tstatus->sp * (60 - 10 * skill_lv) / 100);
+ heal = tstatus->sp;
+ if ( heal <= 0 )
heal = 1;
- tstatus->hp = heal;
- tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100;
+ status->fixed_revive(bl, heal, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- pc->revive((TBL_PC*)bl,heal,0);
- clif->resurrection(bl,1);
+ status->set_sp(bl, 0, 0);
}
}
break;
+ case WM_LULLABY_DEEPSLEEP:
+ if ( flag&1 )
+ sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
+ else if ( sd ) {
+ int rate = 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 1) + status->get_lv(src) / 15 + (sd? sd->status.job_level:0) / 5;
+ if ( rnd()%100 < rate ) {
+ flag |= BCT_PARTY|BCT_GUILD;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_NPC|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ }
+ }
+ break;
case WM_SIRCLEOFNATURE:
flag |= BCT_SELF|BCT_PARTY|BCT_GUILD;
case WM_VOICEOFSIREN:
if( skill_id != WM_SIRCLEOFNATURE )
flag &= ~BCT_SELF;
if( flag&1 ) {
- sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv));
- } else {
- map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ sc_start2(bl,type,100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv));
+ } else if( sd ) {
+ int rate = 6 * skill_lv + (sd ? pc->checkskill(sd,WM_LESSON) : 1) + (sd? sd->status.job_level:0) / 2;
+ if ( rnd()%100 < rate ) {
+ flag |= BCT_PARTY|BCT_GUILD;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_NPC|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ }
}
break;
case WM_GLOOMYDAY:
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if( dstsd && ( pc->checkskill(dstsd,KN_BRANDISHSPEAR) || pc->checkskill(dstsd,LK_SPIRALPIERCE) ||
- pc->checkskill(dstsd,CR_SHIELDCHARGE) || pc->checkskill(dstsd,CR_SHIELDBOOMERANG) ||
- pc->checkskill(dstsd,PA_SHIELDCHAIN) || pc->checkskill(dstsd,LG_SHIELDPRESS) ) )
- {
- sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill->get_time(skill_id,skill_lv));
- break;
- }
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- break;
-
- case WM_SATURDAY_NIGHT_FEVER:
- if( flag&1 ) { // Affect to all targets arround the caster and caster too.
- if( !(tsc && tsc->data[type]) )
- sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv));
- } else if( flag&2 ) {
- if( src->id != bl->id && battle->check_target(src,bl,BCT_ENEMY) > 0 )
- status_fix_damage(src,bl,9999,clif->damage(src,bl,0,0,9999,0,0,0));
- } else if( sd ) {
- short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4;
- if( !sd->status.party_id || (rnd()%100 > chance)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0);
- break;
- }
- if( map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id,skill_lv),
- BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count) > 7 )
- flag |= 2;
- else
- flag |= 1;
- map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill->castend_nodamage_id);
- clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(src,SC_STOP,100,skill_lv,skill->get_time2(skill_id,skill_lv)));
- if( flag&2 ) // Dealed here to prevent conflicts
- status_fix_damage(src,bl,9999,clif->damage(src,bl,0,0,9999,0,0,0));
+ if ( tsc && tsc->data[type] ) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ break;
}
+ // val4 indicates caster's voice lesson level
+ sc_start4(bl,type,100,skill_lv, 0, 0, sd?pc->checkskill(sd,WM_LESSON):10, skill->get_time(skill_id,skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case WM_SONG_OF_MANA:
case WM_DANCE_WITH_WUG:
case WM_LERADS_DEW:
+ case WM_UNLIMITED_HUMMING_VOICE:
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ if( flag&1 )
+ sc_start2(bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ sc_start2(bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ }
+ }
+ break;
+ case WM_SATURDAY_NIGHT_FEVER:
+ {
if( flag&1 ) {
- // These affect to to all party members near the caster.
- struct status_change *sc = status->get_sc(src);
- if( sc && sc->data[type] ) {
- sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill->get_time(skill_id,skill_lv));
- }
+ int madnesscheck = 0;
+ if ( sd )//Required to check if the lord of madness effect will be applied.
+ madnesscheck = map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count);
+ sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv));
+ if ( madnesscheck >= 8 )//The god of madness deals 9999 fixed unreduceable damage when 8 or more enemy players are affected.
+ status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, 0, 0));
+ //skill->attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);//To renable when I can confirm it deals damage like this. Data shows its dealed as reflected damage which I dont have it coded like that yet. [Rytech]
} else if( sd ) {
- uint16 lv = skill_lv;
- int count = skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1);
- if( sc_start2(bl,type,100,skill_lv,count,skill->get_time(skill_id,skill_lv)) )
- party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
-
+ int rate = sstatus->int_ / 6 + (sd? sd->status.job_level:0) / 5 + skill_lv * 4;
+ if ( rnd()%100 < rate ) {
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ }
}
+ }
break;
case WM_MELODYOFSINK:
case WM_BEYOND_OF_WARCRY:
- case WM_UNLIMITED_HUMMING_VOICE:
- if( flag&1 ) {
- sc_start2(bl,type,100,skill_lv,skill->area_temp[0],skill->get_time(skill_id,skill_lv));
- } else { // These affect to all targets arround the caster.
- uint16 lv = skill_lv;
- skill->area_temp[0] = (sd) ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones).
- map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ if( flag&1 )
+ sc_start2(bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ if ( rnd()%100 < 15 + 5 * skill_lv + 5 * chorusbonus ) {
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ }
}
+ }
break;
case WM_RANDOMIZESPELL: {
@@ -8870,26 +9016,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SO_ARRULLO:
{
// [(15 + 5 * Skill Level) + ( Caster?s INT / 5 ) + ( Caster?s Job Level / 5 ) - ( Target?s INT / 6 ) - ( Target?s LUK / 10 )] %
- int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0);
+ int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd? sd->status.job_level:0)/5;
rate -= status_get_int(bl)/6 - status_get_luk(bl)/10;
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
sc_start2(bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv));
}
break;
- case WM_LULLABY_DEEPSLEEP:
- if( flag&1 ){
- //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster?s Base Level / 15) + (Caster?s Job Level / 5)] %
- int rate = (4 * skill_lv) + ( (sd) ? pc->checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status->get_lv(src) / 15;
- if( bl != src )
- sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv));
- }else {
- clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill->castend_nodamage_id);
- }
- break;
-
case SO_SUMMON_AGNI:
case SO_SUMMON_AQUA:
case SO_SUMMON_VENTUS:
@@ -8903,7 +9036,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
// Summoning the new one.
if( !elemental->create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) {
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8971,16 +9104,6 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
break;
- case SO_ELEMENTAL_SHIELD:
- if( sd == NULL || !sd->ed )
- break;
- elemental->delete(sd->ed, 0);
- if( sd->status.party_id == 0 || flag&1 )
- skill->unitsetting(src,MG_SAFETYWALL,skill_lv,bl->x,bl->y,0);
- else
- party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
- break;
-
case GN_CHANGEMATERIAL:
case SO_EL_ANALYSIS:
if( sd ) {
@@ -9013,7 +9136,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int chance = 25 + 10 * skill_lv - (status_get_vit(bl) + status_get_luk(bl)) / 5;
if ( chance < 10 )
chance = 10;//Minimal chance is 10%.
- if ( rand()%100 < chance ) {//Coded to both inflect the status and drain the target's SP only when successful. [Rytech]
+ if ( rnd()%100 < chance ) {//Coded to both inflect the status and drain the target's SP only when successful. [Rytech]
sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100);
}
@@ -9099,7 +9222,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away.
- skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rand()%8,0);
+ skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0);
sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
}
@@ -9387,7 +9510,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
skill->onskillusage(sd, bl, skill_id, tick);
// perform skill requirement consumption
- skill->consume_requirement(sd,skill_id,skill_lv,2);
+ if( skill_id != NC_SELFDESTRUCTION )
+ skill->consume_requirement(sd,skill_id,skill_lv,2);
}
map->freeblock_unlock();
@@ -9551,6 +9675,14 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
+static int check_npc_chaospanic(struct block_list* bl, va_list args) {
+ TBL_NPC* nd = (TBL_NPC*)bl;
+
+ if( nd->option&(OPTION_HIDE|OPTION_INVISIBLE) || nd->class_ != 45 )
+ return 0;
+
+ return 1;
+}
/* skill count without self */
static int skill_count_wos(struct block_list *bl,va_list ap) {
struct block_list* src = va_arg(ap, struct block_list*);
@@ -9790,6 +9922,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
+ case SC_CHAOSPANIC:
+ case SC_MAELSTROM:
+ if (sd && map->foreachinarea(&check_npc_chaospanic,src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
+ }
+
case MG_SAFETYWALL:
case MG_FIREWALL:
case MG_THUNDERSTORM:
@@ -9870,8 +10009,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RA_ICEBOUNDTRAP:
case SC_MANHOLE:
case SC_DIMENSIONDOOR:
- case SC_CHAOSPANIC:
- case SC_MAELSTROM:
case SC_BLOODYLUST:
case WM_REVERBERATION:
case WM_SEVERE_RAINSTORM:
@@ -9898,6 +10035,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case MH_STEINWAND:
case MH_XENO_SLASHER:
case NC_MAGMA_ERUPTION:
+ case SO_ELEMENTAL_SHIELD:
case RL_B_TRAP:
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
@@ -10158,14 +10296,29 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RK_WINDCUTTER:
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
case NC_COLDSLOWER:
- case NC_ARMSCANNON:
case RK_DRAGONBREATH:
case RK_DRAGONBREATH_WATER:
r = skill->get_splash(skill_id,skill_lv);
map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
break;
+ case WM_GREAT_ECHO:
+ case WM_SOUND_OF_DESTRUCTION:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ break;
+
+ case WM_LULLABY_DEEPSLEEP:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ALL|1,skill->castend_damage_id);
+ break;
+ case WM_VOICEOFSIREN:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ALL|1,skill->castend_damage_id);
+ break;
case SO_ARRULLO:
r = skill->get_splash(skill_id,skill_lv);
map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
@@ -10255,8 +10408,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case SC_FEINTBOMB:
skill->unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
- if( skill->blown(src,src,6,unit->getdir(src),0) )
- skill->castend_nodamage_id(src,src,TF_HIDING,1,tick,0x2);
+ skill->blown(src,src,3*skill_lv,unit->getdir(src),0);
+ //After back sliding, the player goes into hiding. Hiding level used is throught to be the learned level.
+ sc_start(src,SC_HIDING,100,(sd?pc->checkskill(sd,TF_HIDING):10),skill->get_time(TF_HIDING,(sd?pc->checkskill(sd,TF_HIDING):10)));
break;
case SC_ESCAPE:
@@ -10301,25 +10455,37 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case WM_DOMINION_IMPULSE:
r = skill->get_splash(skill_id, skill_lv);
- map->foreachinarea( skill->activate_reverberation,
- src->m, x-r, y-r, x+r,y+r,BL_SKILL);
+ map->foreachinarea( skill->activate_reverberation,src->m, x-r, y-r, x+r,y+r,BL_SKILL);
break;
- case WM_GREAT_ECHO:
- flag|=1; // Should counsume 1 item per skill usage.
- map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->castend_damage_id);
- break;
case GN_CRAZYWEED:
{
- int area = skill->get_splash(GN_CRAZYWEED_ATK, skill_lv);
- short x1 = 0, y1 = 0;
- int i;
+ int area = skill->get_splash(skill_id, skill_lv);
+ short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
- for( i = 0; i < 3 + (skill_lv/2); i++ ) {
- x1 = x - area + rnd()%(area * 2 + 1);
- y1 = y - area + rnd()%(area * 2 + 1);
- skill->addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skill_lv,-1,0);
+ for( r = 0; r < 3 + (skill_lv>>1); r++ ) {
+ // Creates a random Cell in the Splash Area
+ tmpx = x - area + rnd()%(area * 2 + 1);
+ tmpy = y - area + rnd()%(area * 2 + 1);
+
+ if( r > 0 )
+ skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,(x1<<16)|y1,flag);
+
+ x1 = tmpx;
+ y1 = tmpy;
}
+
+ skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,-1,flag);
+ }
+ break;
+
+ case GN_CRAZYWEED_ATK: {
+ int dummy = 1;
+ //Enable if any unique animation gets added to this skill ID in the future. [Rytech]
+ //clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->cell_overlap, src->m, x-r, y-r, x+r, y+r, BL_SKILL, skill_id, &dummy, src);
+ map->foreachinarea(skill->area_sub, src->m, x-r, y-r, x+r, y+r, BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
}
break;
case GN_FIRE_EXPANSION: {
@@ -10548,6 +10714,9 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
sc = status->get_sc(src); // for traps, firewall and fogwall - celest
switch( skill_id ) {
+ case SO_ELEMENTAL_SHIELD:
+ val2 = 300 * skill_lv + 65 * (st->int_ + status->get_lv(src)) + st->max_sp;
+ break;
case MH_STEINWAND:
val2 = 4 + skill_lv; //nb of attack blocked
break;
@@ -10600,6 +10769,8 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex]
case AM_DEMONSTRATION:
case GN_HELLS_PLANT:
+ if( skill_id == GN_HELLS_PLANT && map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
+ return NULL;
if (map_flag_vs(src->m) && battle_config.vs_traps_bctall
&& (src->type&battle_config.vs_traps_bctall))
target = BCT_ALL;
@@ -10828,7 +10999,9 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
limit = -1;
break;
case WM_REVERBERATION:
- interval = limit;
+ if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
+ target = BCT_ALL;
+ val1 = skill_lv + 1;
val2 = 1;
case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector.
if( map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
@@ -10840,9 +11013,6 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case SO_WARMER:
skill->clear_group(src, 8);
break;
- case SO_VACUUM_EXTREME:
- range++;
- break;
case GN_WALLOFTHORN:
if( flag&1 )
limit = 3000;
@@ -10956,11 +11126,9 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
if (val1 < 1) val1 = 1;
val2 = 0;
break;
- case WM_REVERBERATION:
- val1 = 1 + skill_lv;
- break;
case GN_WALLOFTHORN:
- val1 = 1000 * skill_lv; // Need official value. [LimitLine]
+ val1 = 2000 + 2000 * skill_lv;
+ val2 = src->id;
break;
default:
if (group->state.song_dance&0x1)
@@ -10970,9 +11138,6 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
if (skill->get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
val2 |= UF_RANGEDSINGLEUNIT; // center.
- if( sd && map->getcell(src->m, ux, uy, CELL_CHKMAELSTROM) ) //Does not recover SP from monster skills
- map->foreachincell(skill->maelstrom_suction,src->m,ux,uy,BL_SKILL,skill_id,skill_lv);
-
if( range <= 0 )
map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
if( !alive )
@@ -11034,13 +11199,14 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
return 0; //AoE skills are ineffective. [Skotlex]
- if( map->getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) )
- return 0;
sc = status->get_sc(bl);
if (sc && sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN )
return 0; //Hidden characters are immune to AoE skills except to these. [Skotlex]
+ if (sc && sc->data[SC_VACUUM_EXTREME] && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR))
+ status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
+
type = status->skill2sc(sg->skill_id);
sce = (sc && type != -1)?sc->data[type]:NULL;
skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still.
@@ -11069,15 +11235,17 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!sce)
sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
break;
-
case UNT_BLOODYLUST:
if (sg->src_id == bl->id)
break; //Does not affect the caster.
+ if (bl->type == BL_MOB)
+ break; //Does not affect the caster.
if( !sce && sc_start4(bl,type,100,sg->skill_lv,0,SC__BLOODYLUST,0,sg->limit) )
sc_start(bl,SC__BLOODYLUST,100,sg->skill_lv,sg->limit);
break;
case UNT_PNEUMA:
case UNT_CHAOSPANIC:
+ case UNT_MAELSTROM:
if (!sce)
sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
break;
@@ -11207,6 +11375,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
+ case UNT_REVERBERATION:
+ clif->changetraplook(&src->bl,UNT_USED_TRAPS);
+ map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ sg->unit_id = UNT_USED_TRAPS;
+ sg->limit = DIFF_TICK32(tick,sg->tick) + 1500;
+ break;
+
case UNT_VOLCANIC_ASH:
if (!sce)
sc_start(bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv));
@@ -11231,7 +11406,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
struct block_list *ss;
TBL_PC* tsd;
struct status_data *tstatus;
- struct status_change *tsc;
+ struct status_change *tsc, *ssc;
struct skill_unit_group_tickset *ts;
enum sc_type type;
uint16 skill_id;
@@ -11247,10 +11422,15 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
nullpo_ret(ss=map->id2bl(sg->src_id));
tsd = BL_CAST(BL_PC, bl);
tsc = status->get_sc(bl);
+ ssc = status->get_sc(ss); // Status Effects for Unit caster.
if ( tsc && tsc->data[SC_HOVERING] )
return 0; //Under hovering characters are immune to trap and ground target skills.
+ // Maestro or Wanderer is unaffected by traps of trappers he or she charmed [SuperHulk]
+ if ( ssc && ssc->data[SC_SIREN] && ssc->data[SC_SIREN]->val2 == bl->id && (skill->get_inf2(sg->skill_id)&INF2_TRAP) )
+ return 0;
+
tstatus = status->get_status_data(bl);
type = status->skill2sc(sg->skill_id);
skill_id = sg->skill_id;
@@ -11392,12 +11572,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if (rnd()%100 < src->val1)
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
- case GN_CRAZYWEED_ATK:
- if( bl->type == BL_SKILL ){
- struct skill_unit *su = (struct skill_unit *)bl;
- if( su && !(skill->get_inf2(su->group->skill_id)&INF2_TRAP) )
- break;
- }
default:
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
@@ -11688,8 +11862,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
* 3rd stuff
**/
case UNT_POISONSMOKE:
- if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 )
- sc_start(bl,sg->val2,100,sg->val3,skill->get_time2(GC_POISONINGWEAPON, 1));
+ if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 50 ) {
+ short rate = 100;
+ if ( sg->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reduceable. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5 ;
+ sc_start(bl,sg->val2,rate,sg->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ }
break;
case UNT_EPICLESIS:
@@ -11711,6 +11889,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
// TODO: check if other hidden status can be removed.
status_change_end(bl,SC_HIDING,INVALID_TIMER);
status_change_end(bl,SC_CLOAKING,INVALID_TIMER);
+ status_change_end(bl,SC_CLOAKINGEXCEED,INVALID_TIMER);
}
}
/* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie]
@@ -11735,20 +11914,18 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_REVERBERATION:
clif->changetraplook(&src->bl,UNT_USED_TRAPS);
map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
- sg->limit = DIFF_TICK32(tick,sg->tick)+1000;
+ sg->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
break;
case UNT_SEVERE_RAINSTORM:
- if( battle->check_target(&src->bl, bl, BCT_ENEMY) > 0 )
+ if( battle->check_target(&src->bl, bl, BCT_ENEMY))
skill->attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
break;
case UNT_NETHERWORLD:
- if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle->check_target(&src->bl, bl, BCT_PARTY) > 0 ) {
+ if( !(status_get_mode(bl)&MD_BOSS)) {
if( !(tsc && tsc->data[type]) ){
sc_start(bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
- sg->limit = DIFF_TICK32(tick,sg->tick);
- sg->unit_id = UNT_USED_TRAPS;
}
}
break;
@@ -11814,10 +11991,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_WARMER:
if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) {
- int hp = 125 * sg->skill_lv; // Officially is 125 * skill_lv.
- struct status_change *ssc = status->get_sc(ss);
+ int hp = 0;
if( ssc && ssc->data[SC_HEATER_OPTION] )
- hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100;
+ hp = tstatus->max_hp * 3 * sg->skill_lv / 100;
+ else
+ hp = tstatus->max_hp * sg->skill_lv / 100;
+ status->heal(bl, hp, 0, 0);
if( tstatus->hp != tstatus->max_hp )
clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0);
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
@@ -11852,31 +12031,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
case UNT_VACUUM_EXTREME:
- {// TODO: official behavior in gvg area. [malufett]
- int sec = sg->limit - DIFF_TICK32(tick, sg->tick);
- int range = skill->get_unit_range(sg->skill_id, sg->skill_lv);
-
- if( tsc && !tsc->data[type] &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range)// don't consider outer bounderies
- sc_start(bl, type, 100, sg->skill_lv, sec);
-
- if( unit->is_walking(bl) && // wait until target stop walking
- ( tsc && tsc->data[type] && tsc->data[type]->val4 >= tsc->data[type]->val3-range ))
- break;
-
- if( tsc && ( !tsc->data[type] || (tsc->data[type] && tsc->data[type]->val4 < 1 ) ) )
- break;
-
- if( unit->is_walking(bl) &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) > range )// going outside of boundaries? then force it to stop
- unit->stop_walking(bl,1);
-
- if( !unit->is_walking(bl) &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range && // only snap if the target is inside the range or
- src->bl.x != bl->x && src->bl.y != bl->y){// diagonal position parallel to VE's center
- unit->movepos(bl, src->bl.x, src->bl.y, 0, 0);
- clif->fixpos(bl);
- }
+ if ( tsc && tsc->data[SC_HALLUCINATIONWALK] ) {
+ return 0;
+ } else {
+ sg->limit -= 100 * tstatus->str/20;
+ sc_start(bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
}
break;
@@ -11947,7 +12106,7 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
sce = (sc && type != -1)?sc->data[type]:NULL;
if( bl->prev == NULL
- || (status->isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB)
+ || (status->isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB && sg->unit_id != UNT_THORNS_TRAP)
) //Need to delete the trap if the source died.
return 0;
@@ -11957,6 +12116,7 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
case UNT_EPICLESIS://Arch Bishop
case UNT_NEUTRALBARRIER:
case UNT_STEALTHFIELD:
+ case UNT_WARMER:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -11970,6 +12130,7 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
status_change_end(bl, type, INVALID_TIMER);
break;
+ case UNT_THORNS_TRAP:
case UNT_SPIDERWEB:
{
struct block_list *target = map->id2bl(sg->val2);
@@ -12041,6 +12202,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case SO_WATER_INSIGNIA:
case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
+ case SO_ELEMENTAL_SHIELD:
case SC_BLOODYLUST:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
@@ -12150,10 +12312,12 @@ int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 da
case UNT_TALKIEBOX:
case UNT_ANKLESNARE:
case UNT_ICEWALL:
- case UNT_REVERBERATION:
case UNT_WALLOFTHORN:
src->val1 -= (int)cap_value(damage,INT_MIN,INT_MAX);
break;
+ case UNT_REVERBERATION:
+ src->val1--;
+ break;
default:
damage = 0;
break;
@@ -12275,12 +12439,6 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16
status->charge(&tsd->bl, 0, i);
}
break;
- case WM_GREAT_ECHO:
- for( i = 0; i < c; i++ ) {
- if( (tsd = map->id2sd(p_sd[i])) != NULL )
- status_zap(&tsd->bl,0,skill->get_sp(skill_id,*skill_lv)/c);
- }
- break;
default: //Warning: Assuming Ensemble skills here (for speed)
if( is_chorus )
break;//Chorus skills are not to be parsed as ensambles
@@ -12986,7 +13144,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sd->spiritball > 0 )
sd->spiritball_old = require.spiritball = sd->spiritball;
else {
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -12997,7 +13155,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SC_MANHOLE:
case SC_DIMENSIONDOOR:
if( sc && sc->data[SC_MAGNETICFIELD] ) {
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -13011,11 +13169,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party.
}
break;
+ case NC_PILEBUNKER:
+ if ( sd->equip_index[EQI_HAND_R] < 0 || sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid != ITEMID_PILEBUNCKER ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
+ }
+ break;
case SO_FIREWALK:
case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
if( sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) {
- clif->skill_fail(sd,skill_id,0x0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -13031,9 +13195,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
- case LG_REFLECTDAMAGE:
case CR_REFLECTSHIELD:
- if( sc && sc->data[SC_KYOMU] && rand()%100 < 5 * sc->data[SC_KYOMU]->val1 ){
+ if( sc && sc->data[SC_KYOMU] && rnd()%100 < 5 * sc->data[SC_KYOMU]->val1 ){
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -13617,7 +13780,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if( sc->data[SC__LAZINESS] )
req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10;
if( sc->data[SC_UNLIMITED_HUMMING_VOICE] )
- req.sp += req.sp * sc->data[SC_UNLIMITED_HUMMING_VOICE]->val2 / 100;
+ req.sp += req.sp * sc->data[SC_UNLIMITED_HUMMING_VOICE]->val3 / 100;
if( sc->data[SC_RECOGNIZEDSPELL] )
req.sp += req.sp / 4;
if( sc->data[SC_TELEKINESIS_INTENSE] && skill->get_ele(skill_id, skill_lv) == ELE_GHOST)
@@ -13735,6 +13898,22 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
req.amount[skill_lv-1] = skill->db[idx].amount[skill_lv-1];
break;
}
+ if (skill_id == NC_REPAIR) {
+ switch(skill_lv) {
+ case 1:
+ case 2:
+ req.itemid[1] = ITEMID_REPAIR_A;
+ break;
+ case 3:
+ case 4:
+ req.itemid[1] = ITEMID_REPAIR_B;
+ break;
+ case 5:
+ req.itemid[1] = ITEMID_REPAIR_C;
+ break;
+ }
+ req.amount[1] = 1;
+ }
// Check for cost reductions due to skills & SCs
switch(skill_id) {
@@ -13811,7 +13990,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
req.sp -= req.sp * (5 + 5 * pc->checkskill(sd,SO_EL_SYMPATHY)) / 100;
break;
case SO_PSYCHIC_WAVE:
- if( sc && sc->data[SC_BLAST_OPTION] )
+ if( sc && (sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ))
req.sp += req.sp * 150 / 100;
break;
}
@@ -13996,13 +14175,15 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
// Fixed cast reduction bonuses
if( sc->data[SC__LAZINESS] )
fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2);
+ if( sc->data[SC_DANCE_WITH_WUG])
+ fixcast_r = max(fixcast_r, sc->data[SC_DANCE_WITH_WUG]->val4);
if( sc->data[SC_SECRAMENT] )
fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2);
if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && (skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) )
fixcast_r = max(fixcast_r, (status_get_int(bl) + status->get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] %
// Fixed cast non percentage bonuses
if( sc->data[SC_MANDRAGORA] )
- fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2;
+ fixed += sc->data[SC_MANDRAGORA]->val1 * 500;
if( sc->data[SC_IZAYOI] )
fixed = 0;
if( sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION] )
@@ -14276,7 +14457,7 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n,
skill->castend_damage_id);
if(skill_lv > 6 && n==3 && c==4) {
- skill_brandishspear_dir(&tc,dir,-1);
+ skill->brandishspear_dir(&tc,dir,-1);
n--;c=-1;
}
}
@@ -14699,6 +14880,10 @@ int skill_clear_group (struct block_list *bl, int flag)
if (flag&1)
group[count++]= ud->skillunit[i];
break;
+ case SO_CLOUD_KILL:
+ if( flag&4 )
+ group[count++]= ud->skillunit[i];
+ break;
case SO_WARMER:
if( flag&8 )
group[count++]= ud->skillunit[i];
@@ -14731,6 +14916,7 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
case SA_VIOLENTGALE:
case SA_LANDPROTECTOR:
case NJ_SUITON:
+ case SO_CLOUD_KILL:
case SO_WARMER:
return ud->skillunit[i];
}
@@ -14839,13 +15025,14 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
skill->delunit(su);
return 1;
}
- if( !(skill->get_inf2(su->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || su->group->skill_id == WZ_FIREPILLAR ) { //It deletes everything except songs/dances and traps
+ if( !(skill->get_inf2(su->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || su->group->skill_id == WZ_FIREPILLAR || su->group->skill_id == GN_HELLS_PLANT) { //It deletes everything except songs/dances and traps
skill->delunit(su);
return 1;
}
break;
case HW_GANBANTEIN:
case LG_EARTHDRIVE:
+ case GN_CRAZYWEED_ATK:
if( !(su->group->state.song_dance&0x1) ) {// Don't touch song/dance.
skill->delunit(su);
return 1;
@@ -14892,25 +15079,6 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
return 1;
}
break;
- case GN_CRAZYWEED_ATK:
- switch(su->group->unit_id) {
- //TODO: look for other ground skills that are affected.
- case UNT_WALLOFTHORN:
- case UNT_THORNS_TRAP:
- case UNT_BLOODYLUST:
- case UNT_CHAOSPANIC:
- case UNT_MAELSTROM:
- case UNT_FIREPILLAR_ACTIVE:
- case UNT_LANDPROTECTOR:
- case UNT_VOLCANO:
- case UNT_DELUGE:
- case UNT_VIOLENTGALE:
- case UNT_SAFETYWALL:
- case UNT_PNEUMA:
- skill->delunit(su);
- return 1;
- }
- break;
}
if (su->group->skill_id == SA_LANDPROTECTOR && !(skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) {
@@ -15002,8 +15170,10 @@ int skill_trap_splash(struct block_list *bl, va_list ap) {
sc_start2(bl,SC_ARMOR_PROPERTY,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv));
break;
case UNT_REVERBERATION:
- skill->addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse
- skill->addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0);
+ if( battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
+ skill->attack(BF_WEAPON,ss,src,bl,WM_REVERBERATION_MELEE,sg->skill_lv,tick,0);
+ skill->addtimerskill(ss,tick+200,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,SD_LEVEL);
+ }
break;
case UNT_FIRINGTRAP:
case UNT_ICEBOUNDTRAP:
@@ -15044,33 +15214,6 @@ int skill_trap_splash(struct block_list *bl, va_list ap) {
return 1;
}
-int skill_maelstrom_suction(struct block_list *bl, va_list ap) {
- uint16 skill_id, skill_lv;
- struct skill_unit *su;
-
- skill_id = va_arg(ap,int);
- skill_lv = va_arg(ap,int);
- su = (struct skill_unit *)bl;
-
- if( su == NULL || su->group == NULL )
- return 0;
-
- if( skill->get_inf2(skill_id)&INF2_TRAP )
- return 0;
-
- if( su->group->skill_id == SC_MAELSTROM ) {
- struct block_list *src;
- if( (src = map->id2bl(su->group->src_id)) ) {
- int sp = su->group->skill_lv * skill_lv;
- if( src->type == BL_PC )
- sp += ((TBL_PC*)src)->status.job_level / 5;
- status->heal(src, 0, sp/2, 1);
- }
- }
-
- return 0;
-}
-
/*==========================================
*
*------------------------------------------*/
@@ -15194,9 +15337,6 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
nullpo_retr(NULL, group->unit); // crash-protection against poor coding
nullpo_retr(NULL, su=&group->unit[idx]);
- if( map->getcell(map->id2bl(group->src_id)->m, x, y, CELL_CHKMAELSTROM) )
- return su;
-
if(!su->alive)
group->alive_count++;
@@ -15228,9 +15368,6 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
case HP_BASILICA:
skill->unitsetmapcell(su,HP_BASILICA,group->skill_lv,CELL_BASILICA,true);
break;
- case SC_MAELSTROM:
- skill->unitsetmapcell(su,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true);
- break;
default:
if (group->state.song_dance&0x1) //Check for dissonance.
skill->dance_overlap(su, 1);
@@ -15289,9 +15426,6 @@ int skill_delunit (struct skill_unit* su) {
status_change_end(target, SC_ELECTRICSHOCKER, INVALID_TIMER);
}
break;
- case SC_MAELSTROM:
- skill->unitsetmapcell(su,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false);
- break;
case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info)
if( group->val2 ) { // Someone Traped
struct status_change *tsc = status->get_sc(map->id2bl(group->val2));
@@ -15720,15 +15854,15 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
}
clif->changetraplook(bl,UNT_USED_TRAPS);
map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
- group->limit = DIFF_TICK32(tick,group->tick)+1000;
- su->limit = DIFF_TICK32(tick,group->tick)+1000;
+ group->limit = DIFF_TICK32(tick,group->tick)+1500;
+ su->limit = DIFF_TICK32(tick,group->tick)+1500;
group->unit_id = UNT_USED_TRAPS;
break;
case UNT_FEINTBOMB: {
struct block_list *src = map->id2bl(group->src_id);
if( src )
- map->foreachinrange(skill->area_sub, &group->unit->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, &group->unit->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|1, skill->castend_damage_id);
skill->delunit(su);
break;
}
@@ -15779,13 +15913,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
}
break;
case UNT_REVERBERATION:
- if( su->val1 <= 0 ) {
- clif->changetraplook(bl,UNT_USED_TRAPS);
- map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
- group->limit = DIFF_TICK32(tick,group->tick)+1000;
- su->limit = DIFF_TICK32(tick,group->tick)+1000;
- group->unit_id = UNT_USED_TRAPS;
- }
+ if( su->val1 <= 0 )
+ su->limit = DIFF_TICK32(tick + 700,group->tick);
break;
case UNT_WALLOFTHORN:
if( su->val1 <= 0 ) {
@@ -16331,7 +16460,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
const int max[10] = {4, 5, 5, 6, 6, 7, 7, 8, 8, 9};
int lv = max(0, pc->checkskill(sd,GC_RESEARCHNEWPOISON) - 1);
qty = min[lv] + rnd()%(max[lv] - min[lv]);
- make_per = 3000 + 500 * (lv+1);
+ make_per = 3000 + 500 * lv + st->dex / 3 * 10 + st->luk * 10 + sd->status.job_level * 10;
}
break;
case GN_CHANGEMATERIAL:
@@ -16776,6 +16905,7 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
return 0;
}
+ status_change_end(&sd->bl, SC_POISONINGWEAPON, -1);//Status must be forced to end so that a new poison will be applied if a player decides to change poisons. [Rytech]
chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv
sc_start4(&sd->bl, SC_POISONINGWEAPON, 100, pc->checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1
type, chance, 0, skill->get_time(GC_POISONINGWEAPON, sd->menuskill_val));
@@ -17604,7 +17734,7 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
switch(type){
case SC_STASIS:
inf = skill->get_inf2(skill_id);
- if( inf == INF2_SONG_DANCE || /*skill->get_inf2(skill_id) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL )
+ if( inf == INF2_SONG_DANCE || skill->get_inf2(skill_id) == INF2_CHORUS_SKILL || inf == INF2_SPIRIT_SKILL )
return 1; // Can't do it.
switch( skill_id ) {
case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER:
@@ -18413,7 +18543,7 @@ void skill_defaults(void) {
skill->check_condition_mercenary = skill_check_condition_mercenary;
skill->locate_element_field = skill_locate_element_field;
skill->graffitiremover = skill_graffitiremover;
- skill->activate_reverberation = skill_activate_reverbetion;
+ skill->activate_reverberation = skill_activate_reverberation;
skill->dance_overlap = skill_dance_overlap;
skill->dance_overlap_sub = skill_dance_overlap_sub;
skill->get_unit_layout = skill_get_unit_layout;
@@ -18470,7 +18600,6 @@ void skill_defaults(void) {
skill->changematerial = skill_changematerial;
skill->get_elemental_type = skill_get_elemental_type;
skill->cooldown_save = skill_cooldown_save;
- skill->maelstrom_suction = skill_maelstrom_suction;
skill->get_new_group_id = skill_get_new_group_id;
skill->check_shadowform = skill_check_shadowform;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 78829f17e..13d34d267 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2006,7 +2006,6 @@ struct skill_interface {
int (*changematerial) (struct map_session_data *sd, int n, unsigned short *item_list);
int (*get_elemental_type) (uint16 skill_id, uint16 skill_lv);
void (*cooldown_save) (struct map_session_data * sd);
- int (*maelstrom_suction) (struct block_list *bl, va_list ap);
int (*get_new_group_id) (void);
bool (*check_shadowform) (struct block_list *bl, int64 damage, int hit);
};
diff --git a/src/map/status.c b/src/map/status.c
index df79cee74..65d982829 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -593,21 +593,19 @@ void initChangeTables(void) {
set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE );
set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
- set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_NONE );
+ set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
/**
* Royal Guard
**/
set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
- set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF );
+ set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP );
set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF );
set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
- set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_DEF , SI_SHIELDSPELL_DEF , SCB_WATK );
- set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_REF , SI_SHIELDSPELL_REF , SCB_DEF );
set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE );
/**
* Shadow Chaser
@@ -626,8 +624,10 @@ void initChangeTables(void) {
set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP );
set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE );
- add_sc( SC_CHAOSPANIC , SC_CONFUSION );
- add_sc( SC_BLOODYLUST , SC_BERSERK );
+ add_sc( SC_CHAOSPANIC , SC__CHAOS );
+ add_sc( SC_MAELSTROM , SC__MAELSTROM );
+ add_sc( SC_BLOODYLUST , SC_BERSERK );
+
/**
* Sura
**/
@@ -646,10 +646,10 @@ void initChangeTables(void) {
set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD );
set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF );
set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK );
- set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_BATK );
+ set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK );
set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 );
set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE );
+ set_sc( WM_POEMOFNETHERWORLD , SC_STOP , SI_NETHERWORLD , SCB_NONE );
set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE );
set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE );
@@ -658,8 +658,8 @@ void initChangeTables(void) {
set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD );
set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP );
- set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK );
- set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK );
+ set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT );
+ set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP );
set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP );
@@ -670,7 +670,7 @@ void initChangeTables(void) {
set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
- add_sc( SO_CLOUD_KILL , SC_POISON );
+ set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
@@ -679,6 +679,7 @@ void initChangeTables(void) {
set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ add_sc( SO_ELEMENTAL_SHIELD , SC_SAFETYWALL );
/**
* Genetic
**/
@@ -712,8 +713,8 @@ void initChangeTables(void) {
set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD );
set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD );
set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP );
- set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_NONE );
- set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE );
+ set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP );
+ set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP );
set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
@@ -854,8 +855,6 @@ void initChangeTables(void) {
status->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF;
status->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE;
- status->IconChangeTable[SC_GLOOMYDAY_SK] = SI_GLOOMYDAY;
-
status->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER;
status->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
@@ -971,10 +970,17 @@ void initChangeTables(void) {
status->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP;
status->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT;
// Guillotine Cross Poison Effects
- status->ChangeFlagTable[SC_PARALYSE] |= SCB_ASPD|SCB_FLEE|SCB_SPEED;
- status->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD;
status->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE;
status->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
+ // RG status
+ status->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK;
+ status->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF;
+ // Meca status
+ status->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED;
status->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR;
status->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT;
@@ -1026,7 +1032,6 @@ void initChangeTables(void) {
status->DisplayType[SC_CURSEDCIRCLE_TARGET]= true;
status->DisplayType[SC_BLOOD_SUCKER] = true;
status->DisplayType[SC__SHADOWFORM] = true;
- status->DisplayType[SC__MANHOLE] = true;
status->DisplayType[SC_MONSTER_TRANSFORM] = true;
status->DisplayType[SC_MOONSTAR] = true;
status->DisplayType[SC_SUPER_STAR] = true;
@@ -1200,8 +1205,6 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
status_change_end(target, SC_CLOAKING, INVALID_TIMER);
status_change_end(target, SC_CHASEWALK, INVALID_TIMER);
status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER);
- status_change_end(target, SC__INVISIBILITY, INVALID_TIMER);
- status_change_end(target, SC_DEEP_SLEEP, INVALID_TIMER);
if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) {
//Endure count is only reduced by non-players on non-gvg maps.
//val4 signals infinite endure. [Skotlex]
@@ -1522,6 +1525,41 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
return 1;
}
+int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) {
+ struct status_data *st;
+ unsigned int hp, sp;
+ if (!status->isdead(bl)) return 0;
+
+ st = status->get_status_data(bl);
+ if (st == &status->dummy)
+ return 0; //Invalid target.
+
+ hp = per_hp;
+ sp = per_sp;
+
+ if(hp > st->max_hp - st->hp)
+ hp = st->max_hp - st->hp;
+ else if (per_hp && !hp)
+ hp = 1;
+
+ if(sp > st->max_sp - st->sp)
+ sp = st->max_sp - st->sp;
+ else if (per_sp && !sp)
+ sp = 1;
+
+ st->hp += hp;
+ st->sp += sp;
+
+ if (bl->prev) //Animation only if character is already on a map.
+ clif->resurrection(bl, 1);
+ switch (bl->type) {
+ case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break;
+ case BL_MOB: mob->revive((TBL_MOB*)bl, hp); break;
+ case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break;
+ }
+ return 1;
+}
+
/*==========================================
* Checks whether the src can use the skill on the target,
* taking into account status/option of both source/target. [Skotlex]
@@ -1694,7 +1732,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
switch(skill_id) {//##TODO## make this a flag in skill_db?
// Skills that can be used even under Man Hole effects.
case SC_SHADOWFORM:
- case SC_STRIPACCESSARY:
break;
default:
return 0;
@@ -1721,8 +1758,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
}
}
- if (sc->option&OPTION_CHASEWALK && skill_id != ST_CHASEWALK)
- return 0;
+ if ( sc->option&OPTION_CHASEWALK ) {
+ if ( sc->data[SC__INVISIBILITY] ) {
+ if ( skill_id != 0 && skill_id != SC_INVISIBILITY )
+ return 0;
+ } 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]
}
@@ -1743,6 +1785,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)))
return 0;
+ if( ( tsc->data[SC_STEALTHFIELD] || tsc->data[SC_CAMOUFLAGE] ) && !(st->mode&(MD_BOSS|MD_DETECTOR)) && flag == 4 )
+ return 0;
}
//If targetting, cloak+hide protect you, otherwise only hiding does.
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
@@ -1770,7 +1814,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
((sd->special_state.perfect_hiding || !is_detect) ||
(tsc->data[SC_CLOAKINGEXCEED] && is_detect)))
return 0;
- if( tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && !skill_id )
+ if( tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && (!skill_id || (flag == 0 && src && src->type != BL_PC)) )
return 0;
if( tsc->data[SC_STEALTHFIELD] && !is_boss )
return 0;
@@ -1825,20 +1869,17 @@ int status_check_visibility(struct block_list *src, struct block_list *target) {
if( ( tsc = status->get_sc(target) ) ) {
struct status_data *st = status->get_status_data(src);
-
- if( tsc->data[SC_STEALTHFIELD] )
- return 0;
switch (target->type) { //Check for chase-walk/hiding/cloaking opponents.
case BL_PC:
if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) )
return 0;
- if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) &&
+ if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) &&
( ((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR) ) )
return 0;
break;
default:
- if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS|MD_DETECTOR)) )
+ if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS|MD_DETECTOR)) )
return 0;
}
@@ -2074,9 +2115,9 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
if (flag&8 && mbl) {
struct status_data *masterstatus = status->get_base_status(mbl);
if ( masterstatus ) {
- if( battle_config.slaves_inherit_speed&(masterstatus->mode&MD_CANMOVE?1:2) )
+ if (battle_config.slaves_inherit_speed&(masterstatus->mode&MD_CANMOVE ? 1 : 2))
mstatus->speed = masterstatus->speed;
- if( mstatus->speed < 2 ) /* minimum for the unit to function properly */
+ if (mstatus->speed < 2) /* minimum for the unit to function properly */
mstatus->speed = 2;
}
}
@@ -2098,6 +2139,8 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
mstatus->mode|= MD_CANATTACK|MD_AGGRESSIVE;
}
mstatus->hp = mstatus->max_hp;
+ if( ud->skill_id == NC_SILVERSNIPER )
+ mstatus->rhw.atk = mstatus->rhw.atk2 = 200 * ud->skill_lv;
}
}
@@ -2937,6 +2980,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->rhw.range += skill_lv;
}
}
+ if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 )
+ bstatus->hit += 3*skill_lv;
+ if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && ((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0))
+ bstatus->hit += 2*skill_lv;
// ----- FLEE CALCULATION -----
@@ -2955,6 +3002,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
}
+ if( pc_ismadogear(sd) && (skill_lv = pc->checkskill(sd,NC_MAINFRAME)) > 0 )
+ bstatus->def += 20 + 20 * skill_lv;
+
#ifndef RENEWAL
if (!battle_config.weapon_defense_type && bstatus->def > battle_config.max_def) {
bstatus->def2 += battle_config.over_def_bonus*(bstatus->def -battle_config.max_def);
@@ -3088,6 +3138,17 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->subrace[RC_DRAGON]+=skill_lv;
}
+ if( (skill_lv = pc->checkskill(sd, AB_EUCHARISTICA)) > 0 ) {
+ sd->right_weapon.addrace[RC_DEMON] += skill_lv;
+ sd->right_weapon.addele[ELE_DARK] += skill_lv;
+ sd->left_weapon.addrace[RC_DEMON] += skill_lv;
+ sd->left_weapon.addele[ELE_DARK] += skill_lv;
+ sd->magic_addrace[RC_DEMON] += skill_lv;
+ sd->magic_addele[ELE_DARK] += skill_lv;
+ sd->subrace[RC_DEMON] += skill_lv;
+ sd->subele[ELE_DARK] += skill_lv;
+ }
+
if(sc->count) {
if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data
sc->data[SC_CONCENTRATION]->val3 = sd->param_bonus[1]; //Agi
@@ -3394,7 +3455,7 @@ void status_calc_regen(struct block_list *bl, struct status_data *st, struct reg
if( (skill_lv=pc->checkskill(sd,NJ_NINPOU)) > 0 )
val += skill_lv*3 + skill_lv*st->max_sp/500;
if( (skill_lv=pc->checkskill(sd,WM_LESSON)) > 0 )
- val += 3 + 3 * skill_lv;
+ val += skill_lv*3 + skill_lv*st->max_sp/500;
sregen->sp = cap_value(val, 0, SHRT_MAX);
@@ -3520,7 +3581,12 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|| (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)
|| (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1))
regen->rate.hp *= 2;
-
+ if( sc->data[SC_VITALITYACTIVATION] )
+ regen->flag &=~RGN_SP;
+ if(sc->data[SC_EXTRACT_WHITE_POTION_Z])
+ regen->rate.hp += regen->rate.hp * sc->data[SC_EXTRACT_WHITE_POTION_Z]->val1/100;
+ if(sc->data[SC_VITATA_500])
+ regen->rate.sp += regen->rate.sp * sc->data[SC_VITATA_500]->val1/100;
}
/// Recalculates parts of an object's battle status according to the specified flags.
/// @param flag bitfield of values from enum scb_flag
@@ -4085,6 +4151,8 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
str -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ str += sc->data[SC_BEYOND_OF_WARCRY]->val3;
if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && str < 50)
return 50;
if(sc->data[SC_INCALLSTATUS])
@@ -4248,6 +4316,8 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
int_ -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
+ if(sc->data[SC_MELODYOFSINK])
+ int_ -= sc->data[SC_MELODYOFSINK]->val3;
if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && int_ < 50)
return 50;
if(sc->data[SC_INCALLSTATUS])
@@ -4287,10 +4357,12 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_KYOUGAKU])
int_ -= sc->data[SC_KYOUGAKU]->val2;
- if(sc->data[SC_NOEQUIPHELM])
- int_ -= int_ * sc->data[SC_NOEQUIPHELM]->val2/100;
- if(sc->data[SC__STRIPACCESSARY])
- int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
+ if(bl->type != BL_PC){
+ if(sc->data[SC_NOEQUIPHELM])
+ int_ -= int_ * sc->data[SC_NOEQUIPHELM]->val2/100;
+ if(sc->data[SC__STRIPACCESSARY])
+ int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
+ }
if(sc->data[SC_FULL_THROTTLE])
int_ += int_ * 20 / 100;
@@ -4349,7 +4421,7 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_MARSHOFABYSS])
dex -= dex * sc->data[SC_MARSHOFABYSS]->val2 / 100;
- if(sc->data[SC__STRIPACCESSARY])
+ if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
dex -= dex * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_FULL_THROTTLE])
dex += dex * 20 / 100;
@@ -4397,7 +4469,7 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_LAUDARAMUS])
luk += 4 + sc->data[SC_LAUDARAMUS]->val1;
- if(sc->data[SC__STRIPACCESSARY])
+ if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
luk -= luk * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_BANANA_BOMB])
luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100;
@@ -4439,7 +4511,7 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_FULL_SWING_K])
batk += sc->data[SC_FULL_SWING_K]->val1;
if(sc->data[SC_ODINS_POWER])
- batk += 70;
+ batk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_element(bl) == ELE_WATER) //water type
batk /= 2;
@@ -4474,14 +4546,8 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
batk += batk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC__ENERVATION])
batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
- if(sc->data[SC_RUSH_WINDMILL])
- batk += batk * sc->data[SC_RUSH_WINDMILL]->val2/100;
if(sc->data[SC_SATURDAY_NIGHT_FEVER])
batk += 100 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1;
- if(sc->data[SC_MELODYOFSINK])
- batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100;
- if(sc->data[SC_BEYOND_OF_WARCRY])
- batk += batk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100;
return (unsigned short)cap_value(batk,0,USHRT_MAX);
}
@@ -4552,16 +4618,16 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += watk * sc->data[SC_PROVOKE]->val3/100;
if(sc->data[SC_SKE])
watk += watk * 3;
- if(sc->data[SC__ENERVATION])
- watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
if(sc->data[SC_HLIF_FLEET])
watk += watk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC_CURSE])
watk -= watk * 25/100;
- if(sc->data[SC_NOEQUIPWEAPON])
+ if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC)
watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100;
if(sc->data[SC__ENERVATION])
watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
+ if(sc->data[SC_RUSH_WINDMILL])
+ watk += sc->data[SC_RUSH_WINDMILL]->val2;
if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
|| (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
|| (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)
@@ -4590,6 +4656,8 @@ unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc
matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
if(sc->data[SC_CHILLY_AIR_OPTION])
matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
+ if(sc->data[SC_COOLER_OPTION])
+ matk += sc->data[SC_COOLER_OPTION]->val2;
if(sc->data[SC_WATER_BARRIER])
matk -= sc->data[SC_WATER_BARRIER]->val3;
if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
@@ -4625,6 +4693,8 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
if (sc->data[SC_CHILLY_AIR_OPTION])
matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
+ if(sc->data[SC_COOLER_OPTION])
+ matk += sc->data[SC_COOLER_OPTION]->val2;
if (sc->data[SC_WATER_BARRIER])
matk -= sc->data[SC_WATER_BARRIER]->val3;
if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
@@ -4644,14 +4714,9 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
matk += matk * sc->data[SC_INCMATKRATE]->val1/100;
if (sc->data[SC_MOONLIT_SERENADE])
matk += matk * sc->data[SC_MOONLIT_SERENADE]->val2/100;
- if (sc->data[SC_MELODYOFSINK])
- matk += matk * sc->data[SC_MELODYOFSINK]->val3/100;
if (sc->data[SC_MTF_MATK])
matk += matk * 25 / 100;
- if (sc->data[SC_BEYOND_OF_WARCRY])
- matk -= matk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100;
-
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
@@ -4683,9 +4748,11 @@ signed short status_calc_critical(struct block_list *bl, struct status_change *s
#endif
if(sc->data[SC__INVISIBILITY])
- critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100;
+ critical += sc->data[SC__INVISIBILITY]->val3;
if(sc->data[SC__UNLUCKY])
critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100;
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ critical += 10 * sc->data[SC_BEYOND_OF_WARCRY]->val3;
return (short)cap_value(critical,10,SHRT_MAX);
}
@@ -4714,7 +4781,7 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
if(sc->data[SC_LKCONCENTRATION])
hit += sc->data[SC_LKCONCENTRATION]->val3;
if(sc->data[SC_INSPIRATION])
- hit += 5 * sc->data[SC_INSPIRATION]->val1;
+ hit += 5 * sc->data[SC_INSPIRATION]->val1 + 25;
if(sc->data[SC_GS_ADJUSTMENT])
hit -= 30;
if(sc->data[SC_GS_ACCURACY])
@@ -4802,19 +4869,19 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
if(sc->data[SC_FEAR])
flee -= flee * 20 / 100;
if(sc->data[SC_PARALYSE])
- flee -= flee * 10 / 100; // 10% Flee reduction
+ flee -= flee / 10; // 10% Flee reduction
if(sc->data[SC_INFRAREDSCAN])
flee -= flee * 30 / 100;
if( sc->data[SC__LAZINESS] )
flee -= flee * sc->data[SC__LAZINESS]->val3 / 100;
if( sc->data[SC_GLOOMYDAY] )
- flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100;
+ flee -= flee * ( 20 + 5 * sc->data[SC_GLOOMYDAY]->val1 ) / 100;
if( sc->data[SC_SATURDAY_NIGHT_FEVER] )
flee -= flee * (40 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
if( sc->data[SC_WIND_STEP_OPTION] )
flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100;
if( sc->data[SC_ZEPHYR] )
- flee += flee * sc->data[SC_ZEPHYR]->val2 / 100;
+ flee += sc->data[SC_ZEPHYR]->val2;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ //mob
if(status_get_element(bl) == ELE_WATER) //water type
flee /= 2;
@@ -4899,7 +4966,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def >>=1;
if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense->
def -= def * sc->data[SC_PROVOKE]->val4/100;
- if(sc->data[SC_NOEQUIPSHIELD])
+ if(sc->data[SC_NOEQUIPSHIELD] && bl->type != BL_PC)
def -= def * sc->data[SC_NOEQUIPSHIELD]->val2/100;
if (sc->data[SC_FLING])
def -= def * (sc->data[SC_FLING]->val2)/100;
@@ -4909,12 +4976,18 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def -= def * (10 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
if(sc->data[SC_EARTHDRIVE])
def -= def * 25 / 100;
+ if(sc->data[SC_SOLID_SKIN_OPTION])
+ def += def * sc->data[SC_SOLID_SKIN_OPTION]->val2 / 100;
if( sc->data[SC_ROCK_CRUSHER] )
def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100;
if( sc->data[SC_POWER_OF_GAIA] )
def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100;
+ if( sc->data[SC_NEUTRALBARRIER] )
+ def += def * (5 * sc->data[SC_NEUTRALBARRIER]->val1 + 10) / 100;
+ if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 2 )
+ def += sc->data[SC_SHIELDSPELL_REF]->val2;
if( sc->data[SC_PRESTIGE] )
- def += def * sc->data[SC_PRESTIGE]->val1 / 100;
+ def += sc->data[SC_PRESTIGE]->val1;
if( sc->data[SC_FROSTMISTY] )
def -= def * 10 / 100;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
@@ -4955,11 +5028,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
return 0;
if(sc->data[SC_SUN_COMFORT])
def2 += sc->data[SC_SUN_COMFORT]->val2;
- if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 )
- def2 += sc->data[SC_SHIELDSPELL_REF]->val2;
if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
-
if(sc->data[SC_ANGELUS])
#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus
def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100;
@@ -4984,7 +5054,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
if(sc->data[SC_ANALYZE])
def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
if( sc->data[SC_ECHOSONG] )
- def2 += def2 * sc->data[SC_ECHOSONG]->val2/100;
+ def2 += def2 * sc->data[SC_ECHOSONG]->val3/100;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_race(bl)==RC_PLANT)
def2 /= 2;
@@ -5040,8 +5110,10 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md
mdef += mdef * sc->data[SC_SYMPHONY_LOVE]->val2 / 100;
if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val4)
mdef -= mdef * sc->data[SC_GENTLETOUCH_CHANGE]->val4 / 100;
+ if(sc->data[SC_NEUTRALBARRIER] )
+ mdef += mdef * (5 * sc->data[SC_NEUTRALBARRIER]->val1 + 10) / 100;
if (sc->data[SC_ODINS_POWER])
- mdef -= 20 * sc->data[SC_ODINS_POWER]->val1;
+ mdef -= 20;
if(sc->data[SC_BURNING])
mdef -= mdef *25 / 100;
@@ -5095,7 +5167,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) )
{
if( sd->ud.skill_id == LG_EXEEDBREAK )
- speed_rate = 100 + 60 - (sd->ud.skill_lv * 10);
+ speed_rate = 160 - 10 * sd->ud.skill_lv;
else
speed_rate = 175 - 5 * pc->checkskill(sd,SA_FREECAST);
}
@@ -5144,7 +5216,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sc->data[SC_DEC_AGI] )
val = max( val, 25 );
- if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] || (sc->data[SC_GLOOMYDAY] && sc->data[SC_GLOOMYDAY]->val4) )
+ if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] )
val = max( val, 50 );
if( sc->data[SC_DONTFORGETME] )
val = max( val, sc->data[SC_DONTFORGETME]->val3 );
@@ -5174,6 +5246,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) );
if( sc->data[SC__GROOMY] )
val = max( val, sc->data[SC__GROOMY]->val2);
+ if( sc->data[SC_GLOOMYDAY] )
+ val = max( val, sc->data[SC_GLOOMYDAY]->val3 ); // Should be 50 (-50% speed)
if( sc->data[SC_STEALTHFIELD_MASTER] )
val = max( val, 30 );
if( sc->data[SC_BANDING_DEFENCE] )
@@ -5226,7 +5300,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sc->data[SC_GN_CARTBOOST] )
val = max( val, sc->data[SC_GN_CARTBOOST]->val2 );
if( sc->data[SC_SWING] )
- val = max( val, sc->data[SC_SWING]->val2 );
+ val = max( val, sc->data[SC_SWING]->val3 );
if( sc->data[SC_WIND_STEP_OPTION] )
val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 );
if( sc->data[SC_FULL_THROTTLE] )
@@ -5335,20 +5409,20 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
if( sc->data[SC_PARALYSE] )
skills2 -= 10;
if( sc->data[SC__BODYPAINT] )
- skills2 -= 2 + 5 * sc->data[SC__BODYPAINT]->val1;
+ skills2 -= sc->data[SC__BODYPAINT]->val1;
if( sc->data[SC__INVISIBILITY] )
skills2 -= sc->data[SC__INVISIBILITY]->val2 ;
if( sc->data[SC__GROOMY] )
skills2 -= sc->data[SC__GROOMY]->val2;
if( sc->data[SC_GLOOMYDAY] )
- skills2 -= sc->data[SC_GLOOMYDAY]->val3;
+ skills2 -= ( 15 + 5 * sc->data[SC_GLOOMYDAY]->val1 );
if( sc->data[SC_EARTHDRIVE] )
skills2 -= 25;
if( sc->data[SC_MELON_BOMB] )
skills2 -= sc->data[SC_MELON_BOMB]->val1;
if( sc->data[SC_SWING] )
- skills2 += sc->data[SC_SWING]->val2;
+ skills2 += sc->data[SC_SWING]->val3;
if( sc->data[SC_DANCE_WITH_WUG] )
skills2 += sc->data[SC_DANCE_WITH_WUG]->val3;
if( sc->data[SC_GENTLETOUCH_CHANGE] )
@@ -5514,17 +5588,17 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
if( sc->data[SC_PARALYSE] )
aspd_rate += 100;
if( sc->data[SC__BODYPAINT] )
- aspd_rate += 200 + 50 * sc->data[SC__BODYPAINT]->val1;
+ aspd_rate += 10 * 5 * sc->data[SC__BODYPAINT]->val1;
if( sc->data[SC__INVISIBILITY] )
aspd_rate += sc->data[SC__INVISIBILITY]->val2 * 10 ;
if( sc->data[SC__GROOMY] )
aspd_rate += sc->data[SC__GROOMY]->val2 * 10;
if( sc->data[SC_SWING] )
- aspd_rate -= sc->data[SC_SWING]->val2 * 10;
+ aspd_rate -= sc->data[SC_SWING]->val3 * 10;
if( sc->data[SC_DANCE_WITH_WUG] )
aspd_rate -= sc->data[SC_DANCE_WITH_WUG]->val3 * 10;
if( sc->data[SC_GLOOMYDAY] )
- aspd_rate += sc->data[SC_GLOOMYDAY]->val3 * 10;
+ aspd_rate += ( 15 + 5 * sc->data[SC_GLOOMYDAY]->val1 );
if( sc->data[SC_EARTHDRIVE] )
aspd_rate += 250;
if( sc->data[SC_GENTLETOUCH_CHANGE] )
@@ -5595,11 +5669,13 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc,
if(sc->data[SC__WEAKNESS])
maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100;
if(sc->data[SC_LERADS_DEW])
- maxhp += maxhp * sc->data[SC_LERADS_DEW]->val3 / 100;
+ maxhp += sc->data[SC_LERADS_DEW]->val3;
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ maxhp -= maxhp * sc->data[SC_BEYOND_OF_WARCRY]->val4 / 100;
if(sc->data[SC_FORCEOFVANGUARD])
maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
- if(sc->data[SC_INSPIRATION]) //Custom value.
- maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100;
+ if(sc->data[SC_INSPIRATION])
+ maxhp += maxhp * 5 * sc->data[SC_INSPIRATION]->val1 / 100 + 600 * sc->data[SC_INSPIRATION]->val1;
if(sc->data[SC_RAISINGDRAGON])
maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100;
if(sc->data[SC_GENTLETOUCH_CHANGE]) // Max HP decrease: [Skill Level x 4] %
@@ -5612,6 +5688,10 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc,
maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100;
if(sc->data[SC_PETROLOGY_OPTION])
maxhp += maxhp * sc->data[SC_PETROLOGY_OPTION]->val2 / 100;
+ if(sc->data[SC_CURSED_SOIL_OPTION])
+ maxhp += maxhp * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100;
+ if(sc->data[SC_UPHEAVAL_OPTION])
+ maxhp += maxhp * sc->data[SC_UPHEAVAL_OPTION]->val3 / 100;
if (sc->data[SC_ANGRIFFS_MODUS])
maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100;
if (sc->data[SC_GOLDENE_FERSE])
@@ -6182,17 +6262,34 @@ void status_change_init(struct block_list *bl) {
//Returns the adjusted duration based on flag values.
//the flag values are the same as in status->change_start.
int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int tick, int flag) {
+ //Temporary to simulate the source block_list [Playtester]
+ struct block_list *src = bl; // FIXME: This should be passed to the function as argument
+
//Percentual resistance: 10000 = 100% Resist
//Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms
int sc_def = 0, tick_def = -1; //-1 = use sc_def
//Linear resistance substracted from rate and tick after percentual resistance was applied
//Example: 25% -> sc_def2=2000 -> 5%; 2500ms -> tick_def2=2000 -> 500ms
- int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2
+ int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2 (pre-re only)
+
struct status_data *st;
struct status_change *sc;
struct map_session_data *sd;
nullpo_ret(bl);
+ if(!src)
+ return tick ? tick : 1; // If no source, it can't be resisted (NPC given)
+
+/// Returns the 'bl's level, capped to 'cap'
+#define SCDEF_LVL_CAP(bl, cap) ( (bl) ? (status->get_lv(bl) > (cap) ? (cap) : status->get_lv(bl)) : 0 )
+/// Renewal level modifier.
+/// In renewal, returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
+/// In pre-renewal, returns zero.
+#ifdef RENEWAL
+#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) ( ( SCDEF_LVL_CAP((bl), (maxlv)) - SCDEF_LVL_CAP((src), (maxlv)) ) * (factor) )
+#else
+#define SCDEF_LVL_DIFF(bl, src, laxlv, factor) 0
+#endif
//Status that are blocked by Golden Thief Bug card or Wand of Hermod
if (status->isimmune(bl))
@@ -6234,53 +6331,145 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
sc = status->get_sc(bl);
if( sc && !sc->count )
sc = NULL;
+
+ if (sc && sc->data[SC_KINGS_GRACE]) {
+ // Protects against status effects
+ switch (type) {
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_FREEZE:
+ case SC_STONE:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_CONFUSION:
+ case SC_ILLUSION:
+ case SC_SILENCE:
+ case SC_BURNING:
+ case SC_COLD:
+ case SC_FROSTMISTY:
+ case SC_DEEP_SLEEP:
+ case SC_FEAR:
+ case SC_MANDRAGORA:
+ case SC__CHAOS:
+ return 0;
+ }
+ }
+
switch (type) {
case SC_STUN:
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
+ break;
case SC_POISON:
- if( sc && sc->data[SC__UNLUCKY] )
- return tick;
case SC_DPOISON:
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ if (sd) {
+ //For players: 60000 - 450*vit - 100*luk
+ tick_def = st->vit*75;
+ tick_def2 = st->luk*100;
+ } else {
+ //For monsters: 30000 - 200*vit
+ tick>>=1;
+ tick_def = (st->vit*200)/3;
+ }
+#endif
+ break;
case SC_SILENCE:
+#ifdef RENEWAL
+ sc_def = st->int_*100;
+ sc_def2 = (st->vit + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def2 = st->luk * 10;
+#else
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#endif
+ break;
case SC_BLOODING:
+#ifdef RENEWAL
+ sc_def = st->agi*100;
+ tick_def2 = st->luk*10;
+#else
sc_def = st->vit*100;
- sc_def2 = st->luk*10;
+#endif
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
break;
case SC_SLEEP:
sc_def = st->int_*100;
- sc_def2 = st->luk*10;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
break;
case SC_DEEP_SLEEP:
sc_def = st->int_*50;
- tick_def = st->int_*10 + status->get_lv(bl) * 65 / 10; //Seems to be -1 sec every 10 int and -5% chance every 10 int.
+ tick_def = 0; // Linear reduction instead
+ tick_def2 = st->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
break;
case SC_DEC_AGI:
- case SC_ADORAMUS: //Arch Bishop
- if (sd) tick>>=1; //Half duration for players.
+ case SC_ADORAMUS:
+ if (sd) tick >>= 1; //Half duration for players.
+ sc_def = st->mdef*100;
+#ifndef RENEWAL
+ sc_def2 = st->luk*10;
+ tick_def2 = 0; //No duration reduction
+#endif
+ tick_def = 0; //No duration reduction
+ break;
case SC_STONE:
- //Impossible to reduce duration with stats
- tick_def = 0;
- tick_def2 = 0;
+ sc_def = st->mdef*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def = 0; //No duration reduction
+#ifndef RENEWAL
+ tick_def2 = 0; //No duration reduction
+#endif
+ break;
case SC_FREEZE:
sc_def = st->mdef*100;
- sc_def2 = st->luk*10;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def = 0; //No duration reduction
+#ifdef RENEWAL
+ tick_def2 = status_get_luk(src) * -10; //Caster can increase final duration with luk
+#else
+ tick_def2 = 0; //No duration reduction
+#endif
break;
case SC_CURSE:
- //Special property: inmunity when luk is greater than level or zero
- if (st->luk > status->get_lv(bl) || st->luk == 0)
+ // Special property: immunity when luk is zero
+ if (st->luk == 0)
+ return 0;
+#ifndef RENEWAL
+ // Special property: immunity when luk is greater than level
+ if (st->luk > status->get_lv(bl))
return 0;
+#endif
sc_def = st->luk*100;
- sc_def2 = st->luk*10;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(NULL, src, 99, 10); // Curse only has a level penalty and no resistance
tick_def = st->vit*100;
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
break;
case SC_BLIND:
- if( sc && sc->data[SC__UNLUCKY] )
- return tick;
sc_def = (st->vit + st->int_)*50;
- sc_def2 = st->luk*10;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
break;
case SC_CONFUSION:
sc_def = (st->str + st->int_)*50;
- sc_def2 = st->luk*10;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ sc_def2 = -sc_def2; // Reversed sc_def2
+ tick_def2 = st->luk*10;
+#endif
break;
case SC_ANKLESNARE:
if(st->mode&MD_BOSS) // Lasts 5 times less on bosses
@@ -6291,7 +6480,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
case SC_STONESKIN:
if (sd) //Duration greatly reduced for players.
tick /= 15;
- sc_def2 = status->get_lv(bl)*20 + st->vit*25 + st->agi*10; // Lineal Reduction of Rate
+ sc_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 99) * 20; // Linear Reduction of Rate
tick_def2 = 0; //No duration reduction
break;
case SC_MARSHOFABYSS:
@@ -6302,49 +6491,60 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
//5 second (fixed) + { Stasis Skill level * 5 - (Target's VIT + DEX) / 20 }
tick_def2 = (st->vit + st->dex)*50;
break;
- if( bl->type == BL_PC )
- tick -= (status->get_lv(bl) / 5 + st->vit / 4 + st->agi / 10)*100;
+ case SC_WHITEIMPRISON:
+ if( tick == 5000 ) // 100% on caster
+ break;
+ if (bl->type == BL_PC)
+ tick_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 150) * 20;
else
- tick -= (st->vit + st->luk) / 20 * 1000;
+ tick_def2 = (st->vit + st->luk)*50;
break;
case SC_BURNING:
- tick -= 75 * st->luk + 125 * st->agi;
- tick = max(tick,5000); // Minimum Duration 5s.
+ tick_def2 = 75*st->luk + 125*st->agi;
break;
case SC_FROSTMISTY:
- tick -= 1000 * ((st->vit + st->dex) / 20);
- tick = max(tick,6000); // Minimum Duration 6s.
+ tick_def2 = (st->vit + st->dex)*50;
break;
case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT)
- sc_def = 100 - ( 100 - st->int_* 8 / 10 );
- sc_def = max(sc_def, 5); // minimum of 5%
+ sc_def = st->int_*80;
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_LEECHESEND:
+ tick_def2 = (st->vit + st->luk) * 500;
break;
case SC_WUGBITE: // {(Base Success chance) - (Target's AGI / 4)}
- rate -= st->agi*100/4;
- rate = max(rate,5000); // minimum of 50%
+ sc_def2 = st->agi*25;
break;
case SC_ELECTRICSHOCKER:
- if( bl->type == BL_MOB )
- tick -= 1000 * (st->agi/10);
+ tick_def2 = (st->vit + st->agi) * 70;
break;
case SC_COLD:
- tick -= (1000*(st->vit/10))+(status->get_lv(bl)/50);
+ tick_def2 = st->vit*100 + status->get_lv(bl)*20;
+ break;
+ case SC_VACUUM_EXTREME:
+ tick_def2 = st->str*50;
+ break;
+ case SC_MANDRAGORA:
+ sc_def = (st->vit + st->luk)*20;
break;
case SC_SIREN:
- tick -= 1000 * ((status->get_lv(bl) / 10) + ((sd?sd->status.job_level:0) / 5));
- tick = max(tick,10000);
+ tick_def2 = (status->get_lv(bl) * 100) + ((bl->type == BL_PC)?((TBL_PC*)bl)->status.job_level : 0);
break;
case SC_KYOUGAKU:
- tick -= 1000 * status_get_int(bl) / 20;
+ tick_def2 = st->int_ * 50;
break;
case SC_NEEDLE_OF_PARALYZE:
- tick -= 50 * (st->vit + st->luk); //(1000/20);
+ tick_def2 = (st->vit + st->luk) * 50;
break;
default:
//Effect that cannot be reduced? Likely a buff.
if (!(rnd()%10000 < rate))
return 0;
- return tick?tick:1;
+ return tick ? tick : 1;
}
if (sd) {
@@ -6384,11 +6584,16 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
sc_def += sc->data[SC_SIEGFRIED]->val3*100; //Status resistance.
}
- //When no tick def, reduction is the same for both.
- if(tick_def < 0)
+ //When tick def not set, reduction is the same for both.
+ if(tick_def == -1)
tick_def = sc_def;
- if(tick_def2 < 0)
+ if(tick_def2 == -1) {
+#ifdef RENEWAL
+ tick_def2 = 0;
+#else
tick_def2 = sc_def2;
+#endif
+ }
//Natural resistance
if (!(flag&8)) {
@@ -6397,8 +6602,11 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
//Minimum chances
switch (type) {
+ case SC_OBLIVIONCURSE:
+ rate = max(rate,500); //Minimum of 5%
+ break;
case SC_WUGBITE:
- rate = max(rate, 5000); //Minimum of 50%
+ rate = max(rate,5000); //Minimum of 50%
break;
}
@@ -6410,6 +6618,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
if( sd->sc.data[SC_TARGET_BLOOD] )
rate -= rate*sd->sc.data[SC_TARGET_BLOOD]->val1/100;
}
+
+ //Aegis accuracy
+ if(rate > 0 && rate%10 != 0) rate += (10 - rate%10);
}
if (!(rnd()%10000 < rate))
@@ -6428,13 +6639,14 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
//Minimum durations
switch (type) {
case SC_ANKLESNARE:
+ case SC_BURNING:
case SC_MARSHOFABYSS:
case SC_STASIS:
+ case SC_DEEP_SLEEP:
tick = max(tick, 5000); //Minimum duration 5s
break;
- case SC_BURNING:
case SC_FROSTMISTY:
- tick = max(tick, 10000); //Minimum duration 10s
+ tick = max(tick, 6000);
break;
default:
//Skills need to trigger even if the duration is reduced below 1ms
@@ -6443,6 +6655,8 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
}
return tick;
+#undef SCDEF_LVL_CAP
+#undef SCDEF_LVL_DIFF
}
/* [Ind/Hercules] fast-checkin sc-display array */
void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) {
@@ -6549,12 +6763,20 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
return 0; // Immune to status ailements
switch( type ) {
- case SC_QUAGMIRE://Tester said it protects against this and decrease agi.
- case SC_DEC_AGI:
+ case SC_DEEP_SLEEP:
+ case SC__CHAOS:
case SC_BURNING:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_CURSE:
+ case SC_STONE:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_SILENCE:
+ case SC_BLOODING:
+ case SC_FREEZE:
case SC_FROSTMISTY:
- //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech]
- case SC_MARSHOFABYSS:
+ case SC_COLD:
case SC_TOXIN:
case SC_PARALYSE:
case SC_VENOMBLEED:
@@ -6562,9 +6784,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_DEATHHURT:
case SC_PYREXIA:
case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- case SC_COLD: ////08/31/2011 - Class Balance Changes
- case SC_DEEP_SLEEP:
+ case SC_MARSHOFABYSS:
case SC_MANDRAGORA:
return 0;
}
@@ -6572,22 +6792,37 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX )
return 0; // Immune to status ailements
switch( type ) {
- case SC_DEEP_SLEEP:
- case SC_SATURDAY_NIGHT_FEVER:
- case SC_PYREXIA:
- case SC_DEATHHURT:
- case SC_MAGICMUSHROOM:
- case SC_VENOMBLEED:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_STUN:
+ case SC_SILENCE:
+ case SC__CHAOS:
+ case SC_STONE:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_BURNING:
+ case SC_FROSTMISTY:
+ case SC_FREEZE:
+ case SC_COLD:
+ case SC_FEAR:
case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
case SC_OBLIVIONCURSE:
case SC_LEECHESEND:
+ case SC_DEEP_SLEEP:
+ case SC_SATURDAY_NIGHT_FEVER:
+ case SC__BODYPAINT:
case SC__ENERVATION:
case SC__GROOMY:
+ case SC__IGNORANCE:
case SC__LAZINESS:
case SC__UNLUCKY:
case SC__WEAKNESS:
- case SC__BODYPAINT:
- case SC__IGNORANCE:
return 0;
}
}
@@ -6616,6 +6851,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|| (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
)
return 0;
+ case SC_VACUUM_EXTREME:
+ if(sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HOVERING])
+ return 0;
+ break;
case SC_STONE:
if(sc->data[SC_POWER_OF_GAIA])
return 0;
@@ -6623,7 +6862,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
//Undead are immune to Freeze/Stone
if (undead_flag && !(flag&1))
return 0;
- case SC_DEEP_SLEEP:
case SC_SLEEP:
case SC_STUN:
case SC_FROSTMISTY:
@@ -6636,7 +6874,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
//There all like berserk, do not everlap each other
case SC_BERSERK:
- if( sc->data[SC__BLOODYLUST] || sc->data[SC_SATURDAY_NIGHT_FEVER] )
+ if( sc->data[SC__BLOODYLUST] )
return 0;
break;
@@ -6879,8 +7117,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if(sc->data[i]) return 0;
}
break;
- case SC_SATURDAY_NIGHT_FEVER:
- if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION])
+ case SC_MAGNETICFIELD:
+ if(sc->data[SC_HOVERING])
return 0;
break;
case SC_OFFERTORIUM:
@@ -6934,6 +7172,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC__WEAKNESS:
case SC__IGNORANCE:
+ // Other Effects
+ case SC_VACUUM_EXTREME:
+
return 0;
}
}
@@ -6958,6 +7199,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
//Also blocks the ones below...
case SC_DEC_AGI:
+ case SC_ADORAMUS:
status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
//Also blocks the ones below...
case SC_DONTFORGETME:
@@ -7022,9 +7264,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
break;
case SC_CARTBOOST:
- if(sc->data[SC_DEC_AGI])
+ if(sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS])
{ //Cancel Decrease Agi, but take no further effect [Skotlex]
status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
return 0;
}
break;
@@ -7093,47 +7336,43 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
break;
+ //Group A Status (doesn't overlap)
case SC_SWING:
case SC_SYMPHONY_LOVE:
case SC_MOONLIT_SERENADE:
case SC_RUSH_WINDMILL:
case SC_ECHOSONG:
- case SC_HARMONIZE: //group A doesn't overlap
+ case SC_HARMONIZE:
+ case SC_FRIGG_SONG:
if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
break;
+ //Group B Status
case SC_SIREN:
case SC_DEEP_SLEEP:
- case SC_GLOOMYDAY:
- case SC_SONG_OF_MANA:
- case SC_DANCE_WITH_WUG:
- case SC_SATURDAY_NIGHT_FEVER:
+ case SC_SIRCLEOFNATURE:
case SC_LERADS_DEW:
case SC_MELODYOFSINK:
case SC_BEYOND_OF_WARCRY:
- case SC_UNLIMITED_HUMMING_VOICE: //group B
+ case SC_UNLIMITED_HUMMING_VOICE:
+ case SC_GLOOMYDAY:
+ case SC_SONG_OF_MANA:
+ case SC_DANCE_WITH_WUG:
if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- if (type != SC_GLOOMYDAY) {
- status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
- status_change_end(bl, SC_GLOOMYDAY_SK, INVALID_TIMER);
- }
+ if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- if (type != SC_SATURDAY_NIGHT_FEVER) {
- if (sc->data[SC_SATURDAY_NIGHT_FEVER]) {
- sc->data[SC_SATURDAY_NIGHT_FEVER]->val2 = 0; //mark to not lose hp
- status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
- }
- }
break;
case SC_REFLECTSHIELD:
status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
@@ -7145,12 +7384,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_SHIELDSPELL_MDEF:
case SC_SHIELDSPELL_REF:
status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_DEF )
- status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_MDEF )
- status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_REF )
- status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
break;
case SC_GENTLETOUCH_ENERGYGAIN:
case SC_GENTLETOUCH_CHANGE:
@@ -7208,6 +7444,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_MARIONETTE:
case SC_NOCHAT:
case SC_HLIF_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation.
+ case SC_ABUNDANCE:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
case SC__INVISIBILITY:
case SC__ENERVATION:
case SC__GROOMY:
@@ -7215,6 +7460,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC__LAZINESS:
case SC__WEAKNESS:
case SC__UNLUCKY:
+ case SC__CHAOS:
return 0;
case SC_COMBOATTACK:
case SC_DANCING:
@@ -7281,6 +7527,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
calc_flag = status->ChangeFlagTable[type];
if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs
switch(type) {
+ case SC_ADORAMUS:
+ sc_start(bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
+ // Fall through to SC_INC_AGI
case SC_DEC_AGI:
case SC_INC_AGI:
val2 = 2 + val1; //Agi change
@@ -7335,7 +7584,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_KYRIE:
val2 = APPLY_RATE(st->max_hp, (val1 * 2 + 10)); //%Max HP to absorb
- val3 = (val1 / 2 + 5); //Hits
+ // val4 holds current about of party memebers when casting AB_PRAEFATIO,
+ // as Praefatio's barrier has more health and blocks more hits than Kyrie Elesion.
+ if( val4 < 1 ) //== PR_KYRIE
+ val3 = (val1 / 2 + 5); // Hits
+ else { //== AB_PRAEFATIO
+ val2 += val4 * 2; //Increase barrier strength per party member.
+ val3 = 6 + val1;
+ }
+ if( sd )
+ val1 = min(val1,pc->checkskill(sd,PR_KYRIE)); // use skill level to determine barrier health.
break;
case SC_MAGICPOWER:
//val1: Skill lv
@@ -8159,8 +8417,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_WEAPONBLOCKING:
val2 = 10 + 2 * val1; // Chance
- val4 = tick / 3000;
- tick_time = 3000; // [GodLesZ] tick time
+ val4 = tick / 5000;
+ tick_time = 5000; // [GodLesZ] tick time
break;
case SC_TOXIN:
val4 = tick / 10000;
@@ -8212,7 +8470,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_READING_SB:
// val2 = sp reduction per second
- tick_time = 5000; // [GodLesZ] tick time
+ tick_time = 10000; // [GodLesZ] tick time
break;
case SC_SUMMON1:
case SC_SUMMON2:
@@ -8233,6 +8491,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case 4: val2 = ELE_WATER; break;
}
break;
+ case SC_STEALTHFIELD_MASTER:
+ val4 = tick / 1000;
+ tick_time = 2000 + (1000 * val1);
+ break;
case SC_ELECTRICSHOCKER:
case SC_COLD:
case SC_MEIKYOUSISUI:
@@ -8255,6 +8517,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
}
tick = -1;
break;
+ case SC__REPRODUCE:
+ val4 = tick / 1000;
+ tick_time = 1000;
+ break;
case SC__SHADOWFORM: {
struct map_session_data * s_sd = map->id2sd(val2);
if( s_sd )
@@ -8269,7 +8535,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC__INVISIBILITY:
val2 = 50 - 10 * val1; // ASPD
- val3 = 20 * val1; // CRITICAL
+ val3 = 200 * val1; // CRITICAL
val4 = tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
@@ -8335,23 +8601,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000; // [GodLesZ] tick time
}
break;
- case SC_VACUUM_EXTREME:
- tick -= (st->str / 20) * 1000;
- val4 = val3 = tick / 100;
- tick_time = 100; // [GodLesZ] tick time
- break;
case SC_SWING:
- val2 = 4 * val1; // Walk speed and aspd reduction.
+ val3 = 5 * val1 + val2;//Movement Speed And ASPD Increase
break;
case SC_SYMPHONY_LOVE:
+ val2 = 12 * val1 + val2 + sd->status.job_level / 4;//MDEF Increase In %
+ case SC_MOONLIT_SERENADE:
case SC_RUSH_WINDMILL:
- case SC_ECHOSONG:
- val2 = 6 * val1;
- val2 += val3; //Adding 1% * Lesson Bonus
- val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel
+ val2 = 6 * val1 + val2 + sd->status.job_level / 5;
break;
- case SC_MOONLIT_SERENADE:
- val2 = 10 * val1;
+ case SC_ECHOSONG:
+ val3 = 6 * val1 + val2 + sd->status.job_level / 4;//DEF Increase In %
break;
case SC_HARMONIZE:
val2 = 5 + 5 * val1;
@@ -8365,34 +8625,36 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 2000; // [GodLesZ] tick time
break;
case SC_SIRCLEOFNATURE:
- val2 = 1 + val1; //SP consume
- val3 = 40 * val1; //HP recovery
+ val2 = 40 * val1;//HP recovery
+ val3 = 4 * val1;//SP drain
val4 = tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_SONG_OF_MANA:
- val3 = 10 + (2 * val2);
- val4 = tick/3000;
- tick_time = 3000; // [GodLesZ] tick time
+ val3 = 10 + 5 * val2;
+ val4 = tick/5000;
+ tick_time = 5000; // [GodLesZ] tick time
break;
case SC_SATURDAY_NIGHT_FEVER:
- if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1);
- if (!val4) val4 = 3000;
- val3 = tick/val4;
- tick_time = val4; // [GodLesZ] tick time
+ /*val2 = 12000 - 2000 * val1;//HP/SP Drain Timer
+ if ( val2 < 1000 )
+ val2 = 1000;//Added to prevent val3 from dividing by 0 when using level 6 or higher through commands. [Rytech]
+ val3 = tick/val2;*/
+ val3 = tick / 3000;
+ tick_time = 3000;// [GodLesZ] tick time
break;
case SC_GLOOMYDAY:
- val2 = 20 + 5 * val1; // Flee reduction.
- val3 = 15 + 5 * val1; // ASPD reduction.
- if( sd && rand()%100 < val1 ){ // (Skill Lv) %
- val4 = 1; // reduce walk speed by half.
- if( pc_isriding(sd) ) pc->setriding(sd, 0);
- if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ if ( !val2 ) {
+ val2 = (val4 > 0 ? max(15, rnd()%(val4*5)) : 0) + val1 * 10;
+ }
+ if ( rnd()%10000 < val1*100 ) { // 1% per SkillLv chance
+ if ( !val3 )
+ val3 = 50;
+ if( sd ) {
+ if( pc_isriding(sd) ) pc->setriding(sd, 0);
+ if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ }
}
- break;
- case SC_GLOOMYDAY_SK:
- // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %.
- val2 = 15 + rand()%( (sd?pc->checkskill(sd, WM_LESSON)*5:0) + val1*10 );
break;
case SC_SITDOWN_FORCE:
case SC_BANANA_BOMB_SITDOWN_POSTDELAY:
@@ -8404,28 +8666,32 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
}
break;
case SC_DANCE_WITH_WUG:
- val3 = (5 * val1) + (1 * val2); //Still need official value.
+ val3 = 5 + 5 * val2;//ASPD Increase
+ val4 = 20 + 10 * val2;//Fixed Cast Time Reduction
break;
case SC_LERADS_DEW:
- val3 = (5 * val1) + (1 * val2);
+ val3 = 200 * val1 + 300 * val2;//MaxHP Increase
break;
case SC_MELODYOFSINK:
- val3 = (5 * val1) + (1 * val2);
+ val3 = val1 * (2 + val2);//INT Reduction. Formula Includes Caster And 2nd Performer.
+ val4 = tick/1000;
+ tick_time = 1000;
break;
case SC_BEYOND_OF_WARCRY:
- val3 = (5 * val1) + (1 * val2);
+ val3 = val1 * (2 + val2);//STR And Crit Reduction. Formula Includes Caster And 2nd Performer.
+ val4 = 4 * val1 + 4 * val2;//MaxHP Reduction
break;
case SC_UNLIMITED_HUMMING_VOICE:
{
struct unit_data *ud = unit->bl2ud(bl);
if( ud == NULL ) return 0;
ud->state.skillcastcancel = 0;
- val3 = 15 - (2 * val2);
+ val3 = 15 - (3 * val2);//Increased SP Cost.
}
break;
case SC_LG_REFLECTDAMAGE:
val2 = 15 + 5 * val1;
- val3 = (val1==5)?20:(val1+4)*2; // SP consumption
+ val3 = 25 + 5 * val1; //Number of Reflects
val4 = tick/10000;
tick_time = 10000; // [GodLesZ] tick time
break;
@@ -8442,11 +8708,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val1 += (sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->wlv) * status->get_lv(bl) / 100;
}
break;
- case SC_PRESTIGE: // Based on suggested formula in iRO Wiki and some test, still need more test. [pakpil]
- val2 = ((st->int_ + st->luk) / 6) + 5; // Chance to evade magic damage.
+ case SC_PRESTIGE:
+ val2 = (st->int_ + st->luk) * val1 / 20;// Chance to evade magic damage.
+ val2 = val2 * status->get_lv(bl) / 200;
+ val2 += val1;
val1 *= 15; // Defence added
if( sd )
val1 += 10 * pc->checkskill(sd,CR_DEFENDER);
+ val1 *= status->get_lv(bl) / 100;
break;
case SC_BANDING:
tick_time = 5000; // [GodLesZ] tick time
@@ -8457,16 +8726,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_INSPIRATION:
if( sd ) {
- val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus
- val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus
+ val2 = 40 * val1 + 3 * sd->status.job_level;// ATK bonus
+ val3 = sd->status.base_level / 10 + sd->status.job_level / 5;// All stat bonus
}
- val4 = tick / 1000;
- tick_time = 1000; // [GodLesZ] tick time
+ val4 = tick / 5000;
+ tick_time = 5000; // [GodLesZ] tick time
status->change_clear_buffs(bl,3); //Remove buffs/debuffs
break;
- case SC_CRESCENTELBOW:
- val2 = 94 + val1;
- break;
case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] %
val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1;
break;
@@ -8492,9 +8758,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
}
break;
+ case SC_PYROTECHNIC_OPTION:
+ val2 = 60;
+ break;
case SC_HEATER_OPTION:
val2 = 120; // Watk. TODO: Renewal (Atk2)
- val3 = 33; // % Increase effects.
+ val3 = (sd ? sd->status.job_level : 0); // % Increase damage.
val4 = 3; // Change into fire element.
break;
case SC_TROPIC_OPTION:
@@ -8505,8 +8774,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 40;
break;
case SC_COOLER_OPTION:
- val2 = 80; // % Freezing chance
- val3 = 33; // % increased damage
+ val2 = 80; // Bonus Matk
+ val3 = (sd ? sd->status.job_level : 0); // % Freezing chance
val4 = 1; // Change into water elemet
break;
case SC_CHILLY_AIR_OPTION:
@@ -8517,7 +8786,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 50; // % Increase speed and flee.
break;
case SC_BLAST_OPTION:
- val2 = 20;
+ val2 = (sd ? sd->status.job_level : 0); // % Increase damage
val3 = ELE_WIND;
break;
case SC_WILD_STORM_OPTION:
@@ -8527,13 +8796,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 5;
val3 = 50;
break;
+ case SC_SOLID_SKIN_OPTION:
+ val2 = 33; // % Increase DEF
+ break;
case SC_CURSED_SOIL_OPTION:
val2 = 10;
- val3 = 33;
+ val3 = (sd ? sd->status.job_level : 0); // % Increase Damage
val4 = 2;
break;
case SC_UPHEAVAL_OPTION:
val2 = WZ_EARTHSPIKE;
+ val3 = 15; // Bonus MaxHP
break;
case SC_CIRCLE_OF_FIRE_OPTION:
val2 = 300;
@@ -8542,7 +8815,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_WATER_DROP_OPTION:
case SC_WIND_CURTAIN_OPTION:
case SC_STONE_SHIELD_OPTION:
- val2 = 20; // Elemental modifier. Not confirmed.
+ val2 = 100; // Elemental modifier.
break;
case SC_CIRCLE_OF_FIRE:
case SC_FIRE_CLOAK:
@@ -8557,10 +8830,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_WATER_BARRIER:
val2 = 40; // Increasement. Mdef1 ???
- val3 = 20; // Reductions. Atk2, Flee1, Matk1 ????
+ val3 = 30; // Reductions. Atk2, Flee1, Matk1 ????
break;
case SC_ZEPHYR:
- val2 = 22; // Flee.
+ val2 = 25; // Flee.
break;
case SC_TIDAL_WEAPON:
val2 = 20; // Increase Elemental's attack.
@@ -8684,10 +8957,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_FRIGG_SONG:
val2 = 5 * val1;
- val3 = 1000 + 100 * val1;
- tick_time = 10000;
+ val3 = (20 * val1) + 80;
+ tick_time = 1000;
val4 = tick / tick_time;
break;
+ case SC_DARKCROW:
+ val2 = 30 * val1;
+ break;
case SC_MONSTER_TRANSFORM:
if( !mob->db_checkid(val1) )
val1 = 1002; // default poring
@@ -8862,6 +9138,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
//Those that make you stop attacking/walking....
switch (type) {
+ case SC_VACUUM_EXTREME:
+ if(!map_flag_gvg(bl->m))
+ unit->stop_walking(bl,1);
+ break;
case SC_FREEZE:
case SC_STUN:
case SC_SLEEP:
@@ -8885,11 +9165,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_WUGBITE:
case SC_THORNS_TRAP:
case SC__MANHOLE:
+ case SC__CHAOS:
case SC_COLD:
case SC_CURSEDCIRCLE_ATKER:
case SC_CURSEDCIRCLE_TARGET:
case SC_FEAR:
- case SC_NETHERWORLD:
case SC_MEIKYOUSISUI:
case SC_KYOUGAKU:
case SC_NEEDLE_OF_PARALYZE:
@@ -8943,7 +9223,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
case SC_STUN: sc->opt1 = OPT1_STUN; break;
- case SC_DEEP_SLEEP: opt_flag = 0;
case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
@@ -8954,6 +9233,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break;
case SC_CRUCIS:
+ case SC__CHAOS:
sc->opt2 |= OPT2_SIGNUMCRUCIS;
break;
@@ -9057,10 +9337,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_CLOAKING:
case SC_CLOAKINGEXCEED:
- case SC__INVISIBILITY:
sc->option |= OPTION_CLOAK;
opt_flag = 2;
break;
+ case SC__INVISIBILITY:
case SC_CHASEWALK:
sc->option |= OPTION_CHASEWALK|OPTION_CLOAK;
opt_flag = 2;
@@ -9366,10 +9646,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
#ifdef ANTI_MAYAP_CHEAT
- if( sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE) )
+ if (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))
invisible = true;
#endif
-
+
vd = status->get_viewdata(bl);
calc_flag = status->ChangeFlagTable[type];
switch(type) {
@@ -9599,7 +9879,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_BERSERK:
- case SC_SATURDAY_NIGHT_FEVER:
if(st->hp > 200 && sc && sc->data[SC__BLOODYLUST]) {
status_percent_heal(bl, 100, 0);
status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER);
@@ -9670,9 +9949,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_STOP:
if( sce->val2 ) {
- struct block_list* tbl = map->id2bl(sce->val2);
+ struct block_list *tbl = map->id2bl(sce->val2);
+ struct status_change *tsc = NULL;
sce->val2 = 0;
- if( tbl && (sc = status->get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id )
+ if( tbl && (tsc = status->get_sc(tbl)) && tsc->data[SC_STOP] && tsc->data[SC_STOP]->val2 == bl->id )
status_change_end(tbl, SC_STOP, INVALID_TIMER);
}
break;
@@ -9811,12 +10091,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
opt_flag = 1;
- switch(type){
+ switch(type) {
case SC_STONE:
case SC_FREEZE:
case SC_STUN:
case SC_SLEEP:
- case SC_DEEP_SLEEP:
case SC_BURNING:
case SC_WHITEIMPRISON:
case SC_COLD:
@@ -9833,6 +10112,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->opt2 &= ~OPT2_DPOISON;
break;
case SC_CRUCIS:
+ case SC__CHAOS:
sc->opt2 &= ~OPT2_SIGNUMCRUCIS;
break;
@@ -9842,11 +10122,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_CLOAKING:
case SC_CLOAKINGEXCEED:
- case SC__INVISIBILITY:
sc->option &= ~OPTION_CLOAK;
case SC_CAMOUFLAGE:
opt_flag|= 2;
break;
+ case SC__INVISIBILITY:
case SC_CHASEWALK:
sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK);
opt_flag|= 2;
@@ -9980,11 +10260,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
#ifdef ANTI_MAYAP_CHEAT
- if( invisible && !(sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE)) ) {
+ if (invisible && !(sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))) {
clif->fixpos(bl);
}
#endif
-
+
if (calc_flag&SCB_DYE) { //Restore DYE color
if (vd && !vd->cloth_color && sce->val4)
clif->changelook(bl,LOOK_CLOTHES_COLOR,sce->val4);
@@ -10495,7 +10775,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if( --(sce->val4) > 0 ) {
if( !status->charge(bl,0,3) )
break;
- sc_timer_next(3000+tick,status->change_timer,bl->id,data);
+ sc_timer_next(5000+tick,status->change_timer,bl->id,data);
return 0;
}
break;
@@ -10563,7 +10843,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
status_change_end(bl, (sc_type)i, INVALID_TIMER);
break;
}
- sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
return 0;
case SC_ELECTRICSHOCKER:
@@ -10583,10 +10863,13 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC__REPRODUCE:
- if(!status->charge(bl, 0, 1))
- break;
- sc_timer_next(1000+tick, status->change_timer, bl->id, data);
- return 0;
+ if( --(sce->val4) >= 0 ) {
+ if( !status_charge(bl, 0, 9 - (1 + sce->val1) / 2) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
case SC__SHADOWFORM:
if( --(sce->val4) > 0 ) {
@@ -10598,8 +10881,8 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC__INVISIBILITY:
- if( --(sce->val4) > 0 ) {
- if( !status->charge(bl, 0, (st->sp * 6 - sce->val1) / 100) )// 6% - skill_lv.
+ if( --(sce->val4) >= 0 ) {
+ if( !status->charge(bl, 0, status_get_max_sp(bl) * (12 - sce->val1*2) / 100) )
break;
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
@@ -10614,12 +10897,6 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
break;
- case SC_VACUUM_EXTREME:
- if( --(sce->val4) > 0 ) {
- sc_timer_next(100 + tick, status->change_timer, bl->id, data);
- return 0;
- }
- break;
case SC_BLOOD_SUCKER:
if( --(sce->val4) > 0 ) {
struct block_list *src = map->id2bl(sce->val2);
@@ -10648,41 +10925,46 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_DEEP_SLEEP:
- if( --(sce->val4) > 0 ) {
- // Recovers 1% HP/SP every 2 seconds.
- status->heal(bl, st->max_hp / 100, st->max_sp / 100, 2);
+ if( --(sce->val4) >= 0 )
+ {// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds.
+ status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2);
sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
return 0;
}
break;
case SC_SIRCLEOFNATURE:
- if( --(sce->val4) > 0 ) {
- if( !status->charge(bl,0,sce->val2) )
+ if( --(sce->val4) >= 0 ) {
+ if( !status_charge(bl,0,sce->val3) )
break;
- status->heal(bl, sce->val3, 0, 1);
- sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ status->heal(bl, sce->val2, 0, 1);
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
return 0;
}
break;
case SC_SONG_OF_MANA:
- if( --(sce->val4) > 0 ) {
+ if( --(sce->val4) >= 0 ) {
status->heal(bl,0,sce->val3,3);
- sc_timer_next(3000 + tick, status->change_timer, bl->id, data);
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
return 0;
}
break;
case SC_SATURDAY_NIGHT_FEVER:
- // 1% HP/SP drain every val4 seconds [Jobbie]
- if( --(sce->val3) > 0 ) {
- int hp = st->hp / 100;
- int sp = st->sp / 100;
- if( !status->charge(bl, hp, sp) )
- break;
- sc_timer_next(sce->val4+tick, status->change_timer, bl->id, data);
+ if( --(sce->val3) >= 0 ) {
+ if( !status_charge(bl, st->max_hp * 1 / 100, st->max_sp * 1 / 100) )
+ break;
+ sc_timer_next(3000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+
+ case SC_MELODYOFSINK:
+ if( --(sce->val4) >= 0 ) {
+ status_charge(bl, 0, st->max_sp * ( 2 * sce->val1 + 2 * sce->val2 ) / 100);
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data);
return 0;
}
break;
@@ -10696,7 +10978,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
break;
-
+
case SC_FORCEOFVANGUARD:
if( !status->charge(bl, 0, (24 - 4 * sce->val1)) )
break;
@@ -10712,10 +10994,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_LG_REFLECTDAMAGE:
- if( --(sce->val4) > 0 ) {
- if( !status->charge(bl,0,sce->val3) )
+ if( --(sce->val4) >= 0 ) {
+ if( !status->charge(bl,0,10) )
break;
- sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
break;
@@ -10744,7 +11026,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if( --(sce->val3) <= 0 )
break; // Time out
if( sce->val2 == bl->id ) {
- if( !status->charge(bl,0,14 + (3 * sce->val1)) )
+ if( !status->charge(bl,0,50) )
break; // No more SP status should end, and in the next second will end for the other affected players
} else {
struct block_list *src = map->id2bl(sce->val2);
@@ -10756,14 +11038,33 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
}
break;
+ case SC_STEALTHFIELD_MASTER:
+ if(--(sce->val4) >= 0) {
+ // 1% SP Upkeep Cost
+ int sp = st->max_sp / 100;
+
+ if( st->sp <= sp )
+ status_change_end(bl,SC_STEALTHFIELD_MASTER,INVALID_TIMER);
+
+ if( !status_charge(bl,0,sp) )
+ break;
+
+ if( !sc->data[SC_STEALTHFIELD_MASTER] )
+ break;
+
+ sc_timer_next((2000 + 1000 * sce->val1)+tick,status->change_timer,bl->id, data);
+ return 0;
+ }
+ break;
+
case SC_INSPIRATION:
- if(--(sce->val4) > 0) {
- int hp = st->max_hp * (7-sce->val1) / 100;
- int sp = st->max_sp * (9-sce->val1) / 100;
+ if(--(sce->val4) >= 0) {
+ int hp = st->max_hp * (35 - 5 * sce->val1) / 1000;
+ int sp = st->max_sp * (45 - 5 * sce->val1) / 1000;
if( !status->charge(bl,hp,sp) ) break;
- sc_timer_next(1000+tick,status->change_timer,bl->id, data);
+ sc_timer_next(5000+tick,status->change_timer,bl->id, data);
return 0;
}
break;
@@ -10854,7 +11155,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_FRIGG_SONG:
if( --(sce->val4) > 0 ) {
status->heal(bl, sce->val3, 0, 0);
- sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
break;
@@ -10891,17 +11192,14 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
break;
case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */
if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] ||
- tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED] ||
- tsc->data[SC__INVISIBILITY])) {
+ tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED])) {
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
if(battle->check_target( src, bl, BCT_ENEMY ) > 0)
skill->attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0);
}
@@ -11110,7 +11408,6 @@ int status_change_clear_buffs (struct block_list* bl, int type) {
continue;
break;
case SC_BERSERK:
- case SC_SATURDAY_NIGHT_FEVER:
if(type&4)
continue;
sc->data[i]->val2 = 0;
@@ -11673,7 +11970,7 @@ void status_defaults(void) {
status->set_sp = status_set_sp;
status->heal = status_heal;
status->revive = status_revive;
-
+ status->fixed_revive = status_fixed_revive;
status->get_regen_data = status_get_regen_data;
status->get_status_data = status_get_status_data;
status->get_base_status = status_get_base_status;
diff --git a/src/map/status.h b/src/map/status.h
index d3148b4e0..87387fe2b 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -373,7 +373,7 @@ typedef enum sc_type {
/**
* 3rd
**/
- SC_FEAR,
+ SC_FEAR, // 310
SC_FROSTMISTY,
/**
* Rune Knight
@@ -386,20 +386,20 @@ typedef enum sc_type {
SC_REUSE_REFRESH,
SC_GIANTGROWTH,
SC_STONEHARDSKIN,
- SC_VITALITYACTIVATION,
+ SC_VITALITYACTIVATION, // 320
SC_STORMBLAST,
SC_FIGHTINGSPIRIT,
SC_ABUNDANCE,
/**
* Arch Bishop
- **/
+ **/
SC_ADORAMUS,
SC_EPICLESIS,
SC_ORATIO,
SC_LAUDAAGNUS,
SC_LAUDARAMUS,
SC_RENOVATIO,
- SC_EXPIATIO,
+ SC_EXPIATIO, // 330
SC_DUPLELIGHT,
SC_SECRAMENT,
/**
@@ -412,7 +412,7 @@ typedef enum sc_type {
SC_SUMMON1,
SC_SUMMON2,
SC_SUMMON3,
- SC_SUMMON4,
+ SC_SUMMON4, // 340
SC_SUMMON5,
SC_READING_SB,
SC_FREEZINGSP,
@@ -428,7 +428,7 @@ typedef enum sc_type {
* Mechanic
**/
SC_ACCELERATION,
- SC_HOVERING,
+ SC_HOVERING, // 350
SC_SHAPESHIFT,
SC_INFRAREDSCAN,
SC_ANALYZE,
@@ -438,7 +438,7 @@ typedef enum sc_type {
SC_STEALTHFIELD,
SC_STEALTHFIELD_MASTER,
SC_OVERHEAT,
- SC_OVERHEAT_LIMITPOINT,
+ SC_OVERHEAT_LIMITPOINT, // 360
/**
* Guillotine Cross
**/
@@ -451,7 +451,7 @@ typedef enum sc_type {
SC_ROLLINGCUTTER,
SC_TOXIN,
SC_PARALYSE,
- SC_VENOMBLEED,
+ SC_VENOMBLEED, // 370
SC_MAGICMUSHROOM,
SC_DEATHHURT,
SC_PYREXIA,
@@ -464,7 +464,7 @@ typedef enum sc_type {
SC_FORCEOFVANGUARD,
SC_SHIELDSPELL_DEF,
SC_SHIELDSPELL_MDEF,
- SC_SHIELDSPELL_REF,
+ SC_SHIELDSPELL_REF, // 380
SC_EXEEDBREAK,
SC_PRESTIGE,
SC_BANDING,
@@ -477,7 +477,7 @@ typedef enum sc_type {
SC_SPELLFIST,
SC_COLD,
SC_STRIKING,
- SC_WARMER,
+ SC_WARMER, // 390
SC_VACUUM_EXTREME,
SC_PROPERTYWALK,
/**
@@ -490,30 +490,30 @@ typedef enum sc_type {
SC_ECHOSONG,
SC_HARMONIZE,
SC_SIREN,
- SC_DEEP_SLEEP,
+ SC_DEEP_SLEEP, // 400
SC_SIRCLEOFNATURE,
SC_GLOOMYDAY,
- SC_GLOOMYDAY_SK,
- SC_SONG_OF_MANA,
+ //SC_GLOOMYDAY_SK,
+ SC_SONG_OF_MANA = 404,
SC_DANCE_WITH_WUG,
SC_SATURDAY_NIGHT_FEVER,
SC_LERADS_DEW,
SC_MELODYOFSINK,
SC_BEYOND_OF_WARCRY,
- SC_UNLIMITED_HUMMING_VOICE,
+ SC_UNLIMITED_HUMMING_VOICE, // 410
SC_SITDOWN_FORCE,
- SC_NETHERWORLD,
+ //SC_NETHERWORLD,
/**
* Sura
**/
- SC_CRESCENTELBOW,
+ SC_CRESCENTELBOW = 413,
SC_CURSEDCIRCLE_ATKER,
SC_CURSEDCIRCLE_TARGET,
SC_LIGHTNINGWALK,
SC_RAISINGDRAGON,
SC_GENTLETOUCH_ENERGYGAIN,
SC_GENTLETOUCH_CHANGE,
- SC_GENTLETOUCH_REVITALIZE,
+ SC_GENTLETOUCH_REVITALIZE, // 420
/**
* Genetic
**/
@@ -526,7 +526,7 @@ typedef enum sc_type {
SC_STOMACHACHE,
SC_MYSTERIOUS_POWDER,
SC_MELON_BOMB,
- SC_BANANA_BOMB,
+ SC_BANANA_BOMB, // 430
SC_BANANA_BOMB_SITDOWN_POSTDELAY,
SC_SAVAGE_STEAK,
SC_COCKTAIL_WARG_BLOOD,
@@ -536,7 +536,7 @@ typedef enum sc_type {
SC_PUTTI_TAILS_NOODLES,
SC_BOOST500,
SC_FULL_SWING_K,
- SC_MANA_PLUS,
+ SC_MANA_PLUS, // 440
SC_MUSTLE_M,
SC_LIFE_FORCE_F,
SC_EXTRACT_WHITE_POTION_Z,
@@ -549,7 +549,7 @@ typedef enum sc_type {
SC__AUTOSHADOWSPELL,
SC__SHADOWFORM,
SC__BODYPAINT,
- SC__INVISIBILITY,
+ SC__INVISIBILITY, // 450
SC__DEADLYINFECT,
SC__ENERVATION,
SC__GROOMY,
@@ -559,7 +559,7 @@ typedef enum sc_type {
SC__WEAKNESS,
SC__STRIPACCESSARY,
SC__MANHOLE,
- SC__BLOODYLUST,
+ SC__BLOODYLUST, // 460
/**
* Elemental Spirits
**/
@@ -572,7 +572,7 @@ typedef enum sc_type {
SC_WATER_DROP,
SC_WATER_DROP_OPTION,
SC_WATER_BARRIER,
- SC_WIND_STEP,
+ SC_WIND_STEP, // 470
SC_WIND_STEP_OPTION,
SC_WIND_CURTAIN,
SC_WIND_CURTAIN_OPTION,
@@ -582,7 +582,7 @@ typedef enum sc_type {
SC_STONE_SHIELD,
SC_STONE_SHIELD_OPTION,
SC_POWER_OF_GAIA,
- SC_PYROTECHNIC,
+ SC_PYROTECHNIC, // 480
SC_PYROTECHNIC_OPTION,
SC_HEATER,
SC_HEATER_OPTION,
@@ -592,7 +592,7 @@ typedef enum sc_type {
SC_AQUAPLAY_OPTION,
SC_COOLER,
SC_COOLER_OPTION,
- SC_CHILLY_AIR,
+ SC_CHILLY_AIR, // 490
SC_CHILLY_AIR_OPTION,
SC_GUST,
SC_GUST_OPTION,
@@ -602,7 +602,7 @@ typedef enum sc_type {
SC_WILD_STORM_OPTION,
SC_PETROLOGY,
SC_PETROLOGY_OPTION,
- SC_CURSED_SOIL,
+ SC_CURSED_SOIL, // 500
SC_CURSED_SOIL_OPTION,
SC_UPHEAVAL,
SC_UPHEAVAL_OPTION,
@@ -613,21 +613,21 @@ typedef enum sc_type {
/* Guild Aura */
SC_LEADERSHIP,
SC_GLORYWOUNDS,
- SC_SOULCOLD,
+ SC_SOULCOLD, // 510
SC_HAWKEYES,
/* ... */
SC_ODINS_POWER,
/* Sorcerer .extra */
SC_FIRE_INSIGNIA,
SC_WATER_INSIGNIA,
- SC_WIND_INSIGNIA,
+ SC_WIND_INSIGNIA,
SC_EARTH_INSIGNIA,
/* new pushcart */
SC_PUSH_CART,
/* Warlock Spell books */
SC_SPELLBOOK1,
SC_SPELLBOOK2,
- SC_SPELLBOOK3,
+ SC_SPELLBOOK3, // 520
SC_SPELLBOOK4,
SC_SPELLBOOK5,
SC_SPELLBOOK6,
@@ -639,13 +639,13 @@ typedef enum sc_type {
/* Max HP & SP */
SC_INCMHP,
SC_INCMSP,
- SC_PARTYFLEE,
+ SC_PARTYFLEE,
/**
* Kagerou & Oboro [malufett]
**/
SC_MEIKYOUSISUI,
SC_KO_JYUMONJIKIRI,
- SC_KYOUGAKU,
+ SC_KYOUGAKU, // 530
SC_IZAYOI,
SC_ZENKAI,
SC_KG_KAGEHUMI,
@@ -656,19 +656,19 @@ typedef enum sc_type {
SC_AKAITSUKI,
//homon S
- SC_STYLE_CHANGE,
- SC_GOLDENE_FERSE,
- SC_ANGRIFFS_MODUS,
- SC_ERASER_CUTTER,
- SC_OVERED_BOOST,
- SC_LIGHT_OF_REGENE,
- SC_VOLCANIC_ASH,
- SC_GRANITIC_ARMOR,
- SC_MAGMA_FLOW,
- SC_PYROCLASTIC,
- SC_NEEDLE_OF_PARALYZE,
- SC_PAIN_KILLER,
-#ifdef RENEWAL
+ SC_STYLE_CHANGE,
+ SC_GOLDENE_FERSE, // 540
+ SC_ANGRIFFS_MODUS,
+ SC_ERASER_CUTTER,
+ SC_OVERED_BOOST,
+ SC_LIGHT_OF_REGENE,
+ SC_VOLCANIC_ASH,
+ SC_GRANITIC_ARMOR,
+ SC_MAGMA_FLOW,
+ SC_PYROCLASTIC,
+ SC_NEEDLE_OF_PARALYZE,
+ SC_PAIN_KILLER, // 550
+#ifdef RENEWAL
SC_EXTREMITYFIST2,
SC_RAID,
#endif
@@ -679,7 +679,7 @@ typedef enum sc_type {
SC_KINGS_GRACE,
SC_TELEKINESIS_INTENSE,
SC_OFFERTORIUM,
- SC_FRIGG_SONG,
+ SC_FRIGG_SONG, // 560
SC_ALL_RIDING,
SC_HANBOK,
@@ -691,7 +691,7 @@ typedef enum sc_type {
SC_MTF_RANGEATK,
SC_MTF_MATK,
SC_MTF_MLEATKED,
- SC_MTF_CRIDAMAGE,
+ SC_MTF_CRIDAMAGE, // 570
SC_MOONSTAR,
SC_SUPER_STAR,
@@ -700,6 +700,8 @@ typedef enum sc_type {
SC_STRANGELIGHTS,
SC_DECORATION_OF_MUSIC,
+ SC__MAELSTROM,
+ SC__CHAOS,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
// Official status change ids, used to display status icons on the client.
@@ -1434,6 +1436,7 @@ enum si_type {
//SI_ = 735,
SI_CHILL = 736,
SI_BURNT = 737,
+ SI_FLASHCOMBO = 740,
SI_B_TRAP = 752,
SI_E_CHAIN = 753,
SI_E_QD_SHOT_READY = 754,
@@ -1912,6 +1915,7 @@ struct status_interface {
int (*set_sp) (struct block_list *bl, unsigned int sp, int flag);
int (*heal) (struct block_list *bl,int64 hp,int64 sp, int flag);
int (*revive) (struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
+ int (*fixed_revive) (struct block_list *bl, unsigned int per_hp, unsigned int per_sp);
struct regen_data * (*get_regen_data) (struct block_list *bl);
struct status_data * (*get_status_data) (struct block_list *bl);
struct status_data * (*get_base_status) (struct block_list *bl);
diff --git a/src/map/unit.c b/src/map/unit.c
index 320649a6c..1f1469c88 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -377,7 +377,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
unit->set_target(ud, 0);
sc = status->get_sc(bl);
- if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
+ if (sc && (sc->data[SC_CONFUSION] || sc->data[SC__CHAOS])) //Randomize the target position
map->random_dir(bl, &ud->to_x, &ud->to_y);
if(ud->walktimer != INVALID_TIMER) {
@@ -449,7 +449,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
unit->set_target(ud, 0);
sc = status->get_sc(bl);
- if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
+ if (sc && (sc->data[SC_CONFUSION] || sc->data[SC__CHAOS])) //Randomize the target position
map->random_dir(bl, &ud->to_x, &ud->to_y);
if(ud->walktimer != INVALID_TIMER) {
@@ -968,7 +968,7 @@ int unit_can_move(struct block_list *bl) {
|| sc->data[SC_CURSEDCIRCLE_ATKER]
|| sc->data[SC_CURSEDCIRCLE_TARGET]
|| (sc->data[SC_COLD] && bl->type != BL_MOB)
- || sc->data[SC_NETHERWORLD]
+ || sc->data[SC_DEEP_SLEEP]
|| (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1))
|| sc->data[SC_MEIKYOUSISUI]
|| sc->data[SC_KG_KAGEHUMI]
@@ -1470,10 +1470,6 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
- if( (skill_id >= SC_MANHOLE && skill_id <= SC_FEINTBOMB) && map->getcell(src->m, skill_x, skill_y, CELL_CHKMAELSTROM) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- return 0;
- }
}
if (!status->check_skilluse(src, NULL, skill_id, 0))
@@ -1956,7 +1952,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
return 0;
if (sd && (sd->special_state.no_castcancel2 ||
- ((sd->sc.data[SC_UNLIMITED_HUMMING_VOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
+ ( sd->special_state.no_castcancel && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
return 0;
}
@@ -2106,6 +2102,11 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
status_change_end(bl, SC_STOP, INVALID_TIMER);
status_change_end(bl, SC_WUGDASH, INVALID_TIMER);
status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
+ status_change_end(bl, SC_MAGNETICFIELD, INVALID_TIMER);
+ status_change_end(bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);
+ status_change_end(bl, SC_NEUTRALBARRIER, INVALID_TIMER);
+ status_change_end(bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
+ status_change_end(bl, SC_STEALTHFIELD, INVALID_TIMER);
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
status_change_end(bl, SC__MANHOLE, INVALID_TIMER);
status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);