diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 7ded4048da..63d9036d2b 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -3634,11 +3634,9 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list * skillratio += 40 * skill_lv; break; case LK_JOINTBEAT: - i = 10 * skill_lv - 50; - // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. - if (wd->miscflag&BREAK_NECK) - i *= 2; - skillratio += i; + skillratio += -100 + 10 * skill_lv - 50; + if (wd->miscflag & BREAK_NECK || (tsc && tsc->data[status_skill2sc(skill_id)]->val2 & BREAK_NECK)) // The 2x damage is only for the BREAK_NECK ailment. + skillratio <<= 1; break; #ifdef RENEWAL // Renewal: skill ratio applies to entire damage [helvetica] diff --git a/src/map/skill.cpp b/src/map/skill.cpp index d6416d2faf..3414274533 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1511,13 +1511,6 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start2(src,bl, SC_BLEEDING,50, skill_lv, src->id, skill_get_time2(skill_id,skill_lv)); break; - case LK_JOINTBEAT: - status = status_skill2sc(skill_id); - if (tsc->jb_flag) { - sc_start4(src,bl,status,(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; case ASC_METEORASSAULT: //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) { @@ -4778,19 +4771,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); break; - case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) - switch( rnd()%6 ){ - case 0: flag |= BREAK_ANKLE; break; - case 1: flag |= BREAK_WRIST; break; - case 2: flag |= BREAK_KNEE; break; - case 3: flag |= BREAK_SHOULDER; break; - case 4: flag |= BREAK_WAIST; break; - case 5: flag |= BREAK_NECK; break; - } - //TODO: is there really no cleaner way to do this? - sc = status_get_sc(bl); - if (sc) sc->jb_flag = flag; - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + case LK_JOINTBEAT: + flag = 1 << rnd() % 6; + if (flag != BREAK_NECK && tsc && tsc->data[status_skill2sc(skill_id)]->val2 & BREAK_NECK) + flag = BREAK_NECK; // Target should always receive double damage if neck is already broken + if (skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag)) + sc_start4(src, bl, status_skill2sc(skill_id), 50 + (skill_lv + 1), skill_lv, flag&BREAK_FLAGS, src->id, 0, skill_get_time2(skill_id, skill_lv)); break; case MO_COMBOFINISH: diff --git a/src/map/status.cpp b/src/map/status.cpp index 2f5618a92b..c19a6deeac 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -8191,6 +8191,10 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_ tick /= 5; sc_def = status->agi*50; break; + case SC_JOINTBEAT: + sc_def2 = 270 * status->str / 100; // 270 * STR / 100 + tick_def2 = (status->luk * 50 + status->agi * 200) / 2; // (50 * LUK / 100 + 20 * AGI / 100) / 2 + break; case SC_DEEPSLEEP: tick_def2 = status_get_base_status(bl)->int_ * 25 + status_get_lv(bl) * 50; break; @@ -9527,6 +9531,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty return 0; break; case SC_JOINTBEAT: + if (sc && sc->data[type]->val2 & BREAK_NECK) + return 0; // BREAK_NECK cannot be stacked with new breaks until the status is over. val2 |= sce->val2; // Stackable ailments default: if(sce->val1 > val1) diff --git a/src/map/status.hpp b/src/map/status.hpp index 7e9ec7c2ea..bd5ee0990a 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -1956,15 +1956,14 @@ enum efst_types : short{ }; /// JOINTBEAT stackable ailments -enum e_joint_break -{ - BREAK_ANKLE = 0x01, ///< MoveSpeed reduced by 50% - BREAK_WRIST = 0x02, ///< ASPD reduced by 25% - BREAK_KNEE = 0x04, ///< MoveSpeed reduced by 30%, ASPD reduced by 10% - BREAK_SHOULDER = 0x08, ///< DEF reduced by 50% - BREAK_WAIST = 0x10, ///< DEF reduced by 25%, ATK reduced by 25% - BREAK_NECK = 0x20, ///< current attack does 2x damage, inflicts 'bleeding' for 30 seconds - BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, +enum e_joint_break : uint8 { + BREAK_ANKLE = 0x01, ///< MoveSpeed reduced by 50% + BREAK_WRIST = 0x02, ///< ASPD reduced by 25% + BREAK_KNEE = 0x04, ///< MoveSpeed reduced by 30%, ASPD reduced by 10% + BREAK_SHOULDER = 0x08, ///< DEF reduced by 50% + BREAK_WAIST = 0x10, ///< DEF reduced by 25%, ATK reduced by 25% + BREAK_NECK = 0x20, ///< Current attack does 2x damage, inflicts 'bleeding' for 30 seconds + BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, }; extern short current_equip_item_index; @@ -2330,7 +2329,6 @@ struct status_change { unsigned short opt2;// health state (bitfield) unsigned char count; //! TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. - unsigned char jb_flag; //Joint Beat type flag struct { unsigned char move; unsigned char pickup;