diff --git a/common/ruletypes.h b/common/ruletypes.h index c7f1ce6fb..456af6bcd 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -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, 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, 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, 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.") diff --git a/zone/bot.cpp b/zone/bot.cpp index c7bdd38ea..14d320373 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2287,7 +2287,7 @@ void Bot::AI_Process() // COMBAT RANGE CALCS bool front_mob = InFrontMob(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 // Item variables const EQ::ItemInstance* p_item = GetBotItem(EQ::invslot::slotPrimary); @@ -2442,7 +2442,7 @@ void Bot::AI_Process() ranged_timer.Start(); } - else if (!IsBotRanged() && GetLevel() < stop_melee_level) { + else if (!IsBotRanged() && !stop_melee_level) { if ( IsTaunting() || !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_shield = input.s_item && input.s_item->GetItem()->IsTypeShield(); 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 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 = std::min(max_distance, desired_range); } - else if (is_stop_melee_level) { // Casters + else if (input.stop_melee_level) { // Casters float desired_range = GetBotDistanceRanged(); o.melee_distance_min = std::max(o.melee_distance_max, (desired_range / 2)); @@ -12020,74 +12019,53 @@ void Bot::DoCombatPositioning( bool behind_mob, bool front_mob ) { - if (HasTargetReflection()) { - if (tar->IsRooted() && !IsTaunting()) { // Move non-taunters out of range - if (tar_distance <= melee_distance_max) { - if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, (melee_distance_max + 1), (melee_distance_max * 1.25f), GetBehindMob(), false)) { - RunToGoalWithJitter(Goal); + if (!tar->IsFeared()) { + bool is_too_close = tar_distance < melee_distance_min; + bool los_adjust = !HasRequiredLoSForPositioning(tar); + 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; } } } - else if ( - 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; - } - } - + else { if (IsTaunting()) { // Taunting adjustments - Mob* mob_tar = tar->GetTarget(); + bool taunting_adjust = (!front_mob || is_too_close || los_adjust); - if (mob_tar) { - if ( - 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(); + if (taunting_adjust) { + if (PlotBotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z, melee_distance_min, melee_distance, false, true)) { RunToGoalWithJitter(Goal); return; } - else { // Otherwise, stick to any other bots that are taunting - if ( - mob_tar->IsBot() && - mob_tar->CastToBot()->IsTaunting() && - (Distance(m_Position, mob_tar->GetPosition()) > RuleI(Bots, DistanceTauntingBotsStickMainHate)) - ) { - Goal = mob_tar->GetPosition(); + } + } + else { + if (tar->IsEnraged() && !stop_melee_level && !IsBotRanged()) { // Move non-taunting melee bots behind target during enrage + bool enraged_adjust = !behind_mob || is_too_close || los_adjust; + + 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); return; @@ -12099,8 +12077,6 @@ void Bot::DoCombatPositioning( } 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) { @@ -12197,7 +12173,11 @@ bool Bot::RequiresLoSForPositioning() { } 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; } } diff --git a/zone/bot.h b/zone/bot.h index 504eafe70..2503006c0 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -235,7 +235,7 @@ static std::map botSubType_names = { struct CombatRangeInput { Mob* target; float target_distance; - uint8 stop_melee_level; + bool stop_melee_level; const EQ::ItemInstance* p_item; const EQ::ItemInstance* s_item; };