From 18c238ab7889e9a207b6c3e0b41c7afb257fda99 Mon Sep 17 00:00:00 2001 From: Jenkijo Date: Mon, 30 Mar 2020 09:49:18 +0700 Subject: [PATCH 1/3] Implement Multi Critical Damage --- conf/map/battle/feature.conf | 5 +++++ db/pre-re/skill_db.conf | 2 +- db/re/skill_db.conf | 2 +- src/map/battle.c | 37 ++++++++++++++++++------------------ src/map/battle.h | 29 +++++++++++++++------------- src/map/clif.c | 7 +++++-- src/map/skill.c | 15 ++++++++++++++- src/map/skill.h | 3 ++- 8 files changed, 63 insertions(+), 37 deletions(-) diff --git a/conf/map/battle/feature.conf b/conf/map/battle/feature.conf index 0d2ab8397a4..8ba8986daed 100644 --- a/conf/map/battle/feature.conf +++ b/conf/map/battle/feature.conf @@ -98,4 +98,9 @@ features: { // true: enable // false: disable (default) replace_refine_npcs: false + + // Enable Multi-Critical damage + // true: enable (Default) + // false: disable + enable_multi_critical: true } diff --git a/db/pre-re/skill_db.conf b/db/pre-re/skill_db.conf index 1222aa1a05e..3b8010128b3 100644 --- a/db/pre-re/skill_db.conf +++ b/db/pre-re/skill_db.conf @@ -44,7 +44,7 @@ Range: Skill Range (int) (optional, defaults to 0) (can be grouped by Levels) Note: Range < 5 is considered Melee range. Hit: Hit Type (int) (optional, default "BDT_NORMAL") - Types - "BDT_SKILL", "BDT_MULTIHIT" or "BDT_NORMAL" + Types - "BDT_SKILL", "BDT_MULTIHIT", "BDT_NORMAL" or "BDT_MULTICRIT" SkillType: { (bool, defaults to "Passive") Passive: true/false (boolean, defaults to false) Enemy: true/false (boolean, defaults to false) diff --git a/db/re/skill_db.conf b/db/re/skill_db.conf index 376fba179a4..fae1bd70c7b 100644 --- a/db/re/skill_db.conf +++ b/db/re/skill_db.conf @@ -44,7 +44,7 @@ Range: Skill Range (int) (optional, defaults to 0) (can be grouped by Levels) Note: Range < 5 is considered Melee range. Hit: Hit Type (int) (optional, default "BDT_NORMAL") - Types - "BDT_SKILL", "BDT_MULTIHIT" or "BDT_NORMAL" + Types - "BDT_SKILL", "BDT_MULTIHIT", "BDT_NORMAL" or "BDT_MULTICRIT" SkillType: { (bool, defaults to "Passive") Passive: true/false (boolean, defaults to false) Enemy: true/false (boolean, defaults to false) diff --git a/src/map/battle.c b/src/map/battle.c index 985d2bca4c1..7e4912da64c 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4358,8 +4358,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl int i, nk; bool n_ele = false; // non-elemental - struct map_session_data *sd, *tsd; struct Damage wd; + struct map_session_data *sd = BL_CAST(BL_PC, src); + struct map_session_data *tsd = BL_CAST(BL_PC, target); struct status_change *sc = status->get_sc(src); struct status_change *tsc = status->get_sc(target); struct status_data *sstatus = status->get_status_data(src); @@ -4426,9 +4427,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if (tsc && !tsc->count) tsc = NULL; //Skip checking as there are no status changes active. - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - if(sd) wd.blewcount += battle->blewcount_bonus(sd, skill_id); @@ -4439,7 +4437,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl ) flag.arrow = 1; - if(skill_id) { + if(skill_id || (skill->get_nk(skill_id) & NK_CRITICAL) == 0) { wd.flag |= battle->range_type(src, target, skill_id, skill_lv); switch(skill_id) { case MO_FINGEROFFENSIVE: @@ -4470,7 +4468,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl case TF_DOUBLE: //For NPC used skill. case GS_CHAINACTION: - wd.type = BDT_MULTIHIT; + wd.type = BDT_CRIT | BDT_MULTICRIT; break; case GS_GROUNDDRIFT: @@ -4483,7 +4481,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl break; case KN_AUTOCOUNTER: - wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; + wd.flag = (wd.flag & ~BF_SKILLMASK) | BF_NORMAL; break; case NPC_CRITICALSLASH: @@ -4598,21 +4596,21 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if (sd && !skill_id) { //Check for double attack. - if (( (skill_lv=pc->checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER ) - || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed - || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST ) // Need confirmation + if (sd->bonus.double_rate > 0 + || (skill_lv = pc->checkskill(sd, TF_DOUBLE)) > 0 + || (sc != NULL && sc->data[SC_KAGEMUSYA] != NULL) ) { //Success chance is not added, the higher one is used [Skotlex] if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) { wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); - wd.type = BDT_MULTIHIT; + wd.type = BDT_CRIT | BDT_MULTICRIT; } } else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc->checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) { wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); - wd.type = BDT_MULTIHIT; + wd.type = BDT_CRIT | BDT_MULTICRIT; } else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ @@ -4646,17 +4644,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if ( wd.div_ > 1 ) { wd.div_ = min(wd.div_, sd->status.inventory[i].amount); sc->data[SC_FEARBREEZE]->val4 = wd.div_ - 1; - wd.type = BDT_MULTIHIT; + wd.type = BDT_CRIT | BDT_MULTICRIT; } } } //Check for critical - if( !flag.cri && wd.type != BDT_MULTIHIT && sstatus->cri && - (!skill_id || - skill_id == KN_AUTOCOUNTER || - skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || - skill_id == NJ_KIRIKAGE)) + if (sstatus->cri != 0) { short cri = sstatus->cri; if (sd != NULL) { @@ -4716,6 +4710,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl } if (flag.cri) { wd.type = BDT_CRIT; +#ifdef RENEWAL +#if PACKETVER >= 20161207 + if (battle_config.feature_enable_multi_crit == 1 && (wd.type & BDT_MULTIHIT) != 0) + wd.type = BDT_MULTICRIT; +#endif +#endif #ifndef RENEWAL flag.idef = flag.idef2 = #endif @@ -7450,6 +7450,7 @@ static const struct battle_data { { "hit_max_limit", &battle_config.hit_max, SHRT_MAX, 1, INT_MAX, }, { "autoloot_adjust", &battle_config.autoloot_adjust, 0, 0, 1, }, { "hom_bonus_exp_from_master", &battle_config.hom_bonus_exp_from_master, 10, 0, 100, }, + { "features/enable_multi_critical", &battle_config.feature_enable_multi_crit, 1, 0, 1, }, }; static bool battle_set_value_sub(int index, int value) diff --git a/src/map/battle.h b/src/map/battle.h index 2e710f7f87d..d1c3353d36f 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -101,19 +101,20 @@ enum e_battle_check_target { //New definitions [Skotlex] * Note: some values may not apply in some contexts. */ enum battle_dmg_type { - BDT_NORMAL = 0, // Normal attack - //BDT_PICKUP = 1, // Pick up item - BDT_SITDOWN = 2, // Sit down - BDT_STANDUP = 3, // Stand up - BDT_ENDURE = 4, // Damage (endure) - BDT_SPLASH = 5, // Splash - BDT_SKILL = 6, // Skill - //BDT_REPEAT = 7, // (repeat damage?) - BDT_MULTIHIT = 8, // Multi-hit damage - BDT_MULTIENDURE = 9, // Multi-hit damage (endure) - BDT_CRIT = 10, // Critical hit - BDT_PDODGE = 11, // Lucky dodge - //BDT_TOUCH = 12, // (touch skill?) + BDT_NORMAL = 0, ///< Normal attack (damage: total damage, div: amount of hits, damage2: assassin dual-wield damage) + //BDT_PICKUP = 1, ///< Pick up item + BDT_SITDOWN = 2, ///< Sit down + BDT_STANDUP = 3, ///< Stand up + BDT_ENDURE = 4, ///< Damage (endure) + BDT_SPLASH = 5, ///< Splash + BDT_SKILL = 6, ///< Skill + //BDT_REPEAT = 7, ///< (Repeat damage?) + BDT_MULTIHIT = 8, ///< Multi-hit damage + BDT_MULTIENDURE = 9, ///< Multi-hit damage (endure) + BDT_CRIT = 10, ///< Critical hit + BDT_PDODGE = 11, ///< Lucky dodge + //BDT_TOUCH = 12, ///< (Touch skill?) + BDT_MULTICRIT = 13, ///< Multi-hit with critical }; /** @@ -592,6 +593,8 @@ struct Battle_Config { int enable_refinery_ui; int replace_refine_npcs; + int feature_enable_multi_crit; + int batk_min; int batk_max; int matk_min; diff --git a/src/map/clif.c b/src/map/clif.c index c9e018f7329..8f10895eed7 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4861,7 +4861,8 @@ static int clif_damage(struct block_list *src, struct block_list *dst, int sdela damage2 = (int)min(in_damage2,INT_MAX); #endif - type = clif_calc_delay(type,div,damage+damage2,ddelay); + if (type != BDT_MULTICRIT) + type = clif_calc_delay(type, div, damage + damage2, ddelay); p.PacketType = damageType; p.GID = src->id; @@ -4906,8 +4907,10 @@ static int clif_damage(struct block_list *src, struct block_list *dst, int sdela unit->set_dir(src, unit->getdir(src)); } + // In case this assignment is bypassed by BDT_MULTICRIT + type = clif_calc_delay(type, div, damage + damage2, ddelay); //Return adjusted can't walk delay for further processing. - return clif->calc_walkdelay(dst,ddelay,type,damage+damage2,div); + return clif->calc_walkdelay(dst, ddelay, type, damage + damage2, div); } /*========================================== diff --git a/src/map/skill.c b/src/map/skill.c index a1a22f74f57..73498eb780f 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -3063,7 +3063,10 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li case NPC_CRITICALSLASH: case TF_DOUBLE: case GS_CHAINACTION: - dmg.dmotion = clif->damage(src,bl,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + case NJ_KIRIKAGE: + dmg.dmotion = clif->damage(src, bl, dmg.amotion, dmg.dmotion, damage, dmg.div_, dmg.type, dmg.damage2); break; case AS_SPLASHER: @@ -20118,6 +20121,10 @@ static void skill_validate_hittype(struct config_setting_t *conf, struct s_skill sk->hit = BDT_MULTIHIT; } else if (strcmpi(type, "BDT_NORMAL") == 0) { sk->hit = BDT_NORMAL; + } else if (strcmpi(type, "BDT_MULTICRIT") == 0) { + sk->hit = BDT_MULTICRIT; + } else if (strcmpi(type, "BDT_CRIT") == 0) { + sk->hit = BDT_CRIT; } else { skilldb_invalid_error(type, "Hit", sk->nameid); return; @@ -20467,6 +20474,12 @@ static void skill_validate_damagetype(struct config_setting_t *conf, struct s_sk } else { sk->nk &= ~NK_NO_CARDFIX_DEF; } + } else if (strcmpi(type, "CritDamage") == 0) { + if (on) { + sk->nk |= NK_CRITICAL; + } else { + sk->nk &= ~NK_CRITICAL; + } } else { skilldb_invalid_error(type, config_setting_name(t), sk->nameid); } diff --git a/src/map/skill.h b/src/map/skill.h index c65547181cb..6421e6473b6 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -98,7 +98,7 @@ enum e_skill_inf { enum e_skill_nk { NK_NONE = 0x00, NK_NO_DAMAGE = 0x01, - NK_SPLASH = 0x02|0x04, // 0x4 = splash & split + NK_SPLASH = 0x02 | 0x04, ///< 0x04 = splash & split NK_SPLASH_ONLY = 0x02, NK_SPLASHSPLIT = 0x04, NK_NO_CARDFIX_ATK = 0x08, @@ -106,6 +106,7 @@ enum e_skill_nk { NK_IGNORE_DEF = 0x20, NK_IGNORE_FLEE = 0x40, NK_NO_CARDFIX_DEF = 0x80, + NK_CRITICAL = 0x100, }; //A skill with 3 would be no damage + splash: area of effect. From acf331beb5092987b93f4d29a29d52a4c8fc6d98 Mon Sep 17 00:00:00 2001 From: Jenkijo Date: Tue, 7 Apr 2020 08:33:29 +0700 Subject: [PATCH 2/3] Clean up --- conf/map/battle/feature.conf | 2 -- src/map/battle.c | 13 +++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/conf/map/battle/feature.conf b/conf/map/battle/feature.conf index 8ba8986daed..f95d5b6573c 100644 --- a/conf/map/battle/feature.conf +++ b/conf/map/battle/feature.conf @@ -100,7 +100,5 @@ features: { replace_refine_npcs: false // Enable Multi-Critical damage - // true: enable (Default) - // false: disable enable_multi_critical: true } diff --git a/src/map/battle.c b/src/map/battle.c index 8497eb8ef52..010410ff61a 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4711,10 +4711,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if (flag.cri) { wd.type = BDT_CRIT; #ifdef RENEWAL -#if PACKETVER >= 20161207 - if (battle_config.feature_enable_multi_crit == 1 && (wd.type & BDT_MULTIHIT) != 0) - wd.type = BDT_MULTICRIT; -#endif + if (battle_config.feature_enable_multi_crit == 1 && (wd.type & BDT_MULTIHIT) != 0) + wd.type = BDT_MULTICRIT; #endif #ifndef RENEWAL flag.idef = flag.idef2 = @@ -7587,6 +7585,13 @@ static void battle_adjust_conf(void) } #endif +#if PACKETVER < 20161207 + if( battle_config.feature_enable_multi_crit ) { + ShowWarning("conf/map/battle/feature.conf feature_enable_multi_crit is enabled but it requires PACKETVER 2016-12-07 or newer, disabling...\n"); + battle_config.feature_enable_multi_crit = 0; + } +#endif + #ifndef CELL_NOSTACK if (battle_config.custom_cell_stack_limit != 1) ShowWarning("Battle setting 'custom_cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); From 0e81281256a27c72cb7164a72f5163a4551e7e08 Mon Sep 17 00:00:00 2001 From: Jenkijo Date: Tue, 7 Apr 2020 19:00:57 +0700 Subject: [PATCH 3/3] Format --- conf/map/battle/feature.conf | 1 + src/map/battle.c | 2 +- src/map/skill.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/conf/map/battle/feature.conf b/conf/map/battle/feature.conf index f95d5b6573c..00fb1f6b288 100644 --- a/conf/map/battle/feature.conf +++ b/conf/map/battle/feature.conf @@ -100,5 +100,6 @@ features: { replace_refine_npcs: false // Enable Multi-Critical damage + // Requires: 2016-12-07 RagexeRE or later enable_multi_critical: true } diff --git a/src/map/battle.c b/src/map/battle.c index 010410ff61a..ff05c25a21d 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7586,7 +7586,7 @@ static void battle_adjust_conf(void) #endif #if PACKETVER < 20161207 - if( battle_config.feature_enable_multi_crit ) { + if (battle_config.feature_enable_multi_crit) { ShowWarning("conf/map/battle/feature.conf feature_enable_multi_crit is enabled but it requires PACKETVER 2016-12-07 or newer, disabling...\n"); battle_config.feature_enable_multi_crit = 0; } diff --git a/src/map/skill.c b/src/map/skill.c index 811f4129d4a..a2b279a4670 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -20474,7 +20474,7 @@ static void skill_validate_damagetype(struct config_setting_t *conf, struct s_sk sk->nk &= ~NK_NO_CARDFIX_DEF; } } else if (strcmpi(type, "CritDamage") == 0) { - if (on) { + if (on != 0) { sk->nk |= NK_CRITICAL; } else { sk->nk &= ~NK_CRITICAL;