Rewrite ^pull logic and handling. **MORE**

Add ^setassistee command to set who your bots will assist. Bots will always assist you first before anyone else.

If the rule Bots, AllowCrossGroupRaidAssist is enabled bots will assist the group or raid main assists.

Rewrites logic in handling of pull and returning to ensure bots make it back to their location.
This commit is contained in:
nytmyr
2024-12-05 07:21:34 -06:00
parent d6df4aae3f
commit 3d4474861c
6 changed files with 199 additions and 25 deletions
+1
View File
@@ -880,6 +880,7 @@ RULE_BOOL(Bots, AllowCommandedResurrect, true, "If enabled bots can be commanded
RULE_BOOL(Bots, AllowCommandedSummonCorpse, true, "If enabled bots can be commanded to summon other's corpses.")
RULE_INT(Bots, CampTimer, 25, "Number of seconds after /camp has begun before bots camp out.")
RULE_BOOL(Bots, SendClassRaceOnHelp, true, "If enabled a reminder of how to check class/race IDs will be sent when using compatible commands.")
RULE_BOOL(Bots, AllowCrossGroupRaidAssist, true, "If enabled bots will autodefend group or raid members set as main assist.")
RULE_CATEGORY_END()
RULE_CATEGORY(Chat)
+133 -25
View File
@@ -2039,6 +2039,7 @@ void Bot::AI_Process()
auto raid = entity_list.GetRaidByBotName(GetName());
uint32 r_group = RAID_GROUPLESS;
if (raid) {
raid->VerifyRaid();
r_group = raid->GetGroup(GetName());
@@ -2135,7 +2136,6 @@ void Bot::AI_Process()
// RETURNING FLAG
if (GetReturningFlag()) {
LogTestDebugDetail("#{}: {} has ReturningFlag", __LINE__, GetCleanName()); //deleteme
ReturningFlagChecks(bot_owner, leash_owner, fm_distance);
return;
@@ -2208,6 +2208,7 @@ void Bot::AI_Process()
if (!DoLosChecks(this, tar)) {
return;
}
if (atCombatRange) {
if (RuleB(Bots, AllowRangedPulling) && IsBotRanged() && ranged_timer.Check(false)) {
StopMoving(CalculateHeadingToTarget(tar->GetX(), tar->GetY()));
@@ -2244,8 +2245,8 @@ void Bot::AI_Process()
}
TryPursueTarget(leash_distance, Goal);
return;
//TODO bot rewrite - need pulling checks below to prevent assist
}
// ENGAGED AT COMBAT RANGE
@@ -2457,42 +2458,150 @@ bool Bot::TryAutoDefend(Client* bot_owner, float leash_distance) {
if (
m_auto_defend_timer.Check() &&
bot_owner->GetAggroCount() &&
NOT_HOLDING &&
NOT_PASSIVE
) {
auto xhaters = bot_owner->GetXTargetAutoMgr();
XTargetAutoHaters* tempHaters;
std::vector<XTargetAutoHaters*> assisteeHaters;
std::vector<Client*> assisteeMembers;
bool found = false;
if (xhaters && !xhaters->empty()) {
for (auto hater_iter : xhaters->get_list()) {
if (!hater_iter.spawn_id) {
continue;
}
if (bot_owner->GetAggroCount()) {
tempHaters = bot_owner->GetXTargetAutoMgr();
if (bot_owner->GetBotPulling() && bot_owner->GetTarget() && hater_iter.spawn_id == bot_owner->GetTarget()->GetID()) {
continue;
}
if (tempHaters && !tempHaters->empty()) {
assisteeHaters.emplace_back(tempHaters);
assisteeMembers.emplace_back(bot_owner);
}
}
auto hater = entity_list.GetMob(hater_iter.spawn_id);
if (hater && hater->CastToNPC()->IsOnHatelist(bot_owner) && !hater->IsMezzed() && DistanceSquared(hater->GetPosition(), bot_owner->GetPosition()) <= leash_distance) {
// This is roughly equivilent to npc attacking a client pet owner
AddToHateList(hater, 1);
SetTarget(hater);
SetAttackingFlag();
if (
(!bot_owner->GetAssistee() || !entity_list.GetClientByCharID(bot_owner->GetAssistee())) &&
RuleB(Bots, AllowCrossGroupRaidAssist)
) {
XTargetAutoHaters* temp_xhaters = bot_owner->GetXTargetAutoMgr();
bool assisteeFound = false;
if (HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
GetPet()->AddToHateList(hater, 1);
GetPet()->SetTarget(hater);
if (IsRaidGrouped()) {
Raid* r = entity_list.GetRaidByBotName(GetName());
if (r) {
for (const auto& m : r->members) {
if (
m.member &&
m.member->IsClient() &&
m.member->GetAggroCount() &&
r->IsAssister(m.member_name)
) {
temp_xhaters = m.member->GetXTargetAutoMgr();
if (!temp_xhaters || temp_xhaters->empty()) {
continue;
}
assisteeHaters.emplace_back(temp_xhaters);
assisteeMembers.emplace_back(m.member);
}
}
}
}
else if (HasGroup()) {
Group* g = GetGroup();
if (g) {
for (auto& m : g->members) {
if (
m &&
m->IsClient() &&
m->CastToClient()->GetAggroCount() &&
g->AmIMainAssist(m->GetName())
) {
temp_xhaters = m->CastToClient()->GetXTargetAutoMgr();
m_auto_defend_timer.Disable();
if (!temp_xhaters || temp_xhaters->empty()) {
continue;
}
return true;
assisteeHaters.emplace_back(temp_xhaters);
assisteeMembers.emplace_back(m->CastToClient());
}
}
}
}
else {
return false;
}
}
else {
if (bot_owner->GetAssistee()) {
Client* c = entity_list.GetClientByCharID(bot_owner->GetAssistee());
if (bot_owner->IsInGroupOrRaid(c) && c->GetAggroCount()) {
tempHaters = bot_owner->GetXTargetAutoMgr();
if (tempHaters && !tempHaters->empty()) {
assisteeHaters.emplace_back(tempHaters);
assisteeMembers.emplace_back(c);
}
}
}
}
if (!assisteeHaters.empty()) {
for (XTargetAutoHaters* xHaters : assisteeHaters) {
if (!xHaters->empty()) {
for (auto hater_iter : xHaters->get_list()) {
if (!hater_iter.spawn_id) {
continue;
}
Mob* hater = nullptr;
for (Client* xMember : assisteeMembers) {
if (
xMember &&
xMember->GetBotPulling() &&
xMember->GetTarget() &&
(hater_iter.spawn_id == xMember->GetTarget()->GetID())
) {
continue;
}
hater = entity_list.GetMob(hater_iter.spawn_id);
if (
hater &&
!hater->IsMezzed() &&
(DistanceSquared(hater->GetPosition(), bot_owner->GetPosition()) <= leash_distance) &&
hater->CastToNPC()->IsOnHatelist(xMember)
) {
break;
}
hater = nullptr;
}
if (hater) {
AddToHateList(hater, 1);
SetTarget(hater);
SetAttackingFlag();
if (HasPet() && (GetClass() != Class::Enchanter || GetPet()->GetPetType() != petAnimation || GetAA(aaAnimationEmpathy) >= 2)) {
GetPet()->AddToHateList(hater, 1);
GetPet()->SetTarget(hater);
}
m_auto_defend_timer.Disable();
return true;
}
}
}
}
}
return false;
}
}
return false;
}
@@ -3052,6 +3161,7 @@ bool Bot::ReturningFlagChecks(Client* bot_owner, Mob* leash_owner, float fm_dist
Goal = follow_mob->GetPosition();
}
RunTo(Goal.x, Goal.y, Goal.z);
}
@@ -11283,8 +11393,6 @@ void Bot::DoCombatPositioning(
bool behindMob,
bool frontMob
) {
//LogTestDebug("{} says, 'DoCombatPositioning. {} #{}", GetCleanName(), __FILE__, __LINE__); //deleteme
if (HasTargetReflection()) {
if (!IsTaunting() && !tar->IsFeared() && !tar->IsStunned()) {
if (TryEvade(tar)) {
+2
View File
@@ -1336,6 +1336,7 @@ int bot_command_init(void)
bot_command_add("precombat", "Sets flag used to determine pre-combat behavior", AccountStatus::Player, bot_command_precombat) ||
bot_command_add("pull", "Orders a designated bot to 'pull' an enemy", AccountStatus::Player, bot_command_pull) ||
bot_command_add("release", "Releases a suspended bot's AI processing (with hate list wipe)", AccountStatus::Player, bot_command_release) ||
bot_command_add("setassistee", "Sets your target to be the person your bots assist. Bots will always assist you before others", AccountStatus::Player, bot_command_set_assistee) ||
bot_command_add("sithppercent", "HP threshold for a bot to start sitting in combat if allowed", AccountStatus::Player, bot_command_sit_hp_percent) ||
bot_command_add("sitincombat", "Toggles whether or a not a bot will attempt to med or sit to heal in combat", AccountStatus::Player, bot_command_sit_in_combat) ||
bot_command_add("sitmanapercent", "Mana threshold for a bot to start sitting in combat if allowed", AccountStatus::Player, bot_command_sit_mana_percent) ||
@@ -2243,6 +2244,7 @@ void SendSpellTypeWindow(Client* c, const Seperator* sep) {
#include "bot_commands/precombat.cpp"
#include "bot_commands/pull.cpp"
#include "bot_commands/release.cpp"
#include "bot_commands/set_assistee.cpp"
#include "bot_commands/sit_hp_percent.cpp"
#include "bot_commands/sit_in_combat.cpp"
#include "bot_commands/sit_mana_percent.cpp"
+1
View File
@@ -1747,6 +1747,7 @@ void bot_command_heritage(Client *c, const Seperator *sep);
void bot_command_inspect_message(Client *c, const Seperator *sep);
void bot_command_list_bots(Client *c, const Seperator *sep);
void bot_command_report(Client *c, const Seperator *sep);
void bot_command_set_assistee(Client* c, const Seperator* sep);
void bot_command_spawn(Client *c, const Seperator *sep);
void bot_command_stance(Client *c, const Seperator *sep);
void bot_command_stop_melee_level(Client *c, const Seperator *sep);
+59
View File
@@ -0,0 +1,59 @@
#include "../bot_command.h"
void bot_command_set_assistee(Client* c, const Seperator* sep)
{
if (helper_is_help_or_usage(sep->arg[1])) {
std::vector<std::string> description =
{
"Sets your bots to assist your target in addition to yourself"
};
std::vector<std::string> notes =
{
"- Your target must be another player in your group or raid.",
"- This needs to be set on every zone/camp you do."
};
std::vector<std::string> example_format = { };
std::vector<std::string> examples_one = { };
std::vector<std::string> examples_two = { };
std::vector<std::string> examples_three = { };
std::vector<std::string> actionables = { };
std::vector<std::string> options = { };
std::vector<std::string> options_one = { };
std::vector<std::string> options_two = { };
std::vector<std::string> options_three = { };
std::string popup_text = c->SendCommandHelpWindow(
c,
description,
notes,
example_format,
examples_one, examples_two, examples_three,
actionables,
options,
options_one, options_two, options_three
);
popup_text = DialogueWindow::Table(popup_text);
c->SendPopupToClient(sep->arg[0], popup_text.c_str());
return;
}
Mob* assistee = c->GetTarget();
if (assistee && assistee->IsClient() && c->IsInGroupOrRaid(assistee)) {
c->SetAssistee(assistee->CastToClient()->CharacterID());
c->Message(Chat::Green, "Your bots will now assist %s.", assistee->GetCleanName());
return;
}
c->Message(Chat::Yellow, "You can only set your bots to assist clients that are in your group or raid.");
return;
}
+3
View File
@@ -2221,6 +2221,8 @@ public:
bool GetBotPulling() { return m_bot_pulling; }
void SetBotPulling(bool flag = true) { m_bot_pulling = flag; }
uint32 GetAssistee() { return _assistee; }
void SetAssistee(uint32 id = 0) { _assistee = id; }
bool GetBotPrecombat() { return m_bot_precombat; }
void SetBotPrecombat(bool flag = true) { m_bot_precombat = flag; }
@@ -2257,6 +2259,7 @@ private:
uint8 cure_min_threshold;
uint8 cure_threshold;
bool illusion_block;
uint32 _assistee;
bool CanTradeFVNoDropItem();
void SendMobPositions();