diff options
-rw-r--r-- | src/map/atcommand.cpp | 12 | ||||
-rw-r--r-- | src/map/battle.cpp | 256 | ||||
-rw-r--r-- | src/map/map.hpp | 4 | ||||
-rw-r--r-- | src/map/pc.cpp | 36 | ||||
-rw-r--r-- | src/mmo/clif.t.hpp | 8 |
5 files changed, 190 insertions, 126 deletions
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index d7d47c9..b537431 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -2570,12 +2570,22 @@ ATCE atcommand_character_stats_full(Session *s, dumb_ptr<map_session_data>, clif_displaymessage(s, output); output = STRPRINTF("PERFECT_HIT_RATE: %d | PERFECT_HIT_ADD_RATE: %d | CRITICAL: %d | CRITICAL_RATE: %d | HIT: %d | HIT_RATE: %d"_fmt, pl_sd->perfect_hit, - pl_sd->perfect_hit_add, + pl_sd->perfect_hit_add_rate, pl_sd->critical, pl_sd->critical_rate, pl_sd->hit, pl_sd->hit_rate); clif_displaymessage(s, output); + output = STRPRINTF("DEADLY_STRIKE_RATE: %d | DEADLY_STRIKE_ADD_RATE: %d"_fmt, + pl_sd->deadly_strike, + pl_sd->deadly_strike_add_rate); + clif_displaymessage(s, output); + output = STRPRINTF("arrow_atk: %d | arrow_cri: %d | arrow_hit: %d | arrow_range: %d"_fmt, + pl_sd->arrow_atk, + pl_sd->arrow_cri, + pl_sd->arrow_hit, + pl_sd->arrow_range); + clif_displaymessage(s, output); output = STRPRINTF("HP_DRAIN_RATE: %d | HP_DRAIN_RATE per: %d | SP_DRAIN_RATE: %d | SP_DRAIN_RATE per: %d"_fmt, pl_sd->hp_drain_rate, pl_sd->hp_drain_per, diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 3b7c6b2..eaa37a0 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -1469,7 +1469,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, ATK dmg_lv = ATK::ZERO; eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data, t_sc_data; int watk; - bool da = false; + bool da = false, ds = false; int ac_flag = 0; int target_distance; @@ -1482,7 +1482,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, sd->state.attack_type = BF::WEAPON; // 攻撃タイプは武器攻撃 | Attack type is weapon attack - // ターゲット + // ターゲット | target if (target->bl_type == BL::PC) // 対象がPCなら | If the target is a PC tsd = target->is_player(); // tsdに代入(tmdはNULL) | Assign to tsd (tmd is NULL) else if (target->bl_type == BL::MOB) // 対象がMobなら | If the target is a mob @@ -1575,143 +1575,154 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, if (atkmin > atkmax && !(sd->state.arrow_atk)) atkmin = atkmax; // 弓は最低が上回る場合あり | Bow may exceed minimum - if (sd->double_rate > 0 && skill_num == SkillID::ZERO && skill_lv >= 0) - da = random_::chance({sd->double_rate, 100}); - - if (!da) - { // ダブルアタックが発動していない | Double Attack is not activated - // クリティカル計算 | critical calculation - cri = battle_get_critical(src); - - if (sd->state.arrow_atk) - cri += sd->arrow_cri; - cri -= battle_get_luk(target) * 3; - if (ac_flag) - cri = 1000; - } - - if (tsd && tsd->critical_def) - cri = cri * (100 - tsd->critical_def) / 100; - else if (tmd && tmd->stats[mob_stat::CRITICAL_DEF]) - cri = cri * (100 - tmd->stats[mob_stat::CRITICAL_DEF]) / 100; + if (tmd && !bool(t_mode & MobMode::BOSS)) // deadly strike works only on mobs but not on mobs with boss flag + if (sd->deadly_strike > 0) + ds = random_::chance({sd->deadly_strike, 100}); - // ダブルアタックが発動していない | Double Attack is not activated - // 判定(スキルの場合は無視) | Judgment (ignored for skills) - if (!da && skill_num == SkillID::ZERO && skill_lv >= 0 - && random_::chance({cri, 1000})) + if (!ds) // no double, crit and normal damage calculation needed if it is a deadly strike { - damage += atkmax; - if (sd->atk_rate != 100) - { - damage = (damage * sd->atk_rate) / 100; - } - if (sd->state.arrow_atk) - damage += sd->arrow_atk; - type = DamageType::CRITICAL; - } - else - { - int vitbonusmax; + if (sd->double_rate > 0 && skill_num == SkillID::ZERO && skill_lv >= 0) + da = random_::chance({sd->double_rate, 100}); - if (atkmax > atkmin) - damage += random_::in(atkmin, atkmax); - else - damage += atkmin; - if (sd->atk_rate != 100) + if (!da) { - damage = (damage * sd->atk_rate) / 100; + // ダブルアタックが発動していない | Double Attack is not activated + // クリティカル計算 | critical calculation + cri = battle_get_critical(src); + + if (sd->state.arrow_atk) + cri += sd->arrow_cri; + cri -= battle_get_luk(target) * 3; + if (ac_flag) + cri = 1000; } - if (sd->state.arrow_atk) + if (tsd && tsd->critical_def) + cri = cri * (100 - tsd->critical_def) / 100; + else if (tmd && tmd->stats[mob_stat::CRITICAL_DEF]) + cri = cri * (100 - tmd->stats[mob_stat::CRITICAL_DEF]) / 100; + + // ダブルアタックが発動していない | Double Attack is not activated + // 判定(スキルの場合は無視) | Judgment (ignored for skills) + if (!da && skill_num == SkillID::ZERO && skill_lv >= 0 + && random_::chance({cri, 1000})) { - if (sd->arrow_atk > 0) - damage += random_::in(0, sd->arrow_atk); - hitrate += sd->arrow_hit; + damage += atkmax; + if (sd->atk_rate != 100) + { + damage = (damage * sd->atk_rate) / 100; + } + if (sd->state.arrow_atk) + damage += sd->arrow_atk; + type = DamageType::CRITICAL; } - - if (skill_num != SkillID::ZERO && skill_num != SkillID::NEGATIVE) + else { - flag = (flag & ~BF::SKILLMASK) | BF::SKILL; - } + int vitbonusmax; - { - // 対 象の防御力によるダメージの減少 | Decreased damage due to target's defense - // ディバインプロテクション(ここでいいのかな?) | Divine Protection (maybe here?) - if (def1 < 1000000) - { // DEF, VIT無視 | DEF, VIT ignore - int t_def; - target_count = - 1 + battle_counttargeted(target, src, - battle_config.vit_penaly_count_lv); - if (battle_config.vit_penaly_type > 0) - { - if (target_count >= battle_config.vit_penaly_count) + if (atkmax > atkmin) + damage += random_::in(atkmin, atkmax); + else + damage += atkmin; + if (sd->atk_rate != 100) + { + damage = (damage * sd->atk_rate) / 100; + } + + if (sd->state.arrow_atk) + { + if (sd->arrow_atk > 0) + damage += random_::in(0, sd->arrow_atk); + hitrate += sd->arrow_hit; + } + + if (skill_num != SkillID::ZERO && skill_num != SkillID::NEGATIVE) + { + flag = (flag & ~BF::SKILLMASK) | BF::SKILL; + } + + { + // 対 象の防御力によるダメージの減少 | Decreased damage due to target's defense + // ディバインプロテクション(ここでいいのかな?) | Divine Protection (maybe here?) + if (def1 < 1000000) + { // DEF, VIT無視 | DEF, VIT ignore + int t_def; + target_count = + 1 + battle_counttargeted(target, src, + battle_config.vit_penaly_count_lv); + if (battle_config.vit_penaly_type > 0) { - if (battle_config.vit_penaly_type == 1) + if (target_count >= battle_config.vit_penaly_count) { - def1 = - (def1 * - (100 - - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num)) / - 100; - def2 = - (def2 * - (100 - - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num)) / - 100; - t_vit = - (t_vit * - (100 - - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num)) / - 100; - } - else if (battle_config.vit_penaly_type == 2) - { - def1 -= - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num; - def2 -= - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num; - t_vit -= - (target_count - - (battle_config.vit_penaly_count - - 1)) * battle_config.vit_penaly_num; + if (battle_config.vit_penaly_type == 1) + { + def1 = + (def1 * + (100 - + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num)) / + 100; + def2 = + (def2 * + (100 - + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num)) / + 100; + t_vit = + (t_vit * + (100 - + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num)) / + 100; + } + else if (battle_config.vit_penaly_type == 2) + { + def1 -= + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num; + def2 -= + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num; + t_vit -= + (target_count - + (battle_config.vit_penaly_count - + 1)) * battle_config.vit_penaly_num; + } + if (def1 < 0) + def1 = 0; + if (def2 < 1) + def2 = 1; + if (t_vit < 1) + t_vit = 1; } - if (def1 < 0) - def1 = 0; - if (def2 < 1) - def2 = 1; - if (t_vit < 1) - t_vit = 1; } - } - t_def = def2 * 8 / 10; - vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1; + t_def = def2 * 8 / 10; + vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1; - { { - damage = damage * (100 - def1) / 100; - damage -= t_def; - if (vitbonusmax > 0) - damage -= random_::in(0, vitbonusmax); + { + damage = damage * (100 - def1) / 100; + damage -= t_def; + if (vitbonusmax > 0) + damage -= random_::in(0, vitbonusmax); + } } } } } + // 精錬ダメージの追加 | Add refining damage + { // DEF, VIT無視 | DEF, VIT ignore + damage += battle_get_atk2(src); + } } - // 精錬ダメージの追加 | Add refining damage - { // DEF, VIT無視 | DEF, VIT ignore - damage += battle_get_atk2(src); - } + else + if (sd->state.arrow_atk) + hitrate += sd->arrow_hit; // 0未満だった場合1に補正 | Corrected to 1 if less than 0 if (damage < 1) @@ -1743,6 +1754,15 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src, if (damage < 0) damage = 0; + if (ds) + { + damage = tmd->hp; + //type = DamageType::DEADLY; + // M+ does not support this value on package 0x008a it lags a bit and displays an error message. + // This can be implemented if ManaVerse is the only supported client so long DamageType::CRITICAL will do + type = DamageType::CRITICAL; + } + // 右手,短剣のみ | right hand, dagger only if (da) { // ダブルアタックが発動しているか | Is double attack activated? diff --git a/src/map/map.hpp b/src/map/map.hpp index af074ba..a4295fd 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -259,10 +259,10 @@ struct map_session_data : block_list, SessionData int aspd_rate, speed_rate, hprecov_rate, sprecov_rate, critical_def, double_rate; int matk_rate; - int perfect_hit; + int perfect_hit, deadly_strike; int critical_rate, hit_rate, flee_rate, flee2_rate, def_rate, def2_rate, mdef_rate, mdef2_rate; - int double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add; + int double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add_rate, deadly_strike_add_rate; short hp_drain_rate, hp_drain_per, sp_drain_rate, sp_drain_per; int die_counter; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 9fd23b9..3e8cd6e 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -1193,11 +1193,11 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->double_rate = 0; sd->atk_rate = sd->matk_rate = 100; sd->arrow_cri = 0; - sd->perfect_hit = 0; + sd->perfect_hit = sd->deadly_strike = 0; sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; sd->speed_add_rate = sd->aspd_add_rate = 100; - sd->double_add_rate = sd->perfect_hit_add = 0; + sd->double_add_rate = sd->perfect_hit_add_rate = sd->deadly_strike_add_rate = 0; sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0; @@ -1328,7 +1328,8 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (sd->status.weapon == ItemLook::BOW) sd->attackrange += sd->arrow_range; sd->double_rate += sd->double_add_rate; - sd->perfect_hit += sd->perfect_hit_add; + sd->perfect_hit += sd->perfect_hit_add_rate; + sd->deadly_strike += sd->deadly_strike_add_rate; if (sd->speed_add_rate != 100) sd->speed_rate += sd->speed_add_rate - 100; if (sd->aspd_add_rate != 100) @@ -1797,7 +1798,7 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) break; case SP::PERFECT_HIT_ADD_RATE: if (!sd->state.lr_flag_is_arrow_2) - sd->perfect_hit_add += val; + sd->perfect_hit_add_rate += val; break; case SP::CRITICAL_RATE: if (!sd->state.lr_flag_is_arrow_2) @@ -1836,10 +1837,35 @@ int pc_bonus(dumb_ptr<map_session_data> sd, SP type, int val) break; case SP::SPEED_CAP: if (!sd->state.lr_flag_is_arrow_2) - // lowest cap is taken others are ignored + // highest value (slowest speed) is taken others are ignored if (sd->speed_cap < interval_t(val)) sd->speed_cap = interval_t(val); break; + case SP::ALL_STATS: + sd->parame[ATTR::STR] += val; + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::VIT] += val; + sd->parame[ATTR::INT] += val; + sd->parame[ATTR::DEX] += val; + sd->parame[ATTR::LUK] += val; + break; + case SP::AGI_VIT: + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::VIT] += val; + break; + case SP::AGI_DEX_STR: + sd->parame[ATTR::AGI] += val; + sd->parame[ATTR::DEX] += val; + sd->parame[ATTR::STR] += val; + break; + case SP::DEADLY_STRIKE_RATE: + if (!sd->state.lr_flag_is_arrow_2 && sd->deadly_strike < val) + sd->deadly_strike = val; + break; + case SP::DEADLY_STRIKE_ADD_RATE: + if (!sd->state.lr_flag_is_arrow_2) + sd->deadly_strike_add_rate += val; + break; default: if (battle_config.error_log) PRINTF("pc_bonus: unknown type %d %d !\n"_fmt, diff --git a/src/mmo/clif.t.hpp b/src/mmo/clif.t.hpp index 830c5bd..e92c349 100644 --- a/src/mmo/clif.t.hpp +++ b/src/mmo/clif.t.hpp @@ -153,6 +153,7 @@ enum class DamageType : uint8_t DOUBLED = 0x08, CRITICAL = 0x0a, FLEE2 = 0x0b, + DEADLY = 0x0c, }; enum class LOOK : uint8_t @@ -474,6 +475,13 @@ enum class SP : uint16_t AUTOMOD = 1086, SPEED_CAP = 1087, + + ALL_STATS = 1088, + AGI_VIT = 1089, + AGI_DEX_STR = 1090, + + DEADLY_STRIKE_RATE = 1091, + DEADLY_STRIKE_ADD_RATE = 1092, }; constexpr |