diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index eab4de36..d10f0348 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -104,6 +104,12 @@ AiPlayerbot.DeleteRandomBotAccounts = 0 # # +# Maximum number of bots added by one account +AiPlayerbot.MaxAddedBots = 40 + +# Maximum number of bots per class added by one account +AiPlayerbot.MaxAddedBotsPerClass = 10 + # Enable/Disable create bot by addclass command (0 = GM only, 1 = enable) # default: 1 (enable) AiPlayerbot.AddClassCommand = 1 @@ -331,7 +337,7 @@ AiPlayerbot.MediumMana = 40 # # Bots pick their quest reward (yes = picks first useful item, no = list all rewards, ask = pick useful item and lists if multiple) -AiPlayerbot.AutoPickReward = no +AiPlayerbot.AutoPickReward = yes # Sync quests with player (Bots will complete quests the moment you hand them in. Bots will ignore looting quest items.) # Default: 1 (enable) @@ -656,7 +662,7 @@ AiPlayerbot.RandomBotArenaTeamCount = 20 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" # 33(stranglethorn vale),440(tanaris) +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" # PvP Restricted Areas (bots don't pvp) AiPlayerbot.PvpProhibitedAreaIds = "976,35,392" diff --git a/src/PerformanceMonitor.cpp b/src/PerformanceMonitor.cpp index d74de730..397cef47 100644 --- a/src/PerformanceMonitor.cpp +++ b/src/PerformanceMonitor.cpp @@ -50,16 +50,17 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack) if (data.empty()) return; - uint32 total = 0; if (!perTick) { + float updateAITotalTime = 0; for (auto& map : data[PERF_MON_TOTAL]) if (map.first.find("PlayerbotAI::UpdateAIInternal") != std::string::npos) - total += map.second->totalTime; + updateAITotalTime += map.second->totalTime; LOG_INFO("playerbots", "--------------------------------------[TOTAL BOT]------------------------------------------------------"); - LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); + LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); + LOG_INFO("playerbots", "-------------------------------------------------------------------------------------------------------"); for (std::map>::iterator i = data.begin(); i != data.end(); ++i) { @@ -103,39 +104,66 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack) return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; }); - for (auto& name : names) + uint64 typeTotalTime = 0; + uint64 typeMinTime = 0xffffffffu; + uint64 typeMaxTime = 0; + uint32 typeCount = 0; + for (auto& name : names) { PerformanceData* pd = pdMap[name]; - float perc = (float)pd->totalTime / (float)total * 100.0f; - float secs = (float)pd->totalTime / 1000.0f; - float avg = (float)pd->totalTime / (float)pd->count; + typeTotalTime += pd->totalTime; + typeCount += pd->count; + if (typeMinTime > pd->minTime) + typeMinTime = pd->minTime; + if (typeMaxTime < pd->maxTime) + typeMaxTime = pd->maxTime; + float perc = (float)pd->totalTime / updateAITotalTime * 100.0f; + float time = (float)pd->totalTime / 1000000.0f; + float minTime = (float)pd->minTime / 1000.0f; + float maxTime = (float)pd->maxTime / 1000.0f; + float avg = (float)pd->totalTime / (float)pd->count / 1000.0f; std::string disName = name; if (!fullStack && disName.find("|") != std::string::npos) disName = disName.substr(0, disName.find("|")) + "]"; - if (avg >= 0.5f || pd->maxTime > 10) + if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000) { - LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:6d} .. {:6d} ({:10.3f} of {:10d}) - {:6} : {}" + LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}" , perc - , secs - , pd->minTime - , pd->maxTime + , time + , minTime + , maxTime , avg , pd->count , key.c_str() , disName.c_str()); } } + float tPerc = (float)typeTotalTime / (float)updateAITotalTime * 100.0f; + float tTime = (float)typeTotalTime / 1000000.0f; + float tMinTime = (float)typeMinTime / 1000.0f; + float tMaxTime = (float)typeMaxTime / 1000.0f; + float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f; + LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}" + , tPerc + , tTime + , tMinTime + , tMaxTime + , tAvg + , typeCount + , key.c_str() + , "Total"); LOG_INFO("playerbots", " "); } } else { - float totalCount = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->count; - total = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->totalTime; + float fullTickCount = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->count; + float fullTickTotalTime = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->totalTime; LOG_INFO("playerbots", "---------------------------------------[PER TICK]------------------------------------------------------"); - LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); + LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); + LOG_INFO("playerbots", "-------------------------------------------------------------------------------------------------------"); for (std::map>::iterator i = data.begin(); i != data.end(); ++i) { @@ -175,30 +203,59 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack) return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; }); + uint64 typeTotalTime = 0; + uint64 typeMinTime = 0xffffffffu; + uint64 typeMaxTime = 0; + uint32 typeCount = 0; for (auto& name : names) { PerformanceData* pd = pdMap[name]; - float perc = (float)pd->totalTime / (float)total * 100.0f; - uint32 secs = pd->totalTime / totalCount; - float avg = (float)pd->totalTime / (float)pd->count; - float amount = (float)pd->count / (float)totalCount; + typeTotalTime += pd->totalTime; + typeCount += pd->count; + if (typeMinTime > pd->minTime) + typeMinTime = pd->minTime; + if (typeMaxTime < pd->maxTime) + typeMaxTime = pd->maxTime; + float perc = (float)pd->totalTime / fullTickTotalTime * 100.0f; + float time = (float)pd->totalTime / fullTickCount / 1000.0f; + float minTime = (float)pd->minTime / 1000.0f; + float maxTime = (float)pd->maxTime / 1000.0f; + float avg = (float)pd->totalTime / (float)pd->count / 1000.0f; + float amount = (float)pd->count / fullTickCount; std::string disName = name; if (!fullStack && disName.find("|") != std::string::npos) disName = disName.substr(0, disName.find("|")) + "]"; - - if (avg >= 0.5f || pd->maxTime > 10) + if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000) { - LOG_INFO("playerbots", "{:7.3f}% {:9d}ms | {:6d} .. {:6d} ({:10.3f} of {:10.3f}) - {:6} : {}" + LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}" , perc - , secs - , pd->minTime - , pd->maxTime + , time + , minTime + , maxTime , avg , amount , key.c_str() , disName.c_str()); } } + if (PERF_MON_TOTAL != i->first) + { + float tPerc = (float)typeTotalTime / (float)fullTickTotalTime * 100.0f; + float tTime = (float)typeTotalTime / fullTickCount / 1000.0f; + float tMinTime = (float)typeMinTime / 1000.0f; + float tMaxTime = (float)typeMaxTime / 1000.0f; + float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f; + float tAmount = (float)typeCount / fullTickCount; + LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}" + , tPerc + , tTime + , tMinTime + , tMaxTime + , tAvg + , tAmount + , key.c_str() + , "Total"); + } LOG_INFO("playerbots", " "); } } @@ -223,13 +280,13 @@ void PerformanceMonitor::Reset() PerformanceMonitorOperation::PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack) : data(data), name(name), stack(stack) { - started = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now())).time_since_epoch(); + started = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now())).time_since_epoch(); } void PerformanceMonitorOperation::finish() { - std::chrono::milliseconds finished = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now())).time_since_epoch(); - uint32 elapsed = (finished - started).count(); + std::chrono::microseconds finished = (std::chrono::time_point_cast(std::chrono::high_resolution_clock::now())).time_since_epoch(); + uint64_t elapsed = (finished - started).count(); std::lock_guard guard(data->lock); if (elapsed > 0) diff --git a/src/PerformanceMonitor.h b/src/PerformanceMonitor.h index 071a9724..1871020a 100644 --- a/src/PerformanceMonitor.h +++ b/src/PerformanceMonitor.h @@ -17,9 +17,9 @@ typedef std::vector PerformanceStack; struct PerformanceData { - uint32 minTime; - uint32 maxTime; - uint32 totalTime; + uint64 minTime; + uint64 maxTime; + uint64 totalTime; uint32 count; std::mutex lock; }; @@ -43,7 +43,7 @@ class PerformanceMonitorOperation PerformanceData* data; std::string const name; PerformanceStack* stack; - std::chrono::milliseconds started; + std::chrono::microseconds started; }; class PerformanceMonitor diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 6996d460..71235156 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -450,22 +450,28 @@ void PlayerbotAI::HandleTeleportAck() bot->GetMotionMaster()->Clear(true); bot->StopMoving(); - if (bot->IsBeingTeleportedNear()) - { - WorldPacket p = WorldPacket(MSG_MOVE_TELEPORT_ACK, 8 + 4 + 4); - p << bot->GetGUID().WriteAsPacked(); - p << (uint32) 0; // supposed to be flags? not used currently - p << (uint32) time(nullptr); // time - not currently used - bot->GetSession()->HandleMoveTeleportAck(p); - - // add delay to simulate teleport delay + if (bot->IsBeingTeleportedNear()) { + // Temporary fix for instance can not enter + if (!bot->IsInWorld()) { + bot->GetMap()->AddPlayerToMap(bot); + } + while (bot->IsInWorld() && bot->IsBeingTeleportedNear()) { + Player* plMover = bot->m_mover->ToPlayer(); + if (!plMover) + return; + WorldPacket p = WorldPacket(MSG_MOVE_TELEPORT_ACK, 20); + p << plMover->GetPackGUID(); + p << (uint32) 0; // supposed to be flags? not used currently + p << (uint32) 0; // time - not currently used + bot->GetSession()->HandleMoveTeleportAck(p); + } SetNextCheckDelay(urand(1000, 3000)); - } - else if (bot->IsBeingTeleportedFar()) + } + if (bot->IsBeingTeleportedFar()) { - bot->GetSession()->HandleMoveWorldportAck(); - - // add delay to simulate teleport delay + while (bot->IsBeingTeleportedFar()) { + bot->GetSession()->HandleMoveWorldportAck(); + } SetNextCheckDelay(urand(2000, 5000)); } diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index a6bcf470..b28aeeba 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -283,6 +283,9 @@ bool PlayerbotAIConfig::Initialize() botRepairWhenSummon = sConfigMgr->GetOption("AiPlayerbot.BotRepairWhenSummon", true); autoInitOnly = sConfigMgr->GetOption("AiPlayerbot.AutoInitOnly", false); autoInitEquipLevelLimitRatio = sConfigMgr->GetOption("AiPlayerbot.AutoInitEquipLevelLimitRatio", 1.0); + + maxAddedBots = sConfigMgr->GetOption("AiPlayerbot.MaxAddedBots", 40); + maxAddedBotsPerClass = sConfigMgr->GetOption("AiPlayerbot.MaxAddedBotsPerClass", 10); addClassCommand = sConfigMgr->GetOption("AiPlayerbot.AddClassCommand", 1); maintenanceCommand = sConfigMgr->GetOption("AiPlayerbot.MaintenanceCommand", 1); autoGearCommand = sConfigMgr->GetOption("AiPlayerbot.AutoGearCommand", 1); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 17da007d..32bd1c59 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -224,6 +224,7 @@ class PlayerbotAIConfig bool botRepairWhenSummon; bool autoInitOnly; float autoInitEquipLevelLimitRatio; + int32 maxAddedBots, maxAddedBotsPerClass; int32 addClassCommand; int32 maintenanceCommand; int32 autoGearCommand, autoGearQualityLimit, autoGearScoreLimit; diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 665c7fdf..2429e369 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -6,6 +6,8 @@ #include "CharacterPackets.h" #include "Common.h" #include "Define.h" +#include "Group.h" +#include "GroupMgr.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "PlayerbotAIConfig.h" @@ -19,6 +21,7 @@ #include "ChannelMgr.h" #include #include +#include #include PlayerbotHolder::PlayerbotHolder() : PlayerbotAIBase(false) @@ -89,25 +92,42 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con Player* bot = botSession->GetPlayer(); if (!bot) { - LogoutPlayerBot(holder.GetGuid()); + botSession->LogoutPlayer(true); + delete botSession; // LOG_ERROR("playerbots", "Error logging in bot {}, please try to reset all random bots", holder.GetGuid().ToString().c_str()); return; } - sRandomPlayerbotMgr->OnPlayerLogin(bot); - uint32 masterAccount = holder.GetMasterAccountId(); WorldSession* masterSession = masterAccount ? sWorld->FindSession(masterAccount) : nullptr; + std::ostringstream out; bool allowed = false; - if (botAccountId == masterAccount) + if (botAccountId == masterAccount) { allowed = true; - else if (masterSession && sPlayerbotAIConfig->allowGuildBots && bot->GetGuildId() != 0 && bot->GetGuildId() == masterSession->GetPlayer()->GetGuildId()) + } else if (masterSession && sPlayerbotAIConfig->allowGuildBots && bot->GetGuildId() != 0 && bot->GetGuildId() == masterSession->GetPlayer()->GetGuildId()) { allowed = true; - else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId)) + } else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId)) { allowed = true; - + } else { + allowed = false; + out << "Failure: You are not allowed to control bot " << bot->GetName().c_str(); + } + if (allowed && masterSession) { + Player* player = masterSession->GetPlayer(); + PlayerbotMgr *mgr = GET_PLAYERBOT_MGR(player); + uint32 count = mgr->GetPlayerbotsCount(); + uint32 cls_count = mgr->GetPlayerbotsCountByClass(bot->getClass()); + if (count >= sPlayerbotAIConfig->maxAddedBots) { + allowed = false; + out << "Failure: You have added too many bots"; + } else if (cls_count >= sPlayerbotAIConfig->maxAddedBotsPerClass) { + allowed = false; + out << "Failure: You have added too many bots for this class"; + } + } if (allowed) { + sRandomPlayerbotMgr->OnPlayerLogin(bot); OnBotLogin(bot); } else @@ -115,10 +135,12 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con if (masterSession) { ChatHandler ch(masterSession); - ch.PSendSysMessage("You are not allowed to control bot %s", bot->GetName()); + ch.SendSysMessage(out.str()); } - OnBotLogin(bot); - LogoutPlayerBot(bot->GetGUID()); + botSession->LogoutPlayer(true); + delete botSession; + // OnBotLogin(bot); + // LogoutPlayerBot(bot->GetGUID()); // LOG_ERROR("playerbots", "Attempt to add not allowed bot {}, please try to reset all random bots", bot->GetName()); } @@ -453,7 +475,22 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) botAI->TellMaster("Hello!", PLAYERBOT_SECURITY_TALK); if (master && master->GetGroup() && !group) { - master->GetGroup()->AddMember(bot); + Group* mgroup = master->GetGroup(); + if (mgroup->GetMembersCount() >= 5) { + if (!mgroup->isRaidGroup() && !mgroup->isLFGGroup() && !mgroup->isBGGroup() && !mgroup->isBFGroup()) { + mgroup->ConvertToRaid(); + } + if (mgroup->isRaidGroup()) { + mgroup->AddMember(bot); + } + } else { + mgroup->AddMember(bot); + } + } else if (master && !group) { + Group* newGroup = new Group(); + newGroup->Create(master); + sGroupMgr->AddGroup(newGroup); + newGroup->AddMember(bot); } uint32 accountId = bot->GetSession()->GetAccountId(); @@ -1157,6 +1194,19 @@ std::string const PlayerbotHolder::LookupBots(Player* master) return ret_msg; } +uint32 PlayerbotHolder::GetPlayerbotsCountByClass(uint32 cls) +{ + uint32 count = 0; + for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) + { + Player* const bot = it->second; + if (bot->getClass() == cls) { + count++; + } + } + return count; +} + PlayerbotMgr::PlayerbotMgr(Player* const master) : PlayerbotHolder(), master(master), lastErrorTell(0) { } diff --git a/src/PlayerbotMgr.h b/src/PlayerbotMgr.h index 16e1aa95..d430d414 100644 --- a/src/PlayerbotMgr.h +++ b/src/PlayerbotMgr.h @@ -48,7 +48,8 @@ class PlayerbotHolder : public PlayerbotAIBase uint32 GetAccountId(ObjectGuid guid); std::string const ListBots(Player* master); std::string const LookupBots(Player* master); - + uint32 GetPlayerbotsCount() { return playerBots.size(); } + uint32 GetPlayerbotsCountByClass(uint32 cls); protected: virtual void OnBotLoginInternal(Player* const bot) = 0; diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 6721c8e4..24d5e08b 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -219,7 +219,7 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender) { - std::string botName = ""; + std::string botName = ""; int tries = 10; while(--tries) { QueryResult result = CharacterDatabase.Query("SELECT name FROM playerbots_names " @@ -235,7 +235,80 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender) return ret; } } - LOG_ERROR("playerbots", "No more names left for random bots. Simply random."); + + //CONLANG NAME GENERATION + LOG_ERROR("playerbots", "No more names left for random bots. Attempting conlang name generation."); + const std::string groupCategory = "SCVKRU"; + const std::string groupFormStart[2][4] = { + {"SV","SV","VK","RV"}, + {"V" ,"SU","VS","RV"} + }; + const std::string groupFormMid[2][6] = { + {"CV","CVC","CVC","CVK","VC","VK"}, + {"CV","CVC","CVK","KVC","VC","KV"} + }; + const std::string groupFormEnd[2][4] = { + {"CV","VC","VK","CV"}, + {"RU","UR","VR","V" } + }; + const std::string groupLetter[2][6] = { + //S C V K R U + {"dtspkThfS","bcCdfghjkmnNqqrrlsStTvwxyz","aaeeiouA" ,"ppttkkbdg","lmmnrr" ,"AEO" }, + {"dtskThfS" ,"bcCdfghjkmmnNqrrlssStTvwyz","aaaeeiiuAAEIO","ppttkbbdg","lmmnrrr","AEOy"} + }; + const std::string replaceRule[2][17] = { + {"ST" ,"ka","ko","ku","kr","S" ,"T" ,"C" ,"N" ,"jj","AA","AI" ,"A" ,"E" ,"O" ,"I" ,"aa"}, + {"sth","ca","co","cu","cr","sh","th","ch","ng","dg","A" ,"ayu","ai","ei","ou","iu","ae"} + }; + + tries = 10; + while (--tries) + { + botName.clear(); + //Build name from groupForms + //Pick random start group + botName = groupFormStart[gender][rand()%4]; + //Pick up to 2 and then up to 1 additional middle group + for (int i = 0; i < rand()%3 + rand()%2; i++) + { + botName += groupFormMid[gender][rand()%6]; + } + //Pick up to 1 end group + botName += rand()%2 ? groupFormEnd[gender][rand()%4] : ""; + //If name is single letter add random end group + botName += (botName.size() < 2) ? groupFormEnd[gender][rand()%4] : ""; + + //Replace Catagory value with random Letter from that Catagory's Letter string for a given bot gender + for (int i=0; i < botName.size(); i++) + { + botName[i] = groupLetter[gender][groupCategory.find(botName[i])][rand()%groupLetter[gender][groupCategory.find(botName[i])].size()]; + } + + //Itterate over replace rules + for (int i = 0; i < 17; i++) + { + int j = botName.find(replaceRule[0][i]); + while ( j > -1) + { + botName.replace(j,replaceRule[0][i].size(),replaceRule[1][i]); + j = botName.find(replaceRule[0][i]); + } + } + + //Capitalize first letter + botName[0] -= 32; + + if (ObjectMgr::CheckPlayerName(botName) != CHAR_NAME_SUCCESS || + (sObjectMgr->IsReservedName(botName) || sObjectMgr->IsProfanityName(botName))) + { + botName.clear(); + continue; + } + return std::move(botName); + } + + //TRUE RANDOM NAME GENERATION + LOG_ERROR("playerbots", "Con​lang name generation failed. True random name fallback."); tries = 10; while(--tries) { for (uint8 i = 0; i < 10; i++) { diff --git a/src/strategy/actions/AttackAction.cpp b/src/strategy/actions/AttackAction.cpp index 1ba9f4b5..61efe14f 100644 --- a/src/strategy/actions/AttackAction.cpp +++ b/src/strategy/actions/AttackAction.cpp @@ -95,6 +95,16 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/) return false; } + if (target->IsPlayer() && !target->IsPvP() && !target->IsFFAPvP() && (!bot->duel || bot->duel->Opponent != target || bot->duel->StartTime)) + { + if (verbose) + { + botAI->TellError(Acore::StringFormat("%s is not flagged for pvp", target->GetName())); + } + + return false; + } + if (bot->IsMounted() && bot->IsWithinLOSInMap(target)) { WorldPacket emptyPacket; diff --git a/src/strategy/actions/CastCustomSpellAction.cpp b/src/strategy/actions/CastCustomSpellAction.cpp index 774c0cd8..aa5b4894 100644 --- a/src/strategy/actions/CastCustomSpellAction.cpp +++ b/src/strategy/actions/CastCustomSpellAction.cpp @@ -9,14 +9,14 @@ #include "Playerbots.h" #include "ServerFacade.h" -uint32 FindLastSeparator(std::string const text, std::string const sep) +size_t FindLastSeparator(std::string const text, std::string const sep) { size_t pos = text.rfind(sep); if (pos == std::string::npos) return pos; - uint32 lastLinkBegin = text.rfind("|H"); - uint32 lastLinkEnd = text.find("|h|r", lastLinkBegin + 1); + size_t lastLinkBegin = text.rfind("|H"); + size_t lastLinkEnd = text.find("|h|r", lastLinkBegin + 1); if (pos >= lastLinkBegin && pos <= lastLinkEnd) pos = text.find_last_of(sep, lastLinkBegin); diff --git a/src/strategy/actions/QueryItemUsageAction.cpp b/src/strategy/actions/QueryItemUsageAction.cpp index 1357d914..2a894ced 100644 --- a/src/strategy/actions/QueryItemUsageAction.cpp +++ b/src/strategy/actions/QueryItemUsageAction.cpp @@ -137,6 +137,8 @@ std::string const QueryItemUsageAction::QueryItemUsage(ItemTemplate const* item) return "Auctionhouse"; case ITEM_USAGE_AMMO: return "Ammunition"; + default: + break; } return ""; diff --git a/src/strategy/actions/SayAction.cpp b/src/strategy/actions/SayAction.cpp index 074b4e22..02f03499 100644 --- a/src/strategy/actions/SayAction.cpp +++ b/src/strategy/actions/SayAction.cpp @@ -588,11 +588,12 @@ void ChatReplyAction::ChatReplyDo(Player* bot, uint32 type, uint32 guid1, uint32 if (ChannelMgr* cMgr = ChannelMgr::forTeam(bot->GetTeamId())) { std::string worldChan = "World"; - if (Channel* chn = cMgr->GetJoinChannel(worldChan.c_str(), 0)) + if (Channel* chn = cMgr->GetJoinChannel(worldChan.c_str(), 0)) { if (bot->GetTeamId() == TEAM_ALLIANCE) chn->Say(bot->GetGUID(), c, LANG_COMMON); else chn->Say(bot->GetGUID(), c, LANG_ORCISH); + } } } else diff --git a/src/strategy/actions/TrainerAction.cpp b/src/strategy/actions/TrainerAction.cpp index af1e7a7c..231dea7d 100644 --- a/src/strategy/actions/TrainerAction.cpp +++ b/src/strategy/actions/TrainerAction.cpp @@ -151,7 +151,7 @@ void TrainerAction::TellFooter(uint32 totalCost) bool MaintenanceAction::Execute(Event event) { if (!sPlayerbotAIConfig->maintenanceCommand) { - botAI->TellMaster("maintenance command is not allowed, please check the configuration."); + botAI->TellError("maintenance command is not allowed, please check the configuration."); return false; } botAI->TellMaster("I'm maintaining"); @@ -187,7 +187,7 @@ bool RemoveGlyphAction::Execute(Event event) bool AutoGearAction::Execute(Event event) { if (!sPlayerbotAIConfig->autoGearCommand) { - botAI->TellMaster("autogear command is not allowed, please check the configuration."); + botAI->TellError("autogear command is not allowed, please check the configuration."); return false; } botAI->TellMaster("I'm auto gearing"); diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index f0267e0c..5cf93e14 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -164,6 +164,15 @@ bool SummonAction::SummonUsingNpcs(Player* summoner, Player* player) bool SummonAction::Teleport(Player* summoner, Player* player) { Player* master = GetMaster(); + if (master->GetMap() && master->GetMap()->IsDungeon()) { + InstanceMap* map = master->GetMap()->ToInstanceMap(); + if (map) { + if (map->CannotEnter(player) == Map::CANNOT_ENTER_MAX_PLAYERS) { + botAI->TellError("I can not enter this dungeon"); + return false; + } + } + } if (!summoner->IsBeingTeleported() && !player->IsBeingTeleported()) { float followAngle = GetFollowAngle(); diff --git a/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp b/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp index 74d95313..b28da727 100644 --- a/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp +++ b/src/strategy/rogue/GenericRogueNonCombatStrategy.cpp @@ -51,5 +51,5 @@ void GenericRogueNonCombatStrategy::InitTriggers(std::vector& trig triggers.push_back(new TriggerNode( "often", - NextAction::array(0, new NextAction("unstealth", 10.0f), NULL))); + NextAction::array(0, new NextAction("unstealth", 30.0f), NULL))); } diff --git a/src/strategy/shaman/GenericShamanStrategy.cpp b/src/strategy/shaman/GenericShamanStrategy.cpp index 96a31cbf..eb4958fd 100644 --- a/src/strategy/shaman/GenericShamanStrategy.cpp +++ b/src/strategy/shaman/GenericShamanStrategy.cpp @@ -35,7 +35,7 @@ class GenericShamanStrategyActionNodeFactory : public NamedObjectFactoryGetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); + Item* const itemForSpell = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); if (!itemForSpell || itemForSpell->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) return false; return true; } bool OffHandWeaponNoImbueTrigger::IsActive() { - Item* const itemForSpell = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); - if (!itemForSpell || itemForSpell->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)) + Item* const itemForSpell = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + if (!itemForSpell || itemForSpell->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT) || itemForSpell->GetTemplate()->InventoryType != INVTYPE_WEAPON) return false; return true; } @@ -106,4 +106,4 @@ bool NoAirTotemTrigger::IsActive() { return !AI_VALUE2(bool, "has totem", "wrath of air totem") && !AI_VALUE2(bool, "has totem", "windfury totem"); -} \ No newline at end of file +} diff --git a/src/strategy/values/AoeValues.h b/src/strategy/values/AoeValues.h index 45fedf87..0eb22bb5 100644 --- a/src/strategy/values/AoeValues.h +++ b/src/strategy/values/AoeValues.h @@ -46,7 +46,7 @@ class AreaDebuffValue : public CalculatedValue { public: AreaDebuffValue(PlayerbotAI* botAI) : - CalculatedValue(botAI, "area debuff", 1 * 1000) { } + CalculatedValue(botAI, "area debuff", 1) { } Aura* Calculate() override; };