diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/atcommand.c | 26 | ||||
-rw-r--r-- | src/map/battle.c | 698 | ||||
-rw-r--r-- | src/map/battle.h | 2 | ||||
-rw-r--r-- | src/map/chrif.c | 7 | ||||
-rw-r--r-- | src/map/clif.c | 28 | ||||
-rw-r--r-- | src/map/guild.c | 2 | ||||
-rw-r--r-- | src/map/intif.c | 2 | ||||
-rw-r--r-- | src/map/itemdb.h | 4 | ||||
-rw-r--r-- | src/map/map.c | 3 | ||||
-rw-r--r-- | src/map/map.h | 3 | ||||
-rw-r--r-- | src/map/mercenary.c | 2 | ||||
-rw-r--r-- | src/map/mob.c | 19 | ||||
-rw-r--r-- | src/map/party.c | 21 | ||||
-rw-r--r-- | src/map/party.h | 1 | ||||
-rw-r--r-- | src/map/pc.c | 47 | ||||
-rw-r--r-- | src/map/script.c | 44 | ||||
-rw-r--r-- | src/map/skill.c | 1938 | ||||
-rw-r--r-- | src/map/skill.h | 1 | ||||
-rw-r--r-- | src/map/status.c | 967 | ||||
-rw-r--r-- | src/map/status.h | 104 | ||||
-rw-r--r-- | src/map/unit.c | 21 |
21 files changed, 2255 insertions, 1685 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 2849ada0b..c5460eb47 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4416,7 +4416,7 @@ ACMD(jail) { } //Duration of INT_MAX to specify infinity. - sc_start4(&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000); + sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000); clif->message(pl_sd->fd, msg_txt(117)); // GM has send you in jails. clif->message(fd, msg_txt(118)); // Player warped in jails. return true; @@ -4454,7 +4454,7 @@ ACMD(unjail) { } //Reset jail time to 1 sec. - sc_start(&pl_sd->bl,SC_JAILED,100,1,1000); + sc_start(NULL,&pl_sd->bl,SC_JAILED,100,1,1000); clif->message(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail. clif->message(fd, msg_txt(121)); // Player unjailed. return true; @@ -4565,7 +4565,7 @@ ACMD(jailfor) { break; } - sc_start4(&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status->change_timer). + sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status->change_timer). return true; } @@ -5477,7 +5477,7 @@ ACMD(autotrade) { sd->state.autotrade = 1; if( battle_config.at_timeout ) { int timeout = atoi(message); - status->change_start(&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); + status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); } clif->chsys_quit(sd); @@ -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; @@ -6263,7 +6263,7 @@ ACMD(summon) md->deletetimer=timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0); clif->specialeffect(&md->bl,344,AREA); mob->spawn(md); - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); + sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick); clif->message(fd, msg_txt(39)); // All monster summoned! @@ -6433,7 +6433,7 @@ ACMD(mute) { if( pl_sd->status.manner < manner ) { pl_sd->status.manner -= manner; - sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); + sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0); } else { pl_sd->status.manner = 0; status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); @@ -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; @@ -7228,7 +7228,7 @@ int atcommand_mutearea_sub(struct block_list *bl,va_list ap) if (id != bl->id && !pc_get_group_level(pl_sd)) { pl_sd->status.manner -= time; if (pl_sd->status.manner < 0) - sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); + sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0); else status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); } @@ -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; @@ -8366,7 +8366,7 @@ ACMD(mount2) { clif->message(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. if( !(sd->sc.data[SC_ALL_RIDING]) ) { clif->message(sd->fd,msg_txt(1363)); // You have mounted. - sc_start(&sd->bl,SC_ALL_RIDING,100,0,-1); + sc_start(NULL,&sd->bl,SC_ALL_RIDING,100,0,-1); } else { clif->message(sd->fd,msg_txt(1364)); // You have released your mount. status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); @@ -9339,7 +9339,7 @@ ACMD(costume){ return false; } - sc_start(&sd->bl, name2id[k], 100, 0, -1); + sc_start(NULL,&sd->bl, name2id[k], 100, 0, -1); return true; } diff --git a/src/map/battle.c b/src/map/battle.c index 1a04aeff9..ce861aa7e 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,11 +2666,26 @@ 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); d->dmg_lv = ATK_BLOCK; - sc_start2(bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000); + sc_start2(src,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 ) @@ -2663,7 +2711,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage d->dmg_lv = ATK_BLOCK; - sc_start(bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. + sc_start(src,bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. if( sce->val3 <= 0 ) { // Shield Down sce->val2--; if( sce->val2 > 0 ) { @@ -2688,21 +2736,16 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if (sd && pc_issit(sd)) pc->setstand(sd); //Stand it to dodge. clif->skill_nodamage(bl,bl,TK_DODGE,1,1); if (!sc->data[SC_COMBOATTACK]) - sc_start4(bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000); + sc_start4(src, bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000); 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 ) { @@ -2873,7 +2921,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); // 30% chance to reduce monster's ATK by 25% for 10 seconds. if( src->type == BL_MOB ) - sc_start(src, SC_NOEQUIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1)); + sc_start(bl,src, SC_NOEQUIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1)); if( sce->val2 <= 0 ) status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER); } @@ -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(src,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 } @@ -5529,11 +5627,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1; int duration = skill->get_time2(MO_BLADESTOP,skill_lv); status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); - if(sc_start4(src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { + if(sc_start4(target, src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. clif->bladestop(target, src->id, 1); - sc_start4(target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); + sc_start4(target, target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; } } @@ -5596,7 +5694,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 ) clif->skill_nodamage(target, target, SM_ENDURE, 5, - sc_start(target, SC_ENDURE, 100, 5, skill->get_time(SM_ENDURE, 5))); + sc_start(target,target, SC_ENDURE, 100, 5, skill->get_time(SM_ENDURE, 5))); } if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp) @@ -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/chrif.c b/src/map/chrif.c index c55b241e6..d6f0e5ef8 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -457,7 +457,6 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) { chrif->changemapserver(sd, ip, port); else //too much lag/timeout is the closest explanation for this error. clif->authfail_fd(sd->fd, 3); - break; } } @@ -1206,7 +1205,7 @@ bool chrif_load_scdata(int fd) { for (i = 0; i < count; i++) { data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); - status->change_start(&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); + status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); } pc->scdata_received(sd); @@ -1565,7 +1564,7 @@ void chrif_send_report(char* buf, int len) { **/ void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) { - if( !chrif->fd ) + if( !chrif->isconnected() ) return; WFIFOHEAD(chrif->fd, 28); @@ -1587,7 +1586,7 @@ void chrif_save_scdata_single(int account_id, int char_id, short type, struct st **/ void chrif_del_scdata_single(int account_id, int char_id, short type) { - if( !chrif->fd ) { + if( !chrif->isconnected() ) { ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id); return; } diff --git a/src/map/clif.c b/src/map/clif.c index 83a3c37bd..e87276d4f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9424,14 +9424,14 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0); if(sd->status.manner < 0) - sc_start(&sd->bl,SC_NOCHAT,100,0,0); + sc_start(NULL,&sd->bl,SC_NOCHAT,100,0,0); //Auron reported that This skill only triggers when you logon on the map o.O [Skotlex] if ((lv = pc->checkskill(sd,SG_KNOWLEDGE)) > 0) { if(sd->bl.m == sd->feel_map[0].m || sd->bl.m == sd->feel_map[1].m || sd->bl.m == sd->feel_map[2].m) - sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); + sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); } if(sd->pd && sd->pd->pet.intimate > 900) @@ -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] @@ -9864,7 +9864,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) sd->state.snovice_call_flag = 3; break; case 3: - sc_start(&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] + sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions sd->state.snovice_call_flag = 0; break; @@ -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 ) @@ -13675,7 +13677,7 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) { if (dstsd->status.manner < value) { dstsd->status.manner -= value; - sc_start(&dstsd->bl,SC_NOCHAT,100,0,0); + sc_start(NULL,&dstsd->bl,SC_NOCHAT,100,0,0); } else { dstsd->status.manner = 0; @@ -13904,7 +13906,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); if( percent && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0% - sc_start(&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] + sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions } } @@ -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/guild.c b/src/map/guild.c index d13c681bb..7989fb070 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1360,7 +1360,7 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1 } group = skill->unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0); if( group ) { - sc_start4(&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4 + sc_start4(NULL,&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4 } return; } diff --git a/src/map/intif.c b/src/map/intif.c index 49fbe4721..f04ec4015 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -273,7 +273,7 @@ int intif_saveregistry(struct map_session_data *sd) { int plen = 0; size_t len; - if (intif->CheckForCharServer()) + if (intif->CheckForCharServer() || !sd->var_db) return -1; WFIFOHEAD(inter_fd, 60000 + 300); 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/mercenary.c b/src/map/mercenary.c index 87e7d2f3c..495621014 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -360,7 +360,7 @@ int mercenary_killbonus(struct mercenary_data *md) const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT }; int index = rnd() % ARRAYLENGTH(scs); - sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000); + sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000); return 0; } diff --git a/src/map/mob.c b/src/map/mob.c index 30658051c..b1fb99859 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -415,7 +415,7 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) { return true; } while(0); - status->change_start(target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0); + status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0); return false; } @@ -506,7 +506,7 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const if (class_ < 0 && battle_config.dead_branch_active) { //Behold Aegis's masterful decisions yet again... //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3 - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000); } } @@ -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); @@ -2927,17 +2928,17 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id) switch (battle_config.slaves_inherit_mode) { case 1: //Always aggressive if (!(md->status.mode&MD_AGGRESSIVE)) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); break; case 2: //Always passive if (md->status.mode&MD_AGGRESSIVE) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); break; default: //Copy master. if (md2->status.mode&MD_AGGRESSIVE) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); else - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); break; } } diff --git a/src/map/party.c b/src/map/party.c index 9f144297d..cf5e7bbe3 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -841,7 +841,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id case TK_COUNTER: //Increase Triple Attack rate of Monks. if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK && pc->checkskill(p_sd,MO_TRIPLEATTACK)) { - sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, + sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, 50+50*skill_lv, //+100/150/200% rate 0,0,skill->get_time(SG_FRIEND, 1)); } @@ -850,7 +850,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && sd->sc.data[SC_COUNTERKICK_READY] && pc->checkskill(p_sd,SG_FRIEND)) { - sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, + sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, 50+50*pc->checkskill(p_sd,SG_FRIEND), //+100/150/200% rate 0,0,skill->get_time(SG_FRIEND, 1)); } @@ -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..394a08d75 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; @@ -1720,9 +1719,9 @@ int pc_updateweightstatus(struct map_session_data *sd) // start new status change if( new_overweight == 1 ) - sc_start(&sd->bl, SC_WEIGHTOVER50, 100, 0, 0); + sc_start(NULL,&sd->bl, SC_WEIGHTOVER50, 100, 0, 0); else if( new_overweight == 2 ) - sc_start(&sd->bl, SC_WEIGHTOVER90, 100, 0, 0); + sc_start(NULL,&sd->bl, SC_WEIGHTOVER90, 100, 0, 0); // update overweight status sd->regen.state.overweight = new_overweight; @@ -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) @@ -5862,16 +5868,16 @@ int pc_checkbaselevelup(struct map_session_data *sd) { status_percent_heal(&sd->bl,100,100); if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { - sc_start(&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1)); - sc_start(&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1)); - sc_start(&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1)); - sc_start(&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1)); - sc_start(&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1)); + sc_start(NULL,&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1)); + sc_start(NULL,&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1)); + sc_start(NULL,&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1)); + sc_start(NULL,&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1)); + sc_start(NULL,&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1)); if (sd->state.snovice_dead_flag) sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead. } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) { - sc_start(&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000); - sc_start(&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000); + sc_start(NULL,&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000); + sc_start(NULL,&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000); } clif->misceffect(&sd->bl,0); npc->script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT @@ -6953,7 +6959,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { if (battle_config.pk_mode&2) { ssd->status.manner -= 5; if(ssd->status.manner < 0) - sc_start(src,SC_NOCHAT,100,0,0); + sc_start(NULL,src,SC_NOCHAT,100,0,0); #if 0 // PK/Karma system code (not enabled yet) [celest] // originally from Kade Online, so i don't know if any of these is correct ^^; @@ -7005,7 +7011,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { clif->resurrection(&sd->bl, 1); if(battle_config.pc_invincible_time) pc->setinvincibletimer(sd, battle_config.pc_invincible_time); - sc_start(&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1)); + sc_start(NULL,&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1)); if(map_flag_gvg2(sd->bl.m)) pc->respawn_timer(INVALID_TIMER, timer->gettick(), sd->bl.id, 0); return 0; @@ -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; @@ -8017,7 +8028,7 @@ int pc_setcart(struct map_session_data *sd,int type) { if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */ clif->cartlist(sd); clif->updatestatus(sd, SP_CARTINFO); - sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0); + sc_start(NULL,&sd->bl, SC_PUSH_CART, 100, type, 0); clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0); if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */ sd->sc.data[SC_PUSH_CART]->val1 = type; @@ -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; @@ -9431,9 +9442,9 @@ void pc_overheat(struct map_session_data *sd, int val) { heat = max(0,heat); // Avoid negative HEAT if( heat >= limit[skill_lv] ) - sc_start(&sd->bl,SC_OVERHEAT,100,0,1000); + sc_start(NULL,&sd->bl,SC_OVERHEAT,100,0,1000); else - sc_start(&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000); + sc_start(NULL,&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000); return; } diff --git a/src/map/script.c b/src/map/script.c index be346cb92..1dff4c202 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -2609,7 +2609,7 @@ void* get_val2(struct script_state* st, int64 uid, struct DBMap** ref) { **/ void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct DBMap** ref) { const char *name = script->get_str(script_getvarid(uid)); - struct DBMap *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref);\ + struct DBMap *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref); struct script_array *sa = NULL; bool insert = false; @@ -4847,8 +4847,17 @@ BUILDIN(callfunc) const char* name = reference_getname(data); if( name[0] == '.' ) { if( !ref ) { - ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); + ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2); ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars); + if( name[1] == '@' ) { + if( !st->stack->array_function_db ) + st->stack->array_function_db = idb_alloc(DB_OPT_BASE); + ref[1] = st->stack->array_function_db; + } else { + if( !st->script->script_arrays_db ) + st->script->script_arrays_db = idb_alloc(DB_OPT_BASE); + ref[1] = st->script->script_arrays_db; + } } data->ref = ref; } @@ -4897,8 +4906,11 @@ BUILDIN(callsub) const char* name = reference_getname(data); if( name[0] == '.' && name[1] == '@' ) { if ( !ref ) { - ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); + ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2); ref[0] = st->stack->var_function; + if( !st->stack->array_function_db ) + st->stack->array_function_db = idb_alloc(DB_OPT_BASE); + ref[1] = st->stack->array_function_db; } data->ref = ref; } @@ -4971,12 +4983,16 @@ BUILDIN(return) const char* name = reference_getname(data); if( name[0] == '.' && name[1] == '@' ) {// scope variable - if( !data->ref || data->ref == (DBMap**)&st->stack->var_function ) + if( !data->ref || data->ref[0] == st->stack->var_function ) script->get_val(st, data);// current scope, convert to value } else if( name[0] == '.' && !data->ref ) {// script variable, link to current script - data->ref = &st->script->script_vars; + data->ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 2); + data->ref[0] = st->script->script_vars; + if( !st->script->script_arrays_db ) + st->script->script_arrays_db = idb_alloc(DB_OPT_BASE); + data->ref[1] = st->script->script_arrays_db; } } } @@ -9868,7 +9884,7 @@ BUILDIN(sc_start) { } if( bl ) - status->change_start(bl, type, 10000, val1, 0, 0, val4, tick, 2); + status->change_start(NULL, bl, type, 10000, val1, 0, 0, val4, tick, 2); return true; } @@ -9906,7 +9922,7 @@ BUILDIN(sc_start2) { } if( bl ) - status->change_start(bl, type, rate, val1, 0, 0, val4, tick, 2); + status->change_start(NULL, bl, type, rate, val1, 0, 0, val4, tick, 2); return true; } @@ -9946,7 +9962,7 @@ BUILDIN(sc_start4) { } if( bl ) - status->change_start(bl, type, 10000, val1, val2, val3, val4, tick, 2); + status->change_start(NULL, bl, type, 10000, val1, val2, val3, val4, tick, 2); return true; } @@ -10013,7 +10029,7 @@ BUILDIN(getscrate) { bl = map->id2bl(st->rid); if (bl) - rate = status->get_sc_def(bl, (sc_type)type, 10000, 10000, 0); + rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, 0); script_pushint(st,rate); return true; @@ -13259,7 +13275,7 @@ BUILDIN(summon) md->deletetimer = timer->add(tick+(timeout>0?timeout*1000:60000),mob->timer_delete,md->bl.id,0); mob->spawn (md); //Now it is ready for spawning. clif->specialeffect(&md->bl,344,AREA); - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); + sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); } return true; } @@ -15812,7 +15828,7 @@ BUILDIN(mercenary_sc_start) { tick = script_getnum(st,3); val1 = script_getnum(st,4); - status->change_start(&sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2); + status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2); return true; } @@ -17044,7 +17060,7 @@ BUILDIN(setmounting) { if( sd->sc.data[SC_ALL_RIDING] ) status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); else - sc_start(&sd->bl, SC_ALL_RIDING, 100, 0, -1); + sc_start(NULL,&sd->bl, SC_ALL_RIDING, 100, 0, -1); script_pushint(st,1);//in both cases, return 1. } return true; @@ -17595,8 +17611,8 @@ BUILDIN(montransform) { sprintf(msg, msg_txt(1485), monster->name); // Traaaansformation-!! %s form!! clif->ShowScript(&sd->bl, msg); status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous - sc_start2(bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick); - sc_start4(bl, type, 100, val1, val2, val3, val4, tick); + sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick); + sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick); } return true; } diff --git a/src/map/skill.c b/src/map/skill.c index 2c2ed0d6c..37ee297ca 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; @@ -702,10 +706,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 temp = skill->get_time2(status->sc2skill(type),7); if (sd->addeff[i].flag&ATF_TARGET) - status->change_start(bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0); + status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0); if (sd->addeff[i].flag&ATF_SELF) - status->change_start(src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0); + status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0); } } @@ -720,9 +724,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 temp = skill->get_time2(status->sc2skill(type),7); if( sd->addeff3[i].target&ATF_TARGET ) - status->change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0); + status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0); if( sd->addeff3[i].target&ATF_SELF ) - status->change_start(src,type,sd->addeff3[i].rate,7,0,0,0,temp,0); + status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,0); } } } @@ -756,15 +760,15 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 // Chance to trigger Taekwon kicks [Dralnu] if(sc && !sc->data[SC_COMBOATTACK]) { if(sc->data[SC_STORMKICK_READY] && - sc_start(src,SC_COMBOATTACK, 15, TK_STORMKICK, + sc_start(NULL,src,SC_COMBOATTACK, 15, TK_STORMKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sc->data[SC_DOWNKICK_READY] && - sc_start(src,SC_COMBOATTACK, 15, TK_DOWNKICK, + sc_start(NULL,src,SC_COMBOATTACK, 15, TK_DOWNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if(sc->data[SC_TURNKICK_READY] && - sc_start(src,SC_COMBOATTACK, 15, TK_TURNKICK, + sc_start(NULL,src,SC_COMBOATTACK, 15, TK_TURNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered else if (sc->data[SC_COUNTERKICK_READY]) { //additional chance from SG_FRIEND [Komurka] @@ -773,7 +777,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); } - sc_start2(src, SC_COMBOATTACK, rate, TK_COUNTER, bl->id, + sc_start2(NULL, src, SC_COMBOATTACK, rate, TK_COUNTER, bl->id, (2000 - 4*sstatus->agi - 2*sstatus->dex)); } } @@ -785,11 +789,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 struct status_change_entry *sce; // Enchant Poison gives a chance to poison attacked enemies if((sce=sc->data[SC_ENCHANTPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. - status->change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, + status->change_start(src,bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, skill->get_time2(AS_ENCHANTPOISON,sce->val1),0); // Enchant Deadly Poison gives a chance to deadly poison attacked enemies if((sce=sc->data[SC_EDP])) - sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, + sc_start4(src,bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, skill->get_time2(ASC_EDP,sce->val1)); } } @@ -797,12 +801,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case SM_BASH: if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ) - status->change_start(bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50, + status->change_start(src,bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50, skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),0); break; case MER_CRASH: - sc_start(bl,SC_STUN,(6*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(6*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case AS_VENOMKNIFE: @@ -810,14 +814,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 skill_lv = pc->checkskill(sd, TF_POISON); case TF_POISON: case AS_SPLASHER: - if(!sc_start2(bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)) + if(!sc_start2(src,bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)) && sd && skill_id==TF_POISON ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; case AS_SONICBLOW: - sc_start(bl,SC_STUN,(2*skill_lv+10),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(2*skill_lv+10),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case WZ_FIREPILLAR: @@ -828,14 +832,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 #ifndef RENEWAL case WZ_FROSTNOVA: #endif - if( !sc_start(bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv)) + if( !sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv)) && sd && skill_id == MG_FROSTDIVER ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; #ifdef RENEWAL case WZ_FROSTNOVA: - sc_start(bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill->get_time2(skill_id,skill_lv)); break; #endif @@ -844,11 +848,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 * Storm Gust counter was dropped in renewal **/ #ifdef RENEWAL - sc_start(bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); #else //Tharis pointed out that this is normal freeze chance with a base of 300% if(tsc->sg_counter >= 3 && - sc_start(bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv))) + sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv))) tsc->sg_counter = 0; /** * being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value @@ -859,25 +863,25 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case WZ_METEOR: - sc_start(bl,SC_STUN,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case WZ_VERMILION: - sc_start(bl,SC_BLIND,4*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,4*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case HT_FREEZINGTRAP: case MA_FREEZINGTRAP: - sc_start(bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case HT_FLASHER: - sc_start(bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case HT_LANDMINE: case MA_LANDMINE: - sc_start(bl,SC_STUN,(5*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(5*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case HT_SHOCKWAVE: @@ -886,32 +890,32 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case HT_SANDMAN: case MA_SANDMAN: - sc_start(bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case TF_SPRINKLESAND: - sc_start(bl,SC_BLIND,20,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,20,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case TF_THROWSTONE: - if( !sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)) ) - sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv)); + if( !sc_start(src,bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)) ) + sc_start(src,bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_DARKCROSS: case CR_HOLYCROSS: - sc_start(bl,SC_BLIND,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case CR_GRANDCROSS: case NPC_GRANDDARKNESS: //Chance to cause blind status vs demon and undead element, but not against players if(!dstsd && (battle->check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case AM_ACIDTERROR: - sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); if (skill->break_equip(bl, EQP_ARMOR, 100*skill->get_time(skill_id,skill_lv), BCT_ENEMY)) clif->emotion(bl,E_OMG); break; @@ -921,7 +925,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case CR_SHIELDCHARGE: - sc_start(bl,SC_STUN,(15+skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(15+skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case PA_PRESSURE: @@ -929,28 +933,28 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case RG_RAID: - sc_start(bl,SC_STUN,(10+3*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(10+3*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); #ifdef RENEWAL - sc_start(bl,SC_RAID,100,7,5000); + sc_start(src,bl,SC_RAID,100,7,5000); break; case RG_BACKSTAP: - sc_start(bl,SC_STUN,(5+2*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(5+2*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); #endif break; case BA_FROSTJOKER: - sc_start(bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case DC_SCREAM: - sc_start(bl,SC_STUN,(25+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(25+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case BD_LULLABY: - sc_start(bl,SC_SLEEP,15,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_SLEEP,15,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case DC_UGLYDANCE: @@ -961,11 +965,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case SL_STUN: if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs. - sc_start(bl,SC_STUN,(30+10*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,(30+10*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); break; case NPC_PETRIFYATTACK: - sc_start4(bl,status->skill2sc(skill_id),50+10*skill_lv, + sc_start4(src,bl,status->skill2sc(skill_id),50+10*skill_lv, skill_lv,0,0,skill->get_time(skill_id,skill_lv), skill->get_time2(skill_id,skill_lv)); break; @@ -976,14 +980,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case NPC_SILENCEATTACK: case NPC_STUNATTACK: case NPC_HELLPOWER: - sc_start(bl,status->skill2sc(skill_id),50+10*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,status->skill2sc(skill_id),50+10*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_ACIDBREATH: case NPC_ICEBREATH: - sc_start(bl,status->skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,status->skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_BLEEDING: - sc_start2(bl,SC_BLOODING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(src,bl,SC_BLOODING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); break; case NPC_MENTALBREAKER: { @@ -1009,32 +1013,32 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case CH_TIGERFIST: - sc_start(bl,SC_STOP,(10+skill_lv*10),0,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STOP,(10+skill_lv*10),0,skill->get_time2(skill_id,skill_lv)); break; case LK_SPIRALPIERCE: case ML_SPIRALPIERCE: - sc_start(bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv)); break; case ST_REJECTSWORD: - sc_start(bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill->get_time(skill_id,skill_lv)); break; case PF_FOGWALL: if (src != bl && !tsc->data[SC_DELUGE]) - sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element if (!(battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start2(bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); + sc_start2(src, bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); break; case LK_JOINTBEAT: if (tsc->jb_flag) { enum sc_type type = status->skill2sc(skill_id); - sc_start4(bl,type,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill->get_time2(skill_id,skill_lv)); + sc_start4(src,bl,type,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill->get_time2(skill_id,skill_lv)); tsc->jb_flag = 0; } break; @@ -1042,22 +1046,22 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*skill_lv% chance. switch(rnd()%3) { case 0: - sc_start(bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,1)); + sc_start(src,bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,1)); break; case 1: - sc_start(bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2)); + sc_start(src,bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2)); break; default: - sc_start2(bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3)); + sc_start2(src,bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3)); } break; case HW_NAPALMVULCAN: - sc_start(bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case WS_CARTTERMINATION: // Cart termination - sc_start(bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case CR_ACIDDEMONSTRATION: @@ -1065,7 +1069,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case TK_DOWNKICK: - sc_start(bl,SC_STUN,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case TK_JUMPKICK: @@ -1082,20 +1086,20 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case TK_TURNKICK: case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs. if(attack_type&BF_MISC) //70% base stun chance... - sc_start(bl,SC_STUN,70,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN,70,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case GS_BULLSEYE: //0.1% coma rate. if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) - status->change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); + status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); break; case GS_PIERCINGSHOT: - sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); break; case NJ_HYOUSYOURAKU: - sc_start(bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); break; case GS_FLING: - sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_FLING,100, sd?sd->spiritball_old:5,skill->get_time(skill_id,skill_lv)); break; case GS_DISARM: rate = 3*skill_lv; @@ -1105,112 +1109,132 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; case NPC_EVILLAND: - sc_start(bl,SC_BLIND,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_HELLJUDGEMENT: - sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; 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); + sc_start(src,bl,SC_CRITICALWOUND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case RK_WINDCUTTER: - sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,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(src,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(src,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(src, 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)); + sc_start(src, bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv)); break; case WL_COMET: - sc_start4(bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); + sc_start4(src,bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); 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: - sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; case WL_FROSTMISTY: - sc_start(bl,SC_FROSTMISTY,25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,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(src,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(src,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(src, 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(src, 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)); + sc_start(src, bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + if ( tsc && !tsc->data[SC_FREEZE] ) + sc_start(src, 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(src, 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; case NC_MAGMA_ERUPTION: - sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv)); - sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start4(src, bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv)); + sc_start(src, bl, SC_STUN, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); break; case GC_WEAPONCRUSH: 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(src, 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(src, 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(src, 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; @@ -1219,135 +1243,103 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( rnd()%100 < rate && dstsd ) // Uses skill->addtimerskill to avoid damage and setsit packet overlaping. Officially clif->setsit is received about 500 ms after damage packet. skill->addtimerskill(src,tick+500,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); else if( dstmd && !is_boss(bl) ) - sc_start(bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters. if ( battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON ) - sc_start(bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv)); + sc_start(src, 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); - sc_start(bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + skill->break_equip(src, EQP_SHIELD, 100 * skill_lv, BCT_SELF); + sc_start(src, bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_DRAGONCOMBO: - sc_start(bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_FALLENEMPIRE: - sc_start(bl, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_WINDMILL: if( dstsd ) skill->addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); else if( dstmd && !is_boss(bl) ) - sc_start(bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3)); + sc_start(src, bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3)); break; case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10] - sc_start(bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status->get_lv(src)) / 10, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status->get_lv(src)) / 10, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SR_EARTHSHAKER: - sc_start(bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); break; 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); - } + sc_start(src, bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); 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] + sc_start2(src, 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; - sc_start(bl, SC_COLD, rate, skill_lv, skill->get_time2(skill_id, skill_lv)); + rate += sc->data[SC_COOLER_OPTION]->val3 / 5; + sc_start(src, 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(src, 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(src, bl, SC_STUN, 100, skill_lv, 5000); // 5 seconds until I get official + sc_start(src, 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(src, 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(src, bl, SC_BANANA_BOMB, 100, skill_lv, 60000); // Reduces LUK? Needed confirm it, may be it's bugged in kRORE? + sc_start(src, 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(src, bl, SC_STUN, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); + sc_start2(src, 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)); + sc_start2(src, bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); break; case EL_STONE_HAMMER: rate = 10 * skill_lv; - sc_start(bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv)); + sc_start(src, bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv)); break; case EL_ROCK_CRUSHER: case EL_ROCK_CRUSHER_ATK: - sc_start(bl,status->skill2sc(skill_id),50,skill_lv,skill->get_time(EL_ROCK_CRUSHER,skill_lv)); + sc_start(src, bl,status->skill2sc(skill_id),50,skill_lv,skill->get_time(EL_ROCK_CRUSHER,skill_lv)); break; case EL_TYPOON_MIS: - sc_start(bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); break; case KO_JYUMONJIKIRI: - sc_start(bl,SC_KO_JYUMONJIKIRI,90,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,SC_KO_JYUMONJIKIRI,90,skill_lv,skill->get_time(skill_id,skill_lv)); break; case KO_MAKIBISHI: - sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, 1000 * (skill_lv / 2 + 2)); + sc_start(src, bl, SC_STUN, 10 * skill_lv, skill_lv, 1000 * (skill_lv / 2 + 2)); break; case MH_LAVA_SLIDE: - if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time(skill_id, skill_lv)); + if (tsc && !tsc->data[SC_BURNING]) sc_start4(src, bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time(skill_id, skill_lv)); break; case MH_STAHL_HORN: - sc_start(bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv)); break; case MH_NEEDLE_OF_PARALYZE: - sc_start(bl, SC_NEEDLE_OF_PARALYZE, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_NEEDLE_OF_PARALYZE, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv)); break; case GN_ILLUSIONDOPING: - if( sc_start(bl, SC_ILLUSIONDOPING, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)) ) //custom rate. - sc_start(bl, SC_ILLUSION, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + if( sc_start(src, bl, SC_ILLUSIONDOPING, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)) ) //custom rate. + sc_start(src, bl, SC_ILLUSION, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; } @@ -1364,7 +1356,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 rate += sd->weapon_coma_race[tstatus->race]; rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; if (rate) - status->change_start(bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0); + status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0); } if( sd && battle_config.equip_self_break_rate ) { // Self weapon breaking @@ -1701,19 +1693,19 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b time = skill->get_time2(status->sc2skill(type),7); if (dstsd->addeff2[i].flag&ATF_TARGET) - status->change_start(src,type,rate,7,0,0,0,time,0); + status->change_start(bl,src,type,rate,7,0,0,0,time,0); if (dstsd->addeff2[i].flag&ATF_SELF && !status->isdead(bl)) - status->change_start(bl,type,rate,7,0,0,0,time,0); + status->change_start(bl,bl,type,rate,7,0,0,0,time,0); } } switch(skill_id){ case MO_EXTREMITYFIST: - sc_start(src,SC_EXTREMITYFIST,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,src,SC_EXTREMITYFIST,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case GS_FULLBUSTER: - sc_start(src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case HFLI_SBR44: //[orn] case HVAN_EXPLOSION: @@ -1732,7 +1724,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && rnd()%10000 < battle_config.sg_miracle_skill_ratio) //SG_MIRACLE [Komurka] - sc_start(src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); + sc_start(src,src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); if( sd && skill_id && attack_type&BF_MAGIC && status->isdead(bl) && !(skill->get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) @@ -1937,7 +1929,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in else if (rnd()%10000 >= rate) where&=~where_list[i]; else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect. - sc_start(bl,scatk[i],100,0,skill->get_time(status->sc2skill(scatk[i]),1)); + sc_start(bl,bl,scatk[i],100,0,skill->get_time(status->sc2skill(scatk[i]),1)); } } if (!where) //Nothing to break. @@ -2002,7 +1994,7 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int if (!where) return 0; for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && !sc_start(bl, sc_atk[i], 100, lv, time)) + if (where&pos[i] && !sc_start(bl, bl, sc_atk[i], 100, lv, time)) where&=~pos[i]; } return where?1:0; @@ -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; } @@ -2325,7 +2317,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc->checkskill(sd, HT_POWER)) { //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] - sc_start2(src,SC_COMBOATTACK,100,HT_POWER,bl->id,2000); + sc_start2(NULL,src,SC_COMBOATTACK,100,HT_POWER,bl->id,2000); clif->combo_delay(src,2000); } break; @@ -2339,7 +2331,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case SL_STIN: case SL_STUN: if (skill_lv >= 7 && !sd->sc.data[SC_SMA_READY]) - sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA, skill_lv)); + sc_start(src, src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA, skill_lv)); break; case GS_FULLBUSTER: //Can't attack nor use items until skill's delay expires. [Skotlex] @@ -2360,7 +2352,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } //Switch End if (combo) { //Possible to chain if ( (combo = DIFF_TICK32(sd->ud.canact_tick, tick)) < 50 ) combo = 50;/* less is a waste. */ - sc_start2(src,SC_COMBOATTACK,100,skill_id,bl->id,combo); + sc_start2(NULL,src,SC_COMBOATTACK,100,skill_id,bl->id,combo); clif->combo_delay(src, combo); } } @@ -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; @@ -2594,7 +2594,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } // Hell Inferno burning status only starts if Fire part hits. if( skill_id == WL_HELLINFERNO && dmg.damage > 0 && !(flag&ELE_DARK) ) - sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); + sc_start4(src,bl,SC_BURNING,55+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); // Apply knock back chance in SC_TRIANGLESHOT skill. else if( skill_id == SC_TRIANGLESHOT && rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0; @@ -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(src, 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) { @@ -3157,20 +3164,20 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { if( skl->type == 4 ){ const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used. int rate = skl->y, index = skl->x-1; - sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1)); + sc_start2(src,target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1)); } 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); @@ -3660,7 +3681,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL - sc_start(src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv)); #endif // RENEWAL } else { status_change_end(src, SC_NJ_NEN, INVALID_TIMER); @@ -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; @@ -3911,7 +3934,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case NPC_MAGICALATTACK: skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - sc_start(src,status->skill2sc(skill_id),100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, src,status->skill2sc(skill_id),100,skill_lv,skill->get_time(skill_id,skill_lv)); break; case HVAN_CAPRICE: //[blackhole89] @@ -3973,7 +3996,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case SL_STIN: case SL_STUN: if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - status->change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10); clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); 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: { @@ -4052,7 +4075,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case NJ_KASUMIKIRI: if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag) > 0) - sc_start(src,SC_HIDING,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,src,SC_HIDING,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; case NJ_KIRIKAGE: if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground ) { @@ -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(src, 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. @@ -4310,7 +4347,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; case NC_MAGNETICFIELD: - sc_start2(bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); + sc_start2(src,bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); break; case SC_FATALMENACE: if( flag&1 ) @@ -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(src,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; @@ -4467,8 +4543,8 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( rnd()%100 < 50 ) skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); else { - sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv)); + sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv)); } clif->skill_nodamage(src,src,skill_id,skill_lv,1); } @@ -4498,7 +4574,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 #endif } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_RG_CCONFINE_S,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start4(src,bl,SC_RG_CCONFINE_S,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); 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 @@ -4780,7 +4859,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { if( td && td->func == status->change_timer && DIFF_TICK(td->tick,timer->gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 ) break; } - sc_start2(src, SC_NOEQUIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv)); + sc_start2(src,src, SC_NOEQUIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv)); break; } } @@ -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); @@ -4840,7 +4922,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL - sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv)); + sc_start(src, src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv)); #endif } if (target && target->m == src->m) { @@ -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: { @@ -4984,7 +5102,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RK_FIGHTINGSPIRIT: case RK_ABUNDANCE: if( sd && !pc->checkskill(sd, RK_RUNEMASTERY) ){ - if( status->change_start(&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){ + if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){ skill->consume_requirement(sd,skill_id,skill_lv,2); map->freeblock_unlock(); return 0; @@ -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); @@ -5138,19 +5256,20 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case AL_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, + sc_start(src, bl, type, (40 + skill_lv * 2 + (status->get_lv(src) + sstatus->int_)/5), skill_lv, /* monsters using lvl 48 get the rate benefit but the duration of lvl 10 */ ( src->type == BL_MOB && skill_lv == 48 ) ? skill->get_time(skill_id,10) : skill->get_time(skill_id,skill_lv))); 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(src, 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: if (flag&1) - sc_start(bl,type, 23+skill_lv*4 +status->get_lv(src) -status->get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,type, 23+skill_lv*4 +status->get_lv(src) -status->get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv)); else { 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); @@ -5163,7 +5282,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsce ) status_change_end(bl,type, INVALID_TIMER); else - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); break; @@ -5220,7 +5339,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SA_COMA: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv))); + sc_start(src, bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv))); break; case SA_FULLRECOVERY: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -5294,7 +5413,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SA_REVERSEORCISH: case ALL_REVERSEORCISH: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); + sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); break; case SA_FORTUNE: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -5319,7 +5438,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case CG_MARIONETTE: @@ -5335,8 +5454,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sc && tsc ) { if( !sc->data[SC_MARIONETTE_MASTER] && !tsc->data[SC_MARIONETTE] ) { - sc_start(src,SC_MARIONETTE_MASTER,100,bl->id,skill->get_time(skill_id,skill_lv)); - sc_start(bl,SC_MARIONETTE,100,src->id,skill->get_time(skill_id,skill_lv)); + sc_start(src,src,SC_MARIONETTE_MASTER,100,bl->id,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_MARIONETTE,100,src->id,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } else if( sc->data[SC_MARIONETTE_MASTER ] && sc->data[SC_MARIONETTE_MASTER ]->val1 == bl->id && tsc->data[SC_MARIONETTE] && tsc->data[SC_MARIONETTE]->val1 == src->id @@ -5355,7 +5474,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RG_CLOSECONFINE: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start4(src,bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); break; case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] case SA_FROSTWEAPON: @@ -5380,7 +5499,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } // 100% success rate at lv4 & 5, but lasts longer at lv5 - if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) { + if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) { if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) @@ -5394,12 +5513,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case ITEM_ENCHANTARMS: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv, + sc_start2(src,bl,type,100,skill_lv, skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id,skill_lv))); break; @@ -5414,16 +5533,16 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case ELE_HOLY : type = SC_ASPERSIO; break; } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - sc_start2(bl,SC_TK_SEVENWIND,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time(skill_id,skill_lv)); + sc_start2(src,bl,SC_TK_SEVENWIND,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time(skill_id,skill_lv)); break; case PR_KYRIE: case MER_KYRIE: clif->skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; //Passive Magnum, should had been casted on yourself. case SM_MAGNUM: @@ -5433,7 +5552,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id); clif->skill_nodamage (src,src,skill_id,skill_lv,1); // Initiate 10% of your damage becomes fire element. - sc_start4(src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); + sc_start4(src,src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); if( sd ) skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv)); else if( bl->type == BL_MER ) @@ -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: @@ -5539,7 +5659,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RK_CRUSHSTRIKE: case ALL_ODINS_POWER: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case SO_STRIKING: @@ -5548,7 +5668,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin bonus += (pc->checkskill(sd, SA_FLAMELAUNCHER)+pc->checkskill(sd, SA_FROSTWEAPON)+pc->checkskill(sd, SA_LIGHTNINGLOADER)+pc->checkskill(sd, SA_SEISMICWEAPON))*5; clif->skill_nodamage( src, bl, skill_id, skill_lv, battle->check_target(src,bl,BCT_PARTY) > 0 ? - sc_start2(bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) : + sc_start2(src, bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) : 0 ); } @@ -5556,15 +5676,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NPC_STOP: if( clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) ) - sc_start2(src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)); + sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) ) + sc_start2(src,src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)); break; case HP_ASSUMPTIO: if( sd && dstmd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); else clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case MG_SIGHT: case MER_SIGHT: @@ -5574,25 +5694,25 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NPC_STONESKIN: case NPC_ANTIMAGIC: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv))); + sc_start2(src,bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv))); break; case HLIF_AVOID: case HAMI_DEFENCE: { int duration = skill->get_time(skill_id,skill_lv); - clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,duration)); // Master - clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,duration)); // Homunc + clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,duration)); // Master + clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,duration)); // Homunc } break; case NJ_BUNSINJYUTSU: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); status_change_end(bl, SC_NJ_NEN, INVALID_TIMER); break; #if 0 /* Was modified to only affect targetted char. [Skotlex] */ case HP_ASSUMPTIO: if (flag&1) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); else { map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_PC, @@ -5604,7 +5724,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin #endif // 0 case SM_ENDURE: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if (sd) skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv)); break; @@ -5612,7 +5732,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case ALL_ANGEL_PROTECT: if( dstsd ) clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); else if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; @@ -5632,12 +5752,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case LK_TENSIONRELAX: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv), + sc_start4(src,bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv), skill->get_time(skill_id,skill_lv))); break; @@ -5669,7 +5789,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case AC_CONCENTRATION: { clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); map->foreachinrange(status->change_timer_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, src,NULL,type,tick); @@ -5687,7 +5807,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] clif->skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv, - (failure = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status->get_lv(src) - status->get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv)))); + (failure = sc_start(src,bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status->get_lv(src) - status->get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv)))); if( !failure ) { if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -5760,7 +5880,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin mer->devotion_flag = 1; // Mercenary Devoting Owner clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv))); + sc_start4(src, bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv))); clif->devotion(src, NULL); } break; @@ -5840,7 +5960,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case BS_HAMMERFALL: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv))); + sc_start(src,bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv))); break; case RG_RAID: skill->area_temp[1] = 0; @@ -5942,18 +6062,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case CASH_ASSUMPTIO: case WM_FRIGG_SONG: if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,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); break; case MER_MAGNIFICAT: if( mer != NULL ) { - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) party->foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); else if( mer->master && !(flag&1) ) - clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } break; @@ -5963,7 +6083,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case BS_OVERTHRUST: if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { clif->skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv))); + sc_start2(src,bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv))); } else if (sd) { party->foreachsamemap(skill->area_sub, sd,skill->get_splash(skill_id, skill_lv), @@ -5992,7 +6112,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - 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_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case SL_KAITE: case SL_KAAHI: @@ -6007,13 +6127,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin || dstsd->status.char_id == sd->status.child ) ) { - status->change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8); + status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,8); clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); break; case SM_AUTOBERSERK: case MER_AUTOBERSERK: @@ -6022,7 +6142,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsce ) failure = status_change_end(bl, type, INVALID_TIMER); else - failure = sc_start(bl,type,100,skill_lv,60000); + failure = sc_start(src,bl,type,100,skill_lv,60000); clif->skill_nodamage(src,bl,skill_id,skill_lv,failure); } break; @@ -6039,7 +6159,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - clif->skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src,bl,skill_id,-1,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case TK_RUN: if (tsce) { @@ -6047,7 +6167,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit->getdir(bl),0,0,0)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit->getdir(bl),0,0,0)); if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] clif->walkok(sd); // So aegis has to resend the walk ok. break; @@ -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 ) @@ -6069,7 +6188,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } case RA_CAMOUFLAGE: { - int failure = sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); if( failure ) clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure); else if( sd ) @@ -6099,18 +6218,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case BA_PANGVOICE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv))); break; case DC_WINKCHARM: if( dstsd ) - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv))); + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv))); else if( dstmd ) { if( status->get_lv(src) > status->get_lv(bl) && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) && !(tstatus->mode&MD_BOSS) ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(src,bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); } else { clif->skill_nodamage(src,bl,skill_id,skill_lv,0); if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -6158,7 +6277,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate, + if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate, skill_lv, 0, 0, skill->get_time(skill_id, skill_lv), skill->get_time2(skill_id,skill_lv))) clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -6210,7 +6329,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } //Is this equation really right? It looks so... special. if( battle->check_undead(tstatus->race,tstatus->def_ele) ) { - status->change_start(bl, SC_BLIND, + status->change_start(src, bl, SC_BLIND, 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), 1,0,0,0, skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); } @@ -6576,7 +6695,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } break; case AM_TWILIGHT1: @@ -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) @@ -6714,7 +6834,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if(sd) { int sp = skill->get_sp(sd->skill_id_old,sd->skill_lv_old); if( skill_id == SO_SPELLFIST ){ - sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv)); sd->skill_id_old = sd->skill_lv_old = 0; break; } @@ -6769,7 +6889,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case SA_MAGICROD: clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; case SA_AUTOSPELL: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -6804,7 +6924,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin maxlv = 3; } if(spellid > 0) - sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, + sc_start4(src,src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, skill->get_time(SA_AUTOSPELL,skill_lv)); } break; @@ -6835,7 +6955,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NPC_CHANGEDARKNESS: case NPC_CHANGETELEKINESIS: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + sc_start2(src, bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id, skill_lv))); break; case NPC_CHANGEUNDEAD: @@ -6843,7 +6963,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //TO-DO This is ugly, fix it if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + sc_start2(src, bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id, skill_lv))); break; @@ -6858,7 +6978,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int skill_time = skill->get_time(skill_id,skill_lv); struct unit_data *ud = unit->bl2ud(bl); if (clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_time)) + sc_start(src,bl,type,100,skill_lv,skill_time)) && ud) { //Disable attacking/acting/moving for skill's duration. ud->attackabletime = ud->canact_tick = @@ -6870,18 +6990,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NPC_REBIRTH: if( md && md->state.rebirth ) break; // only works once - sc_start(bl,type,100,skill_lv,-1); + sc_start(src,bl,type,100,skill_lv,-1); break; case NPC_DARKBLESSING: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv))); + sc_start2(src,bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv))); break; case NPC_LICK: status_zap(bl, 0, 100); clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv))); + sc_start(src,bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv))); break; case NPC_SUICIDE: @@ -6913,7 +7033,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (i > SC_ATTHASTE_INFINITY) i = SC_ATTHASTE_INFINITY; clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); + sc_start(src,bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); } break; @@ -6968,7 +7088,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin mob->unlocktarget(md,tick); if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2]) - sc_start4(src, type, 100, skill_lv, + sc_start4(src, src, type, 100, skill_lv, md->db->skill[md->skill_idx].val[1], md->db->skill[md->skill_idx].val[2], md->db->skill[md->skill_idx].val[3], @@ -6977,21 +7097,21 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case NPC_POWERUP: - sc_start(bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv)); + sc_start(src,bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); + sc_start(src,bl,type,100,100,skill->get_time(skill_id, skill_lv))); break; case NPC_AGIUP: - sc_start(bl,SC_MOVHASTE_INFINITY,100,skill_lv,skill->get_time(skill_id, skill_lv)); + sc_start(src,bl,SC_MOVHASTE_INFINITY,100,skill_lv,skill->get_time(skill_id, skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); + sc_start(src,bl,type,100,100,skill->get_time(skill_id, skill_lv))); break; case NPC_INVISIBLE: //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv))); + sc_start4(src,bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv))); break; case NPC_SIEGEMODE: @@ -7021,12 +7141,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin struct map_session_data *m_sd = pc->get_mother(sd); bool we_baby_parents = false; if(m_sd && check_distance_bl(bl,&m_sd->bl,AREA_SIZE)) { - sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->specialeffect(&m_sd->bl,408,AREA); we_baby_parents = true; } if(f_sd && check_distance_bl(bl,&f_sd->bl,AREA_SIZE)) { - sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->specialeffect(&f_sd->bl,408,AREA); we_baby_parents = true; } @@ -7035,7 +7155,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - else status->change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); + else + status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); } break; @@ -7065,7 +7186,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; @@ -7148,7 +7269,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 1; } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); + sc_start4(src,bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); #ifndef RENEWAL if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000); #endif @@ -7170,7 +7291,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //Has a 55% + skill_lv*5% success chance. if (!clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))) + sc_start(src,bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))) ) { if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map->freeblock_unlock(); @@ -7264,7 +7385,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin for (i=0 ; i<4; i++) { if( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[i]) < 0 ) ) continue; - sc_start(bl,(sc_type)(SC_PROTECTWEAPON + i),100,skill_lv,skilltime); + sc_start(src,bl,(sc_type)(SC_PROTECTWEAPON + i),100,skill_lv,skilltime); s++; } if( sd && !s ){ @@ -7286,7 +7407,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] { clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } } break; @@ -7318,7 +7439,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_percent_damage(src, bl, 0, 100, false); break; case 1: // matk halved - sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); break; case 2: // all buffs removed status->change_clear_buffs(bl,1); @@ -7334,7 +7455,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; case 4: // atk halved - sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); break; case 5: // 2000HP heal, random teleported status->heal(src, 2000, 0, 0); @@ -7350,38 +7471,38 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case 7: // stop freeze or stoned { enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; - sc_start(bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv)); } break; case 8: // curse coma and poison - sc_start(bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case 9: // confusion - sc_start(bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case 10: // 6666 damage, atk matk halved, cursed status_fix_damage(src, bl, 6666, 0); clif->damage(src,bl,0,0,6666,0,0,0); - sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); break; case 11: // 4444 damage status_fix_damage(src, bl, 4444, 0); clif->damage(src,bl,0,0,4444,0,0,0); break; case 12: // stun - sc_start(bl,SC_STUN,100,skill_lv,5000); + sc_start(src,bl,SC_STUN,100,skill_lv,5000); break; case 13: // atk,matk,hit,flee,def reduced - sc_start(bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; default: break; @@ -7419,8 +7540,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //SC_SOULLINK invokes status_calc_pc for us. } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_SOULLINK,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + sc_start4(src,bl,SC_SOULLINK,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; case SL_HIGH: if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { @@ -7428,15 +7549,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + sc_start4(src,bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; case SL_SWOO: if (tsce) { if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status->change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8); + status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,8); status_change_end(bl, SC_SWOO, INVALID_TIMER); break; } @@ -7444,19 +7565,19 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SL_SKE: if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status->change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10); break; } - 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_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if (skill_id == SL_SKE) - sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; // New guild skills [Celest] case GD_BATTLEORDER: if(flag&1) { if (status->get_guild_id(src) == status->get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); } else if (status->get_guild_id(src)) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); map->foreachinrange(skill->area_sub, src, @@ -7470,7 +7591,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case GD_REGENERATION: if(flag&1) { if (status->get_guild_id(src) == status->get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); } else if (status->get_guild_id(src)) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); map->foreachinrange(skill->area_sub, src, @@ -7556,7 +7677,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int rate = 65 -5*distance_bl(src,bl); //Base rate if (rate < 30) rate = 30; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - sc_start(bl,SC_STUN, rate,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,bl,SC_STUN, rate,skill_lv,skill->get_time2(skill_id,skill_lv)); } break; @@ -7636,7 +7757,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case MH_ANGRIFFS_MODUS: case MH_GOLDENE_FERSE: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if (hd) skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); break; @@ -7646,7 +7767,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLOODING }; int i, j; j = i = rnd()%ARRAYLENGTH(sc); - while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) { + while ( !sc_start2(src,bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) { i++; if ( i == ARRAYLENGTH(sc) ) i = 0; @@ -7674,13 +7795,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (flag&1){ switch( type ){ case SC_BURNING: - sc_start4(bl,type,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); + sc_start4(src,bl,type,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); break; case SC_SIREN: - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); break; default: - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); } } else { skill->area_temp[2] = 0; //For SD_PREAMBLE @@ -7714,7 +7835,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin 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 - 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_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; case NPC_TALK: case ALL_WEWISH: @@ -7730,11 +7851,11 @@ 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(src,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) - sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); else { skill->area_temp[2] = 0; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -7760,9 +7881,9 @@ 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))); + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(src,bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv))); else clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } @@ -7771,36 +7892,43 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { int heal = status_get_max_hp(bl) * 25 / 100; clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); status->heal(bl,heal,0,1); status->change_clear_buffs(bl,4); } 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(src,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(src,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(src,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(src,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: @@ -7840,7 +7968,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } if( type > SC_NONE ) clif->skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, skill_lv, value, 0, 1, skill->get_time(skill_id, skill_lv))); + sc_start4(src,bl, type, 100, skill_lv, value, 0, 1, skill->get_time(skill_id, skill_lv))); } }else if( sd ){ if( tsc && tsc->count ){ @@ -7876,7 +8004,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin count = 10; // Max coounter status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); } - sc_start(bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage(src,src,skill_id,skill_lv,1); } break; @@ -7885,7 +8013,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsc && tsc->data[SC_WEAPONBLOCKING] ) status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); else - sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; @@ -7920,15 +8048,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; @@ -7937,7 +8070,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); break; } - 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_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } break; /** @@ -7957,7 +8090,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) level = skill_id == AB_CLEMENTIA ? pc->checkskill(sd,AL_BLESSING) : pc->checkskill(sd,AL_INCAGI); if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl, type, 100, level + (sd?(sd->status.job_level / 10):0), skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, level + (sd?(sd->status.job_level / 10):0), skill->get_time(skill_id,skill_lv))); else if( sd ) { if( !level ) clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); @@ -7968,33 +8101,48 @@ 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(src, 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)); + sc_start(src, bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); else { 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); @@ -8016,7 +8164,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_change_end(bl, SC_COLD, 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))); + sc_start(src, bl, type, 100, skill_lv, 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); @@ -8024,16 +8172,17 @@ 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))); + sc_start(src, bl, type, 100, skill_lv, 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); @@ -8093,7 +8242,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin **/ case WL_STASIS: if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); else { map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); @@ -8109,8 +8258,11 @@ 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)); + int failure = sc_start2(src,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); if( sd && !failure ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -8121,18 +8273,22 @@ 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; case WL_MARSHOFABYSS: clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; case WL_SIENNAEXECRATE: @@ -8142,7 +8298,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsc && tsc->data[SC_STONE] ) status_change_end(bl,SC_STONE,INVALID_TIMER); else - status->change_start(bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2); + status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2); } else { int rate = 45 + 5 * skill_lv; if( rnd()%100 < rate ){ @@ -8163,7 +8319,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsc && !tsc->data[i] ){ // officially it doesn't work like a stack int ele = WLS_FIRE + (skill_id - WL_SUMMONFB) - (skill_id == WL_SUMMONSTONE ? 4 : 0); clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(bl, (sc_type)i, 100, ele, skill->get_time(skill_id, skill_lv))); + sc_start(src, bl, (sc_type)i, 100, ele, skill->get_time(skill_id, skill_lv))); break; } } @@ -8183,7 +8339,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } - sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. + sc_start(src, bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. clif->spellbook_list(sd); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } @@ -8193,7 +8349,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin **/ case RA_FEARBREEZE: clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - 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_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; case RA_WUGMASTERY: @@ -8226,7 +8382,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 0; } if( sd && pc_isridingwug(sd) ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit->getdir(bl),0,0,1)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit->getdir(bl),0,0,1)); clif->walkok(sd); } break; @@ -8262,14 +8418,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NC_ANALYZE: 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, - sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src,bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); if( sd ) pc->overheat(sd,1); break; case NC_MAGNETICFIELD: { int failure; - if( (failure = sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) + if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) { 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|SD_SPLASH|1,skill->castend_damage_id);; clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); @@ -8280,19 +8436,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; @@ -8310,7 +8468,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id); if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) { - sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] + sc_start(src,src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] clif->autoshadowspell_list(sd); clif->skill_nodamage(src,bl,skill_id,1,1); } @@ -8321,7 +8479,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SC_SHADOWFORM: if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { - if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) ) + if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) ) dstsd->shadowform_id = src->id; } else if( sd ) @@ -8331,16 +8489,14 @@ 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,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,20 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); } } else { clif->skill_nodamage(src, bl, skill_id, 0, 1); @@ -8351,34 +8507,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); - 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; + 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(src,bl,type,rate,skill_lv,skill->get_time(skill_id,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(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10); + break; + case 1: + status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10); + break; + case 2: + status->change_start(src,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: @@ -8390,114 +8556,96 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( tsc && tsc->data[type] ) status_change_end(bl,type,INVALID_TIMER); else - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; 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(src,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(src,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(src,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(src,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(src,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(src,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(src,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(src,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(src,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(src,bl,SC_SHIELDSPELL_REF,100,opt,val,shield->refine * 20000)) + clif->skill_nodamage(src,bl,SC_SCRESIST,skill_lv, + sc_start(src,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(src,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; @@ -8508,7 +8656,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case LG_PIETY: if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); else { skill->area_temp[2] = 0; map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id); @@ -8518,7 +8666,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case LG_KINGS_GRACE: if( flag&1 ){ int i; - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); for(i=0; i<SC_MAX; i++) { if (!tsc->data[i]) @@ -8530,9 +8678,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); } } @@ -8552,12 +8700,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->updatestatus(sd,SP_JOBEXP); } clif->skill_nodamage(bl,src,skill_id,skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + sc_start(src,bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; case SR_CURSEDCIRCLE: if( flag&1 ) { if( is_boss(bl) ) break; - if( sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) { + if( sc_start2(src,bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) { if( bl->type == BL_MOB ) mob->unlocktarget((TBL_MOB*)bl,timer->gettick()); unit->stop_attack(bl); @@ -8572,7 +8720,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); if( sd ) pc->delspiritball(sd, count, 0); clif->skill_nodamage(src, src, skill_id, skill_lv, - sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv))); + sc_start2(src, src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv))); } break; @@ -8580,10 +8728,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { short max = 5 + skill_lv; int i; - sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); for( i = 0; i < max; i++ ) // Don't call more than max available spheres. pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max); - 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_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); } break; @@ -8646,41 +8794,32 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SR_GENTLETOUCH_CHANGE: case SR_GENTLETOUCH_REVITALIZE: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); break; case SR_FLASHCOMBO: { 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(src,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(src,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(src,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 +8828,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(src,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(src,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(src,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(src,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(src,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(src, 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(src,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,23 +9017,10 @@ 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); + sc_start2(src,bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv)); } break; @@ -8903,7 +9037,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 +9105,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 ) { @@ -8999,7 +9123,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer } clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + sc_start2(src,bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); (sc->bs_counter)++; } else if( sd ) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); @@ -9013,8 +9137,8 @@ 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] - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + if ( rnd()%100 < chance ) {//Coded to both inflect the status and drain the target's SP only when successful. [Rytech] + sc_start(src, 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); } } else if ( sd ) { @@ -9099,9 +9223,9 @@ 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); - 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)); + skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0); + sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); } } } @@ -9129,8 +9253,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } else { // This not heals at the end. clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); + sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(src, bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); } } } @@ -9179,7 +9303,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } if( dstsd && tsc && !tsc->data[type] && rand()%100 < rate ){ clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); }else if( sd ) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); } @@ -9190,10 +9314,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin && rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv)) ) { clif->skill_nodamage(src, bl, skill_id, skill_lv, - status->change_start(bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1)); + status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1)); status_zap(bl, tstatus->max_hp * skill_lv * 5 / 100 , 0); if( status->get_lv(bl) <= status->get_lv(src) ) - status->change_start(bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0); + status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0); } else if( sd ) clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; @@ -9209,13 +9333,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (unit->movepos(src, bl->x, bl->y, 0, 0)) { clif->skill_nodamage(src, src, skill_id, skill_lv, 1); clif->slide(src, bl->x, bl->y) ; - sc_start(src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv)); if ( !is_boss(bl) && unit->stop_walking(&sd->bl, 1) && unit->movepos(bl, x, y, 0, 0) ) { if( dstsd && pc_issit(dstsd) ) pc->setstand(dstsd); clif->slide(bl, x, y) ; - sc_start(bl, SC_CONFUSION, 75, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_CONFUSION, 75, skill_lv, skill->get_time(skill_id, skill_lv)); } } } @@ -9233,7 +9357,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case KG_KYOMU: case KG_KAGEMUSYA: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); break; @@ -9242,8 +9366,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || tsc->data[SC_MARIONETTE_MASTER] || tsc->data[SC_HARMONIZE])){ - sc_start(src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, type, 100, 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); @@ -9254,7 +9378,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } if( skill->area_temp[2] == 1 ){ clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); } } else { skill->area_temp[2] = 0; @@ -9276,18 +9400,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); } if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target - status->change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + status->change_start(src, bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); } heal = status_get_matk_min(src)*4; status->heal(bl, heal, 0, 7); //now inflict silence on everyone if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status->change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + status->change_start(src, src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); if(m_bl){ struct status_change *msc = status->get_sc(m_bl); if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status->change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + status->change_start(src, m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); } if (hd) skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); @@ -9303,9 +9427,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if(s_bl && s_bl->type==BL_PC) { status->set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info - sc_start(s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus + sc_start(src, s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus } - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); } break; @@ -9315,9 +9439,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin struct block_list *s_bl = battle->get_master(src); if(s_bl) - sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master + sc_start2(src, s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master - sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); + sc_start2(src, bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); } @@ -9331,7 +9455,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //don't break need to start status and start block timer case MH_MAGMA_FLOW: case MH_PAIN_KILLER: - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); if (hd) skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); break; @@ -9354,7 +9478,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin timer->delete(summon_md->deletetimer, mob->timer_delete); summon_md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, summon_md->bl.id, 0); mob->spawn(summon_md); //Now it is ready for spawning. - sc_start4(&summon_md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000); + sc_start4(src,&summon_md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000); } } if (hd) @@ -9387,7 +9511,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 +9676,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 +9923,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 +10010,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 +10036,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. @@ -9920,14 +10059,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui skill->clear_unitgroup(src); if( skill->unitsetting(src,skill_id,skill_lv,x,y,0) ) - sc_start4(src,type,100,skill_lv,0,0,src->id,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,type,100,skill_lv,0,0,src->id,skill->get_time(skill_id,skill_lv)); flag|=1; } break; case CG_HERMODE: skill->clear_unitgroup(src); if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0))) - sc_start4(src,SC_DANCING,100, + sc_start4(src,src,SC_DANCING,100, skill_id,0,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv)); flag|=1; break; @@ -10089,7 +10228,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case HW_GRAVITATION: if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0))) - sc_start4(src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill->get_time(skill_id,skill_lv)); flag|=1; break; @@ -10123,7 +10262,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case SG_STAR_WARM: skill->clear_unitgroup(src); if ((sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0))) - sc_start4(src,type,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,type,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); flag|=1; break; @@ -10137,13 +10276,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui if (sce) status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex] status->change_clear_buffs(src,3); - sc_start4(src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill->get_time(skill_id,skill_lv)); clif->skill_poseffect(src, skill_id, skill_lv, 0, 0, tick); // PA_GOSPEL music packet } break; case NJ_TATAMIGAESHI: if (skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) - sc_start(src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(src,src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case AM_RESURRECTHOMUN: //[orn] @@ -10158,14 +10297,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), @@ -10226,7 +10380,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case NC_STEALTHFIELD: skill->clear_unitgroup(src); // To remove previous skills - cannot used combined if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { - sc_start2(src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv)); + sc_start2(src,src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv)); if( sd ) pc->overheat(sd,1); } break; @@ -10255,8 +10409,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,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: @@ -10284,7 +10439,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui if( sc && sc->data[SC_BANDING] ) status_change_end(src,SC_BANDING,INVALID_TIMER); else if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { - sc_start4(src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); + sc_start4(src,src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); if( sd ) pc->banding(sd,skill_lv); } clif->skill_nodamage(src,src,skill_id,skill_lv,1); @@ -10301,25 +10456,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: { @@ -10362,7 +10529,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui if( sc && sc->data[type] ) status_change_end(src,type,INVALID_TIMER); clif->skill_nodamage(src, src ,skill_id, skill_lv, - sc_start2(src, type, 100, skill_id, skill_lv, skill->get_time(skill_id, skill_lv))); + sc_start2(src,src, type, 100, skill_id, skill_lv, skill->get_time(skill_id, skill_lv))); break; case KO_MAKIBISHI: @@ -10548,6 +10715,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 +10770,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 +11000,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 +11014,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; @@ -10890,7 +11061,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ sd->skill_lv_dance = skill_lv; } if ( - sc_start4(src, SC_DANCING, 100, skill_id, group->group_id, skill_lv, + sc_start4(src,src, SC_DANCING, 100, skill_id, group->group_id, skill_lv, (group->state.song_dance&2?BCT_SELF:0), limit+1000) && sd && group->state.song_dance&2 && skill_id != CG_HERMODE //Hermod is a encore with a warp! ) @@ -10956,11 +11127,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 +11139,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 +11200,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. @@ -11052,7 +11219,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick break; } else if( sc && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) { int sec = skill->get_time2(sg->skill_id,sg->skill_lv); - if( status->change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) { + if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) { const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL; if( td ) sec = DIFF_TICK32(td->tick, tick); @@ -11067,19 +11234,21 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick break; case UNT_SAFETYWALL: if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); + sc_start4(ss,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( !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); + if (bl->type == BL_MOB) + break; //Does not affect the caster. + if( !sce && sc_start4(ss,bl,type,100,sg->skill_lv,0,SC__BLOODYLUST,0,sg->limit) ) + sc_start(ss,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); + sc_start4(ss,bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); break; case UNT_WARP_WAITING: { @@ -11115,19 +11284,19 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_QUAGMIRE: if( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + sc_start4(ss,bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); break; case UNT_VOLCANO: case UNT_DELUGE: case UNT_VIOLENTGALE: if(!sce) - sc_start(bl,type,100,sg->skill_lv,sg->limit); + sc_start(ss,bl,type,100,sg->skill_lv,sg->limit); break; case UNT_SUITON: if(!sce) - sc_start4(bl,type,100,sg->skill_lv, + sc_start4(ss,bl,type,100,sg->skill_lv, map_flag_vs(bl->m) || battle->check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. 0,0,sg->limit); break; @@ -11146,7 +11315,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) return skill_id; if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); break; case UNT_WHISTLE: case UNT_ASSASSINCROSS: @@ -11161,7 +11330,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick if (!sc) return 0; if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); else if (sce->val4 == 1) { //Readjust timers since the effect will not last long. sce->val4 = 0; @@ -11173,7 +11342,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_FOGWALL: if (!sce) { - sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); + sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); if (battle->check_target(&src->bl,bl,BCT_ENEMY)>0) skill->additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); } @@ -11181,7 +11350,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_GRAVITATION: if (!sce) - sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); + sc_start4(ss,bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); break; // officially, icewall has no problems existing on occupied cells [ultramage] @@ -11207,9 +11376,16 @@ 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)); + sc_start(ss, bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv)); break; case UNT_GD_LEADERSHIP: @@ -11217,7 +11393,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_GD_SOULCOLD: case UNT_GD_HAWKEYES: if ( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) - sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); + sc_start4(ss,bl,type,100,sg->skill_lv,0,0,0,1000); break; } return skill_id; @@ -11231,7 +11407,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 +11423,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; @@ -11360,6 +11541,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 int count = 0; const int x = bl->x, y = bl->y; + map->freeblock_lock(); //If target isn't knocked back it should hit every "interval" ms [Playtester] do { if( bl->type == BL_PC ) @@ -11373,8 +11555,9 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 sg->limit = DIFF_TICK32(tick,sg->tick); break; } - } while( x == bl->x && y == bl->y + } while( x == bl->x && y == bl->y && sg->alive_count && ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status->isdead(bl) ); + map->freeblock_unlock(); } break; /** @@ -11392,12 +11575,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); } @@ -11421,7 +11598,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_MANHOLE: if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) { int sec = skill->get_time2(sg->skill_id,sg->skill_lv); - if( status->change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { + if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL; if( td ) sec = DIFF_TICK32(td->tick, tick); @@ -11451,7 +11628,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if( bl->id != ss->id ) { if( status_get_mode(bl)&MD_BOSS ) break; - if( status->change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) { + if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) { map->moveblock(bl, src->bl.x, src->bl.y, tick); clif->fixpos(bl); @@ -11464,7 +11641,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_VENOMDUST: if(tsc && !tsc->data[type]) - status->change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0); + status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0); break; @@ -11567,46 +11744,46 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if (tsd) clif->gospel_info(tsd, 0x15); break; case 2: // Immunity to all status - sc_start(bl,SC_SCRESIST,100,100,time); + sc_start(ss,bl,SC_SCRESIST,100,100,time); if (tsd) clif->gospel_info(tsd, 0x16); break; case 3: // MaxHP +100% - sc_start(bl,SC_INCMHPRATE,100,100,time); + sc_start(ss,bl,SC_INCMHPRATE,100,100,time); if (tsd) clif->gospel_info(tsd, 0x17); break; case 4: // MaxSP +100% - sc_start(bl,SC_INCMSPRATE,100,100,time); + sc_start(ss,bl,SC_INCMSPRATE,100,100,time); if (tsd) clif->gospel_info(tsd, 0x18); break; case 5: // All stats +20 - sc_start(bl,SC_INCALLSTATUS,100,20,time); + sc_start(ss,bl,SC_INCALLSTATUS,100,20,time); if (tsd) clif->gospel_info(tsd, 0x19); break; case 6: // Level 10 Blessing - sc_start(bl,SC_BLESSING,100,10,time); + sc_start(ss,bl,SC_BLESSING,100,10,time); break; case 7: // Level 10 Increase AGI - sc_start(bl,SC_INC_AGI,100,10,time); + sc_start(ss,bl,SC_INC_AGI,100,10,time); break; case 8: // Enchant weapon with Holy element - sc_start(bl,SC_ASPERSIO,100,1,time); + sc_start(ss,bl,SC_ASPERSIO,100,1,time); if (tsd) clif->gospel_info(tsd, 0x1c); break; case 9: // Enchant armor with Holy element - sc_start(bl,SC_BENEDICTIO,100,1,time); + sc_start(ss,bl,SC_BENEDICTIO,100,1,time); if (tsd) clif->gospel_info(tsd, 0x1d); break; case 10: // DEF +25% - sc_start(bl,SC_INCDEFRATE,100,25,time); + sc_start(ss,bl,SC_INCDEFRATE,100,25,time); if (tsd) clif->gospel_info(tsd, 0x1e); break; case 11: // ATK +100% - sc_start(bl,SC_INCATKRATE,100,100,time); + sc_start(ss,bl,SC_INCATKRATE,100,100,time); if (tsd) clif->gospel_info(tsd, 0x1f); break; case 12: // HIT/Flee +50 - sc_start(bl,SC_INCHIT,100,50,time); - sc_start(bl,SC_INCFLEE,100,50,time); + sc_start(ss,bl,SC_INCHIT,100,50,time); + sc_start(ss,bl,SC_INCFLEE,100,50,time); if (tsd) clif->gospel_info(tsd, 0x20); break; } @@ -11621,28 +11798,28 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 skill->attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case 1: // Curse - sc_start(bl,SC_CURSE,100,1,time); + sc_start(ss,bl,SC_CURSE,100,1,time); break; case 2: // Blind - sc_start(bl,SC_BLIND,100,1,time); + sc_start(ss,bl,SC_BLIND,100,1,time); break; case 3: // Poison - sc_start(bl,SC_POISON,100,1,time); + sc_start(ss,bl,SC_POISON,100,1,time); break; case 4: // Level 10 Provoke - sc_start(bl,SC_PROVOKE,100,10,time); + sc_start(ss,bl,SC_PROVOKE,100,10,time); break; case 5: // DEF -100% - sc_start(bl,SC_INCDEFRATE,100,-100,time); + sc_start(ss,bl,SC_INCDEFRATE,100,-100,time); break; case 6: // ATK -100% - sc_start(bl,SC_INCATKRATE,100,-100,time); + sc_start(ss,bl,SC_INCATKRATE,100,-100,time); break; case 7: // Flee -100% - sc_start(bl,SC_INCFLEERATE,100,-100,time); + sc_start(ss,bl,SC_INCFLEERATE,100,-100,time); break; case 8: // Speed/ASPD -25% - sc_start4(bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time); + sc_start4(ss,bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time); break; } } @@ -11658,7 +11835,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 } if( sg->src_id != bl->id && i <= 0 ) - sc_start4(bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100); + sc_start4(ss, bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100); } break; @@ -11688,8 +11865,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(ss,bl,sg->val2,rate,sg->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); + } break; case UNT_EPICLESIS: @@ -11704,13 +11885,14 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 hp = tstatus->max_hp * hp / 100; sp = tstatus->max_sp * sp / 100; status->heal(bl, hp, sp, 2); - sc_start(bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100); + sc_start(ss, bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100); } // Reveal hidden players every 5 seconds. if( sg->val2 % 5 == 0 ) { // 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] @@ -11722,7 +11904,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if( bl->id == sg->src_id ) break; // Dont work on Self (video shows that) case UNT_NEUTRALBARRIER: - sc_start(bl,type,100,sg->skill_lv,sg->interval + 100); + sc_start(ss,bl,type,100,sg->skill_lv,sg->interval + 100); break; case UNT_DIMENSIONDOOR: @@ -11735,20 +11917,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; + sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); } } break; @@ -11756,7 +11936,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if( tsc ) { if( !sg->val2 ) { int sec = skill->get_time2(sg->skill_id, sg->skill_lv); - if( sc_start(bl, type, 100, sg->skill_lv, sec) ) { + if( sc_start(ss, bl, type, 100, sg->skill_lv, sec) ) { const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL; if( td ) sec = DIFF_TICK32(td->tick, tick); @@ -11777,7 +11957,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case 1: case 2: default: - sc_start4(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0, + sc_start4(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv)); skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); @@ -11792,11 +11972,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 break; case UNT_FIRE_EXPANSION_SMOKE_POWDER: - sc_start(bl, status->skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000); + sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000); break; case UNT_FIRE_EXPANSION_TEAR_GAS: - sc_start(bl, status->skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000); + sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000); break; case UNT_HELLS_PLANT: @@ -11808,22 +11988,24 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_CLOUD_KILL: if(tsc && !tsc->data[type]) - status->change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8); + status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8); skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; 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 ) hp = ~hp + 1; status->heal(bl, hp, 0, 0); - sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); + sc_start(ss, bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); } break; @@ -11832,7 +12014,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_WIND_INSIGNIA: case UNT_EARTH_INSIGNIA: case UNT_ZEPHYR: - sc_start(bl,type, 100, sg->skill_lv, sg->interval); + sc_start(ss, bl,type, 100, sg->skill_lv, sg->interval); if (sg->unit_id != UNT_ZEPHYR && !battle->check_undead(tstatus->race, tstatus->def_ele)) { int hp = tstatus->max_hp / 100; //+1% each 5s if ((sg->val3) % 5) { //each 5s @@ -11852,31 +12034,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(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit); } break; @@ -11892,25 +12054,25 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ){ switch( sg->unit_id ){ case UNT_ZENKAI_WATER: - sc_start(bl, SC_COLD, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_COLD, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_LAND: - sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_FIRE: - sc_start4(bl, SC_BURNING, sg->val1*5, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_WIND: - sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_DEEP_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(ss, bl, SC_DEEP_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; } }else - sc_start2(bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start2(ss, bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_LAVA_SLIDE: @@ -11921,7 +12083,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_POISON_MIST: skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - status->change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8); + status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8); break; } @@ -11947,7 +12109,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 +12119,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 +12133,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 +12205,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 +12315,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,18 +12442,12 @@ 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 if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map->id2sd(p_sd[0])) != NULL) { sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; - sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill->get_time(skill_id,*skill_lv)+1000); + sc_start4(&tsd->bl,&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill->get_time(skill_id,*skill_lv)+1000); clif->skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); tsd->skill_id_dance = skill_id; tsd->skill_lv_dance = *skill_lv; @@ -12986,7 +13147,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 +13158,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 +13172,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 +13198,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 +13783,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 +13901,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 +13993,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 +14178,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 +14460,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; } } @@ -14491,7 +14675,7 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id) if(maxlv > lv) maxlv = lv; - sc_start4(&sd->bl,SC_AUTOSPELL,100,skill_lv,skill_id,maxlv,0, + sc_start4(&sd->bl,&sd->bl,SC_AUTOSPELL,100,skill_lv,skill_id,maxlv,0, skill->get_time(SA_AUTOSPELL,skill_lv)); return 0; } @@ -14699,6 +14883,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 +14919,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 +15028,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 +15082,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))) { @@ -14973,19 +15144,19 @@ int skill_trap_splash(struct block_list *bl, va_list ap) { break; case UNT_GROUNDDRIFT_WIND: if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_STUN,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(src,bl,SC_STUN,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_DARK: if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_BLIND,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(src,bl,SC_BLIND,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_POISON: if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_POISON,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(src,bl,SC_POISON,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_WATER: if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(src,bl,SC_FREEZE,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_FIRE: if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) @@ -14999,11 +15170,13 @@ int skill_trap_splash(struct block_list *bl, va_list ap) { case UNT_MAIZETRAP: case UNT_VERDURETRAP: if( bl->type != BL_PC && !is_boss(bl) ) - 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)); + sc_start2(ss,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 +15217,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 +15340,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 +15371,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 +15429,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 +15857,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 +15916,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 +16463,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,8 +16908,9 @@ 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 + sc_start4(&sd->bl, &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)); return 0; @@ -16865,7 +16998,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { if( !pc->checkskill(sd, (skill_id = skill->spellbook_db[i].skill_id)) ) { // User don't know the skill - sc_start(&sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB))); + sc_start(&sd->bl, &sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB))); clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); return 0; } @@ -16881,13 +17014,13 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] if( !sc->data[i] ){ sc->data[SC_READING_SB]->val2 += point; // increase points - sc_start4(&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); + sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); break; } } }else{ - sc_start2(&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); - sc_start4(&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); + sc_start2(&sd->bl,&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); + sc_start4(&sd->bl,&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); } return 1; @@ -16912,7 +17045,7 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { lv = (aslvl + 1) / 2; // The level the skill will be autocasted lv = min(lv,sd->status.skill[idx].lv); prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15. - sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl)); + sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl)); return 0; } int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, unsigned short* item_list) { @@ -17604,7 +17737,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 +18546,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 +18603,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..f4991cff2 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] @@ -1233,7 +1236,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, if (sc->data[SC_AUTOBERSERK] && (!sc->data[SC_PROVOKE] || !sc->data[SC_PROVOKE]->val2) && st->hp < st->max_hp>>2) - sc_start4(target,SC_PROVOKE,100,10,1,0,0,0); + sc_start4(src,target,SC_PROVOKE,100,10,1,0,0,0); if (sc->data[SC_BERSERK] && st->hp <= 100) status_change_end(target, SC_BERSERK, INVALID_TIMER); if( sc->data[SC_RAISINGDRAGON] && st->hp <= 1000 ) @@ -1309,7 +1312,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, status->revive(target, sc->data[SC_KAIZEL]->val2, 0); status->change_clear(target,0); clif->skill_nodamage(target,target,ALL_RESURRECTION,1,1); - sc_start(target,status->skill2sc(PR_KYRIE),100,10,time); + sc_start(target,target,status->skill2sc(PR_KYRIE),100,10,time); if( target->type == BL_MOB ) ((TBL_MOB*)target)->state.rebirth = 1; @@ -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]) @@ -6181,18 +6261,33 @@ void status_change_init(struct block_list *bl) { //Applies SC defense to a given status change. //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) { +int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) { //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, maxlv, factor) 0 +#endif //Status that are blocked by Golden Thief Bug card or Wand of Hermod if (status->isimmune(bl)) @@ -6234,53 +6329,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 +6478,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 +6489,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 +6582,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 +6600,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 +6616,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 +6637,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 +6653,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) { @@ -6514,7 +6726,7 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) { * &4: sc_data loaded, no value has to be altered. * &8: rate should not be reduced *------------------------------------------*/ -int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) { +int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) { struct map_session_data *sd = NULL; struct status_change* sc; struct status_change_entry* sce; @@ -6549,12 +6761,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 +6782,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 +6790,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; } } @@ -6596,7 +6829,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //Adjust tick according to status resistances if( !(flag&(1|4)) ) { - tick = status->get_sc_def(bl, type, rate, tick, flag); + tick = status->get_sc_def(src, bl, type, rate, tick, flag); if( !tick ) return 0; } @@ -6616,6 +6849,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 +6860,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 +6872,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 +7115,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 +7170,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 +7197,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 +7262,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 +7334,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 +7382,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 +7442,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 +7458,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 +7525,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(src,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 @@ -7293,10 +7540,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val int i; for( i = 0; i < 5; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); } } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); } //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) if( val4 ) @@ -7305,7 +7552,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_AUTOBERSERK: if (st->hp < st->max_hp>>2 && (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) - sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); + sc_start4(src,bl,SC_PROVOKE,100,10,1,0,0,60000); tick = -1; break; case SC_CRUCIS: @@ -7335,7 +7582,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 @@ -7381,10 +7637,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val int i; for( i = 0; i < 5; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } break; case SC_NOEQUIPWEAPON: @@ -7520,9 +7776,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if (st->hp - diff < st->max_hp>>2) diff = st->hp - (st->max_hp>>2); if( val2 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(val2); - if( src ) - mob->log_damage((TBL_MOB*)bl,src,diff); + struct block_list* src2 = map->id2bl(val2); + if( src2 ) + mob->log_damage((TBL_MOB*)bl,src2,diff); } status_zap(bl, diff, 0); } @@ -7637,11 +7893,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( sd ) { for( i = 0; i < 5; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status->change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } } break; @@ -7658,7 +7914,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val for (i = 0; i < 5; i++) { //See if there are devoted characters, and pass the status to them. [Skotlex] if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i]))) - status->change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); } } } @@ -7685,14 +7941,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_JOINTBEAT: if( val2&BREAK_NECK ) - sc_start2(bl,SC_BLOODING,100,val1,val3,skill->get_time2(status->sc2skill(type),val1)); + sc_start2(src,bl,SC_BLOODING,100,val1,val3,skill->get_time2(status->sc2skill(type),val1)); break; case SC_BERSERK: if( val3 == SC__BLOODYLUST ) - sc_start(bl,(sc_type)val3,100,val1,tick); + sc_start(src,bl,(sc_type)val3,100,val1,tick); if( !val3 && !(!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) ) - sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); + sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, tick); //HP healing is performing after the calc_status call. //Val2 holds HP penalty if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); @@ -7785,7 +8041,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val while( i >= 0 ) { type2 = types[i]; if( d_sc->data[type2] ) - sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1)); + sc_start(bl, bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1)); i--; } } @@ -7794,25 +8050,25 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp if( val3 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(val3); - if( src ) - mob->log_damage((TBL_MOB*)bl,src,st->hp - 1); + struct block_list* src2 = map->id2bl(val3); + if( src2 ) + mob->log_damage((TBL_MOB*)bl,src2,st->hp - 1); } status_zap(bl, st->hp-1, val2 ? 0 : st->sp); return 1; break; case SC_RG_CCONFINE_S: { - struct block_list *src = val2 ? map->id2bl(val2) : NULL; - struct status_change *sc2 = src ? status->get_sc(src) : NULL; + struct block_list *src2 = val2 ? map->id2bl(val2) : NULL; + struct status_change *sc2 = src ? status->get_sc(src2) : NULL; struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL; - if (src && sc2) { + if (src2 && sc2) { if (!sce2) //Start lock on caster. - sc_start4(src,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); + sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); else { //Increase count of locked enemies and refresh time. (sce2->val2)++; timer->delete(sce2->timer, status->change_timer); - sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src->id, SC_RG_CCONFINE_M); + sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M); } } else //Status failed. return 0; @@ -7910,7 +8166,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 5*val1; //Batk/Watk Increase val3 = 10*val1; //Hit Increase val4 = 5*val1; //Def reduction - sc_start(bl, SC_ENDURE, 100, 1, tick); //Endure effect + sc_start(src, bl, SC_ENDURE, 100, 1, tick); //Endure effect break; case SC_ANGELUS: val2 = 5*val1; //def increase @@ -8159,8 +8415,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; @@ -8171,7 +8427,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick_time = 4000; // [GodLesZ] tick time break; case SC_PYREXIA: - status->change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds + status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds val4 = tick / 3000; tick_time = 3000; // [GodLesZ] tick time break; @@ -8212,7 +8468,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 +8489,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 +8515,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 +8533,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; @@ -8301,8 +8565,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC__WEAKNESS: val2 = 10 * val1; // bypasses coating protection and MADO - sc_start(bl,SC_NOEQUIPWEAPON,100,val1,tick); - sc_start(bl,SC_NOEQUIPSHIELD,100,val1,tick); + sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,tick); + sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,tick); break; case SC_GN_CARTBOOST: if( val1 < 3 ) @@ -8327,31 +8591,25 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_BLOOD_SUCKER: { - struct block_list *src = map->id2bl(val2); + struct block_list *src2 = map->id2bl(val2); val3 = 1; - if(src) - val3 = 200 + 100 * val1 + status_get_int(src); + if(src2) + val3 = 200 + 100 * val1 + status_get_int(src2); val4 = tick / 1000; 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 +8623,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 +8664,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 +8706,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 +8724,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; @@ -8476,25 +8740,28 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_GENTLETOUCH_CHANGE: {// take note there is no def increase as skill desc says. [malufett] - struct block_list * src; + struct block_list * src2; val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if( (src = map->id2bl(val2)) ){ - val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] - val2 = ( status_get_dex(src)/4 + status_get_str(src)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] + if( (src2 = map->id2bl(val2)) ){ + val4 = ( 200/status_get_int(src2) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + val2 = ( status_get_dex(src2)/4 + status_get_str(src2)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] } } break; case SC_GENTLETOUCH_REVITALIZE: {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] - struct block_list * src; + struct block_list * src2; val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % - if( (src = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently - val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] + if( (src2 = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently + val4 = ( status_get_vit(src2)/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 +8772,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 +8784,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 +8794,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 +8813,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 +8828,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. @@ -8657,7 +8928,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 2*val1; //aspd reduction % val3 = 2*val1; //dmg reduction % if(sc->data[SC_NEEDLE_OF_PARALYZE]) - sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + sc_start(src, bl, SC_ENDURE, 100, val1, tick); //start endure for same duration break; case SC_STYLE_CHANGE: //[Lighta] need real info tick = -1; @@ -8684,10 +8955,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 +9136,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 +9163,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 +9221,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 +9231,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 +9335,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 +9644,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) { @@ -9404,7 +9682,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const && DIFF_TICK(timer->gettick(), starttick) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) - sc_start(bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1)); + sc_start(bl, bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1)); } break; case SC_AUTOBERSERK: @@ -9599,7 +9877,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); @@ -9609,9 +9886,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->data[SC_ENDURE]->val4 = 0; status_change_end(bl, SC_ENDURE, INVALID_TIMER); } - sc_start4(bl, SC_GDSKILL_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1)); + sc_start4(bl, bl, SC_GDSKILL_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1)); if( type == SC_SATURDAY_NIGHT_FEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. - sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); + sc_start(bl,bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); break; case SC_GOSPEL: if (sce->val3) { //Clear the group. @@ -9670,9 +9947,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; @@ -9686,7 +9964,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const clif->millenniumshield(bl,0); break; case SC_HALLUCINATIONWALK: - sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1)); + sc_start(bl,bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1)); break; case SC_WHITEIMPRISON: { @@ -9782,7 +10060,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const calc_flag = SCB_ALL;/* required for overlapping */ break; case SC_FULL_THROTTLE: - sc_start(bl,SC_REBOUND,100,sce->val1,skill->get_time2(ALL_FULL_THROTTLE,sce->val1)); + sc_start(bl,bl,SC_REBOUND,100,sce->val1,skill->get_time2(ALL_FULL_THROTTLE,sce->val1)); break; case SC_MONSTER_TRANSFORM: if( sce->val2 ) @@ -9811,12 +10089,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 +10110,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 +10120,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 +10258,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); @@ -10109,7 +10387,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; //Not enough SP to continue. if (!sc->data[SC_CHASEWALK2]) { - sc_start(bl, SC_CHASEWALK2,100,1<<(sce->val1-1), + sc_start(bl,bl, SC_CHASEWALK2,100,1<<(sce->val1-1), (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration * skill->get_time2(status->sc2skill(type),sce->val1)); } @@ -10495,7 +10773,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 +10841,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 +10861,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 +10879,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 +10895,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 +10923,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 +10976,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 +10992,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 +11024,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 +11036,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 +11153,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 +11190,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 +11406,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; @@ -11205,7 +11500,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { data.val2 = sc->data[i]->val2; data.val3 = sc->data[i]->val3; data.val4 = sc->data[i]->val4; - status->change_start(bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8); + status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8); flag = 1; } } @@ -11378,7 +11673,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { val*=2; sd->state.doridori = 0; if ((rate = pc->checkskill(sd,TK_SPTIME))) - sc_start(bl,status->skill2sc(TK_SPTIME), + sc_start(bl,bl,status->skill2sc(TK_SPTIME), 100,rate,skill->get_time(TK_SPTIME, rate)); if ((sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&rnd()%10000 < battle_config.sg_angel_skill_ratio @@ -11673,7 +11968,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..06bea3908 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, @@ -1833,9 +1836,9 @@ struct status_change { #define status_get_mode(bl) (status->get_status_data(bl)->mode) //Short version, receives rate in 1->100 range, and does not uses a flag setting. -#define sc_start(bl, type, rate, val1, tick) (status->change_start((bl),(type),100*(rate),(val1),0,0,0,(tick),0)) -#define sc_start2(bl, type, rate, val1, val2, tick) (status->change_start((bl),(type),100*(rate),(val1),(val2),0,0,(tick),0)) -#define sc_start4(bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),0)) +#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),0)) +#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),0)) +#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),0)) #define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid),__FILE__,__LINE__)) @@ -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); @@ -1932,8 +1936,8 @@ struct status_interface { struct status_change * (*get_sc) (struct block_list *bl); int (*isdead) (struct block_list *bl); int (*isimmune) (struct block_list *bl); - int (*get_sc_def) (struct block_list *bl, enum sc_type type, int rate, int tick, int flag); - int (*change_start) (struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); + int (*get_sc_def) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag); + int (*change_start) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag); int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line); int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer) (int tid, int64 tick, int id, intptr_t data); diff --git a/src/map/unit.c b/src/map/unit.c index 320649a6c..2926661ad 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] @@ -1012,10 +1012,10 @@ int unit_resume_running(int tid, int64 tick, int id, intptr_t data) { if(sd && pc_isridingwug(sd)) clif->skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv, - sc_start4(ud->bl,status->skill2sc(RA_WUGDASH),100,ud->skill_lv,unit->getdir(ud->bl),0,0,1)); + sc_start4(ud->bl,ud->bl,status->skill2sc(RA_WUGDASH),100,ud->skill_lv,unit->getdir(ud->bl),0,0,1)); else clif->skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv, - sc_start4(ud->bl,status->skill2sc(TK_RUN),100,ud->skill_lv,unit->getdir(ud->bl),0,0,0)); + sc_start4(ud->bl,ud->bl,status->skill2sc(TK_RUN),100,ud->skill_lv,unit->getdir(ud->bl),0,0,0)); if (sd) clif->walkok(sd); @@ -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); |