diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 144 |
1 files changed, 100 insertions, 44 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index d0325fc4e..7d5f0d021 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -433,16 +433,12 @@ 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) || (skill_id >= KO_YAMIKUMO && skill_id <= OB_AKAITSUKI))) + if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE))) 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)] ) return 0; - //Never copy new 3rd class skills By OmegaRed - if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE) - return 0; - return 1; } @@ -842,9 +838,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 #ifdef RENEWAL 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% + //On third hit, there is a 150% to freeze the target if(tsc->sg_counter >= 3 && - sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv))) + sc_start(src,bl,SC_FREEZE,150,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 @@ -1010,7 +1006,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case LK_SPIRALPIERCE: case ML_SPIRALPIERCE: - sc_start(src,bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv)); + if( dstsd || ( dstmd && !is_boss(bl) ) ) //Does not work on bosses + sc_start(src,bl,SC_STOP,100,0,skill_get_time2(skill_id,skill_lv)); break; case ST_REJECTSWORD: @@ -1210,6 +1207,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 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_HESPERUSLIT: + if ( sc && sc->data[SC_BANDING] ) { + if ( sc->data[SC_BANDING]->val2 == 4 ) // 4 banding RGs: Targets will be stunned at 100% chance for 4 ~ 8 seconds, irreducible by STAT. + status->change_start(src, bl, SC_STUN, 10000, skill_lv, 0, 0, 0, 1000*(4+rand()%4), 2); + else if ( sc->data[SC_BANDING]->val2 == 6 ) // 6 banding RGs: activate Pinpoint Attack Lv1-5 + skill->castend_damage_id(src,bl,LG_PINPOINTATTACK,1+rand()%5,tick,0); + } + break; case LG_PINPOINTATTACK: rate = 30 + 5 * (sd ? pc->checkskill(sd,LG_PINPOINTATTACK) : 1) + (sstatus->agi + status->get_lv(src)) / 10; switch( skill_lv ) { @@ -1667,6 +1672,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b int rate; struct map_session_data *sd=NULL; struct map_session_data *dstsd=NULL; + struct status_change *sc; nullpo_ret(src); nullpo_ret(bl); @@ -1675,6 +1681,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b sd = BL_CAST(BL_PC, src); dstsd = BL_CAST(BL_PC, bl); + sc = status->get_sc(src); if(dstsd && attack_type&BF_WEAPON) { //Counter effects. @@ -1723,6 +1730,13 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b case NPC_GRANDDARKNESS: attack_type |= BF_WEAPON; break; + case LG_HESPERUSLIT: + if ( sc && sc->data[SC_FORCEOFVANGUARD] && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 6 ) { + char i; + for( i = 0; i < sc->data[SC_FORCEOFVANGUARD]->val3; i++ && sc->fv_counter <= sc->data[SC_FORCEOFVANGUARD]->val3 ) + clif->millenniumshield(bl, sc->fv_counter++); + } + break; } if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR @@ -4068,7 +4082,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,src,SC_STUN,10000,skill_lv,0,0,0,500,2); + 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; } @@ -4507,7 +4521,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 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),0); + 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); @@ -5184,7 +5198,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(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),0) ){ + 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; @@ -6213,7 +6227,7 @@ 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,src,SC_STUN,10000,skill_lv,0,0,0,500,0); + 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; } @@ -6261,25 +6275,24 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case GC_CLOAKINGEXCEED: case LG_FORCEOFVANGUARD: case SC_REPRODUCE: + case RA_CAMOUFLAGE: if (tsce) { int failure = status_change_end(bl, type, INVALID_TIMER); if( failure ) clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure); else if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - if ( skill_id == LG_FORCEOFVANGUARD ) + if ( skill_id == LG_FORCEOFVANGUARD || skill_id == RA_CAMOUFLAGE ) break; map->freeblock_unlock(); return 0; + } else { + 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 ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - case RA_CAMOUFLAGE: - { - 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 ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } break; case BD_ADAPTATION: @@ -6360,7 +6373,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (tsc->data[SC_STONE]) { status_change_end(bl, SC_STONE, INVALID_TIMER); - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; } if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate, @@ -6732,7 +6745,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin sp += sp * i / 100; } } else { - hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100; + //Maybe replace with potion_hp, but I'm unsure how that works [Playtester] + switch (skill_lv) { + case 1: hp = 45; break; + case 2: hp = 105; break; + case 3: hp = 175; break; + default: hp = 325; break; + } + hp = (hp + rnd()%(skill_lv*20+1)) * (150 + skill_lv*10) / 100; hp = hp * (100 + (tstatus->vit<<1)) / 100; if( dstsd ) hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; @@ -7265,7 +7285,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 0; } else - status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),0); + status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); } break; @@ -7671,7 +7691,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (tsce) { if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,0); + status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,8); status_change_end(bl, SC_SWOO, INVALID_TIMER); break; } @@ -7679,7 +7699,7 @@ 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,src,SC_STUN,10000,skill_lv,0,0,0,500,2); + 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(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); @@ -8646,13 +8666,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin //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 regardless of resistance. case 0: - status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),2); + 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),2); + 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),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 ) @@ -9547,8 +9567,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl)); status->heal(bl, heal, 0, 0); clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1)); - status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2); - status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2); + status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8); + status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8); } break; @@ -11018,9 +11038,17 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ } break; case BA_ASSASSINCROSS: - val1 = 10 + skill_lv + (st->agi/10); // ASPD increase if(sd) - val1 += (pc->checkskill(sd,BA_MUSICALLESSON) + 1) / 2; + val1 = (pc->checkskill(sd,BA_MUSICALLESSON) + 1) / 2; +#ifdef RENEWAL + // This formula was taken from a RE calculator + // and the changes published on irowiki + // Luckily, official tests show it's the right one + val1 += skill_lv + (st->agi/20); +#else + val1 += 10 + skill_lv + (st->agi/10); // ASPD increase + val1 *= 10; // ASPD works with 1000 as 100% +#endif break; case DC_FORTUNEKISS: val1 = 10+skill_lv+(st->luk/10); // Critical increase @@ -11135,6 +11163,10 @@ 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: + val1 = x; + val2 = y; + break; case GN_WALLOFTHORN: if( flag&1 ) limit = 3000; @@ -11340,7 +11372,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(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,0) ) { + 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); @@ -11438,10 +11470,12 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick if (!sce) sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); break; + case UNT_APPLEIDUN: // Apple of idun gets it from skill_unit_onplace_timer + if (!battle_config.song_timer_reset) + break; case UNT_WHISTLE: case UNT_ASSASSINCROSS: case UNT_POEMBRAGI: - case UNT_APPLEIDUN: case UNT_HUMMING: case UNT_DONTFORGETME: case UNT_FORTUNEKISS: @@ -11452,12 +11486,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick if (!sc) return 0; if (!sce) sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - else if (sce->val4 == 1) { + else if (battle_config.song_timer_reset && sce->val4 == 1) { //Readjust timers since the effect will not last long. sce->val4 = 0; timer->delete(sce->timer, status->change_timer); sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type); } + break; case UNT_FOGWALL: @@ -11721,7 +11756,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(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 0) ) { + 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); @@ -11751,7 +11786,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(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 0) ) { + 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); @@ -11840,6 +11875,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 heal = ~heal + 1; clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); status->heal(bl, heal, 0, 0); + + if (!(battle_config.song_timer_reset) // songs don't reset prior timers + && !(sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) // Don't affect itself + && (!(tsc->data[type]) || (tsc->data[type] && tsc->data[type]->val4 != 1))) // Check for 20 seconds song effect + sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->interval + 100); + break; } @@ -12111,7 +12152,7 @@ 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(ss,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),8); skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; @@ -12156,11 +12197,16 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 break; case UNT_VACUUM_EXTREME: - if ( tsc && tsc->data[SC_HALLUCINATIONWALK] ) { + if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) { return 0; } else { sg->limit -= 100 * tstatus->str/20; sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit); + + if (unit->movepos(bl, sg->val1, sg->val2, 0, 0)) { + clif->slide(bl, sg->val1, sg->val2); + clif->fixpos(bl); + } } break; @@ -12205,7 +12251,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(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); + 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; } @@ -12264,6 +12310,16 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) } } break; + case UNT_WHISTLE: + case UNT_ASSASSINCROSS: + case UNT_POEMBRAGI: + case UNT_APPLEIDUN: + case UNT_HUMMING: + case UNT_DONTFORGETME: + case UNT_FORTUNEKISS: + case UNT_SERVICEFORYOU: + if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) + return -1; } return sg->skill_id; } @@ -12341,7 +12397,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { case DC_DONTFORGETME: case DC_FORTUNEKISS: case DC_SERVICEFORYOU: - if (sce) { + if ((battle_config.song_timer_reset && sce) || (!battle_config.song_timer_reset && sce && sce->val4 != 1)) { timer->delete(sce->timer, status->change_timer); //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... //not possible on our current implementation. @@ -12404,8 +12460,8 @@ int skill_unit_effect(struct block_list* bl, va_list ap) { } else { if( flag&1 ) skill->unit_onplace(su,bl,tick); - else - skill->unit_onout(su,bl,tick); + else if (skill->unit_onout(su,bl,tick) == -1) + return 0; // Don't let a Bard/Dancer update their own song timer if( flag&4 ) skill->unit_onleft(skill_id, bl, tick); |