mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #759 from liyunfan1223/new_rpg_strats
New rpg strategy
This commit is contained in:
@@ -596,6 +596,11 @@ AiPlayerbot.RandomBotGroupNearby = 0
|
||||
# Default: 1 (enabled)
|
||||
AiPlayerbot.AutoDoQuests = 1
|
||||
|
||||
# Random Bots will behave more like real players (exprimental)
|
||||
# This option will override AutoDoQuests
|
||||
# Default: 0 (disabled)
|
||||
AiPlayerbot.EnableNewRpgStrategy = 0
|
||||
|
||||
# Quest items to leave (do not destroy)
|
||||
AiPlayerbot.RandomBotQuestItems = "6948,5175,5176,5177,5178,16309,12382,13704,11000"
|
||||
|
||||
@@ -717,10 +722,10 @@ AiPlayerbot.RandomBotArenaTeamMinRating = 1000
|
||||
AiPlayerbot.DeleteRandomBotArenaTeams = 0
|
||||
|
||||
# PvP Restricted Zones (bots don't pvp)
|
||||
AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565,3539,3623,4152,3988,4658,4284,4418,4436,4275,4323,4395,3703,4298"
|
||||
AiPlayerbot.PvpProhibitedZoneIds = "2255,656,2361,2362,2363,976,35,2268,3425,392,541,1446,3828,3712,3738,3565,3539,3623,4152,3988,4658,4284,4418,4436,4275,4323,4395,3703,4298,139"
|
||||
|
||||
# PvP Restricted Areas (bots don't pvp)
|
||||
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392"
|
||||
AiPlayerbot.PvpProhibitedAreaIds = "976,35,392,2268"
|
||||
|
||||
# Improve react speed in battleground and arena (may cause lag)
|
||||
AiPlayerbot.FastReactInBG = 1
|
||||
|
||||
@@ -631,7 +631,11 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
// nonCombatEngine->addStrategy("group");
|
||||
// nonCombatEngine->addStrategy("guild");
|
||||
|
||||
if (sPlayerbotAIConfig->autoDoQuests)
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
{
|
||||
nonCombatEngine->addStrategy("new rpg", false);
|
||||
}
|
||||
else if (sPlayerbotAIConfig->autoDoQuests)
|
||||
{
|
||||
// nonCombatEngine->addStrategy("travel");
|
||||
nonCombatEngine->addStrategy("rpg", false);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "MotionMaster.h"
|
||||
#include "MoveSpline.h"
|
||||
#include "MoveSplineInit.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PerformanceMonitor.h"
|
||||
#include "Player.h"
|
||||
@@ -38,6 +39,7 @@
|
||||
#include "Playerbots.h"
|
||||
#include "PointMovementGenerator.h"
|
||||
#include "PositionValue.h"
|
||||
#include "RandomPlayerbotMgr.h"
|
||||
#include "SayAction.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ServerFacade.h"
|
||||
@@ -718,7 +720,7 @@ void PlayerbotAI::HandleTeleportAck()
|
||||
// SetNextCheckDelay(urand(2000, 5000));
|
||||
if (sPlayerbotAIConfig->applyInstanceStrategies)
|
||||
ApplyInstanceStrategies(bot->GetMapId(), true);
|
||||
Reset();
|
||||
Reset(true);
|
||||
}
|
||||
|
||||
SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown);
|
||||
@@ -767,12 +769,13 @@ void PlayerbotAI::Reset(bool full)
|
||||
->setTarget(sTravelMgr->nullTravelDestination, sTravelMgr->nullWorldPosition, true);
|
||||
aiObjectContext->GetValue<TravelTarget*>("travel target")->Get()->setStatus(TRAVEL_STATUS_EXPIRED);
|
||||
aiObjectContext->GetValue<TravelTarget*>("travel target")->Get()->setExpireIn(1000);
|
||||
rpgInfo = NewRpgInfo();
|
||||
}
|
||||
|
||||
aiObjectContext->GetValue<GuidSet&>("ignore rpg target")->Get().clear();
|
||||
|
||||
bot->GetMotionMaster()->Clear();
|
||||
// bot->CleanupAfterTaxiFlight();
|
||||
|
||||
InterruptSpell();
|
||||
|
||||
if (full)
|
||||
@@ -4112,19 +4115,10 @@ inline bool ZoneHasRealPlayers(Player* bot)
|
||||
return false;
|
||||
}
|
||||
|
||||
Map::PlayerList const& players = bot->GetMap()->GetPlayers();
|
||||
if (players.IsEmpty())
|
||||
for (auto& player : sRandomPlayerbotMgr->GetPlayers())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto const& itr : players)
|
||||
{
|
||||
Player* player = itr.GetSource();
|
||||
if (!player || !player->IsVisible())
|
||||
{
|
||||
if (player->GetMapId() != bot->GetMapId())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->GetZoneId() == bot->GetZoneId())
|
||||
{
|
||||
@@ -4143,16 +4137,16 @@ bool PlayerbotAI::AllowActive(ActivityType activityType)
|
||||
{
|
||||
// only keep updating till initializing time has completed,
|
||||
// which prevents unneeded expensive GameTime calls.
|
||||
if (_isBotInitializing)
|
||||
{
|
||||
_isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.12;
|
||||
// if (_isBotInitializing)
|
||||
// {
|
||||
// _isBotInitializing = GameTime::GetUptime().count() < sPlayerbotAIConfig->maxRandomBots * 0.12;
|
||||
|
||||
// no activity allowed during bot initialization
|
||||
if (_isBotInitializing)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// // no activity allowed during bot initialization
|
||||
// if (_isBotInitializing)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// General exceptions
|
||||
if (activityType == PACKET_ACTIVITY)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "PlayerbotTextMgr.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
|
||||
class AiObjectContext;
|
||||
class Creature;
|
||||
@@ -432,7 +433,7 @@ public:
|
||||
std::vector<Player*> GetPlayersInGroup();
|
||||
const AreaTableEntry* GetCurrentArea();
|
||||
const AreaTableEntry* GetCurrentZone();
|
||||
std::string GetLocalizedAreaName(const AreaTableEntry* entry);
|
||||
static std::string GetLocalizedAreaName(const AreaTableEntry* entry);
|
||||
|
||||
bool TellMaster(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
bool TellMaster(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
|
||||
@@ -572,6 +573,7 @@ public:
|
||||
std::set<uint32> GetCurrentIncompleteQuestIds();
|
||||
void PetFollow();
|
||||
static float GetItemScoreMultiplier(ItemQualities quality);
|
||||
NewRpgInfo rpgInfo;
|
||||
|
||||
private:
|
||||
static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore,
|
||||
@@ -580,7 +582,7 @@ private:
|
||||
|
||||
void HandleCommands();
|
||||
void HandleCommand(uint32 type, const std::string& text, Player& fromPlayer, const uint32 lang = LANG_UNIVERSAL);
|
||||
bool _isBotInitializing = true;
|
||||
bool _isBotInitializing = false;
|
||||
|
||||
protected:
|
||||
Player* bot;
|
||||
|
||||
@@ -399,6 +399,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
|
||||
worldBuffs.clear();
|
||||
|
||||
LOG_INFO("playerbots", "Loading Worldbuff...");
|
||||
for (uint32 factionId = 0; factionId < 3; factionId++)
|
||||
{
|
||||
for (uint32 classId = 0; classId < MAX_CLASSES; classId++)
|
||||
@@ -507,7 +508,8 @@ bool PlayerbotAIConfig::Initialize()
|
||||
autoLearnTrainerSpells = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoLearnTrainerSpells", true);
|
||||
autoLearnQuestSpells = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoLearnQuestSpells", false);
|
||||
autoTeleportForLevel = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoTeleportForLevel", false);
|
||||
autoDoQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoDoQuests", false);
|
||||
autoDoQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoDoQuests", true);
|
||||
enableNewRpgStrategy = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableNewRpgStrategy", false);
|
||||
syncLevelWithPlayers = sConfigMgr->GetOption<bool>("AiPlayerbot.SyncLevelWithPlayers", false);
|
||||
freeFood = sConfigMgr->GetOption<bool>("AiPlayerbot.FreeFood", true);
|
||||
randomBotGroupNearby = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGroupNearby", true);
|
||||
@@ -569,7 +571,7 @@ bool PlayerbotAIConfig::IsInRandomQuestItemList(uint32 id)
|
||||
|
||||
bool PlayerbotAIConfig::IsPvpProhibited(uint32 zoneId, uint32 areaId)
|
||||
{
|
||||
return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId);
|
||||
return IsInPvpProhibitedZone(zoneId) || IsInPvpProhibitedArea(areaId) || IsInPvpProhibitedZone(areaId);
|
||||
}
|
||||
|
||||
bool PlayerbotAIConfig::IsInPvpProhibitedZone(uint32 id)
|
||||
|
||||
@@ -287,6 +287,7 @@ public:
|
||||
bool autoUpgradeEquip;
|
||||
bool autoLearnTrainerSpells;
|
||||
bool autoDoQuests;
|
||||
bool enableNewRpgStrategy;
|
||||
bool syncLevelWithPlayers;
|
||||
bool freeFood;
|
||||
bool autoLearnQuestSpells;
|
||||
|
||||
@@ -556,7 +556,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
|
||||
totalRandomBotChars += AccountMgr::GetCharactersCount(accountId);
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", "{} random bot accounts with {} characters available",
|
||||
LOG_INFO("server.loading", ">> {} random bot accounts with {} characters available",
|
||||
sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <algorithm>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
|
||||
@@ -18,6 +19,8 @@
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "CellImpl.h"
|
||||
#include "ChannelMgr.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DBCStructure.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Define.h"
|
||||
#include "FleeManager.h"
|
||||
@@ -28,15 +31,19 @@
|
||||
#include "GuildTaskMgr.h"
|
||||
#include "LFGMgr.h"
|
||||
#include "MapMgr.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "PerformanceMonitor.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "PlayerbotCommandServer.h"
|
||||
#include "PlayerbotFactory.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Position.h"
|
||||
#include "Random.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "TravelMgr.h"
|
||||
#include "Unit.h"
|
||||
#include "UpdateTime.h"
|
||||
#include "World.h"
|
||||
@@ -363,6 +370,17 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
|
||||
sRandomPlayerbotMgr->CheckLfgQueue();
|
||||
}
|
||||
|
||||
if (time(nullptr) > (printStatsTimer + 300))
|
||||
{
|
||||
if (!printStatsTimer)
|
||||
{
|
||||
printStatsTimer = time(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
activatePrintStatsThread();
|
||||
}
|
||||
}
|
||||
uint32 updateBots = sPlayerbotAIConfig->randomBotsPerInterval * onlineBotFocus / 100;
|
||||
uint32 maxNewBots = onlineBotCount < maxAllowedBotCount ? maxAllowedBotCount - onlineBotCount : 0;
|
||||
uint32 loginBots = std::min(sPlayerbotAIConfig->randomBotsPerInterval - updateBots, maxNewBots);
|
||||
@@ -417,25 +435,25 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
|
||||
}
|
||||
}
|
||||
|
||||
//void RandomPlayerbotMgr::ScaleBotActivity()
|
||||
// void RandomPlayerbotMgr::ScaleBotActivity()
|
||||
//{
|
||||
// float activityPercentage = getActivityPercentage();
|
||||
// float activityPercentage = getActivityPercentage();
|
||||
//
|
||||
// // if (activityPercentage >= 100.0f || activityPercentage <= 0.0f) pid.reset(); //Stop integer buildup during
|
||||
// // max/min activity
|
||||
// // if (activityPercentage >= 100.0f || activityPercentage <= 0.0f) pid.reset(); //Stop integer buildup during
|
||||
// // max/min activity
|
||||
//
|
||||
// // % increase/decrease wanted diff , avg diff
|
||||
// float activityPercentageMod = pid.calculate(
|
||||
// sRandomPlayerbotMgr->GetPlayers().empty() ? sPlayerbotAIConfig->diffEmpty : sPlayerbotAIConfig->diffWithPlayer,
|
||||
// sWorldUpdateTime.GetAverageUpdateTime());
|
||||
// // % increase/decrease wanted diff , avg diff
|
||||
// float activityPercentageMod = pid.calculate(
|
||||
// sRandomPlayerbotMgr->GetPlayers().empty() ? sPlayerbotAIConfig->diffEmpty :
|
||||
// sPlayerbotAIConfig->diffWithPlayer, sWorldUpdateTime.GetAverageUpdateTime());
|
||||
//
|
||||
// activityPercentage = activityPercentageMod + 50;
|
||||
// activityPercentage = activityPercentageMod + 50;
|
||||
//
|
||||
// // Cap the percentage between 0 and 100.
|
||||
// activityPercentage = std::max(0.0f, std::min(100.0f, activityPercentage));
|
||||
// // Cap the percentage between 0 and 100.
|
||||
// activityPercentage = std::max(0.0f, std::min(100.0f, activityPercentage));
|
||||
//
|
||||
// setActivityPercentage(activityPercentage);
|
||||
//}
|
||||
// setActivityPercentage(activityPercentage);
|
||||
// }
|
||||
|
||||
uint32 RandomPlayerbotMgr::AddRandomBots()
|
||||
{
|
||||
@@ -521,7 +539,9 @@ uint32 RandomPlayerbotMgr::AddRandomBots()
|
||||
}
|
||||
|
||||
if (maxAllowedBotCount)
|
||||
LOG_ERROR("playerbots", "Not enough random bot accounts available. Need {} more!!",
|
||||
LOG_ERROR("playerbots",
|
||||
"Not enough random bot accounts available. Need {} more, try to increase RandomBotAccountCount "
|
||||
"in your conf file",
|
||||
ceil(maxAllowedBotCount / 10));
|
||||
}
|
||||
|
||||
@@ -597,7 +617,7 @@ void RandomPlayerbotMgr::CheckBgQueue()
|
||||
|
||||
BgCheckTimer = time(nullptr);
|
||||
|
||||
LOG_INFO("playerbots", "Checking BG Queue...");
|
||||
LOG_DEBUG("playerbots", "Checking BG Queue...");
|
||||
|
||||
BattlegroundData.clear();
|
||||
|
||||
@@ -915,7 +935,7 @@ void RandomPlayerbotMgr::LogBattlegroundInfo()
|
||||
bgInfo.bgHordePlayerCount + bgInfo.bgHordeBotCount, bgInfo.bgInstanceCount);
|
||||
}
|
||||
}
|
||||
LOG_INFO("playerbots", "BG Queue check finished");
|
||||
LOG_DEBUG("playerbots", "BG Queue check finished");
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::CheckLfgQueue()
|
||||
@@ -923,7 +943,7 @@ void RandomPlayerbotMgr::CheckLfgQueue()
|
||||
if (!LfgCheckTimer || time(nullptr) > (LfgCheckTimer + 30))
|
||||
LfgCheckTimer = time(nullptr);
|
||||
|
||||
LOG_INFO("playerbots", "Checking LFG Queue...");
|
||||
LOG_DEBUG("playerbots", "Checking LFG Queue...");
|
||||
|
||||
// Clear LFG list
|
||||
LfgDungeons[TEAM_ALLIANCE].clear();
|
||||
@@ -953,7 +973,7 @@ void RandomPlayerbotMgr::CheckLfgQueue()
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "LFG Queue check finished");
|
||||
LOG_DEBUG("playerbots", "LFG Queue check finished");
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::CheckPlayers()
|
||||
@@ -983,10 +1003,7 @@ void RandomPlayerbotMgr::CheckPlayers()
|
||||
LOG_INFO("playerbots", "Max player level is {}, max bot level set to {}", playersLevel - 3, playersLevel);
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::ScheduleRandomize(uint32 bot, uint32 time)
|
||||
{
|
||||
SetEventValue(bot, "randomize", 1, time);
|
||||
}
|
||||
void RandomPlayerbotMgr::ScheduleRandomize(uint32 bot, uint32 time) { SetEventValue(bot, "randomize", 1, time); }
|
||||
|
||||
void RandomPlayerbotMgr::ScheduleTeleport(uint32 bot, uint32 time)
|
||||
{
|
||||
@@ -1102,9 +1119,7 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
|
||||
if (update)
|
||||
ProcessBot(player);
|
||||
|
||||
randomTime = urand(
|
||||
sPlayerbotAIConfig->minRandomBotReviveTime,
|
||||
sPlayerbotAIConfig->maxRandomBotReviveTime);
|
||||
randomTime = urand(sPlayerbotAIConfig->minRandomBotReviveTime, sPlayerbotAIConfig->maxRandomBotReviveTime);
|
||||
SetEventValue(bot, "update", 1, randomTime);
|
||||
|
||||
return true;
|
||||
@@ -1117,9 +1132,8 @@ bool RandomPlayerbotMgr::ProcessBot(uint32 bot)
|
||||
player->GetLevel(), player->GetName().c_str());
|
||||
LogoutPlayerBot(botGUID);
|
||||
currentBots.remove(bot);
|
||||
SetEventValue(bot, "logout", 1, urand(
|
||||
sPlayerbotAIConfig->minRandomBotInWorldTime,
|
||||
sPlayerbotAIConfig->maxRandomBotInWorldTime));
|
||||
SetEventValue(bot, "logout", 1,
|
||||
urand(sPlayerbotAIConfig->minRandomBotInWorldTime, sPlayerbotAIConfig->maxRandomBotInWorldTime));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1141,11 +1155,10 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||
{
|
||||
if (!GetEventValue(bot, "dead"))
|
||||
{
|
||||
uint32 randomTime = urand(
|
||||
sPlayerbotAIConfig->minRandomBotReviveTime,
|
||||
sPlayerbotAIConfig->maxRandomBotReviveTime);
|
||||
LOG_INFO("playerbots", "Mark bot {} as dead, will be revived in {}s.",
|
||||
player->GetName().c_str(), randomTime);
|
||||
uint32 randomTime =
|
||||
urand(sPlayerbotAIConfig->minRandomBotReviveTime, sPlayerbotAIConfig->maxRandomBotReviveTime);
|
||||
LOG_DEBUG("playerbots", "Mark bot {} as dead, will be revived in {}s.", player->GetName().c_str(),
|
||||
randomTime);
|
||||
SetEventValue(bot, "dead", 1, sPlayerbotAIConfig->maxRandomBotInWorldTime);
|
||||
SetEventValue(bot, "revive", 1, randomTime);
|
||||
return false;
|
||||
@@ -1168,7 +1181,6 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||
LOG_INFO("playerbots", "Bot {} remove from group since leader is random bot.", player->GetName().c_str());
|
||||
}
|
||||
|
||||
|
||||
// only randomize and teleport idle bots
|
||||
bool idleBot = false;
|
||||
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
|
||||
@@ -1192,7 +1204,7 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||
uint32 randomize = GetEventValue(bot, "randomize");
|
||||
if (!randomize)
|
||||
{
|
||||
// bool randomiser = true;
|
||||
// bool randomiser = true;
|
||||
// if (player->GetGuildId())
|
||||
// {
|
||||
// if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
|
||||
@@ -1214,11 +1226,10 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||
// if (randomiser)
|
||||
// {
|
||||
Randomize(player);
|
||||
LOG_INFO("playerbots", "Bot #{} {}:{} <{}>: randomized",
|
||||
bot, player->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", player->GetLevel(), player->GetName());
|
||||
uint32 randomTime = urand(
|
||||
sPlayerbotAIConfig->minRandomBotRandomizeTime,
|
||||
sPlayerbotAIConfig->maxRandomBotRandomizeTime);
|
||||
LOG_DEBUG("playerbots", "Bot #{} {}:{} <{}>: randomized", bot,
|
||||
player->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", player->GetLevel(), player->GetName());
|
||||
uint32 randomTime =
|
||||
urand(sPlayerbotAIConfig->minRandomBotRandomizeTime, sPlayerbotAIConfig->maxRandomBotRandomizeTime);
|
||||
ScheduleRandomize(bot, randomTime);
|
||||
return true;
|
||||
}
|
||||
@@ -1234,12 +1245,11 @@ bool RandomPlayerbotMgr::ProcessBot(Player* player)
|
||||
uint32 teleport = GetEventValue(bot, "teleport");
|
||||
if (!teleport)
|
||||
{
|
||||
LOG_INFO("playerbots", "Bot #{} <{}>: teleport for level and refresh", bot, player->GetName());
|
||||
LOG_DEBUG("playerbots", "Bot #{} <{}>: teleport for level and refresh", bot, player->GetName());
|
||||
Refresh(player);
|
||||
RandomTeleportForLevel(player);
|
||||
uint32 time = urand(
|
||||
sPlayerbotAIConfig->minRandomBotTeleportInterval,
|
||||
sPlayerbotAIConfig->maxRandomBotTeleportInterval);
|
||||
uint32 time = urand(sPlayerbotAIConfig->minRandomBotTeleportInterval,
|
||||
sPlayerbotAIConfig->maxRandomBotTeleportInterval);
|
||||
ScheduleTeleport(bot, time);
|
||||
return true;
|
||||
}
|
||||
@@ -1282,9 +1292,8 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
||||
if (botAI)
|
||||
{
|
||||
// ignore when in when taxi with boat/zeppelin and has players nearby
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) &&
|
||||
bot->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) &&
|
||||
botAI->HasPlayerNearby())
|
||||
if (bot->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && bot->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) &&
|
||||
botAI->HasPlayerNearby())
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1373,17 +1382,19 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (bot->GetLevel() <= 18 && (loc.GetMapId() != pInfo->mapId || dis > 10000.0f))
|
||||
if (bot->GetLevel() <= 16 && (loc.GetMapId() != pInfo->mapId || dis > 10000.0f))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const LocaleConstant& locale = sWorld->GetDefaultDbcLocale();
|
||||
LOG_INFO("playerbots",
|
||||
"Random teleporting bot {} (level {}) to Map: {} ({}) Zone: {} ({}) Area: {} ({}) {},{},{} ({}/{} "
|
||||
"locations)",
|
||||
bot->GetName().c_str(), bot->GetLevel(), map->GetId(), map->GetMapName(), zone->ID,
|
||||
zone->area_name[locale], area->ID, area->area_name[locale], x, y, z, i + 1, tlocs.size());
|
||||
LOG_DEBUG("playerbots",
|
||||
"Random teleporting bot {} (level {}) to Map: {} ({}) Zone: {} ({}) Area: {} ({}) ZoneLevel: {} "
|
||||
"AreaLevel: {} {},{},{} ({}/{} "
|
||||
"locations)",
|
||||
bot->GetName().c_str(), bot->GetLevel(), map->GetId(), map->GetMapName(), zone->ID,
|
||||
zone->area_name[locale], area->ID, area->area_name[locale], zone->area_level, area->area_level, x, y,
|
||||
z, i + 1, tlocs.size());
|
||||
|
||||
if (hearth)
|
||||
{
|
||||
@@ -1422,32 +1433,35 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
"position_x, "
|
||||
"position_y, "
|
||||
"position_z, "
|
||||
"t.minlevel "
|
||||
"t.minlevel, "
|
||||
"t.maxlevel "
|
||||
"FROM "
|
||||
"(SELECT "
|
||||
"map, "
|
||||
"MIN( c.guid ) guid, "
|
||||
"t.entry "
|
||||
"MIN( c.guid ) guid "
|
||||
"FROM "
|
||||
"creature c "
|
||||
"INNER JOIN creature_template t ON c.id1 = t.entry "
|
||||
"WHERE "
|
||||
"t.npcflag = 0 "
|
||||
"AND t.lootid != 0 "
|
||||
"AND t.unit_flags != 768 "
|
||||
"AND t.maxlevel - t.minlevel < 3 "
|
||||
"AND map IN ({}) "
|
||||
"AND c.id1 != 32820 "
|
||||
"AND t.entry not in (32820, 24196, 30627, 30617) "
|
||||
"AND c.spawntimesecs < 1000 "
|
||||
"AND t.faction != 188 "
|
||||
"AND t.faction not in (11, 71, 79, 85, 188, 1575) "
|
||||
"AND (t.unit_flags & 256) = 0 "
|
||||
"AND (t.unit_flags & 4096) = 0 "
|
||||
"AND t.rank = 0 "
|
||||
// "AND (t.flags_extra & 32768) = 0 "
|
||||
"GROUP BY "
|
||||
"map, "
|
||||
"ROUND( position_x / 500 ), "
|
||||
"ROUND( position_y / 500 ), "
|
||||
"ROUND( position_z / 50), "
|
||||
"t.entry "
|
||||
"ROUND(position_x / 50), "
|
||||
"ROUND(position_y / 50), "
|
||||
"ROUND(position_z / 50) "
|
||||
"HAVING "
|
||||
"count(*) > 7) AS g "
|
||||
"count(*) >= 2) "
|
||||
"AS g "
|
||||
"INNER JOIN creature c ON g.guid = c.guid "
|
||||
"INNER JOIN creature_template t on c.id1 = t.entry "
|
||||
"ORDER BY "
|
||||
@@ -1463,7 +1477,9 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
float x = fields[1].Get<float>();
|
||||
float y = fields[2].Get<float>();
|
||||
float z = fields[3].Get<float>();
|
||||
uint32 level = fields[4].Get<uint32>();
|
||||
uint32 min_level = fields[4].Get<uint32>();
|
||||
uint32 max_level = fields[5].Get<uint32>();
|
||||
uint32 level = (min_level + max_level + 1) / 2;
|
||||
WorldLocation loc(mapId, x, y, z, 0);
|
||||
collected_locs++;
|
||||
for (int32 l = (int32)level - (int32)sPlayerbotAIConfig->randomBotTeleHigherLevel;
|
||||
@@ -1477,7 +1493,116 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
}
|
||||
} while (results->NextRow());
|
||||
}
|
||||
LOG_INFO("playerbots", "{} locations for level collected.", collected_locs);
|
||||
LOG_INFO("playerbots", ">> {} locations for level collected.", collected_locs);
|
||||
|
||||
LOG_INFO("playerbots", "Preparing innkeepers locations for level collected...");
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
{
|
||||
results = WorldDatabase.Query(
|
||||
"SELECT "
|
||||
"map, "
|
||||
"position_x, "
|
||||
"position_y, "
|
||||
"position_z, "
|
||||
"orientation, "
|
||||
"t.faction, "
|
||||
"t.entry "
|
||||
"FROM "
|
||||
"creature c "
|
||||
"INNER JOIN creature_template t on c.id1 = t.entry "
|
||||
"WHERE "
|
||||
"t.npcflag & 73728 "
|
||||
"AND map IN ({}) "
|
||||
"ORDER BY "
|
||||
"t.minlevel;",
|
||||
sPlayerbotAIConfig->randomBotMapsAsString.c_str());
|
||||
collected_locs = 0;
|
||||
if (results)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = results->Fetch();
|
||||
uint16 mapId = fields[0].Get<uint16>();
|
||||
float x = fields[1].Get<float>();
|
||||
float y = fields[2].Get<float>();
|
||||
float z = fields[3].Get<float>();
|
||||
float orient = fields[4].Get<float>();
|
||||
uint32 faction = fields[5].Get<uint32>();
|
||||
uint32 c_entry = fields[6].Get<uint32>();
|
||||
const FactionTemplateEntry* entry = sFactionTemplateStore.LookupEntry(faction);
|
||||
|
||||
WorldLocation loc(mapId, x + cos(orient) * 5.0f, y + sin(orient) * 5.0f, z + 0.5f, orient + M_PI);
|
||||
collected_locs++;
|
||||
Map* map = sMapMgr->FindMap(loc.GetMapId(), 0);
|
||||
if (!map)
|
||||
continue;
|
||||
const AreaTableEntry* area = sAreaTableStore.LookupEntry(map->GetAreaId(1, x, y, z));
|
||||
uint32 zoneId = area->zone ? area->zone : area->ID;
|
||||
uint32 level = area->area_level;
|
||||
for (int i = 5; i <= maxLevel; i++)
|
||||
{
|
||||
std::vector<WorldLocation>& locs = locsPerLevelCache[i];
|
||||
int counter = 0;
|
||||
WorldLocation levelLoc;
|
||||
for (auto& checkLoc : locs)
|
||||
{
|
||||
if (loc.GetMapId() != checkLoc.GetMapId())
|
||||
continue;
|
||||
|
||||
if (loc.GetExactDist(checkLoc) > 1500.0f)
|
||||
continue;
|
||||
|
||||
if (zoneId !=
|
||||
map->GetZoneId(1, checkLoc.GetPositionX(), checkLoc.GetPositionY(), checkLoc.GetPositionZ()))
|
||||
continue;
|
||||
|
||||
counter++;
|
||||
levelLoc = checkLoc;
|
||||
if (counter >= 15)
|
||||
break;
|
||||
}
|
||||
|
||||
if (counter < 15)
|
||||
continue;
|
||||
|
||||
if (!(entry->hostileMask & 4))
|
||||
{
|
||||
hordeStarterPerLevelCache[i].push_back(loc);
|
||||
}
|
||||
if (!(entry->hostileMask & 2))
|
||||
{
|
||||
allianceStarterPerLevelCache[i].push_back(loc);
|
||||
}
|
||||
LOG_DEBUG("playerbots", "Area: {} Level: {} creature_entry: {} add to: {} {}({},{},{},{})", area->ID,
|
||||
level, c_entry, i, counter, levelLoc.GetPositionX(), levelLoc.GetPositionY(),
|
||||
levelLoc.GetPositionZ(), levelLoc.GetMapId());
|
||||
}
|
||||
} while (results->NextRow());
|
||||
}
|
||||
// add all initial position
|
||||
for (uint32 i = 1; i < MAX_RACES; i++)
|
||||
{
|
||||
for (uint32 j = 1; j < MAX_CLASSES; j++)
|
||||
{
|
||||
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(i, j);
|
||||
|
||||
if (!info)
|
||||
continue;
|
||||
|
||||
WorldPosition pos(info->mapId, info->positionX, info->positionY, info->positionZ, info->orientation);
|
||||
|
||||
for (int32 l = 1; l <= 5; l++)
|
||||
{
|
||||
if ((1 << (i - 1)) & RACEMASK_ALLIANCE)
|
||||
allianceStarterPerLevelCache[(uint8)l].push_back(pos);
|
||||
else
|
||||
hordeStarterPerLevelCache[(uint8)l].push_back(pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG_INFO("playerbots", ">> {} innkeepers locations for level collected.", collected_locs);
|
||||
}
|
||||
|
||||
results = WorldDatabase.Query(
|
||||
"SELECT "
|
||||
@@ -1500,6 +1625,7 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
"AND t.faction != 69 "
|
||||
"AND t.entry != 30606 "
|
||||
"AND t.entry != 30608 "
|
||||
"AND t.entry != 29282 "
|
||||
"AND t.faction != 69 "
|
||||
"AND map IN ({}) "
|
||||
"ORDER BY "
|
||||
@@ -1541,15 +1667,15 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
|
||||
}
|
||||
} while (results->NextRow());
|
||||
}
|
||||
LOG_INFO("playerbots", "{} banker locations for level collected.", collected_locs);
|
||||
LOG_INFO("playerbots", ">> {} banker locations for level collected.", collected_locs);
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::PrepareAddclassCache()
|
||||
{
|
||||
int32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back();
|
||||
int32 minIdx =
|
||||
sPlayerbotAIConfig->randomBotAccounts.size() - 1 >= sPlayerbotAIConfig->addClassAccountPoolSize
|
||||
? sPlayerbotAIConfig->randomBotAccounts.size() - sPlayerbotAIConfig->addClassAccountPoolSize : 0;
|
||||
int32 minIdx = sPlayerbotAIConfig->randomBotAccounts.size() - 1 >= sPlayerbotAIConfig->addClassAccountPoolSize
|
||||
? sPlayerbotAIConfig->randomBotAccounts.size() - sPlayerbotAIConfig->addClassAccountPoolSize
|
||||
: 0;
|
||||
int32 minAccountId = sPlayerbotAIConfig->randomBotAccounts[minIdx];
|
||||
if (minAccountId < 0)
|
||||
{
|
||||
@@ -1579,7 +1705,7 @@ void RandomPlayerbotMgr::PrepareAddclassCache()
|
||||
} while (results->NextRow());
|
||||
}
|
||||
}
|
||||
LOG_INFO("playerbots", "{} characters collected for addclass command.", collected);
|
||||
LOG_INFO("playerbots", ">> {} characters collected for addclass command.", collected);
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot)
|
||||
@@ -1589,15 +1715,20 @@ void RandomPlayerbotMgr::RandomTeleportForLevel(Player* bot)
|
||||
|
||||
uint32 level = bot->GetLevel();
|
||||
uint8 race = bot->getRace();
|
||||
std::vector<WorldLocation>* locs = nullptr;
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
locs = IsAlliance(race) ? &allianceStarterPerLevelCache[level] : &hordeStarterPerLevelCache[level];
|
||||
else
|
||||
locs = &locsPerLevelCache[level];
|
||||
LOG_DEBUG("playerbots", "Random teleporting bot {} for level {} ({} locations available)", bot->GetName().c_str(),
|
||||
bot->GetLevel(), locsPerLevelCache[level].size());
|
||||
if (level > 10 && urand(0, 100) < sPlayerbotAIConfig->probTeleToBankers * 100)
|
||||
bot->GetLevel(), locs->size());
|
||||
if (level >= 10 && urand(0, 100) < sPlayerbotAIConfig->probTeleToBankers * 100)
|
||||
{
|
||||
RandomTeleport(bot, bankerLocsPerLevelCache[level], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
RandomTeleport(bot, locsPerLevelCache[level]);
|
||||
RandomTeleport(bot, *locs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1608,10 +1739,15 @@ void RandomPlayerbotMgr::RandomTeleportGrindForLevel(Player* bot)
|
||||
|
||||
uint32 level = bot->GetLevel();
|
||||
uint8 race = bot->getRace();
|
||||
std::vector<WorldLocation>* locs = nullptr;
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
locs = IsAlliance(race) ? &allianceStarterPerLevelCache[level] : &hordeStarterPerLevelCache[level];
|
||||
else
|
||||
locs = &locsPerLevelCache[level];
|
||||
LOG_DEBUG("playerbots", "Random teleporting bot {} for level {} ({} locations available)", bot->GetName().c_str(),
|
||||
bot->GetLevel(), locsPerLevelCache[level].size());
|
||||
bot->GetLevel(), locs->size());
|
||||
|
||||
RandomTeleport(bot, locsPerLevelCache[level]);
|
||||
RandomTeleport(bot, *locs);
|
||||
}
|
||||
|
||||
void RandomPlayerbotMgr::RandomTeleport(Player* bot)
|
||||
@@ -2379,7 +2515,8 @@ Player* RandomPlayerbotMgr::GetRandomPlayer()
|
||||
|
||||
void RandomPlayerbotMgr::PrintStats()
|
||||
{
|
||||
LOG_INFO("playerbots", "{} Random Bots online", playerBots.size());
|
||||
printStatsTimer = time(nullptr);
|
||||
LOG_INFO("playerbots", "Random Bots Stats: {} online", playerBots.size());
|
||||
|
||||
std::map<uint8, uint32> alliance, horde;
|
||||
for (uint32 i = 0; i < 10; ++i)
|
||||
@@ -2421,13 +2558,17 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
uint32 engine_dead = 0;
|
||||
uint32 stateCount[MAX_TRAVEL_STATE + 1] = {0};
|
||||
std::vector<std::pair<Quest const*, int32>> questCount;
|
||||
std::unordered_map<NewRpgStatus, int> rpgStatusCount;
|
||||
std::unordered_map<uint32, int> zoneCount;
|
||||
uint8 maxBotLevel = 0;
|
||||
for (PlayerBotMap::iterator i = playerBots.begin(); i != playerBots.end(); ++i)
|
||||
{
|
||||
Player* bot = i->second;
|
||||
if (IsAlliance(bot->getRace()))
|
||||
++alliance[bot->GetLevel() / 10];
|
||||
++alliance[bot->GetLevel()];
|
||||
else
|
||||
++horde[bot->GetLevel() / 10];
|
||||
++horde[bot->GetLevel()];
|
||||
maxBotLevel = std::max(maxBotLevel, bot->GetLevel());
|
||||
|
||||
++perRace[bot->getRace()];
|
||||
++perClass[bot->getClass()];
|
||||
@@ -2489,6 +2630,11 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
else
|
||||
++dps;
|
||||
|
||||
zoneCount[bot->GetZoneId()]++;
|
||||
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
rpgStatusCount[botAI->rpgInfo.status]++;
|
||||
|
||||
if (TravelTarget* target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get())
|
||||
{
|
||||
TravelState state = target->getTravelState();
|
||||
@@ -2518,18 +2664,22 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Bots level:");
|
||||
uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
||||
for (uint8 i = 0; i < 10; ++i)
|
||||
// uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
||||
uint32 currentAlliance = 0, currentHorde = 0;
|
||||
uint32 step = std::max(1, (maxBotLevel + 4) / 8);
|
||||
uint32 from = 1;
|
||||
for (uint8 i = 1; i <= maxBotLevel; ++i)
|
||||
{
|
||||
if (!alliance[i] && !horde[i])
|
||||
continue;
|
||||
currentAlliance += alliance[i];
|
||||
currentHorde += horde[i];
|
||||
|
||||
uint32 from = i * 10;
|
||||
uint32 to = std::min(from + 9, maxLevel);
|
||||
if (!from)
|
||||
from = 1;
|
||||
|
||||
LOG_INFO("playerbots", " {}..{}: {} alliance, {} horde", from, to, alliance[i], horde[i]);
|
||||
if (((i + 1) % step == 0) || i == maxBotLevel)
|
||||
{
|
||||
LOG_INFO("playerbots", " {}..{}: {} alliance, {} horde", from, i, currentAlliance, currentHorde);
|
||||
currentAlliance = 0;
|
||||
currentHorde = 0;
|
||||
from = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Bots race:");
|
||||
@@ -2567,19 +2717,38 @@ void RandomPlayerbotMgr::PrintStats()
|
||||
LOG_INFO("playerbots", " In Rest: {}", rest);
|
||||
LOG_INFO("playerbots", " Dead: {}", dead);
|
||||
|
||||
// LOG_INFO("playerbots", "Bots zone:");
|
||||
// for (auto &[zond_id, counter] : zoneCount)
|
||||
// {
|
||||
// const AreaTableEntry* entry = sAreaTableStore.LookupEntry(zond_id);
|
||||
// std::string name = PlayerbotAI::GetLocalizedAreaName(entry);
|
||||
// LOG_INFO("playerbots", " {}: {}", name, counter);
|
||||
// }
|
||||
|
||||
if (sPlayerbotAIConfig->enableNewRpgStrategy)
|
||||
{
|
||||
LOG_INFO("playerbots", "Bots rpg status:", dead);
|
||||
LOG_INFO("playerbots", " IDLE: {}", rpgStatusCount[NewRpgStatus::IDLE]);
|
||||
LOG_INFO("playerbots", " REST: {}", rpgStatusCount[NewRpgStatus::REST]);
|
||||
LOG_INFO("playerbots", " GO_GRIND: {}", rpgStatusCount[NewRpgStatus::GO_GRIND]);
|
||||
LOG_INFO("playerbots", " GO_INNKEEPER: {}", rpgStatusCount[NewRpgStatus::GO_INNKEEPER]);
|
||||
LOG_INFO("playerbots", " NEAR_RANDOM: {}", rpgStatusCount[NewRpgStatus::NEAR_RANDOM]);
|
||||
LOG_INFO("playerbots", " NEAR_NPC: {}", rpgStatusCount[NewRpgStatus::NEAR_NPC]);
|
||||
}
|
||||
|
||||
LOG_INFO("playerbots", "Bots engine:", dead);
|
||||
LOG_INFO("playerbots", " Non-combat: {}", engine_noncombat);
|
||||
LOG_INFO("playerbots", " Combat: {}", engine_combat);
|
||||
LOG_INFO("playerbots", " Dead: {}", engine_dead);
|
||||
|
||||
LOG_INFO("playerbots", "Bots questing:");
|
||||
LOG_INFO("playerbots", " Picking quests: {}",
|
||||
stateCount[TRAVEL_STATE_TRAVEL_PICK_UP_QUEST] + stateCount[TRAVEL_STATE_WORK_PICK_UP_QUEST]);
|
||||
LOG_INFO("playerbots", " Doing quests: {}",
|
||||
stateCount[TRAVEL_STATE_TRAVEL_DO_QUEST] + stateCount[TRAVEL_STATE_WORK_DO_QUEST]);
|
||||
LOG_INFO("playerbots", " Completing quests: {}",
|
||||
stateCount[TRAVEL_STATE_TRAVEL_HAND_IN_QUEST] + stateCount[TRAVEL_STATE_WORK_HAND_IN_QUEST]);
|
||||
LOG_INFO("playerbots", " Idling: {}", stateCount[TRAVEL_STATE_IDLE]);
|
||||
// LOG_INFO("playerbots", "Bots questing:");
|
||||
// LOG_INFO("playerbots", " Picking quests: {}",
|
||||
// stateCount[TRAVEL_STATE_TRAVEL_PICK_UP_QUEST] + stateCount[TRAVEL_STATE_WORK_PICK_UP_QUEST]);
|
||||
// LOG_INFO("playerbots", " Doing quests: {}",
|
||||
// stateCount[TRAVEL_STATE_TRAVEL_DO_QUEST] + stateCount[TRAVEL_STATE_WORK_DO_QUEST]);
|
||||
// LOG_INFO("playerbots", " Completing quests: {}",
|
||||
// stateCount[TRAVEL_STATE_TRAVEL_HAND_IN_QUEST] + stateCount[TRAVEL_STATE_WORK_HAND_IN_QUEST]);
|
||||
// LOG_INFO("playerbots", " Idling: {}", stateCount[TRAVEL_STATE_IDLE]);
|
||||
|
||||
/*sort(questCount.begin(), questCount.end(), [](std::pair<Quest const*, int32> i, std::pair<Quest const*, int32> j)
|
||||
{return i.second > j.second; });
|
||||
|
||||
@@ -171,6 +171,10 @@ public:
|
||||
|
||||
void PrepareAddclassCache();
|
||||
std::map<uint8, std::vector<ObjectGuid>> addclassCache;
|
||||
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
|
||||
std::map<uint8, std::vector<WorldLocation>> allianceStarterPerLevelCache;
|
||||
std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache;
|
||||
std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache;
|
||||
protected:
|
||||
void OnBotLoginInternal(Player* const bot) override;
|
||||
|
||||
@@ -188,6 +192,7 @@ private:
|
||||
time_t BgCheckTimer;
|
||||
time_t LfgCheckTimer;
|
||||
time_t PlayersCheckTimer;
|
||||
time_t printStatsTimer;
|
||||
uint32 AddRandomBots();
|
||||
bool ProcessBot(uint32 bot);
|
||||
void ScheduleRandomize(uint32 bot, uint32 time);
|
||||
@@ -199,8 +204,7 @@ private:
|
||||
|
||||
std::vector<Player*> players;
|
||||
uint32 processTicks;
|
||||
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
|
||||
std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache;
|
||||
|
||||
|
||||
// std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
|
||||
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;
|
||||
|
||||
@@ -424,7 +424,7 @@ void PlayerbotFactory::Randomize(bool incremental)
|
||||
bot->SetHealth(bot->GetMaxHealth());
|
||||
bot->SetPower(POWER_MANA, bot->GetMaxPower(POWER_MANA));
|
||||
bot->SaveToDB(false, false);
|
||||
LOG_INFO("playerbots", "Initialization Done.");
|
||||
// LOG_INFO("playerbots", "Initialization Done.");
|
||||
if (pmo)
|
||||
pmo->finish();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "MeleeCombatStrategy.h"
|
||||
#include "MoveFromGroupStrategy.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "NonCombatStrategy.h"
|
||||
#include "PassiveStrategy.h"
|
||||
#include "PullStrategy.h"
|
||||
@@ -82,6 +83,7 @@ public:
|
||||
creators["reveal"] = &StrategyContext::reveal;
|
||||
creators["collision"] = &StrategyContext::collision;
|
||||
creators["rpg"] = &StrategyContext::rpg;
|
||||
creators["new rpg"] = &StrategyContext::new_rpg;
|
||||
creators["travel"] = &StrategyContext::travel;
|
||||
creators["explore"] = &StrategyContext::explore;
|
||||
creators["map"] = &StrategyContext::map;
|
||||
@@ -152,6 +154,7 @@ private:
|
||||
static Strategy* reveal(PlayerbotAI* botAI) { return new RevealStrategy(botAI); }
|
||||
static Strategy* collision(PlayerbotAI* botAI) { return new CollisionStrategy(botAI); }
|
||||
static Strategy* rpg(PlayerbotAI* botAI) { return new RpgStrategy(botAI); }
|
||||
static Strategy* new_rpg(PlayerbotAI* botAI) { return new NewRpgStrategy(botAI); }
|
||||
static Strategy* travel(PlayerbotAI* botAI) { return new TravelStrategy(botAI); }
|
||||
static Strategy* explore(PlayerbotAI* botAI) { return new ExploreStrategy(botAI); }
|
||||
static Strategy* map(PlayerbotAI* botAI) { return new MapStrategy(botAI); }
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "VehicleActions.h"
|
||||
#include "WorldBuffAction.h"
|
||||
#include "XpGainAction.h"
|
||||
#include "NewRpgAction.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
@@ -240,6 +241,12 @@ public:
|
||||
|
||||
creators["toggle pet spell"] = &ActionContext::toggle_pet_spell;
|
||||
creators["pet attack"] = &ActionContext::pet_attack;
|
||||
|
||||
creators["new rpg status update"] = &ActionContext::new_rpg_status_update;
|
||||
creators["new rpg go grind"] = &ActionContext::new_rpg_go_grind;
|
||||
creators["new rpg go innkeeper"] = &ActionContext::new_rpg_go_innkeeper;
|
||||
creators["new rpg move random"] = &ActionContext::new_rpg_move_random;
|
||||
creators["new rpg move npc"] = &ActionContext::new_rpg_move_npc;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -415,6 +422,12 @@ private:
|
||||
|
||||
static Action* toggle_pet_spell(PlayerbotAI* ai) { return new TogglePetSpellAutoCastAction(ai); }
|
||||
static Action* pet_attack(PlayerbotAI* ai) { return new PetAttackAction(ai); }
|
||||
|
||||
static Action* new_rpg_status_update(PlayerbotAI* ai) { return new NewRpgStatusUpdateAction(ai); }
|
||||
static Action* new_rpg_go_grind(PlayerbotAI* ai) { return new NewRpgGoGrindAction(ai); }
|
||||
static Action* new_rpg_go_innkeeper(PlayerbotAI* ai) { return new NewRpgGoInnKeeperAction(ai); }
|
||||
static Action* new_rpg_move_random(PlayerbotAI* ai) { return new NewRpgMoveRandomAction(ai); }
|
||||
static Action* new_rpg_move_npc(PlayerbotAI* ai) { return new NewRpgMoveNpcAction(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "LootStrategyAction.h"
|
||||
#include "MailAction.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "NewRpgAction.h"
|
||||
#include "PassLeadershipToMasterAction.h"
|
||||
#include "PositionAction.h"
|
||||
#include "QueryItemUsageAction.h"
|
||||
@@ -88,6 +89,7 @@ public:
|
||||
creators["reputation"] = &ChatActionContext::reputation;
|
||||
creators["log"] = &ChatActionContext::log;
|
||||
creators["los"] = &ChatActionContext::los;
|
||||
creators["rpg status"] = &ChatActionContext::rpg_status;
|
||||
creators["aura"] = &ChatActionContext::aura;
|
||||
creators["drop"] = &ChatActionContext::drop;
|
||||
creators["clean quest log"] = &ChatActionContext::clean_quest_log;
|
||||
@@ -258,6 +260,7 @@ private:
|
||||
static Action* reputation(PlayerbotAI* botAI) { return new TellReputationAction(botAI); }
|
||||
static Action* log(PlayerbotAI* botAI) { return new LogLevelAction(botAI); }
|
||||
static Action* los(PlayerbotAI* botAI) { return new TellLosAction(botAI); }
|
||||
static Action* rpg_status(PlayerbotAI* botAI) { return new TellRpgStatusAction(botAI); }
|
||||
static Action* aura(PlayerbotAI* ai) { return new TellAuraAction(ai); }
|
||||
static Action* ll(PlayerbotAI* botAI) { return new LootStrategyAction(botAI); }
|
||||
static Action* ss(PlayerbotAI* botAI) { return new SkipSpellsListAction(botAI); }
|
||||
|
||||
@@ -177,7 +177,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged)
|
||||
}
|
||||
|
||||
bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only,
|
||||
bool exact_waypoint, MovementPriority priority)
|
||||
bool exact_waypoint, MovementPriority priority, bool lessDelay)
|
||||
{
|
||||
UpdateMovementState();
|
||||
if (!IsMovingAllowed(mapId, x, y, z))
|
||||
@@ -210,6 +210,10 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
mm.Clear();
|
||||
mm.MovePoint(0, x, y, z, generatePath);
|
||||
float delay = 1000.0f * (distance / vehicleBase->GetSpeed(MOVE_RUN));
|
||||
if (lessDelay)
|
||||
{
|
||||
delay -= botAI->GetReactDelay();
|
||||
}
|
||||
delay = std::max(.0f, delay);
|
||||
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
|
||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
|
||||
@@ -233,6 +237,10 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
mm.Clear();
|
||||
mm.MovePoint(0, x, y, z, generatePath);
|
||||
float delay = 1000.0f * MoveDelay(distance);
|
||||
if (lessDelay)
|
||||
{
|
||||
delay -= botAI->GetReactDelay();
|
||||
}
|
||||
delay = std::max(.0f, delay);
|
||||
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
|
||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
|
||||
@@ -264,6 +272,10 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
||||
mm.Clear();
|
||||
mm.MovePoint(0, endP.x, endP.y, endP.z, generatePath);
|
||||
float delay = 1000.0f * MoveDelay(distance);
|
||||
if (lessDelay)
|
||||
{
|
||||
delay -= botAI->GetReactDelay();
|
||||
}
|
||||
delay = std::max(.0f, delay);
|
||||
delay = std::min((float)sPlayerbotAIConfig->maxWaitForMove, delay);
|
||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), delay, priority);
|
||||
@@ -822,7 +834,7 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
|
||||
PathGenerator path(bot);
|
||||
path.CalculatePath(tx, ty, tz, false);
|
||||
PathType type = path.GetPathType();
|
||||
int typeOk = PATHFIND_NORMAL | PATHFIND_INCOMPLETE;
|
||||
int typeOk = PATHFIND_NORMAL | PATHFIND_INCOMPLETE | PATHFIND_SHORTCUT;
|
||||
if (!(type & typeOk))
|
||||
return false;
|
||||
float shortenTo = distance;
|
||||
@@ -838,7 +850,7 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
|
||||
path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), shortenTo);
|
||||
G3D::Vector3 endPos = path.GetPath().back();
|
||||
return MoveTo(target->GetMapId(), endPos.x, endPos.y, endPos.z, false, false, false, false,
|
||||
MovementPriority::MOVEMENT_COMBAT);
|
||||
MovementPriority::MOVEMENT_COMBAT, true);
|
||||
}
|
||||
|
||||
float MovementAction::GetFollowAngle()
|
||||
@@ -2013,8 +2025,15 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius)
|
||||
}
|
||||
bool strict = checkAngle.strict;
|
||||
float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance);
|
||||
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, bot->GetPositionY() + sin(angle) * fleeDis,
|
||||
bot->GetPositionZ()};
|
||||
float dx = bot->GetPositionX() + cos(angle) * fleeDis;
|
||||
float dy = bot->GetPositionY() + sin(angle) * fleeDis;
|
||||
float dz = bot->GetPositionZ();
|
||||
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), dx, dy, dz))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Position fleePos{dx, dy, dz};
|
||||
if (strict && currentTarget &&
|
||||
fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() >
|
||||
sPlayerbotAIConfig->tooCloseDistance &&
|
||||
@@ -2069,8 +2088,15 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius)
|
||||
}
|
||||
bool strict = checkAngle.strict;
|
||||
float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance);
|
||||
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, bot->GetPositionY() + sin(angle) * fleeDis,
|
||||
bot->GetPositionZ()};
|
||||
float dx = bot->GetPositionX() + cos(angle) * fleeDis;
|
||||
float dy = bot->GetPositionY() + sin(angle) * fleeDis;
|
||||
float dz = bot->GetPositionZ();
|
||||
if (!bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), dx, dy, dz))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Position fleePos{dx, dy, dz};
|
||||
if (strict && currentTarget &&
|
||||
fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->spellDistance)
|
||||
{
|
||||
@@ -2082,6 +2108,7 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pos.GetExactDist(fleePos) > farestDis)
|
||||
{
|
||||
farestDis = pos.GetExactDist(fleePos);
|
||||
|
||||
@@ -32,7 +32,7 @@ protected:
|
||||
bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
bool MoveToLOS(WorldObject* target, bool ranged = false);
|
||||
bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false,
|
||||
bool normal_only = false, bool exact_waypoint = false, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
bool normal_only = false, bool exact_waypoint = false, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL, bool lessDelay = false);
|
||||
bool MoveTo(WorldObject* target, float distance = 0.0f, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
|
||||
float GetFollowAngle();
|
||||
|
||||
@@ -188,7 +188,7 @@ bool FindCorpseAction::Execute(Event event)
|
||||
|
||||
if (!moved)
|
||||
{
|
||||
moved = botAI->DoSpecificAction("spirit healer");
|
||||
moved = botAI->DoSpecificAction("spirit healer", Event(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,16 +347,16 @@ bool SpiritHealerAction::Execute(Event event)
|
||||
if (moved)
|
||||
return true;
|
||||
|
||||
if (!botAI->HasActivePlayerMaster())
|
||||
{
|
||||
context->GetValue<uint32>("death count")->Set(dCount + 1);
|
||||
return bot->TeleportTo(ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f);
|
||||
}
|
||||
// if (!botAI->HasActivePlayerMaster())
|
||||
// {
|
||||
context->GetValue<uint32>("death count")->Set(dCount + 1);
|
||||
return bot->TeleportTo(ClosestGrave->Map, ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, 0.f);
|
||||
// }
|
||||
|
||||
LOG_INFO("playerbots", "Bot {} {}:{} <{}> can't find a spirit healer", bot->GetGUID().ToString().c_str(),
|
||||
bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str());
|
||||
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> can't find a spirit healer", bot->GetGUID().ToString().c_str(),
|
||||
// bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str());
|
||||
|
||||
botAI->TellError("Cannot find any spirit healer nearby");
|
||||
// botAI->TellError("Cannot find any spirit healer nearby");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ void FeralDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing",
|
||||
// ACTION_NORMAL + 7), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of
|
||||
// enemy contact", ACTION_NORMAL + 8), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
|
||||
@@ -106,6 +106,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
|
||||
supported.push_back("reputation");
|
||||
supported.push_back("log");
|
||||
supported.push_back("los");
|
||||
supported.push_back("rpg status");
|
||||
supported.push_back("aura");
|
||||
supported.push_back("drop");
|
||||
supported.push_back("share");
|
||||
|
||||
@@ -22,7 +22,7 @@ void CombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("not facing target",
|
||||
NextAction::array(0, new NextAction("set facing", ACTION_MOVE + 7), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", ACTION_NORMAL), nullptr)));
|
||||
new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", 40.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("combat long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f),
|
||||
// new NextAction("repop", 0.8f), nullptr)));
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ NextAction** GrindingStrategy::getDefaultActions() { return nullptr; }
|
||||
|
||||
void GrindingStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 4.2f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 4.1f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 10.2f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 10.1f), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 4.0f), nullptr)));
|
||||
new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 10.0f), nullptr)));
|
||||
}
|
||||
|
||||
void MoveRandomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -14,7 +14,7 @@ void MeleeCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing",
|
||||
// ACTION_MOVE + 7), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of
|
||||
// enemy contact", ACTION_NORMAL + 8), nullptr)));
|
||||
}
|
||||
|
||||
@@ -59,8 +59,9 @@ FrostMageStrategy::FrostMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(b
|
||||
|
||||
NextAction** FrostMageStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("frostbolt", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("shoot", ACTION_DEFAULT), nullptr);
|
||||
return NextAction::array(0, new NextAction("frostbolt", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("shoot", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("fireball", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void FrostMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -131,5 +131,5 @@ void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode("enemy out of melee",
|
||||
NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), NULL)));
|
||||
NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), NULL)));
|
||||
}
|
||||
|
||||
@@ -113,5 +113,5 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("not facing target",
|
||||
NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
}
|
||||
|
||||
@@ -88,6 +88,6 @@ void AssassinationRogueStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee",
|
||||
NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("sprint", ACTION_NORMAL + 8),
|
||||
new NextAction("reach melee", ACTION_NORMAL + 7), NULL)));
|
||||
NextAction::array(0, new NextAction("stealth", ACTION_HIGH + 3), new NextAction("sprint", ACTION_HIGH + 2),
|
||||
new NextAction("reach melee", ACTION_HIGH + 1), NULL)));
|
||||
}
|
||||
|
||||
@@ -134,8 +134,8 @@ void DpsRogueStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee",
|
||||
NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("sprint", ACTION_NORMAL + 8),
|
||||
new NextAction("reach melee", ACTION_NORMAL + 7), nullptr)));
|
||||
NextAction::array(0, new NextAction("stealth", ACTION_HIGH + 3), new NextAction("sprint", ACTION_HIGH + 2),
|
||||
new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("expose armor",
|
||||
NextAction::array(0, new NextAction("expose armor", ACTION_HIGH + 3), nullptr)));
|
||||
|
||||
380
src/strategy/rpg/NewRpgAction.cpp
Normal file
380
src/strategy/rpg/NewRpgAction.cpp
Normal file
@@ -0,0 +1,380 @@
|
||||
#include "NewRpgAction.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "ObjectDefines.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "Player.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Random.h"
|
||||
#include "RandomPlayerbotMgr.h"
|
||||
#include "Timer.h"
|
||||
#include "TravelMgr.h"
|
||||
#include "World.h"
|
||||
|
||||
bool TellRpgStatusAction::Execute(Event event)
|
||||
{
|
||||
std::string out = botAI->rpgInfo.ToString();
|
||||
botAI->TellMasterNoFacing(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NewRpgStatusUpdateAction::Execute(Event event)
|
||||
{
|
||||
NewRpgInfo& info = botAI->rpgInfo;
|
||||
switch (info.status)
|
||||
{
|
||||
case NewRpgStatus::IDLE:
|
||||
{
|
||||
uint32 roll = urand(1, 100);
|
||||
// IDLE -> NEAR_NPC
|
||||
// if ((!info.lastNearNpc || info.lastNearNpc + setNpcInterval < getMSTime()) && roll <= 30)
|
||||
if (roll <= 30)
|
||||
{
|
||||
info.lastNearNpc = getMSTime();
|
||||
GuidVector possibleTargets = AI_VALUE(GuidVector, "possible rpg targets");
|
||||
if (!possibleTargets.empty())
|
||||
{
|
||||
info.status = NewRpgStatus::NEAR_NPC;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// IDLE -> GO_INNKEEPER
|
||||
else if (bot->GetLevel() >= 6 && roll <= 40)
|
||||
{
|
||||
WorldPosition pos = SelectRandomInnKeeperPos();
|
||||
if (pos != WorldPosition() && bot->GetExactDist(pos) > 50.0f)
|
||||
{
|
||||
info.lastGoInnKeeper = getMSTime();
|
||||
info.status = NewRpgStatus::GO_INNKEEPER;
|
||||
info.innKeeperPos = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// IDLE -> GO_GRIND
|
||||
else if (roll <= 90)
|
||||
{
|
||||
WorldPosition pos = SelectRandomGrindPos();
|
||||
if (pos != WorldPosition())
|
||||
{
|
||||
info.lastGoGrind = getMSTime();
|
||||
info.status = NewRpgStatus::GO_GRIND;
|
||||
info.grindPos = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// IDLE -> REST
|
||||
info.status = NewRpgStatus::REST;
|
||||
info.lastRest = getMSTime();
|
||||
bot->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
return true;
|
||||
}
|
||||
case NewRpgStatus::GO_GRIND:
|
||||
{
|
||||
WorldPosition& originalPos = info.grindPos;
|
||||
assert(info.grindPos != WorldPosition());
|
||||
// GO_GRIND -> NEAR_RANDOM
|
||||
if (bot->GetExactDist(originalPos) < 10.0f)
|
||||
{
|
||||
info.status = NewRpgStatus::NEAR_RANDOM;
|
||||
info.lastNearRandom = getMSTime();
|
||||
info.grindPos = WorldPosition();
|
||||
return true;
|
||||
}
|
||||
// // just choose another grindPos
|
||||
// if (!info.lastGoGrind || info.lastGoGrind + setGrindInterval < getMSTime())
|
||||
// {
|
||||
// WorldPosition pos = SelectRandomGrindPos();
|
||||
// if (pos == WorldPosition())
|
||||
// break;
|
||||
// info.status = NewRpgStatus::GO_GRIND;
|
||||
// info.lastGoGrind = getMSTime();
|
||||
// info.grindPos = pos;
|
||||
// return true;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
case NewRpgStatus::GO_INNKEEPER:
|
||||
{
|
||||
WorldPosition& originalPos = info.innKeeperPos;
|
||||
assert(info.innKeeperPos != WorldPosition());
|
||||
// GO_INNKEEPER -> NEAR_NPC
|
||||
if (bot->GetExactDist(originalPos) < 10.0f)
|
||||
{
|
||||
info.lastNearNpc = getMSTime();
|
||||
info.status = NewRpgStatus::NEAR_NPC;
|
||||
info.innKeeperPos = WorldPosition();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NewRpgStatus::NEAR_RANDOM:
|
||||
{
|
||||
// NEAR_RANDOM -> IDLE
|
||||
if (info.lastNearRandom + statusNearRandomDuration < getMSTime())
|
||||
{
|
||||
info.status = NewRpgStatus::IDLE;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NewRpgStatus::NEAR_NPC:
|
||||
{
|
||||
if (info.lastNearNpc + statusNearNpcDuration < getMSTime())
|
||||
{
|
||||
info.status = NewRpgStatus::IDLE;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NewRpgStatus::REST:
|
||||
{
|
||||
// REST -> IDLE
|
||||
if (info.lastRest + statusRestDuration < getMSTime())
|
||||
{
|
||||
info.status = NewRpgStatus::IDLE;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldPosition NewRpgStatusUpdateAction::SelectRandomGrindPos()
|
||||
{
|
||||
const std::vector<WorldLocation>& locs = sRandomPlayerbotMgr->locsPerLevelCache[bot->GetLevel()];
|
||||
std::vector<WorldLocation> lo_prepared_locs, hi_prepared_locs;
|
||||
for (auto& loc : locs)
|
||||
{
|
||||
if (bot->GetMapId() != loc.GetMapId())
|
||||
continue;
|
||||
|
||||
if (bot->GetMap()->GetZoneId(bot->GetPhaseMask(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()) !=
|
||||
bot->GetZoneId())
|
||||
continue;
|
||||
|
||||
if (bot->GetExactDist(loc) < 500.0f)
|
||||
{
|
||||
hi_prepared_locs.push_back(loc);
|
||||
}
|
||||
|
||||
if (bot->GetExactDist(loc) < 2500.0f)
|
||||
{
|
||||
lo_prepared_locs.push_back(loc);
|
||||
}
|
||||
}
|
||||
WorldPosition dest;
|
||||
if (urand(1, 100) <= 50 && !hi_prepared_locs.empty())
|
||||
{
|
||||
uint32 idx = urand(0, hi_prepared_locs.size() - 1);
|
||||
dest = hi_prepared_locs[idx];
|
||||
}
|
||||
else if (!lo_prepared_locs.empty())
|
||||
{
|
||||
uint32 idx = urand(0, lo_prepared_locs.size() - 1);
|
||||
dest = lo_prepared_locs[idx];
|
||||
}
|
||||
LOG_DEBUG("playerbots", "[New Rpg] Bot {} select random grind pos Map:{} X:{} Y:{} Z:{} ({}+{} available in {})",
|
||||
bot->GetName(), dest.GetMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(),
|
||||
hi_prepared_locs.size(), lo_prepared_locs.size() - hi_prepared_locs.size(), locs.size());
|
||||
return dest;
|
||||
}
|
||||
|
||||
WorldPosition NewRpgStatusUpdateAction::SelectRandomInnKeeperPos()
|
||||
{
|
||||
const std::vector<WorldLocation>& locs = IsAlliance(bot->getRace())
|
||||
? sRandomPlayerbotMgr->allianceStarterPerLevelCache[bot->GetLevel()]
|
||||
: sRandomPlayerbotMgr->hordeStarterPerLevelCache[bot->GetLevel()];
|
||||
std::vector<WorldLocation> prepared_locs;
|
||||
for (auto& loc : locs)
|
||||
{
|
||||
if (bot->GetMapId() != loc.GetMapId())
|
||||
continue;
|
||||
|
||||
float range = bot->GetLevel() <= 5 ? 500.0f : 2500.0f;
|
||||
if (bot->GetExactDist(loc) < range)
|
||||
{
|
||||
prepared_locs.push_back(loc);
|
||||
}
|
||||
}
|
||||
WorldPosition dest;
|
||||
if (!prepared_locs.empty())
|
||||
{
|
||||
uint32 idx = urand(0, prepared_locs.size() - 1);
|
||||
dest = prepared_locs[idx];
|
||||
}
|
||||
LOG_DEBUG("playerbots", "[New Rpg] Bot {} select random inn keeper pos Map:{} X:{} Y:{} Z:{} ({} available in {})",
|
||||
bot->GetName(), dest.GetMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(),
|
||||
prepared_locs.size(), locs.size());
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool NewRpgGoFarAwayPosAction::MoveFarTo(WorldPosition dest)
|
||||
{
|
||||
float dis = bot->GetExactDist(dest);
|
||||
if (dis < pathFinderDis)
|
||||
{
|
||||
return MoveTo(dest.getMapId(), dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false, false,
|
||||
false, true);
|
||||
}
|
||||
|
||||
// performance optimization
|
||||
if (IsWaitingForLastMove(MovementPriority::MOVEMENT_NORMAL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float minDelta = M_PI;
|
||||
const float x = bot->GetPositionX();
|
||||
const float y = bot->GetPositionY();
|
||||
const float z = bot->GetPositionZ();
|
||||
float rx, ry, rz;
|
||||
bool found = false;
|
||||
int attempt = 10;
|
||||
while (--attempt)
|
||||
{
|
||||
float angle = bot->GetAngle(&dest);
|
||||
float delta = (rand_norm() - 0.5) * M_PI * 2;
|
||||
angle += delta;
|
||||
float dis = rand_norm() * pathFinderDis;
|
||||
float dx = x + cos(angle) * dis;
|
||||
float dy = y + sin(angle) * dis;
|
||||
float dz = z + 5.0f;
|
||||
bot->UpdateAllowedPositionZ(dx, dy, dz);
|
||||
PathGenerator path(bot);
|
||||
path.CalculatePath(dx, dy, dz);
|
||||
PathType type = path.GetPathType();
|
||||
|
||||
bool canReach = type == PATHFIND_INCOMPLETE || type == PATHFIND_NORMAL;
|
||||
|
||||
if (canReach && fabs(delta) <= minDelta)
|
||||
{
|
||||
found = true;
|
||||
const G3D::Vector3& endPos = path.GetActualEndPosition();
|
||||
rx = endPos.x;
|
||||
ry = endPos.y;
|
||||
rz = endPos.z;
|
||||
minDelta = fabs(delta);
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
return MoveTo(bot->GetMapId(), rx, ry, rz, false, false, false, true);
|
||||
}
|
||||
// don't fallback to direct move
|
||||
// float angle = bot->GetAngle(&dest);
|
||||
// return MoveTo(bot->GetMapId(), x + cos(angle) * pathFinderDis, y + sin(angle) * pathFinderDis, z);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewRpgGoGrindAction::Execute(Event event) { return MoveFarTo(botAI->rpgInfo.grindPos); }
|
||||
|
||||
bool NewRpgGoInnKeeperAction::Execute(Event event) { return MoveFarTo(botAI->rpgInfo.innKeeperPos); }
|
||||
|
||||
bool NewRpgMoveRandomAction::Execute(Event event)
|
||||
{
|
||||
float distance = rand_norm() * moveStep;
|
||||
Map* map = bot->GetMap();
|
||||
const float x = bot->GetPositionX();
|
||||
const float y = bot->GetPositionY();
|
||||
const float z = bot->GetPositionZ();
|
||||
int attempts = 5;
|
||||
while (--attempts)
|
||||
{
|
||||
float angle = (float)rand_norm() * 2 * static_cast<float>(M_PI);
|
||||
float dx = x + distance * cos(angle);
|
||||
float dy = y + distance * sin(angle);
|
||||
float dz = z;
|
||||
if (!map->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
dx, dy, dz))
|
||||
continue;
|
||||
|
||||
if (map->IsInWater(bot->GetPhaseMask(), dx, dy, dz, bot->GetCollisionHeight()))
|
||||
continue;
|
||||
|
||||
bool moved = MoveTo(bot->GetMapId(), dx, dy, dz, false, false, false, true);
|
||||
if (moved)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NewRpgMoveNpcAction::Execute(Event event)
|
||||
{
|
||||
NewRpgInfo& info = botAI->rpgInfo;
|
||||
if (!info.npcPos)
|
||||
{
|
||||
GuidVector possibleTargets = AI_VALUE(GuidVector, "possible rpg targets");
|
||||
if (possibleTargets.empty())
|
||||
return false;
|
||||
int idx = urand(0, possibleTargets.size() - 1);
|
||||
ObjectGuid guid = possibleTargets[idx];
|
||||
Unit* unit = botAI->GetUnit(guid);
|
||||
if (unit)
|
||||
{
|
||||
info.npcPos = GuidPosition(unit);
|
||||
info.lastReachNpc = 0;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bot->GetDistance(info.npcPos) <= INTERACTION_DISTANCE)
|
||||
{
|
||||
if (!info.lastReachNpc)
|
||||
{
|
||||
info.lastReachNpc = getMSTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (info.lastReachNpc && info.lastReachNpc + stayTime > getMSTime())
|
||||
return false;
|
||||
|
||||
info.npcPos = GuidPosition();
|
||||
info.lastReachNpc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(info.npcPos);
|
||||
Unit* unit = botAI->GetUnit(info.npcPos);
|
||||
if (!unit)
|
||||
return false;
|
||||
float x = unit->GetPositionX();
|
||||
float y = unit->GetPositionY();
|
||||
float z = unit->GetPositionZ();
|
||||
float mapId = unit->GetMapId();
|
||||
float angle = 0.f;
|
||||
if (bot->IsWithinLOS(x, y, z))
|
||||
{
|
||||
if (!unit->isMoving())
|
||||
angle = unit->GetAngle(bot) + (M_PI * irand(-25, 25) / 100.0); // Closest 45 degrees towards the target
|
||||
else
|
||||
angle = unit->GetOrientation() +
|
||||
(M_PI * irand(-25, 25) / 100.0); // 45 degrees infront of target (leading it's movement)
|
||||
}
|
||||
else
|
||||
angle = 2 * M_PI * rand_norm(); // A circle around the target.
|
||||
float rnd = rand_norm();
|
||||
x += cos(angle) * INTERACTION_DISTANCE * rnd;
|
||||
y += sin(angle) * INTERACTION_DISTANCE * rnd;
|
||||
// bool exact = true;
|
||||
if (!unit->GetMap()->CheckCollisionAndGetValidCoords(unit, unit->GetPositionX(), unit->GetPositionY(),
|
||||
unit->GetPositionZ(), x, y, z))
|
||||
{
|
||||
x = unit->GetPositionX();
|
||||
y = unit->GetPositionY();
|
||||
z = unit->GetPositionZ();
|
||||
// exact = false;
|
||||
}
|
||||
return MoveTo(mapId, x, y, z, false, false, false, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
78
src/strategy/rpg/NewRpgAction.h
Normal file
78
src/strategy/rpg/NewRpgAction.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef _PLAYERBOT_NEWRPGACTION_H
|
||||
#define _PLAYERBOT_NEWRPGACTION_H
|
||||
|
||||
#include "Duration.h"
|
||||
#include "MovementActions.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "TravelMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
|
||||
class TellRpgStatusAction : public Action
|
||||
{
|
||||
public:
|
||||
TellRpgStatusAction(PlayerbotAI* botAI) : Action(botAI, "rpg status") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NewRpgStatusUpdateAction : public Action
|
||||
{
|
||||
public:
|
||||
NewRpgStatusUpdateAction(PlayerbotAI* botAI) : Action(botAI, "new rpg status update") {}
|
||||
bool Execute(Event event) override;
|
||||
protected:
|
||||
// const int32 setGrindInterval = 5 * 60 * 1000;
|
||||
// const int32 setNpcInterval = 1 * 60 * 1000;
|
||||
const int32 statusNearNpcDuration = 2 * 60 * 1000;
|
||||
const int32 statusNearRandomDuration = 2 * 60 * 1000;
|
||||
const int32 statusRestDuration = 30 * 1000;
|
||||
WorldPosition SelectRandomGrindPos();
|
||||
WorldPosition SelectRandomInnKeeperPos();
|
||||
};
|
||||
|
||||
class NewRpgGoFarAwayPosAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NewRpgGoFarAwayPosAction(PlayerbotAI* botAI, std::string name) : MovementAction(botAI, name) {}
|
||||
// bool Execute(Event event) override;
|
||||
bool MoveFarTo(WorldPosition dest);
|
||||
|
||||
protected:
|
||||
// WorldPosition dest;
|
||||
float pathFinderDis = 70.0f; // path finder
|
||||
};
|
||||
|
||||
class NewRpgGoGrindAction : public NewRpgGoFarAwayPosAction
|
||||
{
|
||||
public:
|
||||
NewRpgGoGrindAction(PlayerbotAI* botAI) : NewRpgGoFarAwayPosAction(botAI, "new rpg go grind") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class NewRpgGoInnKeeperAction : public NewRpgGoFarAwayPosAction
|
||||
{
|
||||
public:
|
||||
NewRpgGoInnKeeperAction(PlayerbotAI* botAI) : NewRpgGoFarAwayPosAction(botAI, "new rpg go innkeeper") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
|
||||
class NewRpgMoveRandomAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NewRpgMoveRandomAction(PlayerbotAI* botAI) : MovementAction(botAI, "new rpg move random") {}
|
||||
bool Execute(Event event) override;
|
||||
protected:
|
||||
const float moveStep = 50.0f;
|
||||
};
|
||||
|
||||
class NewRpgMoveNpcAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
NewRpgMoveNpcAction(PlayerbotAI* botAI) : MovementAction(botAI, "new rpg move npcs") {}
|
||||
bool Execute(Event event) override;
|
||||
protected:
|
||||
const uint32 stayTime = 8 * 1000;
|
||||
};
|
||||
|
||||
#endif
|
||||
35
src/strategy/rpg/NewRpgStrategy.cpp
Normal file
35
src/strategy/rpg/NewRpgStrategy.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "NewRpgStrategy.h"
|
||||
|
||||
#include "Playerbots.h"
|
||||
|
||||
NewRpgStrategy::NewRpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
NextAction** NewRpgStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("new rpg status update", 5.0f), nullptr);
|
||||
}
|
||||
|
||||
void NewRpgStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("go grind status", NextAction::array(0, new NextAction("new rpg go grind", 1.0f), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("go innkeeper status", NextAction::array(0, new NextAction("new rpg go innkeeper", 1.0f), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("near random status", NextAction::array(0, new NextAction("new rpg move random", 1.0f), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("near npc status", NextAction::array(0, new NextAction("new rpg move npc", 1.0f), nullptr)));
|
||||
}
|
||||
|
||||
void NewRpgStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
{
|
||||
// multipliers.push_back(new RpgActionMultiplier(botAI));
|
||||
}
|
||||
98
src/strategy/rpg/NewRpgStrategy.h
Normal file
98
src/strategy/rpg/NewRpgStrategy.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PLAYERBOT_NEWRPGSTRATEGY_H
|
||||
#define _PLAYERBOT_NEWRPGSTRATEGY_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "Strategy.h"
|
||||
#include "TravelMgr.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
|
||||
enum class NewRpgStatus
|
||||
{
|
||||
// Going to far away place
|
||||
GO_GRIND,
|
||||
GO_INNKEEPER,
|
||||
// Exploring nearby
|
||||
NEAR_RANDOM,
|
||||
NEAR_NPC,
|
||||
// Taking a break
|
||||
REST,
|
||||
// Initial status
|
||||
IDLE
|
||||
};
|
||||
|
||||
struct NewRpgInfo
|
||||
{
|
||||
NewRpgStatus status{NewRpgStatus::IDLE};
|
||||
// NewRpgStatus::GO_GRIND
|
||||
WorldPosition grindPos{};
|
||||
uint32 lastGoGrind{0};
|
||||
// NewRpgStatus::GO_INNKEEPER
|
||||
WorldPosition innKeeperPos{};
|
||||
uint32 lastGoInnKeeper{0};
|
||||
// NewRpgStatus::NEAR_NPC
|
||||
GuidPosition npcPos{};
|
||||
uint32 lastNearNpc{0};
|
||||
uint32 lastReachNpc{0};
|
||||
// NewRpgStatus::NEAR_RANDOM
|
||||
uint32 lastNearRandom{0};
|
||||
// NewRpgStatus::REST
|
||||
uint32 lastRest{0};
|
||||
|
||||
std::string ToString()
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "Status: ";
|
||||
switch (status)
|
||||
{
|
||||
case NewRpgStatus::GO_GRIND:
|
||||
out << "GO_GRIND";
|
||||
out << "\nGrindPos: " << grindPos.GetMapId() << " " << grindPos.GetPositionX() << " " << grindPos.GetPositionY() << " " << grindPos.GetPositionZ();
|
||||
out << "\nlastGoGrind: " << lastGoGrind;
|
||||
break;
|
||||
case NewRpgStatus::GO_INNKEEPER:
|
||||
out << "GO_INNKEEPER";
|
||||
out << "\nInnKeeperPos: " << innKeeperPos.GetMapId() << " " << innKeeperPos.GetPositionX() << " " << innKeeperPos.GetPositionY() << " " << innKeeperPos.GetPositionZ();
|
||||
out << "\nlastGoInnKeeper: " << lastGoInnKeeper;
|
||||
break;
|
||||
case NewRpgStatus::NEAR_NPC:
|
||||
out << "NEAR_NPC";
|
||||
out << "\nNpcPos: " << npcPos.GetMapId() << " " << npcPos.GetPositionX() << " " << npcPos.GetPositionY() << " " << npcPos.GetPositionZ();
|
||||
out << "\nlastNearNpc: " << lastNearNpc;
|
||||
out << "\nlastReachNpc: " << lastReachNpc;
|
||||
break;
|
||||
case NewRpgStatus::NEAR_RANDOM:
|
||||
out << "NEAR_RANDOM";
|
||||
out << "\nlastNearRandom: " << lastNearRandom;
|
||||
break;
|
||||
case NewRpgStatus::IDLE:
|
||||
out << "IDLE";
|
||||
break;
|
||||
case NewRpgStatus::REST:
|
||||
out << "REST";
|
||||
out << "\nlastRest: " << lastRest;
|
||||
break;
|
||||
default:
|
||||
out << "UNKNOWN";
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
};
|
||||
|
||||
class NewRpgStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
NewRpgStrategy(PlayerbotAI* botAI);
|
||||
|
||||
std::string const getName() override { return "new rpg"; }
|
||||
NextAction** getDefaultActions() override;
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
4
src/strategy/rpg/NewRpgTrigger.cpp
Normal file
4
src/strategy/rpg/NewRpgTrigger.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "NewRpgTriggers.h"
|
||||
#include "PlayerbotAI.h"
|
||||
|
||||
bool NewRpgStatusTrigger::IsActive() { return status == botAI->rpgInfo.status; }
|
||||
20
src/strategy/rpg/NewRpgTriggers.h
Normal file
20
src/strategy/rpg/NewRpgTriggers.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _PLAYERBOT_NEWRPGTRIGGERS_H
|
||||
#define _PLAYERBOT_NEWRPGTRIGGERS_H
|
||||
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "Trigger.h"
|
||||
|
||||
class NewRpgStatusTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
NewRpgStatusTrigger(PlayerbotAI* botAI, NewRpgStatus status = NewRpgStatus::IDLE)
|
||||
: Trigger(botAI, "new rpg status"), status(status)
|
||||
{
|
||||
}
|
||||
bool IsActive() override;
|
||||
|
||||
protected:
|
||||
NewRpgStatus status;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ void HealShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
NextAction::array(0, new NextAction("earthliving weapon", 22.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"group heal setting",
|
||||
NextAction::array(0, new NextAction("riptide on party", 23.0f), new NextAction("chain heal on party", 22.0f), NULL)));
|
||||
NextAction::array(0, new NextAction("riptide on party", 27.0f), new NextAction("chain heal on party", 26.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member critical health",
|
||||
|
||||
@@ -77,7 +77,7 @@ void MeleeShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium aoe", NextAction::array(0, new NextAction("strength of earth totem", ACTION_LIGHT_HEAL), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no fire totem",
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
creators["reputation"] = &ChatTriggerContext::reputation;
|
||||
creators["log"] = &ChatTriggerContext::log;
|
||||
creators["los"] = &ChatTriggerContext::los;
|
||||
creators["rpg status"] = &ChatTriggerContext::rpg_status;
|
||||
creators["aura"] = &ChatTriggerContext::aura;
|
||||
creators["drop"] = &ChatTriggerContext::drop;
|
||||
creators["share"] = &ChatTriggerContext::share;
|
||||
@@ -211,6 +212,7 @@ private:
|
||||
static Trigger* reputation(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reputation"); }
|
||||
static Trigger* log(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "log"); }
|
||||
static Trigger* los(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "los"); }
|
||||
static Trigger* rpg_status(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rpg status"); }
|
||||
static Trigger* aura(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "aura"); }
|
||||
static Trigger* loot_all(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "add all loot"); }
|
||||
static Trigger* release(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "release"); }
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "LfgTriggers.h"
|
||||
#include "LootTriggers.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "NewRpgStrategy.h"
|
||||
#include "NewRpgTriggers.h"
|
||||
#include "PvpTriggers.h"
|
||||
#include "RaidNaxxTriggers.h"
|
||||
#include "RpgTriggers.h"
|
||||
@@ -213,6 +215,10 @@ public:
|
||||
creators["rpg craft"] = &TriggerContext::rpg_craft;
|
||||
creators["rpg trade useful"] = &TriggerContext::rpg_trade_useful;
|
||||
creators["rpg duel"] = &TriggerContext::rpg_duel;
|
||||
creators["go grind status"] = &TriggerContext::go_grind_status;
|
||||
creators["go innkeeper status"] = &TriggerContext::go_innkeeper_status;
|
||||
creators["near random status"] = &TriggerContext::near_random_status;
|
||||
creators["near npc status"] = &TriggerContext::near_npc_status;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -402,6 +408,10 @@ private:
|
||||
static Trigger* rpg_craft(PlayerbotAI* botAI) { return new RpgCraftTrigger(botAI); }
|
||||
static Trigger* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulTrigger(botAI); }
|
||||
static Trigger* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelTrigger(botAI); }
|
||||
static Trigger* go_grind_status(PlayerbotAI* botAI) { return new NewRpgStatusTrigger(botAI, NewRpgStatus::GO_GRIND); }
|
||||
static Trigger* go_innkeeper_status(PlayerbotAI* botAI) { return new NewRpgStatusTrigger(botAI, NewRpgStatus::GO_INNKEEPER); }
|
||||
static Trigger* near_random_status(PlayerbotAI* botAI) { return new NewRpgStatusTrigger(botAI, NewRpgStatus::NEAR_RANDOM); }
|
||||
static Trigger* near_npc_status(PlayerbotAI* botAI) { return new NewRpgStatusTrigger(botAI, NewRpgStatus::NEAR_NPC); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -298,8 +298,9 @@ Unit* DpsTargetValue::Calculate()
|
||||
return rti;
|
||||
|
||||
// FindLeastHpTargetStrategy strategy(botAI);
|
||||
Group* group = bot->GetGroup();
|
||||
float dps = AI_VALUE(float, "estimated group dps");
|
||||
if (botAI->IsCaster(bot))
|
||||
if (group && botAI->IsCaster(bot))
|
||||
{
|
||||
CasterFindTargetSmartStrategy strategy(botAI, dps);
|
||||
return TargetValue::FindTarget(&strategy);
|
||||
|
||||
@@ -52,7 +52,7 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
|
||||
float distance = 0;
|
||||
Unit* result = nullptr;
|
||||
std::unordered_map<uint32, bool> needForQuestMap;
|
||||
// std::unordered_map<uint32, bool> needForQuestMap;
|
||||
|
||||
for (ObjectGuid const guid : targets)
|
||||
{
|
||||
@@ -99,18 +99,18 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
if (!bot->InBattleground() && (int)unit->GetLevel() - (int)bot->GetLevel() > 4 && !unit->GetGUID().IsPlayer())
|
||||
continue;
|
||||
|
||||
if (needForQuestMap.find(unit->GetEntry()) == needForQuestMap.end())
|
||||
needForQuestMap[unit->GetEntry()] = needForQuest(unit);
|
||||
// if (needForQuestMap.find(unit->GetEntry()) == needForQuestMap.end())
|
||||
// needForQuestMap[unit->GetEntry()] = needForQuest(unit);
|
||||
|
||||
if (!needForQuestMap[unit->GetEntry()])
|
||||
{
|
||||
Creature* creature = dynamic_cast<Creature*>(unit);
|
||||
if ((urand(0, 100) < 60 || (context->GetValue<TravelTarget*>("travel target")->Get()->isWorking() &&
|
||||
context->GetValue<TravelTarget*>("travel target")->Get()->getDestination()->getName() != "GrindTravelDestination")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// if (!needForQuestMap[unit->GetEntry()])
|
||||
// {
|
||||
// Creature* creature = dynamic_cast<Creature*>(unit);
|
||||
// if ((urand(0, 100) < 60 || (context->GetValue<TravelTarget*>("travel target")->Get()->isWorking() &&
|
||||
// context->GetValue<TravelTarget*>("travel target")->Get()->getDestination()->getName() != "GrindTravelDestination")))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (Creature* creature = unit->ToCreature())
|
||||
if (CreatureTemplate const* CreatureTemplate = creature->GetCreatureTemplate())
|
||||
@@ -142,8 +142,7 @@ Unit* GrindTargetValue::FindTargetForGrinding(uint32 assistCount)
|
||||
else
|
||||
{
|
||||
float newdistance = bot->GetDistance(unit);
|
||||
if (!result || (newdistance < distance &&
|
||||
urand(0, abs(distance - newdistance)) > sPlayerbotAIConfig->sightDistance * 0.1))
|
||||
if (!result || (newdistance < distance))
|
||||
{
|
||||
distance = newdistance;
|
||||
result = unit;
|
||||
|
||||
@@ -14,7 +14,7 @@ class PlayerbotAI;
|
||||
class PossibleRpgTargetsValue : public NearestUnitsValue
|
||||
{
|
||||
public:
|
||||
PossibleRpgTargetsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->rpgDistance);
|
||||
PossibleRpgTargetsValue(PlayerbotAI* botAI, float range = 70.0f);
|
||||
|
||||
static std::vector<uint32> allowedNpcFlags;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ private:
|
||||
{
|
||||
return new ActionNode("summon succubus",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("summon imp"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* summon_felhunter([[maybe_unused]] PlayerbotAI* botAI)
|
||||
|
||||
@@ -16,7 +16,7 @@ void GenericWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
CombatStrategy::InitTriggers(triggers);
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
|
||||
"enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_HIGH + 1), nullptr)));
|
||||
/*triggers.push_back(new TriggerNode("bloodrage", NextAction::array(0, new NextAction("bloodrage", ACTION_HIGH + 1),
|
||||
nullptr))); triggers.push_back(new TriggerNode("shield bash", NextAction::array(0, new NextAction("shield bash",
|
||||
ACTION_INTERRUPT + 4), nullptr))); triggers.push_back(new TriggerNode("shield bash on enemy healer",
|
||||
|
||||
Reference in New Issue
Block a user