mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-26 13:42:29 +00:00
[Bots] Add checks to ensure bots and pets do not engage on ^pull (#4708)
This commit is contained in:
parent
63b1e6b4b4
commit
8b8b41dab3
160
zone/bot.cpp
160
zone/bot.cpp
@ -1856,6 +1856,7 @@ bool Bot::BotRangedAttack(Mob* other, bool can_double_attack) {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!GetPullingFlag() &&
|
!GetPullingFlag() &&
|
||||||
|
!GetReturningFlag() &&
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
GetBotStance() != Stance::Aggressive &&
|
GetBotStance() != Stance::Aggressive &&
|
||||||
@ -2115,8 +2116,10 @@ void Bot::SetHoldMode() {
|
|||||||
void Bot::AI_Process()
|
void Bot::AI_Process()
|
||||||
{
|
{
|
||||||
|
|
||||||
#define PULLING_BOT (GetPullingFlag() || GetReturningFlag())
|
#define PULLING_BOT (GetPullingFlag())
|
||||||
#define NOT_PULLING_BOT (!GetPullingFlag() && !GetReturningFlag())
|
#define NOT_PULLING_BOT (!GetPullingFlag())
|
||||||
|
#define RETURNING_BOT (GetReturningFlag())
|
||||||
|
#define NOT_RETURNING_BOT (!GetReturningFlag())
|
||||||
#define GUARDING (GetGuardFlag())
|
#define GUARDING (GetGuardFlag())
|
||||||
#define NOT_GUARDING (!GetGuardFlag())
|
#define NOT_GUARDING (!GetGuardFlag())
|
||||||
#define HOLDING (GetHoldFlag())
|
#define HOLDING (GetHoldFlag())
|
||||||
@ -2224,7 +2227,7 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
// PULLING FLAG (TARGET VALIDATION)
|
// PULLING FLAG (TARGET VALIDATION)
|
||||||
|
|
||||||
if (GetPullingFlag()) {
|
if (PULLING_BOT) {
|
||||||
if (!PullingFlagChecks(bot_owner)) {
|
if (!PullingFlagChecks(bot_owner)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2232,10 +2235,10 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
// RETURNING FLAG
|
// RETURNING FLAG
|
||||||
|
|
||||||
if (GetReturningFlag()) {
|
if (RETURNING_BOT) {
|
||||||
ReturningFlagChecks(bot_owner, leash_owner, fm_distance);
|
if (ReturningFlagChecks(bot_owner, leash_owner, fm_distance)) {
|
||||||
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEFAULT (ACQUIRE TARGET)
|
// DEFAULT (ACQUIRE TARGET)
|
||||||
@ -2268,7 +2271,7 @@ void Bot::AI_Process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This causes conflicts with default pet handler (bounces between targets)
|
// This causes conflicts with default pet handler (bounces between targets)
|
||||||
if (NOT_PULLING_BOT && HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
|
if (NOT_PULLING_BOT && NOT_RETURNING_BOT && HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
|
||||||
// We don't add to hate list here because it's assumed to already be on the list
|
// We don't add to hate list here because it's assumed to already be on the list
|
||||||
GetPet()->SetTarget(tar);
|
GetPet()->SetTarget(tar);
|
||||||
}
|
}
|
||||||
@ -2309,7 +2312,7 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
// PULLING FLAG (ACTIONABLE RANGE)
|
// PULLING FLAG (ACTIONABLE RANGE)
|
||||||
|
|
||||||
if (GetPullingFlag()) {
|
if (PULLING_BOT || RETURNING_BOT) {
|
||||||
if (!TargetValidation(tar)) { return; }
|
if (!TargetValidation(tar)) { return; }
|
||||||
|
|
||||||
if (!DoLosChecks(tar)) {
|
if (!DoLosChecks(tar)) {
|
||||||
@ -2368,7 +2371,11 @@ void Bot::AI_Process()
|
|||||||
// ENGAGED AT COMBAT RANGE
|
// ENGAGED AT COMBAT RANGE
|
||||||
|
|
||||||
// We can fight
|
// We can fight
|
||||||
if (at_combat_range) {
|
bool other_bot_pulling =
|
||||||
|
(bot_owner->GetBotPulling() && NOT_PULLING_BOT) &&
|
||||||
|
(bot_owner->GetBotPulling() && NOT_RETURNING_BOT);
|
||||||
|
|
||||||
|
if (!other_bot_pulling && at_combat_range) {
|
||||||
bool jitter_cooldown = false;
|
bool jitter_cooldown = false;
|
||||||
|
|
||||||
if (m_combat_jitter_timer.GetRemainingTime() > 1 && m_combat_jitter_timer.Enabled()) {
|
if (m_combat_jitter_timer.GetRemainingTime() > 1 && m_combat_jitter_timer.Enabled()) {
|
||||||
@ -2459,60 +2466,20 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
// ENGAGED NOT AT COMBAT RANGE
|
// ENGAGED NOT AT COMBAT RANGE
|
||||||
|
|
||||||
else if (!TryPursueTarget(leash_distance, Goal)) {
|
else if (!other_bot_pulling && !TryPursueTarget(leash_distance, Goal)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// End not in combat range
|
// End not in combat range
|
||||||
|
if (bot_owner->GetBotPulling() && HasPet()) {
|
||||||
TryMeditate();
|
|
||||||
}
|
|
||||||
else { // Out-of-combat behavior
|
|
||||||
SetAttackFlag(false);
|
|
||||||
SetCombatRoundForAlerts(false);
|
|
||||||
SetAttackingFlag(false);
|
|
||||||
|
|
||||||
if (!bot_owner->GetBotPulling()) {
|
|
||||||
SetPullingFlag(false);
|
|
||||||
SetReturningFlag(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AUTO DEFEND
|
|
||||||
|
|
||||||
if (TryAutoDefend(bot_owner, leash_distance) ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetTarget(nullptr);
|
|
||||||
|
|
||||||
if (
|
|
||||||
HasPet() &&
|
|
||||||
(
|
|
||||||
GetClass() != Class::Enchanter ||
|
|
||||||
GetPet()->GetPetType() != petAnimation ||
|
|
||||||
GetAA(aaAnimationEmpathy) >= 1
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
GetPet()->WipeHateList();
|
GetPet()->WipeHateList();
|
||||||
GetPet()->SetTarget(nullptr);
|
GetPet()->SetTarget(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)) {
|
TryMeditate();
|
||||||
SendRemovePlayerState(PlayerState::Aggressive);
|
}
|
||||||
}
|
else { // Out-of-combat behavior
|
||||||
|
DoOutOfCombatChecks(bot_owner, follow_mob, Goal, leash_distance, fm_distance);
|
||||||
// OK TO IDLE
|
|
||||||
|
|
||||||
// Ok to idle
|
|
||||||
if (TryNonCombatMovementChecks(bot_owner, follow_mob, Goal)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!IsBotNonSpellFighter() && AI_HasSpells() && TryIdleChecks(fm_distance)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (GetClass() == Class::Bard && AI_HasSpells() && TryBardMovementCasts()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2540,7 +2507,7 @@ bool Bot::TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, g
|
|||||||
|
|
||||||
float destination_distance = DistanceSquared(GetPosition(), Goal);
|
float destination_distance = DistanceSquared(GetPosition(), Goal);
|
||||||
|
|
||||||
if ((!bot_owner->GetBotPulling() || PULLING_BOT) && (destination_distance > GetFollowDistance())) {
|
if (destination_distance > GetFollowDistance()) {
|
||||||
if (!IsRooted()) {
|
if (!IsRooted()) {
|
||||||
if (rest_timer.Enabled()) {
|
if (rest_timer.Enabled()) {
|
||||||
rest_timer.Disable();
|
rest_timer.Disable();
|
||||||
@ -2580,9 +2547,56 @@ bool Bot::TryIdleChecks(float fm_distance) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, glm::vec3& Goal, float leash_distance, float fm_distance) {
|
||||||
|
SetAttackFlag(false);
|
||||||
|
SetCombatRoundForAlerts(false);
|
||||||
|
SetAttackingFlag(false);
|
||||||
|
|
||||||
|
if (PULLING_BOT || RETURNING_BOT || !bot_owner->GetBotPulling()) {
|
||||||
|
SetPullingFlag(false);
|
||||||
|
SetReturningFlag(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryAutoDefend(bot_owner, leash_distance) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetTarget(nullptr);
|
||||||
|
|
||||||
|
if (
|
||||||
|
HasPet() &&
|
||||||
|
(
|
||||||
|
GetClass() != Class::Enchanter ||
|
||||||
|
GetPet()->GetPetType() != petAnimation ||
|
||||||
|
GetAA(aaAnimationEmpathy) >= 1
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
GetPet()->WipeHateList();
|
||||||
|
GetPet()->SetTarget(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)) {
|
||||||
|
SendRemovePlayerState(PlayerState::Aggressive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok to idle
|
||||||
|
if (TryNonCombatMovementChecks(bot_owner, follow_mob, Goal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsBotNonSpellFighter() && AI_HasSpells() && TryIdleChecks(fm_distance)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetClass() == Class::Bard && AI_HasSpells() && TryBardMovementCasts()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This is as close as I could get without modifying the aggro mechanics and making it an expensive process...
|
// This is as close as I could get without modifying the aggro mechanics and making it an expensive process...
|
||||||
// 'class Client' doesn't make use of hate_list
|
// 'class Client' doesn't make use of hate_list
|
||||||
bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) {
|
bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) {
|
||||||
@ -3230,7 +3244,7 @@ bool Bot::IsValidTarget(
|
|||||||
SetCombatRoundForAlerts(false);
|
SetCombatRoundForAlerts(false);
|
||||||
SetAttackingFlag(false);
|
SetAttackingFlag(false);
|
||||||
|
|
||||||
if (PULLING_BOT) {
|
if (PULLING_BOT || RETURNING_BOT) {
|
||||||
SetPullingFlag(false);
|
SetPullingFlag(false);
|
||||||
SetReturningFlag(false);
|
SetReturningFlag(false);
|
||||||
bot_owner->SetBotPulling(false);
|
bot_owner->SetBotPulling(false);
|
||||||
@ -3263,7 +3277,7 @@ Mob* Bot::GetBotTarget(Client* bot_owner)
|
|||||||
SetAttackFlag(false);
|
SetAttackFlag(false);
|
||||||
SetAttackingFlag(false);
|
SetAttackingFlag(false);
|
||||||
|
|
||||||
if (PULLING_BOT) {
|
if (PULLING_BOT || RETURNING_BOT) {
|
||||||
// 'Flags' should only be set on the bot that is pulling
|
// 'Flags' should only be set on the bot that is pulling
|
||||||
SetPullingFlag(false);
|
SetPullingFlag(false);
|
||||||
SetReturningFlag(false);
|
SetReturningFlag(false);
|
||||||
@ -3293,23 +3307,33 @@ bool Bot::TargetValidation(Mob* other) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance) {
|
bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_distance) {
|
||||||
|
auto engage_range = (GetBotDistanceRanged() < 30 ? 30 : GetBotDistanceRanged());
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(NOT_GUARDING && fm_distance <= GetFollowDistance()) ||
|
(GetTarget() && Distance(GetPosition(), GetTarget()->GetPosition()) <= engage_range) &&
|
||||||
(GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())
|
(
|
||||||
|
(NOT_GUARDING && fm_distance <= GetFollowDistance()) ||
|
||||||
|
(GUARDING && DistanceSquared(GetPosition(), GetGuardPoint()) <= GetFollowDistance())
|
||||||
|
)
|
||||||
) { // Once we're back, clear blocking flags so everyone else can join in
|
) { // Once we're back, clear blocking flags so everyone else can join in
|
||||||
|
WipeHateList();
|
||||||
|
SetTarget(nullptr);
|
||||||
|
SetPullingFlag(false);
|
||||||
SetReturningFlag(false);
|
SetReturningFlag(false);
|
||||||
bot_owner->SetBotPulling(false);
|
bot_owner->SetBotPulling(false);
|
||||||
|
|
||||||
if (GetPet()) {
|
if (GetPet()) {
|
||||||
GetPet()->SetPetOrder(m_previous_pet_order);
|
GetPet()->SetPetOrder(m_previous_pet_order);
|
||||||
|
|
||||||
|
if (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 1) {
|
||||||
|
GetPet()->WipeHateList();
|
||||||
|
GetPet()->SetTarget(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to keep puller out of combat until they reach their 'return to' destination
|
|
||||||
WipeHateList();
|
|
||||||
|
|
||||||
if (!IsMoving()) {
|
if (!IsMoving()) {
|
||||||
glm::vec3 Goal(0, 0, 0);
|
glm::vec3 Goal(0, 0, 0);
|
||||||
|
|
||||||
@ -3348,8 +3372,6 @@ bool Bot::PullingFlagChecks(Client* bot_owner) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (GetTarget()->GetHateList().size()) {
|
else if (GetTarget()->GetHateList().size()) {
|
||||||
WipeHateList();
|
|
||||||
SetTarget(nullptr);
|
|
||||||
SetPullingFlag(false);
|
SetPullingFlag(false);
|
||||||
SetReturningFlag();
|
SetReturningFlag();
|
||||||
|
|
||||||
@ -3363,6 +3385,8 @@ bool Bot::PullingFlagChecks(Client* bot_owner) {
|
|||||||
if (GetPlayerState() & static_cast<uint32>(PlayerState::Aggressive)) {
|
if (GetPlayerState() & static_cast<uint32>(PlayerState::Aggressive)) {
|
||||||
SendRemovePlayerState(PlayerState::Aggressive);
|
SendRemovePlayerState(PlayerState::Aggressive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3516,7 +3540,7 @@ Client* Bot::SetLeashOwner(Client* bot_owner, Group* bot_group, Raid* raid, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Bot::SetOwnerTarget(Client* bot_owner) {
|
void Bot::SetOwnerTarget(Client* bot_owner) {
|
||||||
if (GetPet() && PULLING_BOT) {
|
if (GetPet() && (PULLING_BOT || RETURNING_BOT)) {
|
||||||
GetPet()->SetPetOrder(m_previous_pet_order);
|
GetPet()->SetPetOrder(m_previous_pet_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4959,7 +4983,7 @@ bool Bot::Death(Mob *killer_mob, int64 damage, uint16 spell_id, EQ::skills::Skil
|
|||||||
|
|
||||||
LeaveHealRotationMemberPool();
|
LeaveHealRotationMemberPool();
|
||||||
|
|
||||||
if ((GetPullingFlag() || GetReturningFlag()) && my_owner && my_owner->IsClient()) {
|
if ((PULLING_BOT || RETURNING_BOT) && my_owner && my_owner->IsClient()) {
|
||||||
my_owner->CastToClient()->SetBotPulling(false);
|
my_owner->CastToClient()->SetBotPulling(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1127,6 +1127,7 @@ public:
|
|||||||
bool TryAutoDefend(Client* bot_owner, float leash_distance);
|
bool TryAutoDefend(Client* bot_owner, float leash_distance);
|
||||||
bool TryIdleChecks(float fm_distance);
|
bool TryIdleChecks(float fm_distance);
|
||||||
bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal);
|
bool TryNonCombatMovementChecks(Client* bot_owner, const Mob* follow_mob, glm::vec3& Goal);
|
||||||
|
void DoOutOfCombatChecks(Client* bot_owner, Mob* follow_mob, glm::vec3& Goal, float leash_distance, float fm_distance);
|
||||||
bool TryBardMovementCasts();
|
bool TryBardMovementCasts();
|
||||||
bool BotRangedAttack(Mob* other, bool can_double_attack = false);
|
bool BotRangedAttack(Mob* other, bool can_double_attack = false);
|
||||||
bool CheckDoubleRangedAttack();
|
bool CheckDoubleRangedAttack();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user