diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 74 | ||||
-rw-r--r-- | src/map/skill.c | 123 | ||||
-rw-r--r-- | src/map/status.c | 79 |
3 files changed, 203 insertions, 73 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 17779241f..ad5f25d0a 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -325,8 +325,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i return 0; } - //Now damage increasing effects - if(sc->data[SC_AETERNA].timer!=-1 && skill_num != PA_PRESSURE && skill_num != PF_SOULBURN){ + //Now damage increasing effects // not sure for Throw Zeny + if(sc->data[SC_AETERNA].timer!=-1 && skill_num != PA_PRESSURE && skill_num != PF_SOULBURN && skill_num != NJ_ZENYNAGE){ damage<<=1; status_change_end( bl,SC_AETERNA,-1 ); } @@ -615,12 +615,12 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int if((skill = pc_checkskill(sd,AS_KATAR)) > 0) damage += (skill * 3); break; + case W_HUUMA: // Added Tobidougu bonus if wearing a Fuuma Shuriken + if((skill = pc_checkskill(sd,NJ_TOBIDOUGU)) >0) + damage += (skill * 3); + break; } -/*//need to add this on shuriken skills. - if((skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) { - damage += (skill * 3); - } -*/ + return damage; } /*========================================== @@ -633,6 +633,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int * &2: Arrow attack * &4: Skill is Magic Crasher * &8: Skip target size adjustment (Extremity Fist?) + *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) */ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) { @@ -666,7 +667,7 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk if (atkmin > atkmax) atkmin = atkmax; - if(flag&2) + if(flag&2 && !(flag&16)) { //Bows atkmin = atkmin*atkmax/100; if (atkmin > atkmax) @@ -1025,6 +1026,7 @@ static struct Damage battle_calc_weapon_attack( case NPC_MENTALBREAKER: case GS_GROUNDDRIFT: case NJ_TATAMIGAESHI: + case NJ_ISSEN: case HVAN_EXPLOSION: //[orn] flag.hit = 1; break; @@ -1186,10 +1188,19 @@ static struct Damage battle_calc_weapon_attack( default: { i = (flag.cri?1:0)|(flag.arrow?2:0)|(skill_num == HW_MAGICCRASHER?4:0)|(skill_num == MO_EXTREMITYFIST?8:0); + if ( flag.arrow && sd->status.weapon != W_BOW && sd->status.weapon != W_REVOLVER && sd->status.weapon != W_SHOTGUN + && sd->status.weapon != W_GATLING && sd->status.weapon != W_GRENADE ) i |= 16; // for ex. shuriken must not be influenced by DEX wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); if (sstatus->lhw) wd.damage2 = battle_calc_base_damage(sstatus, sstatus->lhw, sc, tstatus->size, sd, i); + // Added split damage for Huuma + if (skill_num == NJ_HUUMA) // Divide ATK in case of multiple targets skill + if(wflag>0) + wd.damage/= wflag; + else if(battle_config.error_log) + ShowError("0 enemies targeted by Throw Huuma, divide per 0 avoided!\n"); + //Add any bonuses that modify the base baseatk+watk (pre-skills) if(sd) { @@ -1698,6 +1709,26 @@ static struct Damage battle_calc_weapon_attack( if (flag.rh && wd.damage < 1) wd.damage = 1; if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; + // Added Tobidougu bonus on throwing weapon ninja skills if not wearing a Fuuma shuriken (bonus already added in battle_addmastery) + switch(skill_num) + { + case NJ_SYURIKEN: + if((skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0 && sd->status.weapon != W_HUUMA) { wd.damage+=skill*3+skill_lv*4; } + else {wd.damage+=skill_lv*4; } + break; + case NJ_KUNAI: + if((skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0 && sd->status.weapon != W_HUUMA) { wd.damage+=skill*3; } + break; + default: + break; + } + + if ( skill_num == NJ_ISSEN ) + { + wd.damage=sstatus->str*80+skill_lv*sstatus->hp*8/100; + status_zap(src, sstatus->hp-1, 0); + } + if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != CR_GRANDCROSS) { //Add mastery damage @@ -2050,6 +2081,7 @@ struct Damage battle_calc_magic_attack( struct map_session_data *sd, *tsd; struct Damage ad; + struct status_change *sc; struct status_data *sstatus = status_get_status_data(src); struct status_data *tstatus = status_get_status_data(target); struct { @@ -2166,6 +2198,8 @@ struct Damage battle_calc_magic_attack( //Adds an absolute value to damage. 100 = +100 damage #define MATK_ADD( a ) { ad.damage+= a; } + sc= status_get_sc(src); + switch (skill_num) { //Calc base damage according to skill case AL_HEAL: @@ -2281,16 +2315,20 @@ struct Damage battle_calc_magic_attack( skillratio -= 10; break; case NJ_BAKUENRYU: - skillratio += 50*(skill_lv-1); + skillratio += 50 + 150*skill_lv; break; + case NJ_HYOUSENSOU: + skillratio -= 30; + if ( sc->data[SC_SUITON].timer != -1 ) skillratio += skillratio*sc->data[SC_SUITON].val1*2/100; + break; case NJ_HYOUSYOURAKU: - skillratio += 50*skill_lv; + skillratio += 100 + 50*skill_lv; break; case NJ_RAIGEKISAI: skillratio += 60 + 40*skill_lv; break; case NJ_KAMAITACHI: - skillratio += 100*skill_lv; + skillratio += 100 + 100*skill_lv; break; } @@ -2471,6 +2509,7 @@ struct Damage battle_calc_misc_attack( switch(skill_num){ case PA_PRESSURE: case GS_FLING: + case NJ_ZENYNAGE: // Throw zeny not affected by cards, elements, race.. flag.elefix = flag.cardfix = 0; case HT_BLITZBEAT: case TF_THROWSTONE: @@ -2557,10 +2596,9 @@ struct Damage battle_calc_misc_attack( case NJ_ZENYNAGE: md.damage = skill_get_zeny(skill_num ,skill_lv); if (!md.damage) md.damage = 2; - md.damage = md.damage/2 + rand()%md.damage; - if (sd) pc_payzeny(sd, md.damage); - if(map_flag_vs(target->m) || is_boss(target)) - md.damage>>=1; //temp value + md.damage = md.damage + rand()%md.damage; + if(is_boss(target)) // deleted || map_flag_vs(target->m) , seemed to reduce damage in PVP mode + md.damage=md.damage*60/100; break; case GS_FLING: md.damage = sd?sd->status.job_level:status_get_lv(src); @@ -2639,16 +2677,18 @@ struct Damage battle_calc_misc_attack( if(md.damage < 0) md.damage = 0; - else if(md.damage && tstatus->mode&MD_PLANT && skill_num != PA_PRESSURE) //Pressure can vaporize plants. + else if(md.damage && tstatus->mode&MD_PLANT && skill_num != PA_PRESSURE && skill_num != NJ_ZENYNAGE) //Pressure can vaporize plants. // damage=1 on plant with Throw zeny ? md.damage = 1; md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - if (skill_num != PA_PRESSURE) //Pressure ignores all these things... + if (skill_num != PA_PRESSURE && skill_num != NJ_ZENYNAGE) //Pressure ignores all these things... and Throw Money ? md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); if (map_flag_gvg(target->m)) md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); + if ( sd && md.damage && skill_num == NJ_ZENYNAGE ) pc_payzeny(sd, md.damage); // conso zenys at the end of the calculation I think + return md; } /*========================================== diff --git a/src/map/skill.c b/src/map/skill.c index 9463e242d..3ea17ef1c 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2824,7 +2824,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case MC_CARTREVOLUTION: case NPC_SPLASHATTACK: case AC_SHOWER: //Targetted skill implementation. - case NJ_BAKUENRYU: if(flag&1){ if(bl->id!=skill_area_temp[1]){ skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick, @@ -2994,6 +2993,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int if (skilllv>1) { int range = skilllv/2; int cnt; + // if caster is ONLY on a NJ_SUITON cell, range will be increased by 1 (consuming suiton cells but also deluge cells if there are ones) + if ( !map_getcell(src->m,src->x,src->y,CELL_CHKWATER) && !map_find_skill_unit_oncell(src,src->x,src->y,SA_DELUGE,NULL) ) range = skilllv/2+1; + if (sd) cnt = skill_count_water(src,range); else { @@ -3152,7 +3154,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case GS_FULLBUSTER: case NJ_SYURIKEN: case NJ_KUNAI: - case NJ_HUUMA: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; case GS_BULLSEYE: @@ -3174,6 +3175,41 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skill_castend_damage_id); } break; + case NJ_HUUMA: + if (flag & 1) { + if (bl->id != skill_area_temp[1]) + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, skill_area_temp[0]); + } else { + skill_area_temp[0] = 0; + skill_area_temp[1] = bl->id; + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY, + skill_area_sub_count); + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, skill_area_temp[0]); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + } + break; + case NJ_BAKUENRYU: + if (flag & 1) { + skill_attack(BF_MAGIC, src, src, bl, skillid, skilllv, tick, skill_area_temp[0]); + } else { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_area_temp[0] = 0; + skill_area_temp[1] = bl->id; + if (flag & 0xf00000) + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, BCT_ENEMY|1, + skill_castend_damage_id); + } + break; case NJ_KASUMIKIRI: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); sc_start(src,SC_HIDING,100,skilllv,skill_get_time(skillid,skilllv)); @@ -3194,18 +3230,13 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int BF_WEAPON,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); // varargs break; //Not implemented yet [Vicious] - - //case NJ_SYURIKEN: - //case NJ_KUNAI: - //case NJ_HUUMA: //case NJ_KASUMIKIRI: //case NJ_KIRIKAGE: - //case NJ_KOUENKA: - //case NJ_HYOUSENSOU: - //case NJ_HUUJIN: - //case NJ_KAMAITACHI: case NJ_ISSEN: - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + + if (sc && sc->data[SC_NEN].timer != -1) + status_change_end(src,SC_NEN,-1); break; case 0: @@ -3683,6 +3714,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sd && sd != dstsd) clif_displaymessage(sd->fd,"You broke target's weapon"); } + clif_skill_nodamage(src,bl,skillid,skilllv,i); break; case PR_ASPERSIO: /* アスペルシオ */ @@ -6095,6 +6127,7 @@ int skill_castend_pos2 (struct block_list *src, int x, int y, int skillid, int s case DC_SERVICEFORYOU: case GS_DESPERADO: case NJ_SUITON: + case NJ_BAKUENRYU: case NJ_KAENSIN: case NJ_HYOUSYOURAKU: case NJ_RAIGEKISAI: @@ -6566,6 +6599,37 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid, && (src->type&battle_config.vs_traps_bctall)) target = BCT_ALL; break; + case NJ_SUITON: + val1 = skilllv*2; + + { + // don't call skill_clear_group(src,1), it deletes also kaensin... and I think it doesn't have to + // so this is a copy paste of skill_clear_group() function, which only deletes suiton (shoud maybe create a new function) + struct unit_data *ud = unit_bl2ud(src); + struct skill_unit_group *group[MAX_SKILLUNITGROUP]; + int i, count=0, tflag=1; + + nullpo_retr(0, src); + if (!ud) break; + + for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) + { + switch (ud->skillunit[i]->skill_id) { + case NJ_SUITON: + if (tflag&1) + group[count++]= ud->skillunit[i]; + break; + default: + if (tflag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) + group[count++]= ud->skillunit[i]; + break; + } + + } + for (i=0;i<count;i++) + skill_delunitgroup(src, group[i]); + } + break; case HT_SHOCKWAVE: /* ショックウェーブトラップ */ val1=skilllv*15+10; case HT_SANDMAN: /* サンドマン */ @@ -6705,8 +6769,35 @@ struct skill_unit_group *skill_unitsetting (struct block_list *src, int skillid, if (sd) val1 = sd->status.child; break; case NJ_KAENSIN: - val2 = (skilllv+1)/2 + 4; - skill_clear_group(src,1); + { + // don't call skill_clear_group(src,1), it deletes also suiton... and I think it doesn't have to + // so this is a copy paste of skill_clear_group() function, which only deletes kaesin (shoud maybe create a new function) + struct unit_data *ud = unit_bl2ud(src); + struct skill_unit_group *group[MAX_SKILLUNITGROUP]; + int i, count=0, tflag=1; + + val2 = (skilllv+1)/2 + 4; + + nullpo_retr(0, src); + if (!ud) break; + + for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) + { + switch (ud->skillunit[i]->skill_id) { + case NJ_KAENSIN: + if (tflag&1) + group[count++]= ud->skillunit[i]; + break; + default: + if (tflag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) + group[count++]= ud->skillunit[i]; + break; + } + + } + for (i=0;i<count;i++) + skill_delunitgroup(src, group[i]); + } break; case GS_GROUNDDRIFT: @@ -7411,6 +7502,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int switch (skill_id) { case WZ_QUAGMIRE: + case NJ_SUITON: if (bl->type==BL_MOB) break; if (sc && sc->data[type].timer != -1) @@ -8296,8 +8388,9 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t break; case NJ_ISSEN: - if (sc && sc->data[SC_NEN].timer!=-1) - return 0; + if (!sc || sc->data[SC_NEN].timer==-1) { + clif_skill_fail(sd,skill,0,0); + return 0; } break; case NJ_ZENYNAGE: diff --git a/src/map/status.c b/src/map/status.c index 06e652950..ebb9d151e 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -358,6 +358,8 @@ void initChangeTables(void) { add_sc(SA_ELEMENTFIRE, SC_ELEMENTALCHANGE); add_sc(SA_ELEMENTGROUND, SC_ELEMENTALCHANGE); add_sc(SA_ELEMENTWIND, SC_ELEMENTALCHANGE); + add_sc(NJ_HYOUSYOURAKU, SC_FREEZE); + set_sc(NJ_NEN, SC_NEN, SI_NEN, SCB_STR|SCB_INT); //Until they're at right position - gs_set_sc- [Vicious] / some of these don't seem to have a status icon adequate [blackhole89] set_sc(GS_MADNESSCANCEL, SC_MADNESSCANCEL, SI_MADNESSCANCEL, SCB_BATK|SCB_ASPD); @@ -369,9 +371,7 @@ void initChangeTables(void) { //Uncomment and update when you plan on implementing. // set_sc(NJ_UTSUSEMI, SC_UTSUSEMI, SI_MAEMI); -// set_sc(NJ_KAENSIN, SC_KAENSIN, SI_BLANK); - set_sc(NJ_SUITON, SC_SUITON, SI_BLANK, SCB_AGI); - set_sc(NJ_NEN, SC_NEN, SI_NEN, SCB_STR|SCB_INT); + set_sc(NJ_SUITON, SC_SUITON, SI_BLANK, SCB_AGI|SCB_SPEED); set_sc(HLIF_AVOID, SC_AVOID, SI_BLANK, SCB_SPEED); set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_INT); set_sc(HAMI_BLOODLUST, SC_BLOODLUST, SI_BLANK, SCB_BATK|SCB_WATK); @@ -2969,7 +2969,7 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi -= 2 + sc->data[SC_DECREASEAGI].val1; if(sc->data[SC_QUAGMIRE].timer!=-1) agi -= sc->data[SC_QUAGMIRE].val2; - if(sc->data[SC_SUITON].timer!=-1) + if(sc->data[SC_SUITON].timer!=-1 && sc->data[SC_SUITON].val4) agi -= sc->data[SC_SUITON].val2; if(sc->data[SC_MARIONETTE].timer!=-1) agi -= (sc->data[SC_MARIONETTE].val3>>8)&0xFF; @@ -3311,7 +3311,7 @@ static signed char status_calc_def(struct block_list *bl, struct status_change * if(sc->data[SC_KEEPING].timer!=-1) return 100; if(sc->data[SC_SKA].timer != -1) - return sc->data[SC_SKA].val3; + return rand()%100; //Reports indicate SKA actually randomizes defense. if (sc->data[SC_DEFENCE].timer != -1) //[orn] def += sc->data[SC_DEFENCE].val2 ; if(sc->data[SC_STEELBODY].timer!=-1) @@ -3453,6 +3453,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha speed = speed * 100/75; if(sc->data[SC_QUAGMIRE].timer!=-1) speed = speed * 100/50; + if(sc->data[SC_SUITON].timer!=-1 && sc->data[SC_SUITON].val4) + speed = speed * 100/50; if(sc->data[SC_DONTFORGETME].timer!=-1) speed = speed * 100/sc->data[SC_DONTFORGETME].val3; if(sc->data[SC_DEFENDER].timer!=-1) @@ -4126,6 +4128,7 @@ int status_get_sc_def(struct block_list *bl, int type) case SC_HALLUCINATION: case SC_STONE: case SC_QUAGMIRE: + case SC_SUITON: return 10000; } @@ -4462,6 +4465,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val case SC_ROKISWEIL: case SC_COMA: case SC_GRAVITATION: + case SC_SUITON: return 0; } } @@ -4760,26 +4764,29 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val val2 = 0; break; case SC_SUITON: - if (status_get_class(bl) != JOB_NINJA) { - //Is there some kind of formula behind this? - switch ((val1+1)/3) { - case 3: - val2 = 8; - break; - case 2: - val2 = 5; - break; - case 1: - val2 = 3; - break; - case 0: - val2 = 0; - break; - default: - val2 = 3*((val1+1)/3); - break; - } - } else val2 = 0; + if (status_get_class(bl) != JOB_NINJA) { + if ( bl->type == BL_PC && !map[sd->bl.m].flag.pvp && !map_flag_gvg(sd->bl.m) ) val4=0; + else val4=1; + + switch ((val1+1)/3) { + case 3: + val2 = 8; + break; + case 2: + val2 = 5; + break; + case 1: + val2 = 3; + break; + case 0: + val2 = 0; + break; + default: + val2 = 3*((val1+1)/3); + break; + + } + } else val2 = 0; break; case SC_ONEHAND: case SC_TWOHANDQUICKEN: @@ -5379,11 +5386,6 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val val2 = 20*val1; //matk increase. val3 = 12*val1; //mdef2 reduction. break; - case SC_SKA: - val2 = tick/1000; - val3 = rand()%100; //Def changes randomly every second... - tick = 1000; - break; case SC_JAILED: tick = val1>0?1000:250; break; @@ -5476,6 +5478,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val case SC_MAXOVERTHRUST: case SC_OVERTHRUST: case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... + case SC_NEN: sc->opt3 |= 2; opt_flag = 0; break; @@ -5986,6 +5989,7 @@ int status_change_end( struct block_list* bl , int type,int tid ) case SC_OVERTHRUST: case SC_MAXOVERTHRUST: case SC_SWOO: + case SC_NEN: sc->opt3 &= ~2; opt_flag = 0; break; @@ -6074,8 +6078,10 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, int data) hp = status->max_hp - status->hp; if (hp > sc->data[data].val2) hp = sc->data[data].val2; - if (hp) - status_heal(bl, hp, 0, 2); + if (hp) { + status_heal(bl, hp, 0, 0); + clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); + } sc->data[data].val4=-1; return 1; } @@ -6145,15 +6151,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) return 0; break; - case SC_SKA: - if((--sc->data[type].val2)>0){ - sc->data[type].val3 = rand()%100; //Random defense. - sc->data[type].timer=add_timer( - 1000+tick, status_change_timer, - bl->id, data); - return 0; - } - case SC_HIDING: if((--sc->data[type].val2)>0){ |