mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
This PR adjusts the execution priority of bot actions in Dungeon Finder (DF), modifying the relevance logic to make responses faster. The relevance calculation formula was changed in RpgAction::SetNextRpgAction to reduce the delay between activating actions, especially to improve the acceptance time of bots in DF queues. With these changes, bots now accept vacancies in a more agile and efficient way, optimizing overall response time.
204 lines
5.6 KiB
C++
204 lines
5.6 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#include "RpgAction.h"
|
|
|
|
#include <random>
|
|
|
|
#include "BattlegroundMgr.h"
|
|
#include "ChatHelper.h"
|
|
#include "EmoteAction.h"
|
|
#include "Event.h"
|
|
#include "Formations.h"
|
|
#include "Playerbots.h"
|
|
#include "ServerFacade.h"
|
|
#include "RpgSubActions.h"
|
|
|
|
bool RpgAction::Execute(Event event)
|
|
{
|
|
GuidPosition guidP = AI_VALUE(GuidPosition, "rpg target");
|
|
if (!guidP && botAI->GetMaster())
|
|
{
|
|
if (WorldObject* target = ObjectAccessor::GetWorldObject(*bot, botAI->GetMaster()->GetTarget()))
|
|
{
|
|
guidP = GuidPosition(target);
|
|
if (guidP)
|
|
{
|
|
RemIgnore(guidP);
|
|
SET_AI_VALUE(GuidPosition, "rpg target", guidP);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bot->GetShapeshiftForm() > 0)
|
|
bot->SetShapeshiftForm(FORM_NONE);
|
|
|
|
if (!SetNextRpgAction())
|
|
RESET_AI_VALUE(GuidPosition, "rpg target");
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RpgAction::isUseful() { return AI_VALUE(GuidPosition, "rpg target"); }
|
|
|
|
bool RpgAction::SetNextRpgAction()
|
|
{
|
|
Strategy* rpgStrategy;
|
|
std::vector<Action*> actions;
|
|
std::vector<uint32> relevances;
|
|
std::vector<TriggerNode*> triggerNodes;
|
|
|
|
|
|
for (auto& strategy : botAI->GetAiObjectContext()->GetSupportedStrategies())
|
|
{
|
|
if (strategy.find("rpg") == std::string::npos)
|
|
continue;
|
|
|
|
rpgStrategy = botAI->GetAiObjectContext()->GetStrategy(strategy);
|
|
|
|
rpgStrategy->InitTriggers(triggerNodes);
|
|
|
|
for (auto& triggerNode : triggerNodes)
|
|
{
|
|
Trigger* trigger = context->GetTrigger(triggerNode->getName());
|
|
|
|
if (trigger)
|
|
{
|
|
|
|
triggerNode->setTrigger(trigger);
|
|
|
|
NextAction** nextActions = triggerNode->getHandlers();
|
|
|
|
Trigger* trigger = triggerNode->getTrigger();
|
|
|
|
bool isChecked = false;
|
|
|
|
for (int32 i = 0; i < NextAction::size(nextActions); i++)
|
|
{
|
|
NextAction* nextAction = nextActions[i];
|
|
|
|
if (nextAction->getRelevance() > 5.0f)
|
|
continue;
|
|
|
|
if (!isChecked && !trigger->IsActive())
|
|
break;
|
|
|
|
isChecked = true;
|
|
|
|
Action* action = botAI->GetAiObjectContext()->GetAction(nextAction->getName());
|
|
if (!dynamic_cast<RpgEnabled*>(action) || !action->isPossible() || !action->isUseful())
|
|
continue;
|
|
|
|
actions.push_back(action);
|
|
relevances.push_back((nextAction->getRelevance() - 1) * 500);
|
|
}
|
|
NextAction::destroy(nextActions);
|
|
}
|
|
}
|
|
|
|
for (const auto i : triggerNodes)
|
|
{
|
|
delete i;
|
|
}
|
|
triggerNodes.clear();
|
|
}
|
|
|
|
if (actions.empty())
|
|
return false;
|
|
|
|
if (botAI->HasStrategy("debug rpg", BotState::BOT_STATE_NON_COMBAT))
|
|
{
|
|
std::vector<std::pair<Action*, uint32>> sortedActions;
|
|
|
|
for (int i = 0; i < actions.size(); i++)
|
|
sortedActions.push_back(std::make_pair(actions[i], relevances[i]));
|
|
|
|
std::sort(sortedActions.begin(), sortedActions.end(), [](std::pair<Action*, uint32>i, std::pair<Action*, uint32> j) {return i.second > j.second; });
|
|
|
|
std::stringstream ss;
|
|
ss << "------" << chat->FormatWorldobject(AI_VALUE(GuidPosition, "rpg target").GetWorldObject()) << "------";
|
|
bot->Say(ss.str(), LANG_UNIVERSAL);
|
|
botAI->TellMasterNoFacing(ss.str());
|
|
|
|
for (auto action : sortedActions)
|
|
{
|
|
std::ostringstream out;
|
|
|
|
out << " " << action.first->getName() << " " << action.second;
|
|
|
|
botAI->TellMasterNoFacing(out);
|
|
}
|
|
}
|
|
|
|
std::mt19937 gen(time(0));
|
|
|
|
sTravelMgr->weighted_shuffle(actions.begin(), actions.end(), relevances.begin(), relevances.end(), gen);
|
|
|
|
Action* action = actions.front();
|
|
|
|
if ((botAI->HasStrategy("debug", BotState::BOT_STATE_NON_COMBAT) || botAI->HasStrategy("debug rpg", BotState::BOT_STATE_NON_COMBAT)))
|
|
{
|
|
std::ostringstream out;
|
|
out << "do: ";
|
|
out << chat->FormatWorldobject(AI_VALUE(GuidPosition, "rpg target").GetWorldObject());
|
|
|
|
out << " " << action->getName();
|
|
|
|
botAI->TellMasterNoFacing(out);
|
|
}
|
|
|
|
SET_AI_VALUE(std::string, "next rpg action", action->getName());
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RpgAction::AddIgnore(ObjectGuid guid)
|
|
{
|
|
if (HasIgnore(guid))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
GuidSet& ignoreList = context->GetValue<GuidSet&>("ignore rpg target")->Get();
|
|
ignoreList.insert(guid);
|
|
|
|
if (ignoreList.size() > 50)
|
|
ignoreList.erase(ignoreList.begin());
|
|
|
|
context->GetValue<GuidSet&>("ignore rpg target")->Set(ignoreList);
|
|
|
|
return true;
|
|
}
|
|
bool RpgAction::RemIgnore(ObjectGuid guid)
|
|
{
|
|
if (!HasIgnore(guid))
|
|
return false;
|
|
|
|
GuidSet& ignoreList = context->GetValue<GuidSet&>("ignore rpg target")->Get();
|
|
ignoreList.erase(ignoreList.find(guid));
|
|
|
|
context->GetValue<GuidSet&>("ignore rpg target")->Set(ignoreList);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RpgAction::HasIgnore(ObjectGuid guid)
|
|
{
|
|
GuidSet& ignoreList = context->GetValue<GuidSet&>("ignore rpg target")->Get();
|
|
if (ignoreList.empty())
|
|
return false;
|
|
|
|
if (ignoreList.find(guid) == ignoreList.end())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CRpgAction::isUseful()
|
|
{
|
|
RESET_AI_VALUE(GuidPosition, "rpg target");
|
|
return true;
|
|
};
|