mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51:29 +00:00
[Bots] Enraged positioning (#4789)
- Non-taunting melee bots will now properly go behind their target when it is enraged. - Reduces how often taunting bots adjust their positioning by removing unnecessary rules. - Cleans up CombatPositioning a bit
This commit is contained in:
parent
19e785b842
commit
deb298dda7
@ -863,8 +863,6 @@ RULE_REAL(Bots, UpperMeleeDistanceMultiplier, 0.55, "Furthest % of the hit box a
|
|||||||
RULE_REAL(Bots, UpperTauntingMeleeDistanceMultiplier, 0.45, "Furthest % of the hit box a taunting melee bot will get from the target. Default 0.45")
|
RULE_REAL(Bots, UpperTauntingMeleeDistanceMultiplier, 0.45, "Furthest % of the hit box a taunting melee bot will get from the target. Default 0.45")
|
||||||
RULE_REAL(Bots, UpperMaxMeleeRangeDistanceMultiplier, 0.95, "Furthest % of the hit box a max melee range melee bot will get from the target. Default 0.95")
|
RULE_REAL(Bots, UpperMaxMeleeRangeDistanceMultiplier, 0.95, "Furthest % of the hit box a max melee range melee bot will get from the target. Default 0.95")
|
||||||
RULE_BOOL(Bots, DisableSpecialAbilitiesAtMaxMelee, true, "If true, when bots are at max melee distance, special abilities including taunt will be disabled. Default True.")
|
RULE_BOOL(Bots, DisableSpecialAbilitiesAtMaxMelee, true, "If true, when bots are at max melee distance, special abilities including taunt will be disabled. Default True.")
|
||||||
RULE_BOOL(Bots, TauntingBotsFollowTopHate, true, "True Default. If true, bots that are taunting will attempt to stick with whoever currently is top hate.")
|
|
||||||
RULE_INT(Bots, DistanceTauntingBotsStickMainHate, 10, "If TauntingBotsFollowTopHate is enabled, this is the distance bots will try to stick to whoever currently is Top Hate.")
|
|
||||||
RULE_INT(Bots, MinJitterTimer, 500, "Minimum ms between bot movement jitter checks.")
|
RULE_INT(Bots, MinJitterTimer, 500, "Minimum ms between bot movement jitter checks.")
|
||||||
RULE_INT(Bots, MaxJitterTimer, 2500, "Maximum ms between bot movement jitter checks. Set to 0 to disable timer checks.")
|
RULE_INT(Bots, MaxJitterTimer, 2500, "Maximum ms between bot movement jitter checks. Set to 0 to disable timer checks.")
|
||||||
RULE_BOOL(Bots, PreventBotCampOnFD, true, "True Default. If true, players will not be able to camp bots while feign death.")
|
RULE_BOOL(Bots, PreventBotCampOnFD, true, "True Default. If true, players will not be able to camp bots while feign death.")
|
||||||
|
|||||||
108
zone/bot.cpp
108
zone/bot.cpp
@ -2287,7 +2287,7 @@ void Bot::AI_Process()
|
|||||||
// COMBAT RANGE CALCS
|
// COMBAT RANGE CALCS
|
||||||
bool front_mob = InFrontMob(tar, GetX(), GetY());
|
bool front_mob = InFrontMob(tar, GetX(), GetY());
|
||||||
bool behind_mob = BehindMob(tar, GetX(), GetY());
|
bool behind_mob = BehindMob(tar, GetX(), GetY());
|
||||||
uint8 stop_melee_level = GetStopMeleeLevel();
|
bool stop_melee_level = GetLevel() >= GetStopMeleeLevel();
|
||||||
tar_distance = sqrt(tar_distance); // sqrt this for future calculations
|
tar_distance = sqrt(tar_distance); // sqrt this for future calculations
|
||||||
// Item variables
|
// Item variables
|
||||||
const EQ::ItemInstance* p_item = GetBotItem(EQ::invslot::slotPrimary);
|
const EQ::ItemInstance* p_item = GetBotItem(EQ::invslot::slotPrimary);
|
||||||
@ -2442,7 +2442,7 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
ranged_timer.Start();
|
ranged_timer.Start();
|
||||||
}
|
}
|
||||||
else if (!IsBotRanged() && GetLevel() < stop_melee_level) {
|
else if (!IsBotRanged() && !stop_melee_level) {
|
||||||
if (
|
if (
|
||||||
IsTaunting() ||
|
IsTaunting() ||
|
||||||
!GetMaxMeleeRange() ||
|
!GetMaxMeleeRange() ||
|
||||||
@ -3128,7 +3128,6 @@ CombatRangeOutput Bot::EvaluateCombatRange(const CombatRangeInput& input) {
|
|||||||
bool is_two_hander = input.p_item && input.p_item->GetItem()->IsType2HWeapon();
|
bool is_two_hander = input.p_item && input.p_item->GetItem()->IsType2HWeapon();
|
||||||
bool is_shield = input.s_item && input.s_item->GetItem()->IsTypeShield();
|
bool is_shield = input.s_item && input.s_item->GetItem()->IsTypeShield();
|
||||||
bool is_backstab_weapon = input.p_item && input.p_item->GetItemBackstabDamage();
|
bool is_backstab_weapon = input.p_item && input.p_item->GetItemBackstabDamage();
|
||||||
bool is_stop_melee_level = GetLevel() >= input.stop_melee_level;
|
|
||||||
|
|
||||||
if (IsTaunting()) { // Taunting bots
|
if (IsTaunting()) { // Taunting bots
|
||||||
o.melee_distance_min = o.melee_distance_max * RuleR(Bots, LowerTauntingMeleeDistanceMultiplier);
|
o.melee_distance_min = o.melee_distance_max * RuleR(Bots, LowerTauntingMeleeDistanceMultiplier);
|
||||||
@ -3143,7 +3142,7 @@ CombatRangeOutput Bot::EvaluateCombatRange(const CombatRangeInput& input) {
|
|||||||
o.melee_distance_min = std::max(min_distance, (desired_range / 2));
|
o.melee_distance_min = std::max(min_distance, (desired_range / 2));
|
||||||
o.melee_distance = std::min(max_distance, desired_range);
|
o.melee_distance = std::min(max_distance, desired_range);
|
||||||
}
|
}
|
||||||
else if (is_stop_melee_level) { // Casters
|
else if (input.stop_melee_level) { // Casters
|
||||||
float desired_range = GetBotDistanceRanged();
|
float desired_range = GetBotDistanceRanged();
|
||||||
|
|
||||||
o.melee_distance_min = std::max(o.melee_distance_max, (desired_range / 2));
|
o.melee_distance_min = std::max(o.melee_distance_max, (desired_range / 2));
|
||||||
@ -12020,74 +12019,53 @@ void Bot::DoCombatPositioning(
|
|||||||
bool behind_mob,
|
bool behind_mob,
|
||||||
bool front_mob
|
bool front_mob
|
||||||
) {
|
) {
|
||||||
if (HasTargetReflection()) {
|
if (!tar->IsFeared()) {
|
||||||
if (tar->IsRooted() && !IsTaunting()) { // Move non-taunters out of range
|
bool is_too_close = tar_distance < melee_distance_min;
|
||||||
if (tar_distance <= melee_distance_max) {
|
bool los_adjust = !HasRequiredLoSForPositioning(tar);
|
||||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, (melee_distance_max + 1), (melee_distance_max * 1.25f), GetBehindMob(), false)) {
|
|
||||||
RunToGoalWithJitter(Goal);
|
|
||||||
|
|
||||||
|
if (tar->IsRooted() && !IsTaunting()) { // Move non-taunting melee out of range
|
||||||
|
bool rooted_adjust = tar_distance <= melee_distance_max && HasTargetReflection();
|
||||||
|
|
||||||
|
if (rooted_adjust) {
|
||||||
|
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, (melee_distance_max + 1), (melee_distance_max * 1.25f), GetBehindMob(), !GetBehindMob())) {
|
||||||
|
RunToGoalWithJitter(Goal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (
|
else {
|
||||||
tar_distance < melee_distance_min ||
|
|
||||||
(!front_mob && IsTaunting())
|
|
||||||
) { // Back up any bots that are too close or if they're taunting and not in front of the mob
|
|
||||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), (IsTaunting() || !GetBehindMob()))) {
|
|
||||||
RunToGoalWithJitter(Goal);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!tar->IsFeared()) {
|
|
||||||
if (
|
|
||||||
tar_distance < melee_distance_min ||
|
|
||||||
(GetBehindMob() && !behind_mob) ||
|
|
||||||
(IsTaunting() && !front_mob) ||
|
|
||||||
!HasRequiredLoSForPositioning(tar)
|
|
||||||
) { // Regular adjustment
|
|
||||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), (IsTaunting() || !GetBehindMob()))) {
|
|
||||||
RunToGoalWithJitter(Goal);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (
|
|
||||||
tar->IsEnraged() &&
|
|
||||||
!IsTaunting() &&
|
|
||||||
!stop_melee_level &&
|
|
||||||
!behind_mob
|
|
||||||
) { // Move non-taunting melee bots behind target during enrage
|
|
||||||
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, true)) {
|
|
||||||
RunToGoalWithJitter(Goal);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsTaunting()) { // Taunting adjustments
|
if (IsTaunting()) { // Taunting adjustments
|
||||||
Mob* mob_tar = tar->GetTarget();
|
bool taunting_adjust = (!front_mob || is_too_close || los_adjust);
|
||||||
|
|
||||||
if (mob_tar) {
|
if (taunting_adjust) {
|
||||||
if (
|
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, false, true)) {
|
||||||
RuleB(Bots, TauntingBotsFollowTopHate) &&
|
|
||||||
(Distance(m_Position, mob_tar->GetPosition()) > RuleI(Bots, DistanceTauntingBotsStickMainHate))
|
|
||||||
) { // If enabled, taunting bots will stick to top hate
|
|
||||||
Goal = mob_tar->GetPosition();
|
|
||||||
RunToGoalWithJitter(Goal);
|
RunToGoalWithJitter(Goal);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else { // Otherwise, stick to any other bots that are taunting
|
}
|
||||||
if (
|
}
|
||||||
mob_tar->IsBot() &&
|
else {
|
||||||
mob_tar->CastToBot()->IsTaunting() &&
|
if (tar->IsEnraged() && !stop_melee_level && !IsBotRanged()) { // Move non-taunting melee bots behind target during enrage
|
||||||
(Distance(m_Position, mob_tar->GetPosition()) > RuleI(Bots, DistanceTauntingBotsStickMainHate))
|
bool enraged_adjust = !behind_mob || is_too_close || los_adjust;
|
||||||
) {
|
|
||||||
Goal = mob_tar->GetPosition();
|
if (enraged_adjust) {
|
||||||
|
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, true)) {
|
||||||
|
RunToGoalWithJitter(Goal);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // Regular adjustments
|
||||||
|
bool regular_adjust =
|
||||||
|
is_too_close ||
|
||||||
|
los_adjust ||
|
||||||
|
(!GetBehindMob() && !front_mob) ||
|
||||||
|
(GetBehindMob() && !behind_mob);
|
||||||
|
|
||||||
|
if (regular_adjust) {
|
||||||
|
if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, GetBehindMob(), !GetBehindMob())) {
|
||||||
RunToGoalWithJitter(Goal);
|
RunToGoalWithJitter(Goal);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -12099,8 +12077,6 @@ void Bot::DoCombatPositioning(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DoFaceCheckNoJitter(tar);
|
DoFaceCheckNoJitter(tar);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only, bool front_only, bool bypass_los) {
|
bool Bot::PlotBotPositionAroundTarget(Mob* target, float& x_dest, float& y_dest, float& z_dest, float min_distance, float max_distance, bool behind_only, bool front_only, bool bypass_los) {
|
||||||
@ -12197,7 +12173,11 @@ bool Bot::RequiresLoSForPositioning() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
for (uint16 i = BotSpellTypes::START; i <= BotSpellTypes::END; ++i) {
|
||||||
if (IsBotSpellTypeDetrimental(i) && !GetSpellTypeHold(i)) {
|
if (IsHealBotSpellType(i) || i == BotSpellTypes::PBAENuke) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetSpellTypeHold(i)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -235,7 +235,7 @@ static std::map<uint16, std::string> botSubType_names = {
|
|||||||
struct CombatRangeInput {
|
struct CombatRangeInput {
|
||||||
Mob* target;
|
Mob* target;
|
||||||
float target_distance;
|
float target_distance;
|
||||||
uint8 stop_melee_level;
|
bool stop_melee_level;
|
||||||
const EQ::ItemInstance* p_item;
|
const EQ::ItemInstance* p_item;
|
||||||
const EQ::ItemInstance* s_item;
|
const EQ::ItemInstance* s_item;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user