Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Multi Critical Damage #2673

Open
wants to merge 5 commits into
base: stable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions conf/map/battle/feature.conf
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ features: {
// true: enable
// false: disable (default)
replace_refine_npcs: false

// Enable Multi-Critical damage
enable_multi_critical: true
jenkijo marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please set this to false otherwise the CI that checks different client types would fail

}
2 changes: 1 addition & 1 deletion db/pre-re/skill_db.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion db/re/skill_db.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
42 changes: 24 additions & 18 deletions src/map/battle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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:
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BDT_* is not a bitmask, is this intended? also this will break pre-re compatibility please add it under #ifdef.

break;

case GS_GROUNDDRIFT:
Expand All @@ -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:
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

) {
//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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

}
}
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

}
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){
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

}
}
}

//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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

{
short cri = sstatus->cri;
if (sd != NULL) {
Expand Down Expand Up @@ -4716,6 +4710,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
}
if (flag.cri) {
wd.type = BDT_CRIT;
#ifdef RENEWAL
if (battle_config.feature_enable_multi_crit == 1 && (wd.type & BDT_MULTIHIT) != 0)
wd.type = BDT_MULTICRIT;
#endif
#ifndef RENEWAL
flag.idef = flag.idef2 =
#endif
Expand Down Expand Up @@ -7449,6 +7447,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)
Expand Down Expand Up @@ -7586,6 +7585,13 @@ static void battle_adjust_conf(void)
}
#endif

#if PACKETVER < 20161207
if( battle_config.feature_enable_multi_crit ) {
jenkijo marked this conversation as resolved.
Show resolved Hide resolved
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");
Expand Down
29 changes: 16 additions & 13 deletions src/map/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

/**
Expand Down Expand Up @@ -591,6 +592,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;
Expand Down
7 changes: 5 additions & 2 deletions src/map/clif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is designed to call clif_calc_delay twice if type is not BDT_MULTICRIT? or this is error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's design to call twice

//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);
}

/*==========================================
Expand Down
15 changes: 14 additions & 1 deletion src/map/skill.c
Original file line number Diff line number Diff line change
Expand Up @@ -3102,7 +3102,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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of this changes should be put under #ifdef RENEWAL

break;

case AS_SPLASHER:
Expand Down Expand Up @@ -20117,6 +20120,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;
Expand Down Expand Up @@ -20466,6 +20473,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) {
jenkijo marked this conversation as resolved.
Show resolved Hide resolved
sk->nk |= NK_CRITICAL;
} else {
sk->nk &= ~NK_CRITICAL;
}
} else {
skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
}
Expand Down
3 changes: 2 additions & 1 deletion src/map/skill.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,15 @@ 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,
NK_NO_ELEFIX = 0x10,
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.
Expand Down