diff --git a/src/map/battle.c b/src/map/battle.c index cdf3dee4938..c361818943e 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1479,7 +1479,7 @@ static int64 battle_calc_defense(int attack_type, struct block_list *src, struct def1 = 0; if (def2 < 1) def2 = 1; - + //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def if (tsd) { //Sd vit-eq @@ -6500,6 +6500,38 @@ static bool battle_check_arrows(struct map_session_data *sd) return true; } +/** + * Check whether an attack from "attacker" unit to "target" unit should cause Blade Stop to start. + * @param attacker the unit performing the attack + * @param target the unit being attacked + * @returns true if Blade Stop should start, false otherwise + */ +static bool battle_should_bladestop_attacker(struct block_list *attacker, struct block_list *target) +{ + nullpo_retr(false, attacker); + nullpo_retr(false, target); + + struct status_change *tsc = status->get_sc(target); + if (tsc == NULL || tsc->data[SC_BLADESTOP_WAIT] == NULL) + return false; // Target is not in BladeStop wait mode + + if (is_boss(attacker)) + return false; // Boss monsters are not affected + +#ifndef RENEWAL + if (attacker->type == BL_PC) + return true; // In Pre-RE (Ep 11.2), player attackers are BladeStopped regardless of the distance +#endif + + if (target->type != BL_PC) { + // Non-player targets causes BladeStop regardless of distance (Hercules-custom). + // Officially, non-player units does not use Blade Stop. + return true; + } + + return (distance_bl(attacker, target) <= 2); +} + /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ @@ -6565,8 +6597,7 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_ return ATK_BLOCK; } } - if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->weapontype == W_FIST ? 1 : 2)) ) - { + if (tsc != NULL && battle->should_bladestop_attacker(src, target)) { uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1; int duration = skill->get_time2(MO_BLADESTOP,skill_lv); status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); @@ -8150,6 +8181,7 @@ void battle_defaults(void) battle->calc_gvg_damage = battle_calc_gvg_damage; battle->calc_bg_damage = battle_calc_bg_damage; battle->weapon_attack = battle_weapon_attack; + battle->should_bladestop_attacker = battle_should_bladestop_attacker; battle->check_arrows = battle_check_arrows; battle->calc_weapon_attack = battle_calc_weapon_attack; battle->delay_damage = battle_delay_damage; diff --git a/src/map/battle.h b/src/map/battle.h index 5f5aba80c60..493a9aab184 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -707,6 +707,8 @@ struct battle_interface { int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); /* normal weapon attack */ enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag); + /* returns whether bladestop should start for attacker/target */ + bool (*should_bladestop_attacker) (struct block_list *src, struct block_list *target); /* check is equipped ammo and this ammo allowed */ bool (*check_arrows) (struct map_session_data *sd); /* calculate weapon attack */ diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 4fc5b5ac6ef..ffcd18b114a 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -464,6 +464,8 @@ typedef int64 (*HPMHOOK_pre_battle_calc_bg_damage) (struct block_list **src, str typedef int64 (*HPMHOOK_post_battle_calc_bg_damage) (int64 retVal___, struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); typedef enum damage_lv (*HPMHOOK_pre_battle_weapon_attack) (struct block_list **bl, struct block_list **target, int64 *tick, int *flag); typedef enum damage_lv (*HPMHOOK_post_battle_weapon_attack) (enum damage_lv retVal___, struct block_list *bl, struct block_list *target, int64 tick, int flag); +typedef bool (*HPMHOOK_pre_battle_should_bladestop_attacker) (struct block_list **src, struct block_list **target); +typedef bool (*HPMHOOK_post_battle_should_bladestop_attacker) (bool retVal___, struct block_list *src, struct block_list *target); typedef bool (*HPMHOOK_pre_battle_check_arrows) (struct map_session_data **sd); typedef bool (*HPMHOOK_post_battle_check_arrows) (bool retVal___, struct map_session_data *sd); typedef struct Damage (*HPMHOOK_pre_battle_calc_weapon_attack) (struct block_list **src, struct block_list **target, uint16 *skill_id, uint16 *skill_lv, int *wflag); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index fcbcb1af46d..e82ebbe6ce7 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -230,6 +230,8 @@ struct { struct HPMHookPoint *HP_battle_calc_bg_damage_post; struct HPMHookPoint *HP_battle_weapon_attack_pre; struct HPMHookPoint *HP_battle_weapon_attack_post; + struct HPMHookPoint *HP_battle_should_bladestop_attacker_pre; + struct HPMHookPoint *HP_battle_should_bladestop_attacker_post; struct HPMHookPoint *HP_battle_check_arrows_pre; struct HPMHookPoint *HP_battle_check_arrows_post; struct HPMHookPoint *HP_battle_calc_weapon_attack_pre; @@ -7783,6 +7785,8 @@ struct { int HP_battle_calc_bg_damage_post; int HP_battle_weapon_attack_pre; int HP_battle_weapon_attack_post; + int HP_battle_should_bladestop_attacker_pre; + int HP_battle_should_bladestop_attacker_post; int HP_battle_check_arrows_pre; int HP_battle_check_arrows_post; int HP_battle_calc_weapon_attack_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index f8374cbb049..386ec7093ed 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -133,6 +133,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(battle->calc_gvg_damage, HP_battle_calc_gvg_damage) }, { HP_POP(battle->calc_bg_damage, HP_battle_calc_bg_damage) }, { HP_POP(battle->weapon_attack, HP_battle_weapon_attack) }, + { HP_POP(battle->should_bladestop_attacker, HP_battle_should_bladestop_attacker) }, { HP_POP(battle->check_arrows, HP_battle_check_arrows) }, { HP_POP(battle->calc_weapon_attack, HP_battle_calc_weapon_attack) }, { HP_POP(battle->delay_damage, HP_battle_delay_damage) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index d0cbea1c529..431d9dc28c8 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -2780,6 +2780,33 @@ enum damage_lv HP_battle_weapon_attack(struct block_list *bl, struct block_list } return retVal___; } +bool HP_battle_should_bladestop_attacker(struct block_list *src, struct block_list *target) { + int hIndex = 0; + bool retVal___ = false; + if (HPMHooks.count.HP_battle_should_bladestop_attacker_pre > 0) { + bool (*preHookFunc) (struct block_list **src, struct block_list **target); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_battle_should_bladestop_attacker_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_battle_should_bladestop_attacker_pre[hIndex].func; + retVal___ = preHookFunc(&src, &target); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + retVal___ = HPMHooks.source.battle.should_bladestop_attacker(src, target); + } + if (HPMHooks.count.HP_battle_should_bladestop_attacker_post > 0) { + bool (*postHookFunc) (bool retVal___, struct block_list *src, struct block_list *target); + for (hIndex = 0; hIndex < HPMHooks.count.HP_battle_should_bladestop_attacker_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_battle_should_bladestop_attacker_post[hIndex].func; + retVal___ = postHookFunc(retVal___, src, target); + } + } + return retVal___; +} bool HP_battle_check_arrows(struct map_session_data *sd) { int hIndex = 0; bool retVal___ = false;