diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 276 |
1 files changed, 252 insertions, 24 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 976f50bd4..26d812d86 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -311,7 +311,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill // Calculate base heal rate hp = ( ( ( status_get_lv(src) + status_get_int(src) ) / 5) * 30 ) * skill / 10; - // Increment skill and status based modifiers + // Increment heal by skill/type modifiers if( sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) ) mod += skill * 2; else if( src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 ) @@ -319,7 +319,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill break; } - // Increment skill and status based modifiers + // Increment heal by item-based modifiers if( sd && (skill = pc_skillheal_bonus(sd, skill_id)) ) mod += skill; if( tsd && (skill = pc_skillheal2_bonus(tsd, skill_id)) ) @@ -332,8 +332,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill mod -= sc->data[SC_CRITICALWOUND]->val2; if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN ) mod += sc->data[SC_INCHEALRATE]->val1; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish] -// if( sc->data[SC_VITALITYACTIVATION] && heal && skill_id != BA_APPLEIDUN ) -// mod += sc->data[SC_VITALITYACTIVATION]->val2; + if( sc->data[SC_VITALITYACTIVATION] && heal && skill_id != BA_APPLEIDUN ) + mod += sc->data[SC_VITALITYACTIVATION]->val2; } // Adjust the HP recovered rate by adding all of the modifiers together. @@ -981,9 +981,19 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case NPC_CRITICALWOUND: sc_start(bl,SC_CRITICALWOUND,100,skilllv,skill_get_time2(skillid,skilllv)); break; + case RK_WINDCUTTER: + sc_start(bl,SC_FEAR,3+2*skilllv,skilllv,skill_get_time(skillid,skilllv)); + break; + case RK_DRAGONBREATH: + sc_start4(bl,SC_BURNING,15,skilllv,src->id,0,0,skill_get_time(skillid,skilllv)); + break; case AB_ADORAMUS: - sc_start(bl, SC_BLIND, 100, skilllv, skill_get_time(skillid, skilllv)); - sc_start(bl, SC_ADORAMUS, 100, skilllv, skill_get_time2(skillid, skilllv)); + if ( sd ) + { + int rate = (skilllv*4) + sd->status.job_level / 2; + sc_start(bl, SC_BLIND, rate, skilllv, skill_get_time(skillid, skilllv)); + sc_start(bl, SC_ADORAMUS, rate, skilllv, skill_get_time2(skillid, skilllv)); + } break; } @@ -1734,8 +1744,19 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if( damage > 0 && dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) ) && skillid != WS_CARTTERMINATION ) - rdamage = battle_calc_return_damage(bl, damage, dmg.flag); - + { + if( sc && sc->data[SC_DEATHBOUND] && !is_boss(bl) && map_check_dir(map_calc_dir(src,bl->x,bl->y),unit_getdir(bl))) + { + int skilllv = sc->data[SC_DEATHBOUND]->val1; + clif_skill_damage(src,src, tick, 0, 0, 0, 0, RK_DEATHBOUND,-1, 1); + rdamage = damage * ((500 + 100*skilllv) / 100); + damage = rdamage * 70 / 100; + skill_blown(src, src, skill_get_blewcount(skillid,skilllv), unit_getdir(src), 0); + status_change_end(dsrc,SC_DEATHBOUND,INVALID_TIMER); + } + else + rdamage = battle_calc_return_damage(bl, damage, dmg.flag); + } //Skill hit type type=(skillid==0)?5:skill_get_hit(skillid); @@ -1851,6 +1872,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case NPC_CRITICALSLASH: case TF_DOUBLE: case GS_CHAINACTION: + case RK_DEATHBOUND: dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); break; @@ -1994,6 +2016,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); } + if( damage > 0 && skillid == RK_CRUSHSTRIKE ) + skill_break_equip(src,EQP_WEAPON,2000,BCT_SELF); + if (!(flag&2) && ( skillid == MG_COLDBOLT || skillid == MG_FIREBOLT || skillid == MG_LIGHTNINGBOLT @@ -2402,6 +2427,16 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) } } break; + case RK_HUNDREDSPEAR: + if(src->type == BL_PC) + { + int skill_lv = pc_checkskill((struct map_session_data *)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; default: skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); break; @@ -2625,6 +2660,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case NPC_BLEEDING: case NPC_CRITICALWOUND: case NPC_HELLPOWER: + case RK_SONICWAVE: + case RK_WINDCUTTER: case AB_DUPLELIGHT_MELEE: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; @@ -3068,6 +3105,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case NPC_SMOKING: case GS_FLING: case NJ_ZENYNAGE: + case RK_DRAGONBREATH: skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); break; @@ -3124,6 +3162,18 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int status_change_end(src, SC_HIDING, INVALID_TIMER); skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; + + case RK_HUNDREDSPEAR: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + if(rand()%100 < (10 + 3*skilllv)) { + skill_blown(src,bl,6,-1,0); + skill_addtimerskill(src,tick+800,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag); + } + break; + case RK_CRUSHSTRIKE: + if( sd ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; case 0: if(sd) { if (flag & 3){ @@ -3371,9 +3421,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AL_DECAGI: case MER_DECAGI: - if (skilllv >= battle_config.max_decagi_lv) + if (skilllv = battle_config.max_decagi_lv) clif_skill_nodamage (src, bl, skillid, skilllv, - sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), (battle_config.max_decagi - 2), (battle_config.max_decagi_dur * 100))); + sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), (battle_config.max_decagi - 2), battle_config.max_decagi_dur)); else clif_skill_nodamage (src, bl, skillid, skilllv, sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv))); @@ -3729,6 +3779,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case ST_PRESERVE: case NPC_INVINCIBLE: case NPC_INVINCIBLEOFF: + case RK_DEATHBOUND: + case RK_MILLENNIUMSHIELD: + case RK_CRUSHSTRIKE: + case RK_GIANTGROWTH: + case RK_STONEHARDSKIN: + case RK_VITALITYACTIVATION: + case RK_ABUNDANCE: case AB_RENOVATIO: case AB_EXPIATIO: case AB_DUPLELIGHT: @@ -4099,6 +4156,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case BS_ADRENALINE2: case BS_WEAPONPERFECT: case BS_OVERTHRUST: + case RK_FIGHTINGSPIRIT: //Splash range in skill_db is 0, should be map-wide according to party_foreachsamemap if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { clif_skill_nodamage(bl,bl,skillid,skilllv, sc_start2(bl,type,100,skilllv,(src == bl)? 1:0,skill_get_time(skillid,skilllv))); @@ -5743,6 +5801,74 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS)); } break; + case RK_ENCHANTBLADE: + i = status_get_int(src) + status_get_lv(src) / 10; + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,i,skill_get_time(skillid,skilllv))); + break; + case RK_IGNITIONBREAK: + if(flag&1) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + else + { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_nodamage_id); + } + break; + case RK_DRAGONHOWLING: + if(flag&1) + sc_start(bl,SC_FEAR,50 + skilllv * 6,skilllv,skill_get_time2(skillid,skilllv)); + else + { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_nodamage_id); + } + break; + case RK_REFRESH: + { + int heal = sstatus->max_hp * 25 / 100; + status_heal(bl,heal,0,0); + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + status_change_clear_buffs(bl,6); + } + break; + case RK_STORMBLAST: + if( flag&1 ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + else + { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_nodamage_id); + } + break; + case RK_PHANTOMTHRUST: + if(battle_check_target(src,bl,BCT_ENEMY) > 0 || battle_check_target(src,bl,BCT_PARTY) > 0) + { + if(!map[bl->m].flag.gvg && !map[bl->m].flag.battleground && !(status_get_mode(bl)&MD_BOSS)) + { + int x = 0, y = 0; + if(bl->x > src->x) x = 1; + else if(bl->x < src->x) x = -1; + if(bl->y >= src->y) y = 1; + else if(bl->y < src->y) y = -1; + unit_movepos(bl, src->x+x, src->y+y, 1, 0); + clif_slide(bl,src->x+x, src->y+y); + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (battle_check_target(src,bl,BCT_ENEMY) > 0 ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + } + break; case AB_ANCILLA: if(sd) { if (skill_produce_mix(sd, skillid, 12333, 0, 0, 0, 1)) @@ -5774,6 +5900,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in int heal = skill_calc_heal(src, bl, AL_HEAL, lv, true); if( status_isimmune(bl) ) heal = 0; + + if( sd->status.party_id && (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) + heal += ((heal / 100) * (i * 10) / 4); + clif_skill_nodamage(bl, bl, skillid, heal, 1); status_heal(bl, heal, 0, 0); } @@ -5786,15 +5916,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in { if( dstsd && dstsd->special_state.no_magic_damage ) break; - clif_skill_nodamage(bl, bl, skillid, skilllv, - sc_start4(bl, type, 100, skilllv, 0, 0, 1, skill_get_time(skillid, skilllv))); + + if ( sd && sd->status.party_id && (i = party_foreachsamemap(party_sub_count, sd, 0)) > 0) + { + clif_skill_nodamage(bl, bl, skillid, skilllv, + sc_start4(bl, type, 100, skilllv, 0, 0, i, skill_get_time(skillid, skilllv))); + } } else party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); break; case AB_ORATIO: if (flag&1) - sc_start(bl, type, 40+skilllv*5, skilllv, skill_get_time(skillid, skilllv)); + sc_start(bl, type, 40+5*skilllv, skilllv, skill_get_time(skillid, skilllv)); else { clif_skill_nodamage(src, bl, skillid, skilllv, 1); @@ -5808,30 +5942,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AB_LAUDARAMUS: if( (flag&1) || sd == NULL || sd->status.party_id == 0 ) { - if( tsc && (rand()%100 < 30+5*skilllv) ) + if( tsc && (rand()%100 < 40+10*skilllv) ) { switch(skillid) { case AB_LAUDAAGNUS: - if( tsc->data[SC_STONE] || tsc->data[SC_FREEZE] || tsc->data[SC_BLIND] ) + if( tsc->data[SC_STONE] || tsc->data[SC_FREEZE] || tsc->data[SC_BLIND] ) //TODO: Freezing, Crystallization and Burning { status_change_end(bl, SC_STONE, INVALID_TIMER); status_change_end(bl, SC_FREEZE, INVALID_TIMER); status_change_end(bl, SC_BLIND, INVALID_TIMER); } + else + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); break; case AB_LAUDARAMUS: - if( tsc->data[SC_STUN] || tsc->data[SC_SLEEP] || tsc->data[SC_SILENCE] ) + if( tsc->data[SC_STUN] || tsc->data[SC_SLEEP] || tsc->data[SC_SILENCE] ) // TODO: Howling of Mandragora, and Deep Sleep { status_change_end(bl, SC_STUN, INVALID_TIMER); status_change_end(bl, SC_SLEEP, INVALID_TIMER); status_change_end(bl, SC_SILENCE, INVALID_TIMER); } + else + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); break; } } - clif_skill_nodamage(bl, bl, skillid, skilllv, - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); } else if( sd ) party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), @@ -5839,7 +5975,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case AB_CLEARANCE: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if( rand()%100 >= 50+10*skilllv ) + if( rand()%100 >= 60+10*skilllv ) { if (sd) clif_skill_fail(sd,skillid,0,0); @@ -5903,7 +6039,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE: case SC_SERVICE4U: case SC_PARTYFLEE: /*case SC_ANGEL_PROTECT:*/ - case SC_EPICLESIS: + case SC_EPICLESIS: case SC_DEATHBOUND: case SC_FIGHTINGSPIRIT: + case SC_ABUNDANCE: case SC_MILLENNIUMSHIELD: // not implemented //case SC_BUCHEDENOEL: case SC_POPECOOKIE: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: @@ -6801,6 +6938,23 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk } break; + case RK_WINDCUTTER: + i = skill_get_splash(skillid, skilllv); + clif_skill_damage(src, src, tick, 0, 0, -1, 1, skillid, -1, 0); + map_foreachinarea(skill_area_sub, + src->m,x-i,y-i,x+i,y+i,(BL_CHAR|BL_SKILL), + src,skillid,skilllv,tick,flag|BCT_ENEMY|1, + skill_castend_damage_id); + break; + + case RK_DRAGONBREATH: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_area_sub, + src->m,x-i,y-i,x+i,y+i,(BL_CHAR|BL_SKILL), + src,skillid,skilllv,tick,flag|BCT_ENEMY|1, + skill_castend_damage_id); + break; + case AB_EPICLESIS: if( skill_unitsetting(src, skillid, skilllv, x, y, 0) ) { @@ -6862,7 +7016,8 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char sd->sc.data[SC_DANCING] || sd->sc.data[SC_BERSERK] || sd->sc.data[SC_BASILICA] || - sd->sc.data[SC_MARIONETTE] + sd->sc.data[SC_MARIONETTE] || + sd->sc.data[SC_DEATHBOUND] )) { skill_failed(sd); return 0; @@ -8960,13 +9115,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh clif_skill_fail(sd,skill,0,0); return 0; break; -/* case ST_DRAGON: if(!pc_isdragon(sd)) { clif_skill_fail(sd,skill,25,0); return 0; } break; +/* case ST_WARG: if(!pc_iswarg(sd)) { clif_skill_fail(sd,skill,0,0); @@ -11274,12 +11429,32 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in } } + if(skill_id == RK_RUNEMASTERY) + { // Now we figure out how many runes we're going to make. :3 + int skill_lv = pc_checkskill(sd,skill_id); + if( skill_lv > 4 && skill_lv < 10) // level 5~9 can make 1~2 runes + qty=(rand()%2)+1; + else if( skill_lv == 10 ) // Level 10 can make 1~3 runes + qty=(rand()%3)+1; + + // Check to see if the amount of runes will exceed 20. + i = pc_search_inventory(sd,nameid); + if( i >= 0 && sd->status.inventory[i].amount+qty > 20 ) // Cancel creation if created stones will exceed 20. + { + clif_msg(sd,0x61b); + return 0; + } + } + for(i=0;i<MAX_PRODUCE_RESOURCE;i++){ int j,id,x; if( (id=skill_produce_db[idx].mat_id[i]) <= 0 ) continue; num++; - x=qty*skill_produce_db[idx].mat_amount[i]; + if (skill_id == RK_RUNEMASTERY) + x=skill_produce_db[idx].mat_amount[i]; // RK_RUNEMASTERY only uses one set of required items, even if making more than 1 item + else + x=qty*skill_produce_db[idx].mat_amount[i]; do{ int y=0; j = pc_search_inventory(sd,id); @@ -11372,8 +11547,57 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in make_per = make_per * battle_config.pp_rate / 100; break; case SA_CREATECON: // Elemental Converter Creation + case AB_ANCILLA: // Ancilla Creation make_per = 100000; // should be 100% success rate break; + case RK_RUNEMASTERY: //Information from iROWiki and RuneItemInfo.lua + { + int skill_lv = pc_checkskill(sd,skill_id); + + make_per = 5100 + 20 * skill_lv; // Base chance. + + //Take stats into account before applying non-modified values. + make_per += (status->dex / 30 + status->luk / 10) + sd->status.job_level / 10 * 100; + + switch(sd->produce_itemusedid) + { // Add success rate based on what type of stone is used. + case 12737: + make_per += 200; break; + case 12734: + make_per += 500; break; + case 12738: + make_per += 800; break; + case 12735: + make_per += 1100; break; + case 12736: + make_per += 1400; break; + default: + break; + } + sd->produce_itemusedid = 0; + + switch(nameid) + { // Reduce success rate based on what rank stone we're making. + case 12727: // Runstone_Verkana + make_per -= 2000; // S Class + break; + case 12725: // Runstone_Nosiege + case 12730: // Runstone_Urj + make_per -= 1500; // A Rank + break; + case 12728: // Runstone_Isia + case 12732: // Runstone_Pertz + make_per -= 1000; // B Rank + break; + case 12726: // Runstone_Rhydo + case 12729: // Runstone_Asir + case 12731: // Runstone_Turisus + case 12733: // Runstone_Hagalas + make_per -= 500; // C Rank + break; + } + break; + } default: if (sd->menuskill_id == AM_PHARMACY && sd->menuskill_val > 10 && sd->menuskill_val <= 20) @@ -11412,7 +11636,6 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in if(make_per < 1) make_per = 1; - if(rand()%10000 < make_per || qty > 1){ //Success, or crafting multiple items. struct item tmp_item; memset(&tmp_item,0,sizeof(tmp_item)); @@ -11512,6 +11735,7 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in case AM_TWILIGHT2: case AM_TWILIGHT3: case ASC_CDP: + case RK_RUNEMASTERY: clif_produceeffect(sd,2,nameid); clif_misceffect(&sd->bl,5); break; @@ -11565,6 +11789,10 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in clif_produceeffect(sd,1,nameid); clif_misceffect(&sd->bl,2); break; + case RK_RUNEMASTERY: + clif_produceeffect(sd,3,nameid); + clif_misceffect(&sd->bl,6); + break; default: if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 ) { //Cooking items. |