mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-02-23 12:04:34 +00:00
# Pull Request
This is the first in a series of PRs intended to eliminate warnings in
the module. The design intent is to eliminate the calling event when not
needed in the body of the function. Based off of SmashingQuasars work.
---
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific
configuration)
- Expected behavior and how to verify it
## Complexity & Impact
- Does this change add new decision branches?
- [x] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [x] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [x] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [x] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working
on this change?
- [x] No
- [ ] Yes (**explain below**)
---
## Final Checklist
- [x] Stability is not compromised
- [x] Performance impact is understood, tested, and acceptable
- [x] Added logic complexity is justified and explained
- [x] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or
performance should be carefully discussed
before merging.
---------
Co-authored-by: bashermens <31279994+hermensbas@users.noreply.github.com>
170 lines
4.8 KiB
C++
170 lines
4.8 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#include "FollowActions.h"
|
|
|
|
#include "Event.h"
|
|
#include "Formations.h"
|
|
#include "LastMovementValue.h"
|
|
#include "PlayerbotAI.h"
|
|
#include "Playerbots.h"
|
|
#include "ServerFacade.h"
|
|
|
|
bool FollowAction::Execute(Event /*event*/)
|
|
{
|
|
Formation* formation = AI_VALUE(Formation*, "formation");
|
|
std::string const target = formation->GetTargetName();
|
|
|
|
bool moved = false;
|
|
if (!target.empty())
|
|
{
|
|
moved = Follow(AI_VALUE(Unit*, target));
|
|
}
|
|
else
|
|
{
|
|
WorldLocation loc = formation->GetLocation();
|
|
if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1)
|
|
return false;
|
|
|
|
MovementPriority priority = botAI->GetState() == BOT_STATE_COMBAT ? MovementPriority::MOVEMENT_COMBAT : MovementPriority::MOVEMENT_NORMAL;
|
|
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), false, false, false,
|
|
true, priority, true);
|
|
}
|
|
|
|
// This section has been commented out because it was forcing the pet to
|
|
// follow the bot on every "follow" action tick, overriding any attack or
|
|
// stay commands that might have been issued by the player.
|
|
// if (Pet* pet = bot->GetPet())
|
|
// {
|
|
// botAI->PetFollow();
|
|
// }
|
|
// if (moved)
|
|
// botAI->SetNextCheckDelay(sPlayerbotAIConfig.reactDelay);
|
|
|
|
return moved;
|
|
}
|
|
|
|
bool FollowAction::isUseful()
|
|
{
|
|
// move from group takes priority over follow as it's added and removed automatically
|
|
// (without removing/adding follow)
|
|
if (botAI->HasStrategy("move from group", BOT_STATE_COMBAT) ||
|
|
botAI->HasStrategy("move from group", BOT_STATE_NON_COMBAT))
|
|
return false;
|
|
|
|
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr)
|
|
return false;
|
|
|
|
Formation* formation = AI_VALUE(Formation*, "formation");
|
|
if (!formation)
|
|
return false;
|
|
|
|
std::string const target = formation->GetTargetName();
|
|
|
|
Unit* fTarget = nullptr;
|
|
if (!target.empty())
|
|
fTarget = AI_VALUE(Unit*, target);
|
|
else
|
|
fTarget = AI_VALUE(Unit*, "group leader");
|
|
|
|
if (fTarget)
|
|
{
|
|
if (fTarget->HasUnitState(UNIT_STATE_IN_FLIGHT))
|
|
return false;
|
|
|
|
if (!CanDeadFollow(fTarget))
|
|
return false;
|
|
|
|
if (fTarget->GetGUID() == bot->GetGUID())
|
|
return false;
|
|
}
|
|
|
|
float distance = 0.f;
|
|
if (!target.empty())
|
|
{
|
|
distance = AI_VALUE2(float, "distance", target);
|
|
}
|
|
else
|
|
{
|
|
WorldLocation loc = formation->GetLocation();
|
|
if (Formation::IsNullLocation(loc) || bot->GetMapId() != loc.GetMapId())
|
|
return false;
|
|
|
|
distance = bot->GetDistance(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
|
|
}
|
|
if (botAI->HasStrategy("master fishing", BOT_STATE_NON_COMBAT))
|
|
return ServerFacade::instance().IsDistanceGreaterThan(distance, sPlayerbotAIConfig.fishingDistanceFromMaster);
|
|
|
|
return ServerFacade::instance().IsDistanceGreaterThan(distance, formation->GetMaxDistance());
|
|
}
|
|
|
|
bool FollowAction::CanDeadFollow(Unit* target)
|
|
{
|
|
// In battleground, wait for spirit healer
|
|
if (bot->InBattleground() && !bot->IsAlive())
|
|
return false;
|
|
|
|
// Move to corpse when dead and player is alive or not a ghost.
|
|
if (!bot->IsAlive() && (target->IsAlive() || !target->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FleeToGroupLeaderAction::Execute(Event /*event*/)
|
|
{
|
|
Unit* fTarget = AI_VALUE(Unit*, "group leader");
|
|
bool canFollow = Follow(fTarget);
|
|
if (!canFollow)
|
|
{
|
|
// botAI->SetNextCheckDelay(5000);
|
|
return false;
|
|
}
|
|
|
|
WorldPosition targetPos(fTarget);
|
|
WorldPosition bosPos(bot);
|
|
float distance = bosPos.fDist(targetPos);
|
|
|
|
if (distance < sPlayerbotAIConfig.reactDistance * 3)
|
|
{
|
|
if (!urand(0, 3))
|
|
botAI->TellMaster("I am close, wait for me!");
|
|
}
|
|
else if (distance < 1000)
|
|
{
|
|
if (!urand(0, 10))
|
|
botAI->TellMaster("I heading to your position.");
|
|
}
|
|
else if (!urand(0, 20))
|
|
botAI->TellMaster("I am traveling to your position.");
|
|
|
|
botAI->SetNextCheckDelay(3000);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FleeToGroupLeaderAction::isUseful()
|
|
{
|
|
if (!botAI->GetGroupLeader())
|
|
return false;
|
|
|
|
if (botAI->GetGroupLeader() == bot)
|
|
return false;
|
|
|
|
Unit* target = AI_VALUE(Unit*, "current target");
|
|
if (target && botAI->GetGroupLeader()->GetTarget() == target->GetGUID())
|
|
return false;
|
|
|
|
if (!botAI->HasStrategy("follow", BOT_STATE_NON_COMBAT))
|
|
return false;
|
|
|
|
Unit* fTarget = AI_VALUE(Unit*, "group leader");
|
|
|
|
if (!CanDeadFollow(fTarget))
|
|
return false;
|
|
|
|
return true;
|
|
}
|