diff --git a/zone/bot.cpp b/zone/bot.cpp index 05fdf184e..b0435dbe4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2041,6 +2041,20 @@ void Bot::SetTarget(Mob* mob) { } } +void Bot::SetGuardMode() { + WipeHateList(); + SetTarget(nullptr); + SetFollowID(GetID()); + StopMoving(); + m_GuardPoint = GetPosition(); + + if (HasPet()) { + GetPet()->WipeHateList(); + GetPet()->SetTarget(nullptr); + GetPet()->StopMoving(); + } +} + // AI Processing for the Bot object void Bot::AI_Process() { @@ -2091,6 +2105,8 @@ void Bot::AI_Process() { return; } + bool guard_mode = (follow_mob == this); + auto fm_dist = DistanceSquared(m_Position, follow_mob->GetPosition()); auto lo_distance = DistanceSquared(m_Position, leash_owner->GetPosition()); @@ -2113,6 +2129,17 @@ void Bot::AI_Process() { return; if (fm_dist > GetFollowDistance()) // Cancel out-of-combat casting if movement is required InterruptSpell(); + if (guard_mode) { + auto& my_pos = GetPosition(); + auto& my_guard = GetGuardPoint(); + + if (my_pos.x != my_guard.x || + my_pos.y != my_guard.y || + my_pos.z != my_guard.z) + { + InterruptSpell(); + } + } return; } @@ -2147,7 +2174,7 @@ void Bot::AI_Process() { } // Empty hate list - let's find a target - if (!IsEngaged()) { + if (!guard_mode && !IsEngaged()) { Mob* lo_target = leash_owner->GetTarget(); if (lo_target && lo_target->IsNPC() && @@ -2234,7 +2261,8 @@ void Bot::AI_Process() { // Let's check if we have a los with our target. // If we don't, our hate_list is wiped. // Else, it was causing the bot to aggro behind wall etc... causing massive trains. - if (!tar->IsNPC() || + if (guard_mode || + !tar->IsNPC() || tar->IsMezzed() || (!tar->GetHateAmount(this) && !tar->GetHateAmount(leash_owner) && !leash_owner->AutoAttackEnabled()) || lo_distance > BOT_LEASH_DISTANCE || @@ -2698,8 +2726,28 @@ void Bot::AI_Process() { if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); + // Check guard point + if (guard_mode) { + auto& my_pos = GetPosition(); + auto& my_guard = GetGuardPoint(); + + if (my_pos.x != my_guard.x || + my_pos.y != my_guard.y || + my_pos.z != my_guard.z) + { + if (IsMoving()) + StopMoving(); + + Warp(glm::vec3(my_guard)); + + if (HasPet()) + GetPet()->Warp(glm::vec3(my_guard)); + + return; + } + } // Leash the bot - if (lo_distance > BOT_LEASH_DISTANCE) { + else if (lo_distance > BOT_LEASH_DISTANCE) { if (IsMoving()) StopMoving(); diff --git a/zone/bot.h b/zone/bot.h index d945c13be..c69405011 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -339,6 +339,7 @@ public: bool IsStanding(); int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); } + int GetBotFearSpeed() const { return (int)((float)_GetFearSpeed() * 1.786f); } bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); @@ -405,6 +406,7 @@ public: bool AIHealRotation(Mob* tar, bool useFastHeals); bool GetPauseAI() { return _pauseAI; } void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; } + void SetGuardMode(); // Mob AI Virtual Override Methods virtual void AI_Process(); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index b45c2b26a..e94825929 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -3047,13 +3047,7 @@ void bot_command_guard(Client *c, const Seperator *sep) sbl.remove(nullptr); for (auto bot_iter : sbl) { - bot_iter->WipeHateList(); - bot_iter->SetFollowID(0); - if (!bot_iter->GetPet()) - continue; - - bot_iter->GetPet()->WipeHateList(); - bot_iter->GetPet()->SetFollowID(0); + bot_iter->SetGuardMode(); } if (sbl.size() == 1) Bot::BotGroupSay(sbl.front(), "Guarding this position");