Merge pull request #405 from liyunfan1223/code-style-and-check

Code style and check
This commit is contained in:
Yunfan Li
2024-08-04 13:37:02 +08:00
committed by GitHub
838 changed files with 35145 additions and 31861 deletions

12
.clang-format Normal file
View File

@@ -0,0 +1,12 @@
BasedOnStyle: google
IndentWidth: 4
TabWidth: 4
ColumnLimit: 120
UseTab: Never
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
BreakBeforeBraces: Allman
AccessModifierOffset: -4
DerivePointerAlignment: false
PointerAlignment: Left

30
.github/workflows/code_style.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Codestyle
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
lint:
name: "clang-format-always-success"
runs-on: ubuntu-latest
steps:
- name: Checkout Playerbot Module
uses: actions/checkout@v4
- name: Install clang-format
run: sudo apt-get install clang-format -y
- name: Run clang-format
run: |
# Find all C/C++ source files
FILES=$(find . -name "*.h" -o -name "*.cpp" -o -name "*.c" -o -name "*.hpp")
# Run clang-format in dry-run mode to check for formatting issues
clang-format -i $FILES
# Check if there are any formatting changes
git diff --exit-code
shell: bash
continue-on-error: true

18
code_format.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
CLANG_FORMAT_PATH=$(which clang-format)
if [ -z "$CLANG_FORMAT_PATH" ]; then
echo "clang-format not found."
exit 1
fi
PROJECT_ROOT=$(dirname "$0")
cpp_files=$(find $PROJECT_ROOT -name '*.cpp' -or -name '*.h' )
for file in $cpp_files; do
echo "Formatting $file"
$CLANG_FORMAT_PATH -i $file
done
echo "All .cpp or .h files have been formatted."

View File

@@ -1,28 +1,30 @@
/* /*
* 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. * 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 "AiFactory.h" #include "AiFactory.h"
#include "BattlegroundMgr.h" #include "BattlegroundMgr.h"
#include "DKAiObjectContext.h"
#include "DruidAiObjectContext.h"
#include "Engine.h"
#include "Group.h"
#include "HunterAiObjectContext.h"
#include "Item.h" #include "Item.h"
#include "MageAiObjectContext.h"
#include "PaladinAiObjectContext.h"
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Engine.h"
#include "Group.h"
#include "DKAiObjectContext.h"
#include "PriestAiObjectContext.h" #include "PriestAiObjectContext.h"
#include "MageAiObjectContext.h" #include "RogueAiObjectContext.h"
#include "ShamanAiObjectContext.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "SpellInfo.h" #include "SpellInfo.h"
#include "SpellMgr.h" #include "SpellMgr.h"
#include "WarlockAiObjectContext.h" #include "WarlockAiObjectContext.h"
#include "WarriorAiObjectContext.h" #include "WarriorAiObjectContext.h"
#include "ShamanAiObjectContext.h"
#include "PaladinAiObjectContext.h"
#include "DruidAiObjectContext.h"
#include "HunterAiObjectContext.h"
#include "RogueAiObjectContext.h"
AiObjectContext* AiFactory::createAiObjectContext(Player* player, PlayerbotAI* botAI) AiObjectContext* AiFactory::createAiObjectContext(Player* player, PlayerbotAI* botAI)
{ {
@@ -100,11 +102,12 @@ std::map<uint8, uint32> AiFactory::GetPlayerSpecTabs(Player* bot)
for (PlayerTalentMap::const_iterator i = talentMap.begin(); i != talentMap.end(); ++i) for (PlayerTalentMap::const_iterator i = talentMap.begin(); i != talentMap.end(); ++i)
{ {
uint32 spellId = i->first; uint32 spellId = i->first;
if ((bot->GetActiveSpecMask() & i->second->specMask) == 0) { if ((bot->GetActiveSpecMask() & i->second->specMask) == 0)
{
continue; continue;
} }
TalentSpellPos const* talentPos = GetTalentSpellPos(spellId); TalentSpellPos const* talentPos = GetTalentSpellPos(spellId);
if(!talentPos) if (!talentPos)
continue; continue;
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id); TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id);
if (!talentInfo) if (!talentInfo)
@@ -186,7 +189,8 @@ std::string AiFactory::GetPlayerSpecName(Player* player)
specName = "holy"; specName = "holy";
else else
specName = "disc"; specName = "disc";
; break; ;
break;
case CLASS_SHAMAN: case CLASS_SHAMAN:
if (tab == 2) if (tab == 2)
specName = "resto"; specName = "resto";
@@ -286,11 +290,16 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
switch (player->getClass()) switch (player->getClass())
{ {
case CLASS_PRIEST: case CLASS_PRIEST:
if (tab == 2) { if (tab == 2)
{
engine->addStrategies("dps", "shadow debuff", "shadow aoe", nullptr); engine->addStrategies("dps", "shadow debuff", "shadow aoe", nullptr);
} else if (tab == PRIEST_TAB_DISIPLINE) { }
else if (tab == PRIEST_TAB_DISIPLINE)
{
engine->addStrategies("heal", nullptr); engine->addStrategies("heal", nullptr);
} else { }
else
{
engine->addStrategies("holy heal", nullptr); engine->addStrategies("holy heal", nullptr);
} }
@@ -310,13 +319,13 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
if (tab == 2) if (tab == 2)
engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr); engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr);
else if (player->GetLevel() < 36 || tab == 0) else if (player->GetLevel() < 36 || tab == 0)
engine->addStrategies("arms", "aoe", "dps assist",/*"behind",*/ nullptr); engine->addStrategies("arms", "aoe", "dps assist", /*"behind",*/ nullptr);
else else
engine->addStrategies("fury", "aoe", "dps assist",/*"behind",*/ nullptr); engine->addStrategies("fury", "aoe", "dps assist", /*"behind",*/ nullptr);
break; break;
case CLASS_SHAMAN: case CLASS_SHAMAN:
if (tab == 0) if (tab == 0)
engine->addStrategies("caster", "caster aoe", "bmana",nullptr); engine->addStrategies("caster", "caster aoe", "bmana", nullptr);
else if (tab == 2) else if (tab == 2)
engine->addStrategies("heal", "bmana", nullptr); engine->addStrategies("heal", "bmana", nullptr);
else else
@@ -343,9 +352,12 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
engine->addStrategies("heal", "cure", "dps assist", nullptr); engine->addStrategies("heal", "cure", "dps assist", nullptr);
else else
{ {
if (player->GetLevel() >= 20 && !player->HasAura(16931)/*thick hide*/) { if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/)
{
engine->addStrategies("cat", "dps assist", nullptr); engine->addStrategies("cat", "dps assist", nullptr);
} else { }
else
{
engine->addStrategies("bear", "tank assist", nullptr); engine->addStrategies("bear", "tank assist", nullptr);
} }
} }
@@ -355,9 +367,12 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
engine->addStrategy("dps debuff"); engine->addStrategy("dps debuff");
break; break;
case CLASS_ROGUE: case CLASS_ROGUE:
if (tab == ROGUE_TAB_ASSASSINATION) { if (tab == ROGUE_TAB_ASSASSINATION)
{
engine->addStrategies("melee", "dps assist", "aoe", /*"behind",*/ nullptr); engine->addStrategies("melee", "dps assist", "aoe", /*"behind",*/ nullptr);
} else { }
else
{
engine->addStrategies("dps", "dps assist", "aoe", /*"behind",*/ nullptr); engine->addStrategies("dps", "dps assist", "aoe", /*"behind",*/ nullptr);
} }
break; break;
@@ -384,28 +399,37 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
engine->addStrategy("dps assist"); engine->addStrategy("dps assist");
engine->removeStrategy("threat"); engine->removeStrategy("threat");
// engine- // engine-
switch (player->getClass()) { switch (player->getClass())
case CLASS_PRIEST: { {
if (tab != PRIEST_TAB_SHADOW) { case CLASS_PRIEST:
{
if (tab != PRIEST_TAB_SHADOW)
{
engine->addStrategies("holy dps", "shadow debuff", "shadow aoe", nullptr); engine->addStrategies("holy dps", "shadow debuff", "shadow aoe", nullptr);
} }
break; break;
} }
case CLASS_DRUID: { case CLASS_DRUID:
if (tab == DRUID_TAB_RESTORATION) { {
if (tab == DRUID_TAB_RESTORATION)
{
engine->addStrategies("caster", "caster aoe", nullptr); engine->addStrategies("caster", "caster aoe", nullptr);
engine->addStrategy("caster debuff"); engine->addStrategy("caster debuff");
} }
break; break;
} }
case CLASS_SHAMAN: { case CLASS_SHAMAN:
if (tab == SHAMAN_TAB_RESTORATION) { {
if (tab == SHAMAN_TAB_RESTORATION)
{
engine->addStrategies("caster", "caster aoe", "bmana", nullptr); engine->addStrategies("caster", "caster aoe", "bmana", nullptr);
} }
break; break;
} }
case CLASS_PALADIN: { case CLASS_PALADIN:
if (tab == PALADIN_TAB_HOLY) { {
if (tab == PALADIN_TAB_HOLY)
{
engine->addStrategies("dps", "dps assist", "baoe", nullptr); engine->addStrategies("dps", "dps assist", "baoe", nullptr);
} }
break; break;
@@ -447,7 +471,8 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
engine->addStrategy("arena"); engine->addStrategy("arena");
} }
engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "cast time", "dps assist", nullptr); engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "cast time", "dps assist",
nullptr);
engine->removeStrategy("custom::say"); engine->removeStrategy("custom::say");
engine->removeStrategy("flee"); engine->removeStrategy("flee");
engine->removeStrategy("threat"); engine->removeStrategy("threat");
@@ -466,7 +491,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
Engine* AiFactory::createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext) Engine* AiFactory::createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext)
{ {
Engine* engine = new Engine(facade, aiObjectContext); Engine* engine = new Engine(facade, aiObjectContext);
AddDefaultCombatStrategies(player, facade, engine); AddDefaultCombatStrategies(player, facade, engine);
return engine; return engine;
} }
@@ -481,18 +506,22 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->addStrategies("dps assist", "cure", nullptr); nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
break; break;
case CLASS_PALADIN: case CLASS_PALADIN:
if (tab == 1) { if (tab == 1)
{
nonCombatEngine->addStrategies("bthreat", "tank assist", "barmor", nullptr); nonCombatEngine->addStrategies("bthreat", "tank assist", "barmor", nullptr);
if (player->GetLevel() >= 20) { if (player->GetLevel() >= 20)
{
nonCombatEngine->addStrategy("bstats"); nonCombatEngine->addStrategy("bstats");
} else { }
else
{
nonCombatEngine->addStrategy("bdps"); nonCombatEngine->addStrategy("bdps");
} }
} }
else if (tab == 0) else if (tab == 0)
nonCombatEngine->addStrategies("dps assist", "bmana", "bcast", nullptr); nonCombatEngine->addStrategies("dps assist", "bmana", "bcast", nullptr);
else else
nonCombatEngine->addStrategies("dps assist", "bdps", "baoe",nullptr); nonCombatEngine->addStrategies("dps assist", "bdps", "baoe", nullptr);
nonCombatEngine->addStrategies("cure", nullptr); nonCombatEngine->addStrategies("cure", nullptr);
break; break;
@@ -516,10 +545,14 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->addStrategies("dps assist", "cure", nullptr); nonCombatEngine->addStrategies("dps assist", "cure", nullptr);
break; break;
case CLASS_DRUID: case CLASS_DRUID:
if (tab == 1) { if (tab == 1)
if (player->GetLevel() >= 20 && !player->HasAura(16931)/*thick hide*/) { {
if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/)
{
nonCombatEngine->addStrategy("dps assist"); nonCombatEngine->addStrategy("dps assist");
} else { }
else
{
nonCombatEngine->addStrategy("tank assist"); nonCombatEngine->addStrategy("tank assist");
} }
} }
@@ -533,11 +566,16 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->addStrategy("dps assist"); nonCombatEngine->addStrategy("dps assist");
break; break;
case CLASS_WARLOCK: case CLASS_WARLOCK:
if (tab == WARLOCK_TAB_AFFLICATION) { if (tab == WARLOCK_TAB_AFFLICATION)
{
nonCombatEngine->addStrategies("bmana", nullptr); nonCombatEngine->addStrategies("bmana", nullptr);
} else if (tab == WARLOCK_TAB_DEMONOLOGY) { }
else if (tab == WARLOCK_TAB_DEMONOLOGY)
{
nonCombatEngine->addStrategies("bdps", nullptr); nonCombatEngine->addStrategies("bdps", nullptr);
} else if (tab == WARLOCK_TAB_DESTRUCTION) { }
else if (tab == WARLOCK_TAB_DESTRUCTION)
{
nonCombatEngine->addStrategies("bhealth", nullptr); nonCombatEngine->addStrategies("bhealth", nullptr);
} }
nonCombatEngine->addStrategies("dps assist", nullptr); nonCombatEngine->addStrategies("dps assist", nullptr);
@@ -555,17 +593,18 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
if (!player->InBattleground()) if (!player->InBattleground())
{ {
nonCombatEngine->addStrategies("nc", "food", "chat", "follow", nonCombatEngine->addStrategies("nc", "food", "chat", "follow", "default", "quest", "loot", "gather", "duel",
"default", "quest", "loot", "gather", "duel", "buff", "mount", "emote", nullptr); "buff", "mount", "emote", nullptr);
} }
if (sPlayerbotAIConfig->autoSaveMana) { if (sPlayerbotAIConfig->autoSaveMana)
{
nonCombatEngine->addStrategy("auto save mana"); nonCombatEngine->addStrategy("auto save mana");
} }
if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground()) if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground())
{ {
Player* master = facade->GetMaster(); Player* master = facade->GetMaster();
// let 25% of free bots start duels. // let 25% of free bots start duels.
if (!urand(0, 3)) if (!urand(0, 3))
nonCombatEngine->addStrategy("start duel"); nonCombatEngine->addStrategy("start duel");
@@ -588,7 +627,9 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
{ {
// nonCombatEngine->addStrategy("travel"); // nonCombatEngine->addStrategy("travel");
nonCombatEngine->addStrategy("rpg"); nonCombatEngine->addStrategy("rpg");
} else { }
else
{
nonCombatEngine->addStrategy("move random"); nonCombatEngine->addStrategy("move random");
} }
@@ -627,7 +668,8 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->randomBotNonCombatStrategies);
} }
else { else
{
nonCombatEngine->addStrategy("pvp"); nonCombatEngine->addStrategy("pvp");
nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies);
} }
@@ -644,7 +686,8 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
// Battleground switch // Battleground switch
if (player->InBattleground() && player->GetBattleground()) if (player->InBattleground() && player->GetBattleground())
{ {
nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", "emote", nullptr); nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist",
"attack tagged", "emote", nullptr);
nonCombatEngine->removeStrategy("custom::say"); nonCombatEngine->removeStrategy("custom::say");
nonCombatEngine->removeStrategy("travel"); nonCombatEngine->removeStrategy("travel");
nonCombatEngine->removeStrategy("rpg"); nonCombatEngine->removeStrategy("rpg");
@@ -654,7 +697,8 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
if (bgType == BATTLEGROUND_RB) if (bgType == BATTLEGROUND_RB)
bgType = player->GetBattleground()->GetBgTypeID(true); bgType = player->GetBattleground()->GetBgTypeID(true);
if ((bgType <= BATTLEGROUND_EY || bgType == BATTLEGROUND_IC) && !player->InArena()) // do not add for not supported bg or arena if ((bgType <= BATTLEGROUND_EY || bgType == BATTLEGROUND_IC) &&
!player->InArena()) // do not add for not supported bg or arena
nonCombatEngine->addStrategy("battleground"); nonCombatEngine->addStrategy("battleground");
if (bgType == BATTLEGROUND_WS) if (bgType == BATTLEGROUND_WS)
@@ -682,15 +726,15 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
Engine* AiFactory::createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext) Engine* AiFactory::createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext)
{ {
Engine* nonCombatEngine = new Engine(facade, aiObjectContext); Engine* nonCombatEngine = new Engine(facade, aiObjectContext);
AddDefaultNonCombatStrategies(player, facade, nonCombatEngine); AddDefaultNonCombatStrategies(player, facade, nonCombatEngine);
return nonCombatEngine; return nonCombatEngine;
} }
void AiFactory::AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine) void AiFactory::AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine)
{ {
(void)facade; // unused and remove warning (void)facade; // unused and remove warning
deadEngine->addStrategies("dead", "stay", "chat", "default", "follow", nullptr); deadEngine->addStrategies("dead", "stay", "chat", "default", "follow", nullptr);
if (sRandomPlayerbotMgr->IsRandomBot(player) && !player->GetGroup()) if (sRandomPlayerbotMgr->IsRandomBot(player) && !player->GetGroup())

View File

@@ -1,14 +1,15 @@
/* /*
* 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. * 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_AIFACTORY_H #ifndef _PLAYERBOT_AIFACTORY_H
#define _PLAYERBOT_AIFACTORY_H #define _PLAYERBOT_AIFACTORY_H
#include "Common.h"
#include <map> #include <map>
#include "Common.h"
class AiObjectContext; class AiObjectContext;
class Engine; class Engine;
class Player; class Player;
@@ -18,19 +19,19 @@ enum BotRoles : uint8;
class AiFactory class AiFactory
{ {
public: public:
static AiObjectContext* createAiObjectContext(Player* player, PlayerbotAI* botAI); static AiObjectContext* createAiObjectContext(Player* player, PlayerbotAI* botAI);
static Engine* createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext); static Engine* createCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext);
static Engine* createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext); static Engine* createNonCombatEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aiObjectContext);
static Engine* createDeadEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aibjectContext); static Engine* createDeadEngine(Player* player, PlayerbotAI* const facade, AiObjectContext* aibjectContext);
static void AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* nonCombatEngine); static void AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* nonCombatEngine);
static void AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine); static void AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine);
static void AddDefaultCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* engine); static void AddDefaultCombatStrategies(Player* player, PlayerbotAI* const facade, Engine* engine);
static uint8 GetPlayerSpecTab(Player* player); static uint8 GetPlayerSpecTab(Player* player);
static std::map<uint8, uint32> GetPlayerSpecTabs(Player* player); static std::map<uint8, uint32> GetPlayerSpecTabs(Player* player);
static BotRoles GetPlayerRoles(Player* player); static BotRoles GetPlayerRoles(Player* player);
static std::string GetPlayerSpecName(Player* player); static std::string GetPlayerSpecName(Player* player);
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "ChatFilter.h" #include "ChatFilter.h"
#include "Group.h" #include "Group.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RtiTargetValue.h" #include "RtiTargetValue.h"
@@ -17,252 +19,252 @@ std::string const ChatFilter::Filter(std::string& message)
class StrategyChatFilter : public ChatFilter class StrategyChatFilter : public ChatFilter
{ {
public: public:
StrategyChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { } StrategyChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) {}
std::string const Filter(std::string& message) override std::string const Filter(std::string& message) override
{ {
Player* bot = botAI->GetBot(); Player* bot = botAI->GetBot();
bool tank = message.find("@tank") == 0; bool tank = message.find("@tank") == 0;
if (tank && !botAI->IsTank(bot)) if (tank && !botAI->IsTank(bot))
return ""; return "";
bool dps = message.find("@dps") == 0; bool dps = message.find("@dps") == 0;
if (dps && (botAI->IsTank(bot) || botAI->IsHeal(bot))) if (dps && (botAI->IsTank(bot) || botAI->IsHeal(bot)))
return ""; return "";
bool heal = message.find("@heal") == 0; bool heal = message.find("@heal") == 0;
if (heal && !botAI->IsHeal(bot)) if (heal && !botAI->IsHeal(bot))
return ""; return "";
bool ranged = message.find("@ranged") == 0; bool ranged = message.find("@ranged") == 0;
if (ranged && !botAI->IsRanged(bot)) if (ranged && !botAI->IsRanged(bot))
return ""; return "";
bool melee = message.find("@melee") == 0; bool melee = message.find("@melee") == 0;
if (melee && botAI->IsRanged(bot)) if (melee && botAI->IsRanged(bot))
return ""; return "";
if (tank || dps || heal || ranged || melee) if (tank || dps || heal || ranged || melee)
return ChatFilter::Filter(message); return ChatFilter::Filter(message);
return message; return message;
} }
}; };
class LevelChatFilter : public ChatFilter class LevelChatFilter : public ChatFilter
{ {
public: public:
LevelChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { } LevelChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) {}
std::string const Filter(std::string& message) override std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
if (message[0] != '@')
return message;
if (message.find("-") != std::string::npos)
{ {
Player* bot = botAI->GetBot(); uint32 fromLevel = atoi(message.substr(message.find("@") + 1, message.find("-")).c_str());
uint32 toLevel = atoi(message.substr(message.find("-") + 1, message.find(" ")).c_str());
if (message[0] != '@') if (bot->GetLevel() >= fromLevel && bot->GetLevel() <= toLevel)
return message;
if (message.find("-") != std::string::npos)
{
uint32 fromLevel = atoi(message.substr(message.find("@") + 1, message.find("-")).c_str());
uint32 toLevel = atoi(message.substr(message.find("-") + 1, message.find(" ")).c_str());
if (bot->GetLevel() >= fromLevel && bot->GetLevel() <= toLevel)
return ChatFilter::Filter(message);
return message;
}
uint32 level = atoi(message.substr(message.find("@") + 1, message.find(" ")).c_str());
if (bot->GetLevel() == level)
return ChatFilter::Filter(message); return ChatFilter::Filter(message);
return message; return message;
} }
uint32 level = atoi(message.substr(message.find("@") + 1, message.find(" ")).c_str());
if (bot->GetLevel() == level)
return ChatFilter::Filter(message);
return message;
}
}; };
class CombatTypeChatFilter : public ChatFilter class CombatTypeChatFilter : public ChatFilter
{ {
public: public:
CombatTypeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { } CombatTypeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) {}
std::string const Filter(std::string& message) override std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
bool melee = message.find("@melee") == 0;
bool ranged = message.find("@ranged") == 0;
if (!melee && !ranged)
return message;
switch (bot->getClass())
{ {
Player* bot = botAI->GetBot(); case CLASS_WARRIOR:
case CLASS_PALADIN:
bool melee = message.find("@melee") == 0; case CLASS_ROGUE:
bool ranged = message.find("@ranged") == 0; case CLASS_DEATH_KNIGHT:
if (ranged)
if (!melee && !ranged) return "";
return message; break;
case CLASS_HUNTER:
switch (bot->getClass()) case CLASS_PRIEST:
{ case CLASS_MAGE:
case CLASS_WARRIOR: case CLASS_WARLOCK:
case CLASS_PALADIN: if (melee)
case CLASS_ROGUE: return "";
case CLASS_DEATH_KNIGHT: break;
if (ranged) case CLASS_DRUID:
return ""; if (ranged && botAI->IsTank(bot))
break; return "";
case CLASS_HUNTER: if (melee && !botAI->IsTank(bot))
case CLASS_PRIEST: return "";
case CLASS_MAGE: break;
case CLASS_WARLOCK: case CLASS_SHAMAN:
if (melee) if (melee && botAI->IsHeal(bot))
return ""; return "";
break; if (ranged && !botAI->IsHeal(bot))
case CLASS_DRUID: return "";
if (ranged && botAI->IsTank(bot)) break;
return "";
if (melee && !botAI->IsTank(bot))
return "";
break;
case CLASS_SHAMAN:
if (melee && botAI->IsHeal(bot))
return "";
if (ranged && !botAI->IsHeal(bot))
return "";
break;
}
return ChatFilter::Filter(message);
} }
return ChatFilter::Filter(message);
}
}; };
class RtiChatFilter : public ChatFilter class RtiChatFilter : public ChatFilter
{ {
public: public:
RtiChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) RtiChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
{
rtis.push_back("@star");
rtis.push_back("@circle");
rtis.push_back("@diamond");
rtis.push_back("@triangle");
rtis.push_back("@moon");
rtis.push_back("@square");
rtis.push_back("@cross");
rtis.push_back("@skull");
}
std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
Group* group = bot->GetGroup();
if (!group)
return message;
bool found = false;
bool isRti = false;
for (std::vector<std::string>::iterator i = rtis.begin(); i != rtis.end(); i++)
{ {
rtis.push_back("@star"); std::string const rti = *i;
rtis.push_back("@circle");
rtis.push_back("@diamond");
rtis.push_back("@triangle");
rtis.push_back("@moon");
rtis.push_back("@square");
rtis.push_back("@cross");
rtis.push_back("@skull");
}
std::string const Filter(std::string& message) override bool isRti = message.find(rti) == 0;
{ if (!isRti)
Player* bot = botAI->GetBot(); continue;
Group* group = bot->GetGroup();
if (!group)
return message;
bool found = false; ObjectGuid rtiTarget = group->GetTargetIcon(RtiTargetValue::GetRtiIndex(rti.substr(1)));
bool isRti = false; if (bot->GetGUID() == rtiTarget)
for (std::vector<std::string>::iterator i = rtis.begin(); i != rtis.end(); i++)
{
std::string const rti = *i;
bool isRti = message.find(rti) == 0;
if (!isRti)
continue;
ObjectGuid rtiTarget = group->GetTargetIcon(RtiTargetValue::GetRtiIndex(rti.substr(1)));
if (bot->GetGUID() == rtiTarget)
return ChatFilter::Filter(message);
Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
if (!target)
return "";
if (target->GetGUID() != rtiTarget)
return "";
found |= isRti;
if (found)
break;
}
if (found)
return ChatFilter::Filter(message); return ChatFilter::Filter(message);
return message; Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
if (!target)
return "";
if (target->GetGUID() != rtiTarget)
return "";
found |= isRti;
if (found)
break;
} }
private: if (found)
std::vector<std::string> rtis; return ChatFilter::Filter(message);
return message;
}
private:
std::vector<std::string> rtis;
}; };
class ClassChatFilter : public ChatFilter class ClassChatFilter : public ChatFilter
{ {
public: public:
ClassChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) ClassChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
{
classNames["@death_knight"] = CLASS_DEATH_KNIGHT;
classNames["@druid"] = CLASS_DRUID;
classNames["@hunter"] = CLASS_HUNTER;
classNames["@mage"] = CLASS_MAGE;
classNames["@paladin"] = CLASS_PALADIN;
classNames["@priest"] = CLASS_PRIEST;
classNames["@rogue"] = CLASS_ROGUE;
classNames["@shaman"] = CLASS_SHAMAN;
classNames["@warlock"] = CLASS_WARLOCK;
classNames["@warrior"] = CLASS_WARRIOR;
}
std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
bool found = false;
bool isClass = false;
for (std::map<std::string, uint8>::iterator i = classNames.begin(); i != classNames.end(); i++)
{ {
classNames["@death_knight"] = CLASS_DEATH_KNIGHT; bool isClass = message.find(i->first) == 0;
classNames["@druid"] = CLASS_DRUID; if (isClass && bot->getClass() != i->second)
classNames["@hunter"] = CLASS_HUNTER; return "";
classNames["@mage"] = CLASS_MAGE;
classNames["@paladin"] = CLASS_PALADIN;
classNames["@priest"] = CLASS_PRIEST;
classNames["@rogue"] = CLASS_ROGUE;
classNames["@shaman"] = CLASS_SHAMAN;
classNames["@warlock"] = CLASS_WARLOCK;
classNames["@warrior"] = CLASS_WARRIOR;
}
std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
bool found = false;
bool isClass = false;
for (std::map<std::string, uint8>::iterator i = classNames.begin(); i != classNames.end(); i++)
{
bool isClass = message.find(i->first) == 0;
if (isClass && bot->getClass() != i->second)
return "";
found |= isClass;
if (found)
break;
}
found |= isClass;
if (found) if (found)
return ChatFilter::Filter(message); break;
return message;
} }
private: if (found)
std::map<std::string, uint8> classNames; return ChatFilter::Filter(message);
return message;
}
private:
std::map<std::string, uint8> classNames;
}; };
class SubGroupChatFilter : public ChatFilter class SubGroupChatFilter : public ChatFilter
{ {
public: public:
SubGroupChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) { } SubGroupChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) {}
std::string const Filter(std::string& message) override std::string const Filter(std::string& message) override
{
Player* bot = botAI->GetBot();
if (message.find("@group") == 0)
{ {
Player* bot = botAI->GetBot(); std::string const pnum = message.substr(6, message.find(" "));
uint32 from = atoi(pnum.c_str());
if (message.find("@group") == 0) uint32 to = from;
if (pnum.find("-") != std::string::npos)
{ {
std::string const pnum = message.substr(6, message.find(" ")); from = atoi(pnum.substr(pnum.find("@") + 1, pnum.find("-")).c_str());
uint32 from = atoi(pnum.c_str()); to = atoi(pnum.substr(pnum.find("-") + 1, pnum.find(" ")).c_str());
uint32 to = from;
if (pnum.find("-") != std::string::npos)
{
from = atoi(pnum.substr(pnum.find("@") + 1, pnum.find("-")).c_str());
to = atoi(pnum.substr(pnum.find("-") + 1, pnum.find(" ")).c_str());
}
if (!bot->GetGroup())
return message;
uint32 sg = bot->GetSubGroup() + 1;
if (sg >= from && sg <= to)
return ChatFilter::Filter(message);
} }
return message; if (!bot->GetGroup())
return message;
uint32 sg = bot->GetSubGroup() + 1;
if (sg >= from && sg <= to)
return ChatFilter::Filter(message);
} }
return message;
}
}; };
CompositeChatFilter::CompositeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI) CompositeChatFilter::CompositeChatFilter(PlayerbotAI* botAI) : ChatFilter(botAI)
@@ -295,4 +297,3 @@ std::string const CompositeChatFilter::Filter(std::string& message)
return message; return message;
} }

View File

@@ -1,36 +1,37 @@
/* /*
* 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. * 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_CHATFILTER_H #ifndef _PLAYERBOT_CHATFILTER_H
#define _PLAYERBOT_CHATFILTER_H #define _PLAYERBOT_CHATFILTER_H
#include <vector>
#include "Common.h" #include "Common.h"
#include "PlayerbotAIAware.h" #include "PlayerbotAIAware.h"
#include <vector>
class PlayerbotAI; class PlayerbotAI;
class ChatFilter : public PlayerbotAIAware class ChatFilter : public PlayerbotAIAware
{ {
public: public:
ChatFilter(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) { } ChatFilter(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) {}
virtual ~ChatFilter() { } virtual ~ChatFilter() {}
virtual std::string const Filter(std::string& message); virtual std::string const Filter(std::string& message);
}; };
class CompositeChatFilter : public ChatFilter class CompositeChatFilter : public ChatFilter
{ {
public: public:
CompositeChatFilter(PlayerbotAI* botAI); CompositeChatFilter(PlayerbotAI* botAI);
virtual ~CompositeChatFilter(); virtual ~CompositeChatFilter();
std::string const Filter(std::string& message) override; std::string const Filter(std::string& message) override;
private: private:
std::vector<ChatFilter*> filters; std::vector<ChatFilter*> filters;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "ChatHelper.h" #include "ChatHelper.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "SpellInfo.h" #include "SpellInfo.h"
@@ -18,13 +20,13 @@ std::map<uint8, std::string> ChatHelper::classes;
std::map<uint8, std::string> ChatHelper::races; std::map<uint8, std::string> ChatHelper::races;
std::map<uint8, std::map<uint8, std::string> > ChatHelper::specs; std::map<uint8, std::map<uint8, std::string> > ChatHelper::specs;
template<class T> template <class T>
static bool substrContainsInMap(std::string const searchTerm, std::map<std::string, T> searchIn) static bool substrContainsInMap(std::string const searchTerm, std::map<std::string, T> searchIn)
{ {
for (typename std::map<std::string, T>::iterator i = searchIn.begin(); i != searchIn.end(); ++i) for (typename std::map<std::string, T>::iterator i = searchIn.begin(); i != searchIn.end(); ++i)
{ {
std::string const term = i->first; std::string const term = i->first;
if (term.size() > 1 && searchTerm.find(term) != std::string::npos) if (term.size() > 1 && searchTerm.find(term) != std::string::npos)
return true; return true;
} }
@@ -57,19 +59,19 @@ ChatHelper::ChatHelper(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
projectileSubClasses["arrows"] = ITEM_SUBCLASS_ARROW; projectileSubClasses["arrows"] = ITEM_SUBCLASS_ARROW;
projectileSubClasses["bullets"] = ITEM_SUBCLASS_BULLET; projectileSubClasses["bullets"] = ITEM_SUBCLASS_BULLET;
//tradeSubClasses["cloth"] = ITEM_SUBCLASS_CLOTH; // tradeSubClasses["cloth"] = ITEM_SUBCLASS_CLOTH;
//tradeSubClasses["leather"] = ITEM_SUBCLASS_LEATHER; // tradeSubClasses["leather"] = ITEM_SUBCLASS_LEATHER;
//tradeSubClasses["metal"] = ITEM_SUBCLASS_METAL_STONE; // tradeSubClasses["metal"] = ITEM_SUBCLASS_METAL_STONE;
//tradeSubClasses["stone"] = ITEM_SUBCLASS_METAL_STONE; // tradeSubClasses["stone"] = ITEM_SUBCLASS_METAL_STONE;
//tradeSubClasses["ore"] = ITEM_SUBCLASS_METAL_STONE; // tradeSubClasses["ore"] = ITEM_SUBCLASS_METAL_STONE;
//tradeSubClasses["meat"] = ITEM_SUBCLASS_MEAT; // tradeSubClasses["meat"] = ITEM_SUBCLASS_MEAT;
//tradeSubClasses["herb"] = ITEM_SUBCLASS_HERB; // tradeSubClasses["herb"] = ITEM_SUBCLASS_HERB;
//tradeSubClasses["elemental"] = ITEM_SUBCLASS_ELEMENTAL; // tradeSubClasses["elemental"] = ITEM_SUBCLASS_ELEMENTAL;
//tradeSubClasses["disenchants"] = ITEM_SUBCLASS_ENCHANTING; // tradeSubClasses["disenchants"] = ITEM_SUBCLASS_ENCHANTING;
//tradeSubClasses["enchanting"] = ITEM_SUBCLASS_ENCHANTING; // tradeSubClasses["enchanting"] = ITEM_SUBCLASS_ENCHANTING;
//tradeSubClasses["gems"] = ITEM_SUBCLASS_JEWELCRAFTING; // tradeSubClasses["gems"] = ITEM_SUBCLASS_JEWELCRAFTING;
//tradeSubClasses["jewels"] = ITEM_SUBCLASS_JEWELCRAFTING; // tradeSubClasses["jewels"] = ITEM_SUBCLASS_JEWELCRAFTING;
//tradeSubClasses["jewelcrafting"] = ITEM_SUBCLASS_JEWELCRAFTING; // tradeSubClasses["jewelcrafting"] = ITEM_SUBCLASS_JEWELCRAFTING;
slots["head"] = EQUIPMENT_SLOT_HEAD; slots["head"] = EQUIPMENT_SLOT_HEAD;
slots["neck"] = EQUIPMENT_SLOT_NECK; slots["neck"] = EQUIPMENT_SLOT_NECK;
@@ -179,11 +181,11 @@ ChatHelper::ChatHelper(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
std::string const ChatHelper::formatMoney(uint32 copper) std::string const ChatHelper::formatMoney(uint32 copper)
{ {
std::ostringstream out; std::ostringstream out;
if (!copper) if (!copper)
{ {
out << "0"; out << "0";
return out.str(); return out.str();
} }
uint32 gold = uint32(copper / 10000); uint32 gold = uint32(copper / 10000);
copper -= (gold * 10000); copper -= (gold * 10000);
@@ -193,7 +195,7 @@ std::string const ChatHelper::formatMoney(uint32 copper)
bool space = false; bool space = false;
if (gold > 0) if (gold > 0)
{ {
out << gold << "g"; out << gold << "g";
space = true; space = true;
} }
@@ -202,17 +204,17 @@ std::string const ChatHelper::formatMoney(uint32 copper)
if (space) if (space)
out << " "; out << " ";
out << silver << "s"; out << silver << "s";
space = true; space = true;
} }
if (copper > 0 && gold < 10) if (copper > 0 && gold < 10)
{ {
if (space) if (space)
out << " "; out << " ";
out << copper << "c"; out << copper << "c";
} }
return out.str(); return out.str();
} }
@@ -281,22 +283,27 @@ ItemIds ChatHelper::parseItems(std::string const text)
std::string const ChatHelper::FormatQuest(Quest const* quest) std::string const ChatHelper::FormatQuest(Quest const* quest)
{ {
std::ostringstream out; std::ostringstream out;
out << "|cFFFFFF00|Hquest:" << quest->GetQuestId() << ':' << quest->GetQuestLevel() << "|h[" << quest->GetTitle() << "]|h|r"; out << "|cFFFFFF00|Hquest:" << quest->GetQuestId() << ':' << quest->GetQuestLevel() << "|h[" << quest->GetTitle()
<< "]|h|r";
return out.str(); return out.str();
} }
std::string const ChatHelper::FormatGameobject(GameObject* go) std::string const ChatHelper::FormatGameobject(GameObject* go)
{ {
std::ostringstream out; std::ostringstream out;
out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":" << "|h[" << go->GetNameForLocaleIdx(LOCALE_enUS) << "]|h|r"; out << "|cFFFFFF00|Hfound:" << go->GetGUID().GetRawValue() << ":" << go->GetEntry() << ":"
<< "|h[" << go->GetNameForLocaleIdx(LOCALE_enUS) << "]|h|r";
return out.str(); return out.str();
} }
std::string const ChatHelper::FormatWorldobject(WorldObject* wo) std::string const ChatHelper::FormatWorldobject(WorldObject* wo)
{ {
std::ostringstream out; std::ostringstream out;
out << "|cFFFFFF00|Hfound:" << wo->GetGUID().GetRawValue() << ":" << wo->GetEntry() << ":" << "|h["; out << "|cFFFFFF00|Hfound:" << wo->GetGUID().GetRawValue() << ":" << wo->GetEntry() << ":"
out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(LOCALE_enUS) : wo->GetNameForLocaleIdx(LOCALE_enUS)) << "]|h|r"; << "|h[";
out << (wo->ToGameObject() ? ((GameObject*)wo)->GetNameForLocaleIdx(LOCALE_enUS)
: wo->GetNameForLocaleIdx(LOCALE_enUS))
<< "]|h|r";
return out.str(); return out.str();
} }
@@ -311,7 +318,8 @@ std::string const ChatHelper::FormatWorldEntry(int32 entry)
gInfo = sObjectMgr->GetGameObjectTemplate(entry * -1); gInfo = sObjectMgr->GetGameObjectTemplate(entry * -1);
std::ostringstream out; std::ostringstream out;
out << "|cFFFFFF00|Hentry:" << abs(entry) << ":" << "|h["; out << "|cFFFFFF00|Hentry:" << abs(entry) << ":"
<< "|h[";
if (entry < 0 && gInfo) if (entry < 0 && gInfo)
out << gInfo->name; out << gInfo->name;
@@ -339,9 +347,8 @@ std::string const ChatHelper::FormatItem(ItemTemplate const* proto, uint32 count
// const std::string &name = sObjectMgr->GetItemLocale(proto->ItemId)->Name[LOCALE_enUS]; // const std::string &name = sObjectMgr->GetItemLocale(proto->ItemId)->Name[LOCALE_enUS];
std::ostringstream out; std::ostringstream out;
out << "|c" << color << "|Hitem:" << proto->ItemId out << "|c" << color << "|Hitem:" << proto->ItemId << ":0:0:0:0:0:0:0"
<< ":0:0:0:0:0:0:0" << "|h[" << proto->Name1 << "|h[" << proto->Name1 << "]|h|r";
<< "]|h|r";
if (count > 1) if (count > 1)
out << "x" << count; out << "x" << count;
@@ -392,7 +399,6 @@ std::string const ChatHelper::FormatChat(ChatMsg chat)
return "unknown"; return "unknown";
} }
uint32 ChatHelper::parseSpell(std::string const text) uint32 ChatHelper::parseSpell(std::string const text)
{ {
PlayerbotChatHandler handler(botAI->GetBot()); PlayerbotChatHandler handler(botAI->GetBot());
@@ -410,13 +416,13 @@ GuidVector ChatHelper::parseGameobjects(std::string const text)
while (true) while (true)
{ {
// extract GO guid // extract GO guid
auto i = text.find("Hfound:", pos); // base H = 11 auto i = text.find("Hfound:", pos); // base H = 11
if (i == std::string::npos) // break if error if (i == std::string::npos) // break if error
break; break;
pos = i + 7; //start of window in text 11 + 7 = 18 pos = i + 7; // start of window in text 11 + 7 = 18
auto endPos = text.find(':', pos); // end of window in text 22 auto endPos = text.find(':', pos); // end of window in text 22
if (endPos == std::string::npos) //break if error if (endPos == std::string::npos) // break if error
break; break;
std::istringstream stream(text.substr(pos, endPos - pos)); std::istringstream stream(text.substr(pos, endPos - pos));
@@ -426,11 +432,11 @@ GuidVector ChatHelper::parseGameobjects(std::string const text)
// extract GO entry // extract GO entry
pos = endPos + 1; pos = endPos + 1;
endPos = text.find(':', pos); // end of window in text endPos = text.find(':', pos); // end of window in text
if (endPos == std::string::npos) //break if error if (endPos == std::string::npos) // break if error
break; break;
std::string const entryC = text.substr(pos, endPos - pos); // get std::string const within window i.e entry std::string const entryC = text.substr(pos, endPos - pos); // get std::string const within window i.e entry
uint32 entry = atol(entryC.c_str()); // convert ascii to float uint32 entry = atol(entryC.c_str()); // convert ascii to float
ObjectGuid lootCurrent = ObjectGuid(guid); ObjectGuid lootCurrent = ObjectGuid(guid);
@@ -444,8 +450,8 @@ GuidVector ChatHelper::parseGameobjects(std::string const text)
std::string const ChatHelper::FormatQuestObjective(std::string const name, uint32 available, uint32 required) std::string const ChatHelper::FormatQuestObjective(std::string const name, uint32 available, uint32 required)
{ {
std::ostringstream out; std::ostringstream out;
out << "|cFFFFFFFF" << name << (available >= required ? "|c0000FF00: " : "|c00FF0000: ") out << "|cFFFFFFFF" << name << (available >= required ? "|c0000FF00: " : "|c00FF0000: ") << available << "/"
<< available << "/" << required << "|r"; << required << "|r";
return out.str(); return out.str();
} }
@@ -501,9 +507,11 @@ uint32 ChatHelper::parseSlot(std::string const text)
bool ChatHelper::parseable(std::string const text) bool ChatHelper::parseable(std::string const text)
{ {
return text.find("|H") != std::string::npos || text == "questitem" || text == "ammo" || substrContainsInMap<uint32>(text, consumableSubClasses) || return text.find("|H") != std::string::npos || text == "questitem" || text == "ammo" ||
substrContainsInMap<uint32>(text, tradeSubClasses) || substrContainsInMap<uint32>(text, itemQualities) || substrContainsInMap<uint32>(text, slots) || substrContainsInMap<uint32>(text, consumableSubClasses) ||
substrContainsInMap<ChatMsg>(text, chats) || substrContainsInMap<uint32>(text, skills) || parseMoney(text) > 0; substrContainsInMap<uint32>(text, tradeSubClasses) || substrContainsInMap<uint32>(text, itemQualities) ||
substrContainsInMap<uint32>(text, slots) || substrContainsInMap<ChatMsg>(text, chats) ||
substrContainsInMap<uint32>(text, skills) || parseMoney(text) > 0;
} }
std::string const ChatHelper::FormatClass(Player* player, int8 spec) std::string const ChatHelper::FormatClass(Player* player, int8 spec)
@@ -526,15 +534,9 @@ std::string const ChatHelper::FormatClass(Player* player, int8 spec)
return out.str(); return out.str();
} }
std::string const ChatHelper::FormatClass(uint8 cls) std::string const ChatHelper::FormatClass(uint8 cls) { return classes[cls]; }
{
return classes[cls];
}
std::string const ChatHelper::FormatRace(uint8 race) std::string const ChatHelper::FormatRace(uint8 race) { return races[race]; }
{
return races[race];
}
uint32 ChatHelper::parseSkill(std::string const text) uint32 ChatHelper::parseSkill(std::string const text)
{ {
@@ -555,10 +557,7 @@ std::string const ChatHelper::FormatSkill(uint32 skill)
return ""; return "";
} }
std::string const ChatHelper::FormatBoolean(bool flag) std::string const ChatHelper::FormatBoolean(bool flag) { return flag ? "|cff00ff00ON|r" : "|cffffff00OFF|r"; }
{
return flag ? "|cff00ff00ON|r" : "|cffffff00OFF|r";
}
void ChatHelper::eraseAllSubStr(std::string& mainStr, std::string const toErase) void ChatHelper::eraseAllSubStr(std::string& mainStr, std::string const toErase)
{ {

View File

@@ -1,17 +1,18 @@
/* /*
* 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. * 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_CHATHELPER_H #ifndef _PLAYERBOT_CHATHELPER_H
#define _PLAYERBOT_CHATHELPER_H #define _PLAYERBOT_CHATHELPER_H
#include <map>
#include "Common.h" #include "Common.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "PlayerbotAIAware.h" #include "PlayerbotAIAware.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include <map>
class GameObject; class GameObject;
class Quest; class Quest;
class Player; class Player;
@@ -26,52 +27,52 @@ typedef std::set<uint32> SpellIds;
class ChatHelper : public PlayerbotAIAware class ChatHelper : public PlayerbotAIAware
{ {
public: public:
ChatHelper(PlayerbotAI* botAI); ChatHelper(PlayerbotAI* botAI);
static std::string const formatMoney(uint32 copper); static std::string const formatMoney(uint32 copper);
static uint32 parseMoney(std::string const text); static uint32 parseMoney(std::string const text);
static ItemIds parseItems(std::string const text); static ItemIds parseItems(std::string const text);
uint32 parseSpell(std::string const text); uint32 parseSpell(std::string const text);
static std::string const FormatQuest(Quest const* quest); static std::string const FormatQuest(Quest const* quest);
static std::string const FormatItem(ItemTemplate const* proto, uint32 count = 0, uint32 total = 0); static std::string const FormatItem(ItemTemplate const* proto, uint32 count = 0, uint32 total = 0);
static std::string const FormatQItem(uint32 itemId); static std::string const FormatQItem(uint32 itemId);
static std::string const FormatSpell(SpellInfo const* spellInfo); static std::string const FormatSpell(SpellInfo const* spellInfo);
static std::string const FormatGameobject(GameObject* go); static std::string const FormatGameobject(GameObject* go);
static std::string const FormatWorldobject(WorldObject* wo); static std::string const FormatWorldobject(WorldObject* wo);
static std::string const FormatWorldEntry(int32 entry); static std::string const FormatWorldEntry(int32 entry);
static std::string const FormatQuestObjective(std::string const name, uint32 available, uint32 required); static std::string const FormatQuestObjective(std::string const name, uint32 available, uint32 required);
static GuidVector parseGameobjects(std::string const text); static GuidVector parseGameobjects(std::string const text);
static ChatMsg parseChat(std::string const text); static ChatMsg parseChat(std::string const text);
static std::string const FormatChat(ChatMsg chat); static std::string const FormatChat(ChatMsg chat);
static std::string const FormatClass(Player* player, int8 spec); static std::string const FormatClass(Player* player, int8 spec);
static std::string const FormatClass(uint8 cls); static std::string const FormatClass(uint8 cls);
static std::string const FormatRace(uint8 race); static std::string const FormatRace(uint8 race);
static std::string const FormatSkill(uint32 skill); static std::string const FormatSkill(uint32 skill);
static std::string const FormatBoolean(bool flag); static std::string const FormatBoolean(bool flag);
static uint32 parseItemQuality(std::string const text); static uint32 parseItemQuality(std::string const text);
static bool parseItemClass(std::string const text, uint32* itemClass, uint32* itemSubClass); static bool parseItemClass(std::string const text, uint32* itemClass, uint32* itemSubClass);
static uint32 parseSlot(std::string const text); static uint32 parseSlot(std::string const text);
uint32 parseSkill(std::string const text); uint32 parseSkill(std::string const text);
static bool parseable(std::string const text); static bool parseable(std::string const text);
void eraseAllSubStr(std::string& mainStr, std::string const toErase); void eraseAllSubStr(std::string& mainStr, std::string const toErase);
private: private:
static std::map<std::string, uint32> consumableSubClasses; static std::map<std::string, uint32> consumableSubClasses;
static std::map<std::string, uint32> tradeSubClasses; static std::map<std::string, uint32> tradeSubClasses;
static std::map<std::string, uint32> itemQualities; static std::map<std::string, uint32> itemQualities;
static std::map<std::string, uint32> projectileSubClasses; static std::map<std::string, uint32> projectileSubClasses;
static std::map<std::string, uint32> slots; static std::map<std::string, uint32> slots;
static std::map<std::string, uint32> skills; static std::map<std::string, uint32> skills;
static std::map<std::string, ChatMsg> chats; static std::map<std::string, ChatMsg> chats;
static std::map<uint8, std::string> classes; static std::map<uint8, std::string> classes;
static std::map<uint8, std::string> races; static std::map<uint8, std::string> races;
static std::map<uint8, std::map<uint8, std::string>> specs; static std::map<uint8, std::map<uint8, std::string>> specs;
}; };
#endif #endif

View File

@@ -1,36 +1,44 @@
/* /*
* 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. * 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 "FleeManager.h" #include "FleeManager.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "ServerFacade.h" #include "ServerFacade.h"
FleeManager::FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance, WorldPosition startPosition) : FleeManager::FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance,
bot(bot), maxAllowedDistance(maxAllowedDistance), followAngle(followAngle), forceMaxDistance(forceMaxDistance), startPosition(startPosition ? startPosition : WorldPosition(bot)) WorldPosition startPosition)
: bot(bot),
maxAllowedDistance(maxAllowedDistance),
followAngle(followAngle),
forceMaxDistance(forceMaxDistance),
startPosition(startPosition ? startPosition : WorldPosition(bot))
{ {
} }
void FleeManager::calculateDistanceToCreatures(FleePoint *point) void FleeManager::calculateDistanceToCreatures(FleePoint* point)
{ {
point->minDistance = -1.0f; point->minDistance = -1.0f;
point->sumDistance = 0.0f; point->sumDistance = 0.0f;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los"); GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
for (GuidVector::iterator i = units.begin(); i != units.end(); ++i) for (GuidVector::iterator i = units.begin(); i != units.end(); ++i)
{ {
Unit* unit = botAI->GetUnit(*i); Unit* unit = botAI->GetUnit(*i);
if (!unit) if (!unit)
continue; continue;
float d = sServerFacade->GetDistance2d(unit, point->x, point->y); float d = sServerFacade->GetDistance2d(unit, point->x, point->y);
point->sumDistance += d; point->sumDistance += d;
if (point->minDistance < 0 || point->minDistance > d) if (point->minDistance < 0 || point->minDistance > d)
point->minDistance = d; point->minDistance = d;
} }
} }
bool intersectsOri(float angle, std::vector<float>& angles, float angleIncrement) bool intersectsOri(float angle, std::vector<float>& angles, float angleIncrement)
@@ -45,20 +53,21 @@ bool intersectsOri(float angle, std::vector<float>& angles, float angleIncrement
return false; return false;
} }
void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*> &points) void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*>& points)
{ {
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target"); Unit* target = *botAI->GetAiObjectContext()->GetValue<Unit*>("current target");
float botPosX = startPosition.getX(); float botPosX = startPosition.getX();
float botPosY = startPosition.getY(); float botPosY = startPosition.getY();
float botPosZ = startPosition.getZ(); float botPosZ = startPosition.getZ();
FleePoint start(botAI, botPosX, botPosY, botPosZ); FleePoint start(botAI, botPosX, botPosY, botPosZ);
calculateDistanceToCreatures(&start); calculateDistanceToCreatures(&start);
std::vector<float> enemyOri; std::vector<float> enemyOri;
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los"); GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
@@ -72,19 +81,24 @@ void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*> &points)
enemyOri.push_back(ori); enemyOri.push_back(ori);
} }
float distIncrement = std::max(sPlayerbotAIConfig->followDistance, (maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance) / 10.0f); float distIncrement = std::max(sPlayerbotAIConfig->followDistance,
for (float dist = maxAllowedDistance; dist >= sPlayerbotAIConfig->tooCloseDistance ; dist -= distIncrement) (maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance) / 10.0f);
for (float dist = maxAllowedDistance; dist >= sPlayerbotAIConfig->tooCloseDistance; dist -= distIncrement)
{ {
float angleIncrement = std::max(M_PI / 20, M_PI / 4 / (1.0 + dist - sPlayerbotAIConfig->tooCloseDistance)); float angleIncrement = std::max(M_PI / 20, M_PI / 4 / (1.0 + dist - sPlayerbotAIConfig->tooCloseDistance));
for (float add = 0.0f; add < M_PI / 4 + angleIncrement; add += angleIncrement) for (float add = 0.0f; add < M_PI / 4 + angleIncrement; add += angleIncrement)
{ {
for (float angle = add; angle < add + 2 * static_cast<float>(M_PI) + angleIncrement; angle += static_cast<float>(M_PI) / 4) for (float angle = add; angle < add + 2 * static_cast<float>(M_PI) + angleIncrement;
angle += static_cast<float>(M_PI) / 4)
{ {
if (intersectsOri(angle, enemyOri, angleIncrement)) if (intersectsOri(angle, enemyOri, angleIncrement))
continue; continue;
float x = botPosX + cos(angle) * maxAllowedDistance, y = botPosY + sin(angle) * maxAllowedDistance, z = botPosZ + CONTACT_DISTANCE; float x = botPosX + cos(angle) * maxAllowedDistance, y = botPosY + sin(angle) * maxAllowedDistance,
if (forceMaxDistance && sServerFacade->IsDistanceLessThan(sServerFacade->GetDistance2d(bot, x, y), maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance)) z = botPosZ + CONTACT_DISTANCE;
if (forceMaxDistance &&
sServerFacade->IsDistanceLessThan(sServerFacade->GetDistance2d(bot, x, y),
maxAllowedDistance - sPlayerbotAIConfig->tooCloseDistance))
continue; continue;
bot->UpdateAllowedPositionZ(x, y, z); bot->UpdateAllowedPositionZ(x, y, z);
@@ -99,7 +113,8 @@ void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*> &points)
FleePoint* point = new FleePoint(botAI, x, y, z); FleePoint* point = new FleePoint(botAI, x, y, z);
calculateDistanceToCreatures(point); calculateDistanceToCreatures(point);
if (sServerFacade->IsDistanceGreaterOrEqualThan(point->minDistance - start.minDistance, sPlayerbotAIConfig->followDistance)) if (sServerFacade->IsDistanceGreaterOrEqualThan(point->minDistance - start.minDistance,
sPlayerbotAIConfig->followDistance))
points.push_back(point); points.push_back(point);
else else
delete point; delete point;
@@ -108,14 +123,14 @@ void FleeManager::calculatePossibleDestinations(std::vector<FleePoint*> &points)
} }
} }
void FleeManager::cleanup(std::vector<FleePoint*> &points) void FleeManager::cleanup(std::vector<FleePoint*>& points)
{ {
for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++) for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++)
{ {
delete *i; delete *i;
} }
points.clear(); points.clear();
} }
bool FleeManager::isBetterThan(FleePoint* point, FleePoint* other) bool FleeManager::isBetterThan(FleePoint* point, FleePoint* other)
@@ -123,23 +138,23 @@ bool FleeManager::isBetterThan(FleePoint* point, FleePoint* other)
return point->sumDistance - other->sumDistance > 0; return point->sumDistance - other->sumDistance > 0;
} }
FleePoint* FleeManager::selectOptimalDestination(std::vector<FleePoint*> &points) FleePoint* FleeManager::selectOptimalDestination(std::vector<FleePoint*>& points)
{ {
FleePoint* best = nullptr; FleePoint* best = nullptr;
for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++) for (std::vector<FleePoint*>::iterator i = points.begin(); i != points.end(); i++)
{ {
FleePoint* point = *i; FleePoint* point = *i;
if (!best || isBetterThan(point, best)) if (!best || isBetterThan(point, best))
best = point; best = point;
} }
return best; return best;
} }
bool FleeManager::CalculateDestination(float* rx, float* ry, float* rz) bool FleeManager::CalculateDestination(float* rx, float* ry, float* rz)
{ {
std::vector<FleePoint*> points; std::vector<FleePoint*> points;
calculatePossibleDestinations(points); calculatePossibleDestinations(points);
FleePoint* point = selectOptimalDestination(points); FleePoint* point = selectOptimalDestination(points);
if (!point) if (!point)
@@ -148,18 +163,19 @@ bool FleeManager::CalculateDestination(float* rx, float* ry, float* rz)
return false; return false;
} }
*rx = point->x; *rx = point->x;
*ry = point->y; *ry = point->y;
*rz = point->z; *rz = point->z;
cleanup(points); cleanup(points);
return true; return true;
} }
bool FleeManager::isUseful() bool FleeManager::isUseful()
{ {
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return false; return false;
} }
GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los"); GuidVector units = *botAI->GetAiObjectContext()->GetValue<GuidVector>("possible targets no los");
@@ -169,7 +185,8 @@ bool FleeManager::isUseful()
if (!creature) if (!creature)
continue; continue;
if (startPosition.sqDistance(WorldPosition(creature)) < creature->GetAttackDistance(bot) * creature->GetAttackDistance(bot)) if (startPosition.sqDistance(WorldPosition(creature)) <
creature->GetAttackDistance(bot) * creature->GetAttackDistance(bot))
return true; return true;
// float d = sServerFacade->GetDistance2d(unit, bot); // float d = sServerFacade->GetDistance2d(unit, bot);

View File

@@ -1,54 +1,59 @@
/* /*
* 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. * 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_FLEEMANAGER_H #ifndef _PLAYERBOT_FLEEMANAGER_H
#define _PLAYERBOT_FLEEMANAGER_H #define _PLAYERBOT_FLEEMANAGER_H
#include <vector>
#include "Common.h" #include "Common.h"
#include "TravelMgr.h" #include "TravelMgr.h"
#include <vector>
class Player; class Player;
class PlayerbotAI; class PlayerbotAI;
class FleePoint class FleePoint
{ {
public: public:
FleePoint(PlayerbotAI* botAI, float x, float y, float z) : botAI(botAI), sumDistance(0.0f), minDistance(0.0f), x(x), y(y), z(z) { } FleePoint(PlayerbotAI* botAI, float x, float y, float z)
: botAI(botAI), sumDistance(0.0f), minDistance(0.0f), x(x), y(y), z(z)
{
}
float x; float x;
float y; float y;
float z; float z;
float sumDistance; float sumDistance;
float minDistance; float minDistance;
private: private:
PlayerbotAI* botAI; PlayerbotAI* botAI;
}; };
class FleeManager class FleeManager
{ {
public: public:
FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance = false, WorldPosition startPosition = WorldPosition()); FleeManager(Player* bot, float maxAllowedDistance, float followAngle, bool forceMaxDistance = false,
WorldPosition startPosition = WorldPosition());
bool CalculateDestination(float* rx, float* ry, float* rz); bool CalculateDestination(float* rx, float* ry, float* rz);
bool isUseful(); bool isUseful();
private: private:
void calculatePossibleDestinations(std::vector<FleePoint*> &points); void calculatePossibleDestinations(std::vector<FleePoint*>& points);
void calculateDistanceToCreatures(FleePoint *point); void calculateDistanceToCreatures(FleePoint* point);
void cleanup(std::vector<FleePoint*> &points); void cleanup(std::vector<FleePoint*>& points);
FleePoint* selectOptimalDestination(std::vector<FleePoint*> &points); FleePoint* selectOptimalDestination(std::vector<FleePoint*>& points);
bool isBetterThan(FleePoint* point, FleePoint* other); bool isBetterThan(FleePoint* point, FleePoint* other);
Player* bot; Player* bot;
float maxAllowedDistance; float maxAllowedDistance;
[[maybe_unused]] float followAngle; // unused - whipowill [[maybe_unused]] float followAngle; // unused - whipowill
bool forceMaxDistance; bool forceMaxDistance;
WorldPosition startPosition; WorldPosition startPosition;
}; };
#endif #endif

View File

@@ -1,15 +1,17 @@
/* /*
* 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. * 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 "GuildTaskMgr.h" #include "GuildTaskMgr.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "GuildMgr.h"
#include "Group.h" #include "Group.h"
#include "GuildMgr.h"
#include "Mail.h" #include "Mail.h"
#include "MapMgr.h" #include "MapMgr.h"
#include "Playerbots.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "RandomItemMgr.h" #include "RandomItemMgr.h"
#include "ServerFacade.h" #include "ServerFacade.h"
@@ -42,13 +44,15 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster)
if (!player->IsFriendlyTo(guildMaster)) if (!player->IsFriendlyTo(guildMaster))
return; return;
Guild* guild = sGuildMgr->GetGuildById(guildMaster->GetGuildId()); Guild* guild = sGuildMgr->GetGuildById(guildMaster->GetGuildId());
DenyReason reason = PLAYERBOT_DENY_NONE; DenyReason reason = PLAYERBOT_DENY_NONE;
PlayerbotSecurityLevel secLevel = masterBotAI->GetSecurity()->LevelFor(player, &reason); PlayerbotSecurityLevel secLevel = masterBotAI->GetSecurity()->LevelFor(player, &reason);
if (secLevel == PLAYERBOT_SECURITY_DENY_ALL || (secLevel == PLAYERBOT_SECURITY_TALK && reason != PLAYERBOT_DENY_FAR)) if (secLevel == PLAYERBOT_SECURITY_DENY_ALL ||
(secLevel == PLAYERBOT_SECURITY_TALK && reason != PLAYERBOT_DENY_FAR))
{ {
LOG_DEBUG("playerbots", "{} / {}: skipping guild task update - not enough security level, reason = {}", guild->GetName().c_str(), player->GetName().c_str(), reason); LOG_DEBUG("playerbots", "{} / {}: skipping guild task update - not enough security level, reason = {}",
guild->GetName().c_str(), player->GetName().c_str(), reason);
return; return;
} }
@@ -72,14 +76,18 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster)
if (task == GUILD_TASK_TYPE_NONE) if (task == GUILD_TASK_TYPE_NONE)
{ {
LOG_ERROR("playerbots", "{} / {}: error creating guild task", guild->GetName().c_str(), player->GetName().c_str()); LOG_ERROR("playerbots", "{} / {}: error creating guild task", guild->GetName().c_str(),
player->GetName().c_str());
} }
uint32 time = urand(sPlayerbotAIConfig->minGuildTaskChangeTime, sPlayerbotAIConfig->maxGuildTaskChangeTime); uint32 time = urand(sPlayerbotAIConfig->minGuildTaskChangeTime, sPlayerbotAIConfig->maxGuildTaskChangeTime);
SetTaskValue(owner, guildId, "activeTask", task, time); SetTaskValue(owner, guildId, "activeTask", task, time);
SetTaskValue(owner, guildId, "advertisement", 1, urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime, sPlayerbotAIConfig->maxGuildTaskAdvertisementTime)); SetTaskValue(owner, guildId, "advertisement", 1,
urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime,
sPlayerbotAIConfig->maxGuildTaskAdvertisementTime));
LOG_DEBUG("playerbots", "{} / {}: guild task {} is set for {} secs", guild->GetName().c_str(), player->GetName().c_str(), task, time); LOG_DEBUG("playerbots", "{} / {}: guild task {} is set for {} secs", guild->GetName().c_str(),
player->GetName().c_str(), task, time);
return; return;
} }
@@ -92,11 +100,14 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster)
if (SendAdvertisement(trans, owner, guildId)) if (SendAdvertisement(trans, owner, guildId))
{ {
SetTaskValue(owner, guildId, "advertisement", 1, urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime, sPlayerbotAIConfig->maxGuildTaskAdvertisementTime)); SetTaskValue(owner, guildId, "advertisement", 1,
urand(sPlayerbotAIConfig->minGuildTaskAdvertisementTime,
sPlayerbotAIConfig->maxGuildTaskAdvertisementTime));
} }
else else
{ {
LOG_DEBUG("playerbots", "{} / {}: error sending advertisement", guild->GetName().c_str(), player->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: error sending advertisement", guild->GetName().c_str(),
player->GetName().c_str());
} }
} }
@@ -112,7 +123,8 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster)
} }
else else
{ {
LOG_DEBUG("playerbots", "{} / {}: error sending thanks", guild->GetName().c_str(), player->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: error sending thanks", guild->GetName().c_str(),
player->GetName().c_str());
} }
} }
@@ -128,7 +140,8 @@ void GuildTaskMgr::Update(Player* player, Player* guildMaster)
} }
else else
{ {
LOG_DEBUG("playerbots", "{} / {}: error sending reward", guild->GetName().c_str(), player->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: error sending reward", guild->GetName().c_str(),
player->GetName().c_str());
} }
} }
@@ -151,7 +164,7 @@ uint32 GuildTaskMgr::CreateTask(Player* owner, uint32 guildId)
class RandomItemBySkillGuildTaskPredicate : public RandomItemPredicate class RandomItemBySkillGuildTaskPredicate : public RandomItemPredicate
{ {
public: public:
RandomItemBySkillGuildTaskPredicate(Player* player) : RandomItemPredicate(), player(player) { } RandomItemBySkillGuildTaskPredicate(Player* player) : RandomItemPredicate(), player(player) {}
bool Apply(ItemTemplate const* proto) override bool Apply(ItemTemplate const* proto) override
{ {
@@ -180,16 +193,20 @@ bool GuildTaskMgr::CreateItemTask(Player* player, uint32 guildId)
uint32 itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, RANDOM_ITEM_GUILD_TASK, &predicate); uint32 itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, RANDOM_ITEM_GUILD_TASK, &predicate);
if (!itemId) if (!itemId)
{ {
LOG_ERROR("playerbots", "{} / {}: no items avaible for item task", sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str()); LOG_ERROR("playerbots", "{} / {}: no items avaible for item task",
sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str());
return false; return false;
} }
uint32 count = GetMaxItemTaskCount(itemId); uint32 count = GetMaxItemTaskCount(itemId);
LOG_DEBUG("playerbots", "{} / {}: item task {} (x{})", sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str(), itemId, count); LOG_DEBUG("playerbots", "{} / {}: item task {} (x{})", sGuildMgr->GetGuildById(guildId)->GetName().c_str(),
player->GetName().c_str(), itemId, count);
SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemCount", count, sPlayerbotAIConfig->maxGuildTaskChangeTime); SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemCount", count,
SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemTask", itemId, sPlayerbotAIConfig->maxGuildTaskChangeTime); sPlayerbotAIConfig->maxGuildTaskChangeTime);
SetTaskValue(player->GetGUID().GetCounter(), guildId, "itemTask", itemId,
sPlayerbotAIConfig->maxGuildTaskChangeTime);
return true; return true;
} }
@@ -204,8 +221,10 @@ bool GuildTaskMgr::CreateKillTask(Player* player, uint32 guildId)
std::vector<uint32> ids; std::vector<uint32> ids;
uint32 level = player->GetLevel(); uint32 level = player->GetLevel();
QueryResult results = WorldDatabase.Query("SELECT ct.Entry, c.map, c.position_x, c.position_y, ct.Name FROM creature_template ct " QueryResult results = WorldDatabase.Query(
"JOIN creature c ON ct.Entry = c.id1 WHERE ct.MaxLevel < {} AND ct.MinLevel > {} AND ct.Rank = {} ", level + 4, level - 3, rank); "SELECT ct.Entry, c.map, c.position_x, c.position_y, ct.Name FROM creature_template ct "
"JOIN creature c ON ct.Entry = c.id1 WHERE ct.MaxLevel < {} AND ct.MinLevel > {} AND ct.Rank = {} ",
level + 4, level - 3, rank);
if (results) if (results)
{ {
do do
@@ -231,16 +250,19 @@ bool GuildTaskMgr::CreateKillTask(Player* player, uint32 guildId)
if (ids.empty()) if (ids.empty())
{ {
LOG_ERROR("playerbots", "{} / {}: no rare creatures available for kill task", sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str()); LOG_ERROR("playerbots", "{} / {}: no rare creatures available for kill task",
sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str());
return false; return false;
} }
uint32 index = urand(0, ids.size() - 1); uint32 index = urand(0, ids.size() - 1);
uint32 creatureId = ids[index]; uint32 creatureId = ids[index];
LOG_DEBUG("playerbots", "{} / {}: kill task {}", sGuildMgr->GetGuildById(guildId)->GetName().c_str(), player->GetName().c_str(), creatureId); LOG_DEBUG("playerbots", "{} / {}: kill task {}", sGuildMgr->GetGuildById(guildId)->GetName().c_str(),
player->GetName().c_str(), creatureId);
SetTaskValue(player->GetGUID().GetCounter(), guildId, "killTask", creatureId, sPlayerbotAIConfig->maxGuildTaskChangeTime); SetTaskValue(player->GetGUID().GetCounter(), guildId, "killTask", creatureId,
sPlayerbotAIConfig->maxGuildTaskChangeTime);
return true; return true;
} }
@@ -283,7 +305,8 @@ std::string const formatTime(uint32 secs)
else if (secs < 3600 * 24) else if (secs < 3600 * 24)
{ {
out << secs / 3600 << " hr"; out << secs / 3600 << " hr";
} else }
else
{ {
out << secs / 3600 / 24 << " days"; out << secs / 3600 / 24 << " days";
} }
@@ -294,7 +317,7 @@ std::string const formatTime(uint32 secs)
std::string const formatDateTime(uint32 secs) std::string const formatDateTime(uint32 secs)
{ {
time_t rawtime = time(nullptr) + secs; time_t rawtime = time(nullptr) + secs;
tm* timeinfo = localtime (&rawtime); tm* timeinfo = localtime(&rawtime);
char buffer[256]; char buffer[256];
strftime(buffer, sizeof(buffer), "%b %d, %H:%M", timeinfo); strftime(buffer, sizeof(buffer), "%b %d, %H:%M", timeinfo);
@@ -318,7 +341,8 @@ std::string const GetHelloText(uint32 owner)
return body.str(); return body.str();
} }
bool GuildTaskMgr::SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner, uint32 guildId, uint32 validIn) bool GuildTaskMgr::SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner,
uint32 guildId, uint32 validIn)
{ {
Guild* guild = sGuildMgr->GetGuildById(guildId); Guild* guild = sGuildMgr->GetGuildById(guildId);
Player* leader = ObjectAccessor::FindPlayer(guild->GetLeaderGUID()); Player* leader = ObjectAccessor::FindPlayer(guild->GetLeaderGUID());
@@ -352,7 +376,8 @@ bool GuildTaskMgr::SendItemAdvertisement(CharacterDatabaseTransaction& trans, ui
return true; return true;
} }
bool GuildTaskMgr::SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner, uint32 guildId, uint32 validIn) bool GuildTaskMgr::SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner,
uint32 guildId, uint32 validIn)
{ {
Guild* guild = sGuildMgr->GetGuildById(guildId); Guild* guild = sGuildMgr->GetGuildById(guildId);
Player* leader = ObjectAccessor::FindPlayer(guild->GetLeaderGUID()); Player* leader = ObjectAccessor::FindPlayer(guild->GetLeaderGUID());
@@ -361,7 +386,8 @@ bool GuildTaskMgr::SendKillAdvertisement(CharacterDatabaseTransaction& trans, ui
if (!proto) if (!proto)
return false; return false;
QueryResult result = WorldDatabase.Query("SELECT map, position_x, position_y, position_z FROM creature WHERE id1 = {}", creatureId); QueryResult result =
WorldDatabase.Query("SELECT map, position_x, position_y, position_z FROM creature WHERE id1 = {}", creatureId);
if (!result) if (!result)
return false; return false;
@@ -387,7 +413,8 @@ bool GuildTaskMgr::SendKillAdvertisement(CharacterDatabaseTransaction& trans, ui
std::ostringstream body; std::ostringstream body;
body << GetHelloText(owner); body << GetHelloText(owner);
body << "As you probably know " << proto->Name << " is wanted dead for the crimes it did against our guild. If you should kill it "; body << "As you probably know " << proto->Name
<< " is wanted dead for the crimes it did against our guild. If you should kill it ";
body << "we'd really appreciate that.\n\n"; body << "we'd really appreciate that.\n\n";
if (!location.empty()) if (!location.empty())
body << proto->Name << "'s the last known location was " << location << ".\n"; body << proto->Name << "'s the last known location was " << location << ".\n";
@@ -399,7 +426,8 @@ bool GuildTaskMgr::SendKillAdvertisement(CharacterDatabaseTransaction& trans, ui
std::ostringstream subject; std::ostringstream subject;
subject << "Guild Task: "; subject << "Guild Task: ";
if (proto->rank == CREATURE_ELITE_ELITE || proto->rank == CREATURE_ELITE_RAREELITE || proto->rank == CREATURE_ELITE_WORLDBOSS) if (proto->rank == CREATURE_ELITE_ELITE || proto->rank == CREATURE_ELITE_RAREELITE ||
proto->rank == CREATURE_ELITE_WORLDBOSS)
subject << "(Elite) "; subject << "(Elite) ";
subject << proto->Name; subject << proto->Name;
if (!location.empty()) if (!location.empty())
@@ -441,9 +469,7 @@ bool GuildTaskMgr::SendThanks(CharacterDatabaseTransaction& trans, uint32 owner,
body << guild->GetName() << "\n"; body << guild->GetName() << "\n";
body << leader->GetName() << "\n"; body << leader->GetName() << "\n";
MailDraft("Thank You", body.str()). MailDraft("Thank You", body.str()).AddMoney(payment).SendMailTo(trans, MailReceiver(owner), MailSender(leader));
AddMoney(payment).
SendMailTo(trans, MailReceiver(owner), MailSender(leader));
Player* player = ObjectAccessor::FindPlayer(ObjectGuid::Create<HighGuid::Player>(owner)); Player* player = ObjectAccessor::FindPlayer(ObjectGuid::Create<HighGuid::Player>(owner));
if (player) if (player)
@@ -501,7 +527,8 @@ bool GuildTaskMgr::IsGuildTaskItem(uint32 itemId, uint32 guildId)
{ {
uint32 value = 0; uint32 value = 0;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_VALUE); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_VALUE);
stmt->SetData(0, itemId); stmt->SetData(0, itemId);
stmt->SetData(1, guildId); stmt->SetData(1, guildId);
stmt->SetData(2, "itemTask"); stmt->SetData(2, "itemTask");
@@ -518,11 +545,13 @@ bool GuildTaskMgr::IsGuildTaskItem(uint32 itemId, uint32 guildId)
return value; return value;
} }
std::map<uint32, uint32> GuildTaskMgr::GetTaskValues(uint32 owner, std::string const type, uint32* validIn /* = nullptr */) std::map<uint32, uint32> GuildTaskMgr::GetTaskValues(uint32 owner, std::string const type,
uint32* validIn /* = nullptr */)
{ {
std::map<uint32, uint32> results; std::map<uint32, uint32> results;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER);
stmt->SetData(0, owner); stmt->SetData(0, owner);
stmt->SetData(1, type); stmt->SetData(1, type);
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt)) if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
@@ -542,14 +571,15 @@ std::map<uint32, uint32> GuildTaskMgr::GetTaskValues(uint32 owner, std::string c
} while (result->NextRow()); } while (result->NextRow());
} }
return std::move(results); return std::move(results);
} }
uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn /* = nullptr */) uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn /* = nullptr */)
{ {
uint32 value = 0; uint32 value = 0;
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_AND_TYPE); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_AND_TYPE);
stmt->SetData(0, owner); stmt->SetData(0, owner);
stmt->SetData(1, guildId); stmt->SetData(1, guildId);
stmt->SetData(2, type); stmt->SetData(2, type);
@@ -566,7 +596,7 @@ uint32 GuildTaskMgr::GetTaskValue(uint32 owner, uint32 guildId, std::string cons
*validIn = secs; *validIn = secs;
} }
return value; return value;
} }
uint32 GuildTaskMgr::SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn) uint32 GuildTaskMgr::SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn)
@@ -596,13 +626,13 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* handler, char const* args)
{ {
if (!sPlayerbotAIConfig->guildTaskEnabled) if (!sPlayerbotAIConfig->guildTaskEnabled)
{ {
LOG_ERROR("playerbots", "Guild task system is currently disabled!"); LOG_ERROR("playerbots", "Guild task system is currently disabled!");
return false; return false;
} }
if (!args || !*args) if (!args || !*args)
{ {
LOG_ERROR("playerbots", "Usage: gtask stats/reset"); LOG_ERROR("playerbots", "Usage: gtask stats/reset");
return false; return false;
} }
@@ -627,13 +657,14 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* handler, char const* args)
ObjectGuid guid = sCharacterCache->GetCharacterGuidByName(charName); ObjectGuid guid = sCharacterCache->GetCharacterGuidByName(charName);
if (!guid) if (!guid)
{ {
LOG_ERROR("playerbots", "Player {} not found", charName.c_str()); LOG_ERROR("playerbots", "Player {} not found", charName.c_str());
return false; return false;
} }
uint32 owner = guid.GetCounter(); uint32 owner = guid.GetCounter();
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_ORDERED); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_ORDERED);
stmt->SetData(0, owner); stmt->SetData(0, owner);
stmt->SetData(1, "activeTask"); stmt->SetData(1, "activeTask");
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt)) if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
@@ -731,11 +762,10 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* handler, char const* args)
if (payment && paymentValidIn < validIn) if (payment && paymentValidIn < validIn)
name << " payment " << ChatHelper::formatMoney(payment) << " in " << formatTime(paymentValidIn); name << " payment " << ChatHelper::formatMoney(payment) << " in " << formatTime(paymentValidIn);
LOG_INFO("playerbots", "{}: {} valid in {} [{}]", LOG_INFO("playerbots", "{}: {} valid in {} [{}]", charName.c_str(), name.str().c_str(),
charName.c_str(), name.str().c_str(), formatTime(validIn).c_str(), guild->GetName().c_str()); formatTime(validIn).c_str(), guild->GetName().c_str());
} } while (result->NextRow());
while (result->NextRow());
} }
return true; return true;
@@ -774,13 +804,14 @@ bool GuildTaskMgr::HandleConsoleCommand(ChatHandler* handler, char const* args)
ObjectGuid guid = sCharacterCache->GetCharacterGuidByName(charName); ObjectGuid guid = sCharacterCache->GetCharacterGuidByName(charName);
if (!guid) if (!guid)
{ {
LOG_ERROR("playerbots", "Player {} not found", charName.c_str()); LOG_ERROR("playerbots", "Player {} not found", charName.c_str());
return false; return false;
} }
uint32 owner = guid.GetCounter(); uint32 owner = guid.GetCounter();
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_DISTINCT); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_GUILD_TASKS_BY_OWNER_DISTINCT);
stmt->SetData(0, owner); stmt->SetData(0, owner);
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt)) if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
{ {
@@ -818,19 +849,20 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl
return false; return false;
uint32 owner = ownerPlayer->GetGUID().GetCounter(); uint32 owner = ownerPlayer->GetGUID().GetCounter();
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId()); Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
if (!guild) if (!guild)
return false; return false;
if (!sRandomPlayerbotMgr->IsRandomBot(bot)) if (!sRandomPlayerbotMgr->IsRandomBot(bot))
return false; return false;
LOG_DEBUG("playerbots", "{} / {}: checking guild task", guild->GetName().c_str(), ownerPlayer->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: checking guild task", guild->GetName().c_str(), ownerPlayer->GetName().c_str());
uint32 itemTask = GetTaskValue(owner, guildId, "itemTask"); uint32 itemTask = GetTaskValue(owner, guildId, "itemTask");
if (itemTask != itemId) if (itemTask != itemId)
{ {
LOG_DEBUG("playerbots", "{} / {}: item {} is not guild task item ({})", guild->GetName().c_str(), ownerPlayer->GetName().c_str(), itemId, itemTask); LOG_DEBUG("playerbots", "{} / {}: item {} is not guild task item ({})", guild->GetName().c_str(),
ownerPlayer->GetName().c_str(), itemId, itemTask);
if (byMail) if (byMail)
SendCompletionMessage(ownerPlayer, "made a mistake with"); SendCompletionMessage(ownerPlayer, "made a mistake with");
@@ -857,7 +889,8 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl
if (obtained >= count) if (obtained >= count)
{ {
LOG_DEBUG("playerbots", "{} / {}: guild task complete", guild->GetName().c_str(), ownerPlayer->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: guild task complete", guild->GetName().c_str(),
ownerPlayer->GetName().c_str());
SetTaskValue(owner, guildId, "reward", 1, rewardTime - 15); SetTaskValue(owner, guildId, "reward", 1, rewardTime - 15);
SetTaskValue(owner, guildId, "itemCount", 0, 0); SetTaskValue(owner, guildId, "itemCount", 0, 0);
SetTaskValue(owner, guildId, "thanks", 0, 0); SetTaskValue(owner, guildId, "thanks", 0, 0);
@@ -865,7 +898,8 @@ bool GuildTaskMgr::CheckItemTask(uint32 itemId, uint32 obtained, Player* ownerPl
} }
else else
{ {
LOG_DEBUG("playerbots", "{} / {}: guild task progress {}/{}", guild->GetName().c_str(), ownerPlayer->GetName().c_str(), obtained, count); LOG_DEBUG("playerbots", "{} / {}: guild task progress {}/{}", guild->GetName().c_str(),
ownerPlayer->GetName().c_str(), obtained, count);
SetTaskValue(owner, guildId, "itemCount", count - obtained, sPlayerbotAIConfig->maxGuildTaskChangeTime); SetTaskValue(owner, guildId, "itemCount", count - obtained, sPlayerbotAIConfig->maxGuildTaskChangeTime);
SetTaskValue(owner, guildId, "thanks", 1, rewardTime - 30); SetTaskValue(owner, guildId, "thanks", 1, rewardTime - 30);
SendCompletionMessage(ownerPlayer, "made a progress with"); SendCompletionMessage(ownerPlayer, "made a progress with");
@@ -904,12 +938,14 @@ bool GuildTaskMgr::Reward(CharacterDatabaseTransaction& trans, uint32 owner, uin
if (!proto) if (!proto)
return false; return false;
body << "We wish to thank you for the " << proto->Name1 << " you provided so kindly. We really appreciate this and may this small gift bring you our thanks!\n"; body << "We wish to thank you for the " << proto->Name1
<< " you provided so kindly. We really appreciate this and may this small gift bring you our thanks!\n";
body << "\n"; body << "\n";
body << "Many thanks,\n"; body << "Many thanks,\n";
body << guild->GetName() << "\n"; body << guild->GetName() << "\n";
body << leader->GetName() << "\n"; body << leader->GetName() << "\n";
rewardType = proto->Quality > ITEM_QUALITY_NORMAL ? RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_BLUE : RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_GREEN; rewardType = proto->Quality > ITEM_QUALITY_NORMAL ? RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_BLUE
: RANDOM_ITEM_GUILD_TASK_REWARD_EQUIP_GREEN;
itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, rewardType); itemId = sRandomItemMgr->GetRandomItem(player->GetLevel() - 5, rewardType);
} }
else if (killTask) else if (killTask)
@@ -918,12 +954,14 @@ bool GuildTaskMgr::Reward(CharacterDatabaseTransaction& trans, uint32 owner, uin
if (!proto) if (!proto)
return false; return false;
body << "We wish to thank you for the " << proto->Name << " you've killed recently. We really appreciate this and may this small gift bring you our thanks!\n"; body << "We wish to thank you for the " << proto->Name
<< " you've killed recently. We really appreciate this and may this small gift bring you our thanks!\n";
body << "\n"; body << "\n";
body << "Many thanks,\n"; body << "Many thanks,\n";
body << guild->GetName() << "\n"; body << guild->GetName() << "\n";
body << leader->GetName() << "\n"; body << leader->GetName() << "\n";
rewardType = proto->rank == CREATURE_ELITE_RARE ? RANDOM_ITEM_GUILD_TASK_REWARD_TRADE : RANDOM_ITEM_GUILD_TASK_REWARD_TRADE_RARE; rewardType = proto->rank == CREATURE_ELITE_RARE ? RANDOM_ITEM_GUILD_TASK_REWARD_TRADE
: RANDOM_ITEM_GUILD_TASK_REWARD_TRADE_RARE;
itemId = sRandomItemMgr->GetRandomItem(player->GetLevel(), rewardType); itemId = sRandomItemMgr->GetRandomItem(player->GetLevel(), rewardType);
if (itemId) if (itemId)
{ {
@@ -1032,7 +1070,8 @@ void GuildTaskMgr::CheckKillTaskInternal(Player* player, Unit* victim)
continue; continue;
LOG_DEBUG("playerbots", "{} / {}: guild task complete", guild->GetName().c_str(), player->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: guild task complete", guild->GetName().c_str(), player->GetName().c_str());
SetTaskValue(owner, guildId, "reward", 1, urand(sPlayerbotAIConfig->minGuildTaskRewardTime, sPlayerbotAIConfig->maxGuildTaskRewardTime)); SetTaskValue(owner, guildId, "reward", 1,
urand(sPlayerbotAIConfig->minGuildTaskRewardTime, sPlayerbotAIConfig->maxGuildTaskRewardTime));
SendCompletionMessage(player, "completed"); SendCompletionMessage(player, "completed");
} }
@@ -1041,7 +1080,8 @@ void GuildTaskMgr::CheckKillTaskInternal(Player* player, Unit* victim)
void GuildTaskMgr::CleanupAdverts() void GuildTaskMgr::CleanupAdverts()
{ {
uint32 deliverTime = time(nullptr) - sPlayerbotAIConfig->minGuildTaskChangeTime; uint32 deliverTime = time(nullptr) - sPlayerbotAIConfig->minGuildTaskChangeTime;
QueryResult result = CharacterDatabase.Query("SELECT id, receiver FROM mail WHERE subject LIKE 'Guild Task%%' AND deliver_time <= {}", deliverTime); QueryResult result = CharacterDatabase.Query(
"SELECT id, receiver FROM mail WHERE subject LIKE 'Guild Task%%' AND deliver_time <= {}", deliverTime);
if (!result) if (!result)
return; return;
@@ -1059,7 +1099,8 @@ void GuildTaskMgr::CleanupAdverts()
if (count > 0) if (count > 0)
{ {
CharacterDatabase.Execute("DELETE FROM mail WHERE subject LIKE 'Guild Task%%' AND deliver_time <= {}", deliverTime); CharacterDatabase.Execute("DELETE FROM mail WHERE subject LIKE 'Guild Task%%' AND deliver_time <= {}",
deliverTime);
LOG_INFO("playerbots", "{} old gtask adverts removed", count); LOG_INFO("playerbots", "{} old gtask adverts removed", count);
} }
} }
@@ -1067,8 +1108,12 @@ void GuildTaskMgr::CleanupAdverts()
void GuildTaskMgr::RemoveDuplicatedAdverts() void GuildTaskMgr::RemoveDuplicatedAdverts()
{ {
uint32 deliverTime = time(nullptr); uint32 deliverTime = time(nullptr);
QueryResult result = CharacterDatabase.Query("SELECT m.id, m.receiver FROM (SELECT MAX(id) AS id, subject, receiver FROM mail WHERE subject LIKE 'Guild Task%%' " QueryResult result = CharacterDatabase.Query(
"AND deliver_time <= {} GROUP BY subject, receiver) q JOIN mail m ON m.subject = q.subject WHERE m.id <> q.id AND m.deliver_time <= {}", deliverTime, deliverTime); "SELECT m.id, m.receiver FROM (SELECT MAX(id) AS id, subject, receiver FROM mail WHERE subject LIKE 'Guild "
"Task%%' "
"AND deliver_time <= {} GROUP BY subject, receiver) q JOIN mail m ON m.subject = q.subject WHERE m.id <> q.id "
"AND m.deliver_time <= {}",
deliverTime, deliverTime);
if (!result) if (!result)
return; return;
@@ -1103,7 +1148,6 @@ void GuildTaskMgr::RemoveDuplicatedAdverts()
DeleteMail(buffer); DeleteMail(buffer);
LOG_INFO("playerbots", "{} duplicated gtask adverts removed", count); LOG_INFO("playerbots", "{} duplicated gtask adverts removed", count);
} }
} }
void GuildTaskMgr::DeleteMail(std::vector<uint32> buffer) void GuildTaskMgr::DeleteMail(std::vector<uint32> buffer)
@@ -1147,7 +1191,8 @@ bool GuildTaskMgr::CheckTaskTransfer(std::string const text, Player* ownerPlayer
if (text.empty()) if (text.empty())
return false; return false;
LOG_DEBUG("playerbots", "{} / {}: checking guild task transfer", guild->GetName().c_str(), ownerPlayer->GetName().c_str()); LOG_DEBUG("playerbots", "{} / {}: checking guild task transfer", guild->GetName().c_str(),
ownerPlayer->GetName().c_str());
uint32 account = ownerPlayer->GetSession()->GetAccountId(); uint32 account = ownerPlayer->GetSession()->GetAccountId();

View File

@@ -1,57 +1,60 @@
/* /*
* 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. * 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_GUILDTASKMGR_H #ifndef _PLAYERBOT_GUILDTASKMGR_H
#define _PLAYERBOT_GUILDTASKMGR_H #define _PLAYERBOT_GUILDTASKMGR_H
#include <map>
#include "Common.h" #include "Common.h"
#include "Transaction.h" #include "Transaction.h"
#include <map>
class ChatHandler; class ChatHandler;
class Player; class Player;
class Unit; class Unit;
class GuildTaskMgr class GuildTaskMgr
{ {
public: public:
GuildTaskMgr() { }; GuildTaskMgr(){};
virtual ~GuildTaskMgr() { }; virtual ~GuildTaskMgr(){};
static GuildTaskMgr* instance() static GuildTaskMgr* instance()
{ {
static GuildTaskMgr instance; static GuildTaskMgr instance;
return &instance; return &instance;
} }
void Update(Player* owner, Player* guildMaster); void Update(Player* owner, Player* guildMaster);
static bool HandleConsoleCommand(ChatHandler* handler, char const* args); static bool HandleConsoleCommand(ChatHandler* handler, char const* args);
bool IsGuildTaskItem(uint32 itemId, uint32 guildId); bool IsGuildTaskItem(uint32 itemId, uint32 guildId);
bool CheckItemTask(uint32 itemId, uint32 obtained, Player* owner, Player* bot, bool byMail = false); bool CheckItemTask(uint32 itemId, uint32 obtained, Player* owner, Player* bot, bool byMail = false);
void CheckKillTask(Player* owner, Unit* victim); void CheckKillTask(Player* owner, Unit* victim);
void CheckKillTaskInternal(Player* owner, Unit* victim); void CheckKillTaskInternal(Player* owner, Unit* victim);
bool CheckTaskTransfer(std::string const text, Player* owner, Player* bot); bool CheckTaskTransfer(std::string const text, Player* owner, Player* bot);
private: private:
std::map<uint32, uint32> GetTaskValues(uint32 owner, std::string const type, uint32* validIn = nullptr); std::map<uint32, uint32> GetTaskValues(uint32 owner, std::string const type, uint32* validIn = nullptr);
uint32 GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn = nullptr); uint32 GetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32* validIn = nullptr);
uint32 SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn); uint32 SetTaskValue(uint32 owner, uint32 guildId, std::string const type, uint32 value, uint32 validIn);
uint32 CreateTask(Player* owner, uint32 guildId); uint32 CreateTask(Player* owner, uint32 guildId);
bool SendAdvertisement(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId); bool SendAdvertisement(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId);
bool SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner, uint32 guildId, uint32 validIn); bool SendItemAdvertisement(CharacterDatabaseTransaction& trans, uint32 itemId, uint32 owner, uint32 guildId,
bool SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner, uint32 guildId, uint32 validIn); uint32 validIn);
bool SendThanks(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId, uint32 payment); bool SendKillAdvertisement(CharacterDatabaseTransaction& trans, uint32 creatureId, uint32 owner, uint32 guildId,
bool Reward(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId); uint32 validIn);
bool CreateItemTask(Player* owner, uint32 guildId); bool SendThanks(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId, uint32 payment);
bool CreateKillTask(Player* owner, uint32 guildId); bool Reward(CharacterDatabaseTransaction& trans, uint32 owner, uint32 guildId);
uint32 GetMaxItemTaskCount(uint32 itemId); bool CreateItemTask(Player* owner, uint32 guildId);
void CleanupAdverts(); bool CreateKillTask(Player* owner, uint32 guildId);
void RemoveDuplicatedAdverts(); uint32 GetMaxItemTaskCount(uint32 itemId);
void DeleteMail(std::vector<uint32> buffer); void CleanupAdverts();
void SendCompletionMessage(Player* player, std::string const verb); void RemoveDuplicatedAdverts();
void DeleteMail(std::vector<uint32> buffer);
void SendCompletionMessage(Player* player, std::string const verb);
}; };
#define sGuildTaskMgr GuildTaskMgr::instance() #define sGuildTaskMgr GuildTaskMgr::instance()

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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 "Helpers.h" #include "Helpers.h"
@@ -15,7 +16,7 @@ char* strstri(char const* haystack, char const* needle)
{ {
if (tolower(*haystack) == tolower(*needle)) if (tolower(*haystack) == tolower(*needle))
{ {
char const* h = haystack, * n = needle; char const *h = haystack, *n = needle;
for (; *h && *n; ++h, ++n) for (; *h && *n; ++h, ++n)
{ {
if (tolower(*h) != tolower(*n)) if (tolower(*h) != tolower(*n))
@@ -36,17 +37,14 @@ char* strstri(char const* haystack, char const* needle)
std::string& ltrim(std::string& s) std::string& ltrim(std::string& s)
{ {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) {return !std::isspace(c); })); s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
return s; return s;
} }
std::string& rtrim(std::string& s) std::string& rtrim(std::string& s)
{ {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) {return !std::isspace(c); }).base(), s.end()); s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
return s; return s;
} }
std::string& trim(std::string& s) std::string& trim(std::string& s) { return ltrim(rtrim(s)); }
{
return ltrim(rtrim(s));
}

View File

@@ -1,21 +1,23 @@
/* /*
* 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. * 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_HELPERS_H #ifndef _PLAYERBOT_HELPERS_H
#define _PLAYERBOT_HELPERS_H #define _PLAYERBOT_HELPERS_H
#include "Common.h"
#include <map>
#include <vector>
#include <functional>
#include <cctype>
#include <locale>
#include <sstream>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <cctype>
#include <functional>
#include <locale>
#include <map>
#include <sstream>
#include <vector>
#include "Common.h"
void split(std::vector<std::string>& dest, std::string const str, char const* delim) void split(std::vector<std::string>& dest, std::string const str, char const* delim)
{ {

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_LAZYCALCULATEDVALUE_H #ifndef _PLAYERBOT_LAZYCALCULATEDVALUE_H
@@ -8,37 +9,31 @@
template <class TValue, class TOwner> template <class TValue, class TOwner>
class LazyCalculatedValue class LazyCalculatedValue
{ {
public: public:
typedef TValue (TOwner::*Calculator)(); typedef TValue (TOwner::*Calculator)();
public: public:
LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner) LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner) { Reset(); }
public:
TValue GetValue()
{
if (!calculated)
{ {
Reset(); value = (owner->*calculator)();
calculated = true;
} }
public: return value;
TValue GetValue() }
{
if (!calculated)
{
value = (owner->*calculator)();
calculated = true;
}
return value; void Reset() { calculated = false; }
}
void Reset() protected:
{ Calculator calculator;
calculated = false; TOwner* owner;
} bool calculated;
TValue value;
protected:
Calculator calculator;
TOwner* owner;
bool calculated;
TValue value;
}; };
#endif #endif

View File

@@ -1,17 +1,17 @@
/* /*
* 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. * 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 "LootObjectStack.h" #include "LootObjectStack.h"
#include "LootMgr.h" #include "LootMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Unit.h" #include "Unit.h"
#define MAX_LOOT_OBJECT_COUNT 10 #define MAX_LOOT_OBJECT_COUNT 10
LootTarget::LootTarget(ObjectGuid guid) : guid(guid), asOfTime(time(nullptr)) LootTarget::LootTarget(ObjectGuid guid) : guid(guid), asOfTime(time(nullptr)) {}
{
}
LootTarget::LootTarget(LootTarget const& other) LootTarget::LootTarget(LootTarget const& other)
{ {
@@ -30,19 +30,16 @@ LootTarget& LootTarget::operator=(LootTarget const& other)
return *this; return *this;
} }
bool LootTarget::operator<(LootTarget const& other) const bool LootTarget::operator<(LootTarget const& other) const { return guid < other.guid; }
{
return guid < other.guid;
}
void LootTargetList::shrink(time_t fromTime) void LootTargetList::shrink(time_t fromTime)
{ {
for (std::set<LootTarget>::iterator i = begin(); i != end(); ) for (std::set<LootTarget>::iterator i = begin(); i != end();)
{ {
if (i->asOfTime <= fromTime) if (i->asOfTime <= fromTime)
erase(i++); erase(i++);
else else
++i; ++i;
} }
} }
@@ -59,7 +56,8 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
guid.Clear(); guid.Clear();
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
Creature* creature = botAI->GetCreature(lootGUID); Creature* creature = botAI->GetCreature(lootGUID);
@@ -73,7 +71,7 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
skillId = creature->GetCreatureTemplate()->GetRequiredLootSkill(); skillId = creature->GetCreatureTemplate()->GetRequiredLootSkill();
uint32 targetLevel = creature->GetLevel(); uint32 targetLevel = creature->GetLevel();
reqSkillValue = targetLevel < 10 ? 1 : targetLevel < 20 ? (targetLevel - 10) * 10 : targetLevel * 5; reqSkillValue = targetLevel < 10 ? 1 : targetLevel < 20 ? (targetLevel - 10) * 10 : targetLevel * 5;
if (botAI->HasSkill((SkillType) skillId) && bot->GetSkillValue(skillId) >= reqSkillValue) if (botAI->HasSkill((SkillType)skillId) && bot->GetSkillValue(skillId) >= reqSkillValue)
guid = lootGUID; guid = lootGUID;
} }
@@ -83,7 +81,6 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
GameObject* go = botAI->GetGameObject(lootGUID); GameObject* go = botAI->GetGameObject(lootGUID);
if (go && go->isSpawned() && go->GetGoState() == GO_STATE_READY) if (go && go->isSpawned() && go->GetGoState() == GO_STATE_READY)
{ {
bool isQuestItemOnly = false; bool isQuestItemOnly = false;
GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(go->GetEntry()); GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(go->GetEntry());
@@ -123,21 +120,21 @@ void LootObject::Refresh(Player* bot, ObjectGuid lootGUID)
} }
break; break;
case LOCK_KEY_SKILL: case LOCK_KEY_SKILL:
if (goId == 13891 || goId == 19535) // Serpentbloom if (goId == 13891 || goId == 19535) // Serpentbloom
{ {
this->guid = lootGUID; this->guid = lootGUID;
} }
else if (SkillByLockType(LockType(lockInfo->Index[i])) > 0) else if (SkillByLockType(LockType(lockInfo->Index[i])) > 0)
{ {
skillId = SkillByLockType(LockType(lockInfo->Index[i])); skillId = SkillByLockType(LockType(lockInfo->Index[i]));
reqSkillValue = std::max((uint32) 1, lockInfo->Skill[i]); reqSkillValue = std::max((uint32)1, lockInfo->Skill[i]);
guid = lootGUID; guid = lootGUID;
} }
break; break;
case LOCK_KEY_NONE: case LOCK_KEY_NONE:
guid = lootGUID; guid = lootGUID;
break; break;
} }
} }
} }
} }
@@ -178,7 +175,8 @@ WorldObject* LootObject::GetWorldObject(Player* bot)
Refresh(bot, guid); Refresh(bot, guid);
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return nullptr; return nullptr;
} }
Creature* creature = botAI->GetCreature(guid); Creature* creature = botAI->GetCreature(guid);
@@ -206,7 +204,8 @@ bool LootObject::IsLootPossible(Player* bot)
return false; return false;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return false; return false;
} }
if (reqItem && !bot->HasItemCount(reqItem, 1)) if (reqItem && !bot->HasItemCount(reqItem, 1))
@@ -249,11 +248,13 @@ bool LootObject::IsLootPossible(Player* bot)
bool LootObjectStack::Add(ObjectGuid guid) bool LootObjectStack::Add(ObjectGuid guid)
{ {
if (availableLoot.size() >= MAX_LOOT_OBJECT_COUNT) { if (availableLoot.size() >= MAX_LOOT_OBJECT_COUNT)
{
availableLoot.shrink(time(nullptr) - 30); availableLoot.shrink(time(nullptr) - 30);
} }
if (availableLoot.size() >= MAX_LOOT_OBJECT_COUNT) { if (availableLoot.size() >= MAX_LOOT_OBJECT_COUNT)
{
availableLoot.clear(); availableLoot.clear();
} }
@@ -270,10 +271,7 @@ void LootObjectStack::Remove(ObjectGuid guid)
availableLoot.erase(i); availableLoot.erase(i);
} }
void LootObjectStack::Clear() void LootObjectStack::Clear() { availableLoot.clear(); }
{
availableLoot.clear();
}
bool LootObjectStack::CanLoot(float maxDistance) bool LootObjectStack::CanLoot(float maxDistance)
{ {
@@ -311,4 +309,3 @@ std::vector<LootObject> LootObjectStack::OrderByDistance(float maxDistance)
return result; return result;
} }

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_LOOTOBJECTSTACK_H #ifndef _PLAYERBOT_LOOTOBJECTSTACK_H
@@ -15,29 +16,29 @@ struct ItemTemplate;
class LootStrategy class LootStrategy
{ {
public: public:
LootStrategy() { } LootStrategy() {}
virtual ~LootStrategy() { }; virtual ~LootStrategy(){};
virtual bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) = 0; virtual bool CanLoot(ItemTemplate const* proto, AiObjectContext* context) = 0;
virtual std::string const GetName() = 0; virtual std::string const GetName() = 0;
}; };
class LootObject class LootObject
{ {
public: public:
LootObject() : skillId(0), reqSkillValue(0), reqItem(0) { } LootObject() : skillId(0), reqSkillValue(0), reqItem(0) {}
LootObject(Player* bot, ObjectGuid guid); LootObject(Player* bot, ObjectGuid guid);
LootObject(LootObject const& other); LootObject(LootObject const& other);
bool IsEmpty() { return !guid; } bool IsEmpty() { return !guid; }
bool IsLootPossible(Player* bot); bool IsLootPossible(Player* bot);
void Refresh(Player* bot, ObjectGuid guid); void Refresh(Player* bot, ObjectGuid guid);
WorldObject* GetWorldObject(Player* bot); WorldObject* GetWorldObject(Player* bot);
ObjectGuid guid; ObjectGuid guid;
uint32 skillId; uint32 skillId;
uint32 reqSkillValue; uint32 reqSkillValue;
uint32 reqItem; uint32 reqItem;
private: private:
static bool IsNeededForQuest(Player* bot, uint32 itemId); static bool IsNeededForQuest(Player* bot, uint32 itemId);
@@ -45,41 +46,41 @@ private:
class LootTarget class LootTarget
{ {
public: public:
LootTarget(ObjectGuid guid); LootTarget(ObjectGuid guid);
LootTarget(LootTarget const& other); LootTarget(LootTarget const& other);
public: public:
LootTarget& operator=(LootTarget const& other); LootTarget& operator=(LootTarget const& other);
bool operator<(LootTarget const& other) const; bool operator<(LootTarget const& other) const;
public: public:
ObjectGuid guid; ObjectGuid guid;
time_t asOfTime; time_t asOfTime;
}; };
class LootTargetList : public std::set<LootTarget> class LootTargetList : public std::set<LootTarget>
{ {
public: public:
void shrink(time_t fromTime); void shrink(time_t fromTime);
}; };
class LootObjectStack class LootObjectStack
{ {
public: public:
LootObjectStack(Player* bot) : bot(bot) { } LootObjectStack(Player* bot) : bot(bot) {}
bool Add(ObjectGuid guid); bool Add(ObjectGuid guid);
void Remove(ObjectGuid guid); void Remove(ObjectGuid guid);
void Clear(); void Clear();
bool CanLoot(float maxDistance); bool CanLoot(float maxDistance);
LootObject GetLoot(float maxDistance = 0); LootObject GetLoot(float maxDistance = 0);
private: private:
std::vector<LootObject> OrderByDistance(float maxDistance = 0); std::vector<LootObject> OrderByDistance(float maxDistance = 0);
Player* bot; Player* bot;
LootTargetList availableLoot; LootTargetList availableLoot;
}; };
#endif #endif

View File

@@ -1,11 +1,14 @@
/* /*
* 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. * 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 "PerformanceMonitor.h" #include "PerformanceMonitor.h"
#include "Playerbots.h" #include "Playerbots.h"
PerformanceMonitorOperation* PerformanceMonitor::start(PerformanceMetric metric, std::string const name, PerformanceStack* stack) PerformanceMonitorOperation* PerformanceMonitor::start(PerformanceMetric metric, std::string const name,
PerformanceStack* stack)
{ {
if (!sPlayerbotAIConfig->perfMonEnabled) if (!sPlayerbotAIConfig->perfMonEnabled)
return nullptr; return nullptr;
@@ -50,7 +53,6 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
if (data.empty()) if (data.empty())
return; return;
if (!perTick) if (!perTick)
{ {
float updateAITotalTime = 0; float updateAITotalTime = 0;
@@ -58,11 +60,17 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
if (map.first.find("PlayerbotAI::UpdateAIInternal") != std::string::npos) if (map.first.find("PlayerbotAI::UpdateAIInternal") != std::string::npos)
updateAITotalTime += map.second->totalTime; updateAITotalTime += map.second->totalTime;
LOG_INFO("playerbots", "--------------------------------------[TOTAL BOT]------------------------------------------------------"); LOG_INFO(
LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); "playerbots",
LOG_INFO("playerbots", "-------------------------------------------------------------------------------------------------------"); "--------------------------------------[TOTAL BOT]------------------------------------------------------");
LOG_INFO("playerbots",
"percentage time | min .. max ( avg of count) - type : name");
LOG_INFO(
"playerbots",
"-------------------------------------------------------------------------------------------------------");
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin(); i != data.end(); ++i) for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
i != data.end(); ++i)
{ {
std::map<std::string, PerformanceData*> pdMap = i->second; std::map<std::string, PerformanceData*> pdMap = i->second;
@@ -99,10 +107,9 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
names.push_back(j->first); names.push_back(j->first);
} }
std::sort(names.begin(), names.end(), [pdMap](std::string const i, std::string const j) std::sort(names.begin(), names.end(),
{ [pdMap](std::string const i, std::string const j)
return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; { return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; });
});
uint64 typeTotalTime = 0; uint64 typeTotalTime = 0;
uint64 typeMinTime = 0xffffffffu; uint64 typeMinTime = 0xffffffffu;
@@ -128,15 +135,9 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000) if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000)
{ {
LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}" LOG_INFO("playerbots",
, perc "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}", perc, time,
, time minTime, maxTime, avg, pd->count, key.c_str(), disName.c_str());
, minTime
, maxTime
, avg
, pd->count
, key.c_str()
, disName.c_str());
} }
} }
float tPerc = (float)typeTotalTime / (float)updateAITotalTime * 100.0f; float tPerc = (float)typeTotalTime / (float)updateAITotalTime * 100.0f;
@@ -144,15 +145,8 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
float tMinTime = (float)typeMinTime / 1000.0f; float tMinTime = (float)typeMinTime / 1000.0f;
float tMaxTime = (float)typeMaxTime / 1000.0f; float tMaxTime = (float)typeMaxTime / 1000.0f;
float tAvg = (float)typeTotalTime / (float)typeCount / 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} : {}" LOG_INFO("playerbots", "{:7.3f}% {:10.3f}s | {:7.1f} .. {:7.1f} ({:10.3f} of {:10d}) - {:6} : {}", tPerc,
, tPerc tTime, tMinTime, tMaxTime, tAvg, typeCount, key.c_str(), "Total");
, tTime
, tMinTime
, tMaxTime
, tAvg
, typeCount
, key.c_str()
, "Total");
LOG_INFO("playerbots", " "); LOG_INFO("playerbots", " ");
} }
} }
@@ -161,11 +155,17 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
float fullTickCount = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->count; float fullTickCount = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->count;
float fullTickTotalTime = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->totalTime; float fullTickTotalTime = data[PERF_MON_TOTAL]["RandomPlayerbotMgr::FullTick"]->totalTime;
LOG_INFO("playerbots", "---------------------------------------[PER TICK]------------------------------------------------------"); LOG_INFO(
LOG_INFO("playerbots", "percentage time | min .. max ( avg of count) - type : name"); "playerbots",
LOG_INFO("playerbots", "-------------------------------------------------------------------------------------------------------"); "---------------------------------------[PER TICK]------------------------------------------------------");
LOG_INFO("playerbots",
"percentage time | min .. max ( avg of count) - type : name");
LOG_INFO(
"playerbots",
"-------------------------------------------------------------------------------------------------------");
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin(); i != data.end(); ++i) for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
i != data.end(); ++i)
{ {
std::map<std::string, PerformanceData*> pdMap = i->second; std::map<std::string, PerformanceData*> pdMap = i->second;
@@ -198,10 +198,9 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
names.push_back(j->first); names.push_back(j->first);
} }
std::sort(names.begin(), names.end(), [pdMap](std::string const i, std::string const j) std::sort(names.begin(), names.end(),
{ [pdMap](std::string const i, std::string const j)
return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; { return pdMap.at(i)->totalTime < pdMap.at(j)->totalTime; });
});
uint64 typeTotalTime = 0; uint64 typeTotalTime = 0;
uint64 typeMinTime = 0xffffffffu; uint64 typeMinTime = 0xffffffffu;
@@ -227,15 +226,9 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
disName = disName.substr(0, disName.find("|")) + "]"; disName = disName.substr(0, disName.find("|")) + "]";
if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000) if (perc >= 0.1f || avg >= 0.25f || pd->maxTime > 1000)
{ {
LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}" LOG_INFO("playerbots",
, perc "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}", perc,
, time time, minTime, maxTime, avg, amount, key.c_str(), disName.c_str());
, minTime
, maxTime
, avg
, amount
, key.c_str()
, disName.c_str());
} }
} }
if (PERF_MON_TOTAL != i->first) if (PERF_MON_TOTAL != i->first)
@@ -246,15 +239,8 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
float tMaxTime = (float)typeMaxTime / 1000.0f; float tMaxTime = (float)typeMaxTime / 1000.0f;
float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f; float tAvg = (float)typeTotalTime / (float)typeCount / 1000.0f;
float tAmount = (float)typeCount / fullTickCount; float tAmount = (float)typeCount / fullTickCount;
LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}" LOG_INFO("playerbots", "{:7.3f}% {:9.3f}ms | {:7.1f} .. {:7.1f} ({:10.3f} of {:10.2f}) - {:6} : {}",
, tPerc tPerc, tTime, tMinTime, tMaxTime, tAvg, tAmount, key.c_str(), "Total");
, tTime
, tMinTime
, tMaxTime
, tAvg
, tAmount
, key.c_str()
, "Total");
} }
LOG_INFO("playerbots", " "); LOG_INFO("playerbots", " ");
} }
@@ -263,7 +249,8 @@ void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
void PerformanceMonitor::Reset() void PerformanceMonitor::Reset()
{ {
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*> >::iterator i = data.begin(); i != data.end(); ++i) for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
i != data.end(); ++i)
{ {
std::map<std::string, PerformanceData*> pdMap = i->second; std::map<std::string, PerformanceData*> pdMap = i->second;
for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j) for (std::map<std::string, PerformanceData*>::iterator j = pdMap.begin(); j != pdMap.end(); ++j)
@@ -278,14 +265,19 @@ void PerformanceMonitor::Reset()
} }
} }
PerformanceMonitorOperation::PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack) : data(data), name(name), stack(stack) PerformanceMonitorOperation::PerformanceMonitorOperation(PerformanceData* data, std::string const name,
PerformanceStack* stack)
: data(data), name(name), stack(stack)
{ {
started = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now())).time_since_epoch(); started = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()))
.time_since_epoch();
} }
void PerformanceMonitorOperation::finish() void PerformanceMonitorOperation::finish()
{ {
std::chrono::microseconds finished = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now())).time_since_epoch(); std::chrono::microseconds finished =
(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()))
.time_since_epoch();
uint64_t elapsed = (finished - started).count(); uint64_t elapsed = (finished - started).count();
std::lock_guard<std::mutex> guard(data->lock); std::lock_guard<std::mutex> guard(data->lock);
@@ -309,4 +301,3 @@ void PerformanceMonitorOperation::finish()
delete this; delete this;
} }

View File

@@ -1,18 +1,19 @@
/* /*
* 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. * 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_PERFORMANCEMONITOR_H #ifndef _PLAYERBOT_PERFORMANCEMONITOR_H
#define _PLAYERBOT_PERFORMANCEMONITOR_H #define _PLAYERBOT_PERFORMANCEMONITOR_H
#include "Common.h"
#include <chrono> #include <chrono>
#include <ctime> #include <ctime>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include "Common.h"
typedef std::vector<std::string> PerformanceStack; typedef std::vector<std::string> PerformanceStack;
struct PerformanceData struct PerformanceData
@@ -35,36 +36,37 @@ enum PerformanceMetric
class PerformanceMonitorOperation class PerformanceMonitorOperation
{ {
public: public:
PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack); PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack);
void finish(); void finish();
private: private:
PerformanceData* data; PerformanceData* data;
std::string const name; std::string const name;
PerformanceStack* stack; PerformanceStack* stack;
std::chrono::microseconds started; std::chrono::microseconds started;
}; };
class PerformanceMonitor class PerformanceMonitor
{ {
public: public:
PerformanceMonitor() { }; PerformanceMonitor(){};
virtual ~PerformanceMonitor() { }; virtual ~PerformanceMonitor(){};
static PerformanceMonitor* instance() static PerformanceMonitor* instance()
{ {
static PerformanceMonitor instance; static PerformanceMonitor instance;
return &instance; return &instance;
} }
public: public:
PerformanceMonitorOperation* start(PerformanceMetric metric, std::string const name, PerformanceStack* stack = nullptr); PerformanceMonitorOperation* start(PerformanceMetric metric, std::string const name,
void PrintStats(bool perTick = false, bool fullStack = false); PerformanceStack* stack = nullptr);
void Reset(); void PrintStats(bool perTick = false, bool fullStack = false);
void Reset();
private: private:
std::map<PerformanceMetric, std::map<std::string, PerformanceData*> > data; std::map<PerformanceMetric, std::map<std::string, PerformanceData*> > data;
std::mutex lock; std::mutex lock;
}; };
#define sPerformanceMonitor PerformanceMonitor::instance() #define sPerformanceMonitor PerformanceMonitor::instance()

View File

@@ -1,18 +1,17 @@
/* /*
* 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. * 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 "PlaceholderHelper.h" #include "PlaceholderHelper.h"
#include "AiFactory.h" #include "AiFactory.h"
#include "Playerbots.h"
#include "PlayerbotTextMgr.h" #include "PlayerbotTextMgr.h"
#include "Playerbots.h"
#include "Util.h" #include "Util.h"
void PlaceholderHelper::MapDungeon( void PlaceholderHelper::MapDungeon(PlaceholderMap& placeholders, DungeonSuggestion const* dungeonSuggestion,
PlaceholderMap& placeholders, Player* bot)
DungeonSuggestion const* dungeonSuggestion,
Player* bot
)
{ {
std::ostringstream out; std::ostringstream out;
Insertion insertion = {out, dungeonSuggestion}; Insertion insertion = {out, dungeonSuggestion};
@@ -23,7 +22,6 @@ void PlaceholderHelper::MapDungeon(
placeholders["%dungeon"] = out.str(); placeholders["%dungeon"] = out.str();
} }
void PlaceholderHelper::MapRole(PlaceholderMap& placeholders, Player* bot) void PlaceholderHelper::MapRole(PlaceholderMap& placeholders, Player* bot)
{ {
BotRoles const role = AiFactory::GetPlayerRoles(bot); BotRoles const role = AiFactory::GetPlayerRoles(bot);
@@ -82,8 +80,8 @@ void PlaceholderHelper::InsertDifficulty(Insertion& insertion, [[maybe_unused]]
{ {
bool const isRandomlyNormal = urand(0, 1); bool const isRandomlyNormal = urand(0, 1);
bool const isRandomlyHeroic = urand(0, 1); bool const isRandomlyHeroic = urand(0, 1);
std::vector<std::string> normalAbbrevations = { "Normal", "N" }; std::vector<std::string> normalAbbrevations = {"Normal", "N"};
std::vector<std::string> heroicAbbrevations = { "Heroic", "HC", "H"}; std::vector<std::string> heroicAbbrevations = {"Heroic", "HC", "H"};
uint32 const randomAbbrevationIndex = urand(0, 1); uint32 const randomAbbrevationIndex = urand(0, 1);
if (isRandomlyNormal) if (isRandomlyNormal)
{ {

View File

@@ -1,38 +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. * 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_PLACEHOLDERHELPER_H #ifndef _PLAYERBOT_PLACEHOLDERHELPER_H
#define _PLAYERBOT_PLACEHOLDERHELPER_H #define _PLAYERBOT_PLACEHOLDERHELPER_H
#include <map>
#include "Common.h" #include "Common.h"
#include "Player.h" #include "Player.h"
#include "PlayerbotDungeonSuggestionMgr.h" #include "PlayerbotDungeonSuggestionMgr.h"
#include <map>
typedef std::map<std::string, std::string> PlaceholderMap; typedef std::map<std::string, std::string> PlaceholderMap;
class PlaceholderHelper class PlaceholderHelper
{ {
public: public:
static void MapRole(PlaceholderMap& placeholders, Player* bot); static void MapRole(PlaceholderMap& placeholders, Player* bot);
static void MapDungeon( static void MapDungeon(PlaceholderMap& placeholders, DungeonSuggestion const* dungeonSuggestion, Player* bot);
PlaceholderMap& placeholders,
DungeonSuggestion const* dungeonSuggestion,
Player* bot
);
private: private:
struct Insertion struct Insertion
{ {
std::ostringstream& out; std::ostringstream& out;
DungeonSuggestion const* dungeonSuggestion; DungeonSuggestion const* dungeonSuggestion;
}; };
static void InsertDungeonName(Insertion& insertion); static void InsertDungeonName(Insertion& insertion);
static void InsertDungeonStrategy(Insertion& insertion); static void InsertDungeonStrategy(Insertion& insertion);
static void InsertDifficulty(Insertion& insertion, Player* bot); static void InsertDifficulty(Insertion& insertion, Player* bot);
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,26 @@
/* /*
* 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. * 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_PLAYERbotAI_H #ifndef _PLAYERBOT_PLAYERbotAI_H
#define _PLAYERBOT_PLAYERbotAI_H #define _PLAYERBOT_PLAYERbotAI_H
#include <queue>
#include <stack>
#include "Chat.h" #include "Chat.h"
#include "ChatHelper.h"
#include "ChatFilter.h" #include "ChatFilter.h"
#include "ChatHelper.h"
#include "Common.h" #include "Common.h"
#include "Event.h" #include "Event.h"
#include "Item.h" #include "Item.h"
#include "PlayerbotAIBase.h" #include "PlayerbotAIBase.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "PlayerbotSecurity.h" #include "PlayerbotSecurity.h"
#include "PlayerbotTextMgr.h"
#include "SpellAuras.h" #include "SpellAuras.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "PlayerbotTextMgr.h"
#include <stack>
#include <queue>
class AiObjectContext; class AiObjectContext;
class Creature; class Creature;
@@ -43,228 +44,239 @@ enum StrategyType : uint32;
enum HealingItemDisplayId enum HealingItemDisplayId
{ {
HEALTHSTONE_DISPLAYID = 8026, HEALTHSTONE_DISPLAYID = 8026,
MAJOR_HEALING_POTION = 24152, MAJOR_HEALING_POTION = 24152,
WHIPPER_ROOT_TUBER = 21974, WHIPPER_ROOT_TUBER = 21974,
NIGHT_DRAGON_BREATH = 21975, NIGHT_DRAGON_BREATH = 21975,
LIMITED_INVULNERABILITY_POTION = 24213, LIMITED_INVULNERABILITY_POTION = 24213,
GREATER_DREAMLESS_SLEEP_POTION = 17403, GREATER_DREAMLESS_SLEEP_POTION = 17403,
SUPERIOR_HEALING_POTION = 15714, SUPERIOR_HEALING_POTION = 15714,
CRYSTAL_RESTORE = 2516, CRYSTAL_RESTORE = 2516,
DREAMLESS_SLEEP_POTION = 17403, DREAMLESS_SLEEP_POTION = 17403,
GREATER_HEALING_POTION = 15713, GREATER_HEALING_POTION = 15713,
HEALING_POTION = 15712, HEALING_POTION = 15712,
LESSER_HEALING_POTION = 15711, LESSER_HEALING_POTION = 15711,
DISCOLORED_HEALING_POTION = 15736, DISCOLORED_HEALING_POTION = 15736,
MINOR_HEALING_POTION = 15710, MINOR_HEALING_POTION = 15710,
VOLATILE_HEALING_POTION = 24212, VOLATILE_HEALING_POTION = 24212,
SUPER_HEALING_POTION = 37807, SUPER_HEALING_POTION = 37807,
CRYSTAL_HEALING_POTION = 47132, CRYSTAL_HEALING_POTION = 47132,
FEL_REGENERATION_POTION = 37864, FEL_REGENERATION_POTION = 37864,
MAJOR_DREAMLESS_SLEEP_POTION = 37845 MAJOR_DREAMLESS_SLEEP_POTION = 37845
}; };
enum BotState enum BotState
{ {
BOT_STATE_COMBAT = 0, BOT_STATE_COMBAT = 0,
BOT_STATE_NON_COMBAT = 1, BOT_STATE_NON_COMBAT = 1,
BOT_STATE_DEAD = 2, BOT_STATE_DEAD = 2,
BOT_STATE_MAX BOT_STATE_MAX
}; };
bool IsAlliance(uint8 race); bool IsAlliance(uint8 race);
class PlayerbotChatHandler: protected ChatHandler class PlayerbotChatHandler : protected ChatHandler
{ {
public: public:
explicit PlayerbotChatHandler(Player* pMasterPlayer); explicit PlayerbotChatHandler(Player* pMasterPlayer);
void sysmessage(std::string const str) { SendSysMessage(str.c_str()); } void sysmessage(std::string const str) { SendSysMessage(str.c_str()); }
uint32 extractQuestId(std::string const str); uint32 extractQuestId(std::string const str);
uint32 extractSpellId(std::string const str) uint32 extractSpellId(std::string const str)
{ {
char* source = (char*)str.c_str(); char* source = (char*)str.c_str();
return extractSpellIdFromLink(source); return extractSpellIdFromLink(source);
} }
}; };
class MinValueCalculator class MinValueCalculator
{ {
public: public:
MinValueCalculator(float def = 0.0f) : param(nullptr), minValue(def) { } MinValueCalculator(float def = 0.0f) : param(nullptr), minValue(def) {}
void probe(float value, void* p) void probe(float value, void* p)
{
if (!param || minValue >= value)
{ {
if (!param || minValue >= value) minValue = value;
{ param = p;
minValue = value; }
param = p; }
}
}
void* param; void* param;
float minValue; float minValue;
}; };
enum RoguePoisonDisplayId enum RoguePoisonDisplayId
{ {
DEADLY_POISON_DISPLAYID = 13707, DEADLY_POISON_DISPLAYID = 13707,
INSTANT_POISON_DISPLAYID = 13710, INSTANT_POISON_DISPLAYID = 13710,
WOUND_POISON_DISPLAYID = 37278 WOUND_POISON_DISPLAYID = 37278
}; };
enum SharpeningStoneDisplayId enum SharpeningStoneDisplayId
{ {
ROUGH_SHARPENING_DISPLAYID = 24673, ROUGH_SHARPENING_DISPLAYID = 24673,
COARSE_SHARPENING_DISPLAYID = 24674, COARSE_SHARPENING_DISPLAYID = 24674,
HEAVY_SHARPENING_DISPLAYID = 24675, HEAVY_SHARPENING_DISPLAYID = 24675,
SOLID_SHARPENING_DISPLAYID = 24676, SOLID_SHARPENING_DISPLAYID = 24676,
DENSE_SHARPENING_DISPLAYID = 24677, DENSE_SHARPENING_DISPLAYID = 24677,
CONSECRATED_SHARPENING_DISPLAYID = 24674, // will not be used because bot can not know if it will face undead targets CONSECRATED_SHARPENING_DISPLAYID =
ELEMENTAL_SHARPENING_DISPLAYID = 21072, 24674, // will not be used because bot can not know if it will face undead targets
FEL_SHARPENING_DISPLAYID = 39192, ELEMENTAL_SHARPENING_DISPLAYID = 21072,
ADAMANTITE_SHARPENING_DISPLAYID = 39193 FEL_SHARPENING_DISPLAYID = 39192,
ADAMANTITE_SHARPENING_DISPLAYID = 39193
}; };
enum WeightStoneDisplayId enum WeightStoneDisplayId
{ {
ROUGH_WEIGHTSTONE_DISPLAYID = 24683, ROUGH_WEIGHTSTONE_DISPLAYID = 24683,
COARSE_WEIGHTSTONE_DISPLAYID = 24684, COARSE_WEIGHTSTONE_DISPLAYID = 24684,
HEAVY_WEIGHTSTONE_DISPLAYID = 24685, HEAVY_WEIGHTSTONE_DISPLAYID = 24685,
SOLID_WEIGHTSTONE_DISPLAYID = 24686, SOLID_WEIGHTSTONE_DISPLAYID = 24686,
DENSE_WEIGHTSTONE_DISPLAYID = 24687, DENSE_WEIGHTSTONE_DISPLAYID = 24687,
FEL_WEIGHTSTONE_DISPLAYID = 39548, FEL_WEIGHTSTONE_DISPLAYID = 39548,
ADAMANTITE_WEIGHTSTONE_DISPLAYID = 39549 ADAMANTITE_WEIGHTSTONE_DISPLAYID = 39549
}; };
enum WizardOilDisplayId enum WizardOilDisplayId
{ {
MINOR_WIZARD_OIL = 9731, MINOR_WIZARD_OIL = 9731,
LESSER_WIZARD_OIL = 47903, LESSER_WIZARD_OIL = 47903,
BRILLIANT_WIZARD_OIL = 47901, BRILLIANT_WIZARD_OIL = 47901,
WIZARD_OIL = 47905, WIZARD_OIL = 47905,
SUPERIOR_WIZARD_OIL = 47904, SUPERIOR_WIZARD_OIL = 47904,
/// Blessed Wizard Oil = 26865 //scourge inv /// Blessed Wizard Oil = 26865 //scourge inv
}; };
enum ManaOilDisplayId enum ManaOilDisplayId
{ {
MINOR_MANA_OIL = 34492, MINOR_MANA_OIL = 34492,
LESSER_MANA_OIL = 47902, LESSER_MANA_OIL = 47902,
BRILLIANT_MANA_OIL = 41488, BRILLIANT_MANA_OIL = 41488,
SUPERIOR_MANA_OIL = 36862 SUPERIOR_MANA_OIL = 36862
}; };
enum ShieldWardDisplayId enum ShieldWardDisplayId
{ {
LESSER_WARD_OFSHIELDING = 38759, LESSER_WARD_OFSHIELDING = 38759,
GREATER_WARD_OFSHIELDING = 38760 GREATER_WARD_OFSHIELDING = 38760
}; };
enum class BotTypeNumber : uint8 enum class BotTypeNumber : uint8
{ {
ACTIVITY_TYPE_NUMBER = 1, ACTIVITY_TYPE_NUMBER = 1,
GROUPER_TYPE_NUMBER = 2, GROUPER_TYPE_NUMBER = 2,
GUILDER_TYPE_NUMBER = 3, GUILDER_TYPE_NUMBER = 3,
}; };
enum class GrouperType : uint8 enum class GrouperType : uint8
{ {
SOLO = 0, SOLO = 0,
MEMBER = 1, MEMBER = 1,
LEADER_2 = 2, LEADER_2 = 2,
LEADER_3 = 3, LEADER_3 = 3,
LEADER_4 = 4, LEADER_4 = 4,
LEADER_5 = 5 LEADER_5 = 5
}; };
enum class GuilderType : uint8 enum class GuilderType : uint8
{ {
SOLO = 0, SOLO = 0,
TINY = 30, TINY = 30,
SMALL = 50, SMALL = 50,
MEDIUM = 70, MEDIUM = 70,
LARGE = 120, LARGE = 120,
VERY_LARGE = 250 VERY_LARGE = 250
}; };
enum ActivityType enum ActivityType
{ {
GRIND_ACTIVITY = 1, GRIND_ACTIVITY = 1,
RPG_ACTIVITY = 2, RPG_ACTIVITY = 2,
TRAVEL_ACTIVITY = 3, TRAVEL_ACTIVITY = 3,
OUT_OF_PARTY_ACTIVITY = 4, OUT_OF_PARTY_ACTIVITY = 4,
PACKET_ACTIVITY = 5, PACKET_ACTIVITY = 5,
DETAILED_MOVE_ACTIVITY = 6, DETAILED_MOVE_ACTIVITY = 6,
PARTY_ACTIVITY = 7, PARTY_ACTIVITY = 7,
ALL_ACTIVITY = 8, ALL_ACTIVITY = 8,
MAX_ACTIVITY_TYPE MAX_ACTIVITY_TYPE
}; };
enum BotRoles : uint8 enum BotRoles : uint8
{ {
BOT_ROLE_NONE = 0x00, BOT_ROLE_NONE = 0x00,
BOT_ROLE_TANK = 0x01, BOT_ROLE_TANK = 0x01,
BOT_ROLE_HEALER = 0x02, BOT_ROLE_HEALER = 0x02,
BOT_ROLE_DPS = 0x04 BOT_ROLE_DPS = 0x04
}; };
enum HUNTER_TABS { enum HUNTER_TABS
{
HUNTER_TAB_BEASTMASTER, HUNTER_TAB_BEASTMASTER,
HUNTER_TAB_MARKSMANSHIP, HUNTER_TAB_MARKSMANSHIP,
HUNTER_TAB_SURVIVAL, HUNTER_TAB_SURVIVAL,
}; };
enum ROGUE_TABS { enum ROGUE_TABS
{
ROGUE_TAB_ASSASSINATION, ROGUE_TAB_ASSASSINATION,
ROGUE_TAB_COMBAT, ROGUE_TAB_COMBAT,
ROGUE_TAB_SUBTLETY ROGUE_TAB_SUBTLETY
}; };
enum PRIEST_TABS { enum PRIEST_TABS
{
PRIEST_TAB_DISIPLINE, PRIEST_TAB_DISIPLINE,
PRIEST_TAB_HOLY, PRIEST_TAB_HOLY,
PRIEST_TAB_SHADOW, PRIEST_TAB_SHADOW,
}; };
enum DEATHKNIGT_TABS { enum DEATHKNIGT_TABS
{
DEATHKNIGT_TAB_BLOOD, DEATHKNIGT_TAB_BLOOD,
DEATHKNIGT_TAB_FROST, DEATHKNIGT_TAB_FROST,
DEATHKNIGT_TAB_UNHOLY, DEATHKNIGT_TAB_UNHOLY,
}; };
enum DRUID_TABS { enum DRUID_TABS
{
DRUID_TAB_BALANCE, DRUID_TAB_BALANCE,
DRUID_TAB_FERAL, DRUID_TAB_FERAL,
DRUID_TAB_RESTORATION, DRUID_TAB_RESTORATION,
}; };
enum MAGE_TABS { enum MAGE_TABS
{
MAGE_TAB_ARCANE, MAGE_TAB_ARCANE,
MAGE_TAB_FIRE, MAGE_TAB_FIRE,
MAGE_TAB_FROST, MAGE_TAB_FROST,
}; };
enum SHAMAN_TABS { enum SHAMAN_TABS
{
SHAMAN_TAB_ELEMENTAL, SHAMAN_TAB_ELEMENTAL,
SHAMAN_TAB_ENHANCEMENT, SHAMAN_TAB_ENHANCEMENT,
SHAMAN_TAB_RESTORATION, SHAMAN_TAB_RESTORATION,
}; };
enum PALADIN_TABS { enum PALADIN_TABS
{
PALADIN_TAB_HOLY, PALADIN_TAB_HOLY,
PALADIN_TAB_PROTECTION, PALADIN_TAB_PROTECTION,
PALADIN_TAB_RETRIBUTION, PALADIN_TAB_RETRIBUTION,
}; };
enum WARLOCK_TABS { enum WARLOCK_TABS
{
WARLOCK_TAB_AFFLICATION, WARLOCK_TAB_AFFLICATION,
WARLOCK_TAB_DEMONOLOGY, WARLOCK_TAB_DEMONOLOGY,
WARLOCK_TAB_DESTRUCTION, WARLOCK_TAB_DESTRUCTION,
}; };
enum WARRIOR_TABS { enum WARRIOR_TABS
{
WARRIOR_TAB_ARMS, WARRIOR_TAB_ARMS,
WARRIOR_TAB_FURY, WARRIOR_TAB_FURY,
WARRIOR_TAB_PROTECTION, WARRIOR_TAB_PROTECTION,
@@ -272,215 +284,238 @@ enum WARRIOR_TABS {
class PacketHandlingHelper class PacketHandlingHelper
{ {
public: public:
void AddHandler(uint16 opcode, std::string const handler); void AddHandler(uint16 opcode, std::string const handler);
void Handle(ExternalEventHelper &helper); void Handle(ExternalEventHelper& helper);
void AddPacket(WorldPacket const& packet); void AddPacket(WorldPacket const& packet);
private: private:
std::map<uint16, std::string> handlers; std::map<uint16, std::string> handlers;
std::stack<WorldPacket> queue; std::stack<WorldPacket> queue;
}; };
class ChatCommandHolder class ChatCommandHolder
{ {
public: public:
ChatCommandHolder(std::string const command, Player* owner = nullptr, uint32 type = CHAT_MSG_WHISPER, time_t time = 0) : command(command), owner(owner), type(type), time(time) { } ChatCommandHolder(std::string const command, Player* owner = nullptr, uint32 type = CHAT_MSG_WHISPER,
ChatCommandHolder(ChatCommandHolder const& other) : command(other.command), owner(other.owner), type(other.type), time(other.time) { } time_t time = 0)
: command(command), owner(owner), type(type), time(time)
{
}
ChatCommandHolder(ChatCommandHolder const& other)
: command(other.command), owner(other.owner), type(other.type), time(other.time)
{
}
std::string const GetCommand() { return command; } std::string const GetCommand() { return command; }
Player* GetOwner() { return owner; } Player* GetOwner() { return owner; }
uint32 GetType() { return type; } uint32 GetType() { return type; }
time_t GetTime() { return time; } time_t GetTime() { return time; }
private: private:
std::string const command; std::string const command;
Player* owner; Player* owner;
uint32 type; uint32 type;
time_t time; time_t time;
}; };
class PlayerbotAI : public PlayerbotAIBase class PlayerbotAI : public PlayerbotAIBase
{ {
public: public:
PlayerbotAI(); PlayerbotAI();
PlayerbotAI(Player* bot); PlayerbotAI(Player* bot);
virtual ~PlayerbotAI(); virtual ~PlayerbotAI();
void UpdateAI(uint32 elapsed, bool minimal = false) override; void UpdateAI(uint32 elapsed, bool minimal = false) override;
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override; void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
std::string const HandleRemoteCommand(std::string const command); std::string const HandleRemoteCommand(std::string const command);
void HandleCommand(uint32 type, std::string const text, Player* fromPlayer); void HandleCommand(uint32 type, std::string const text, Player* fromPlayer);
void QueueChatResponse(uint8 msgtype, ObjectGuid guid1, ObjectGuid guid2, std::string message, std::string chanName, std::string name); void QueueChatResponse(uint8 msgtype, ObjectGuid guid1, ObjectGuid guid2, std::string message, std::string chanName,
void HandleBotOutgoingPacket(WorldPacket const& packet); std::string name);
void HandleMasterIncomingPacket(WorldPacket const& packet); void HandleBotOutgoingPacket(WorldPacket const& packet);
void HandleMasterOutgoingPacket(WorldPacket const& packet); void HandleMasterIncomingPacket(WorldPacket const& packet);
void HandleTeleportAck(); void HandleMasterOutgoingPacket(WorldPacket const& packet);
void ChangeEngine(BotState type); void HandleTeleportAck();
void DoNextAction(bool minimal = false); void ChangeEngine(BotState type);
virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false, std::string const qualifier = ""); void DoNextAction(bool minimal = false);
void ChangeStrategy(std::string const name, BotState type); virtual bool DoSpecificAction(std::string const name, Event event = Event(), bool silent = false,
void ClearStrategies(BotState type); std::string const qualifier = "");
std::vector<std::string> GetStrategies(BotState type); void ChangeStrategy(std::string const name, BotState type);
bool ContainsStrategy(StrategyType type); void ClearStrategies(BotState type);
bool HasStrategy(std::string const name, BotState type); std::vector<std::string> GetStrategies(BotState type);
BotState GetState() { return currentState; }; bool ContainsStrategy(StrategyType type);
void ResetStrategies(bool load = false); bool HasStrategy(std::string const name, BotState type);
void ReInitCurrentEngine(); BotState GetState() { return currentState; };
void Reset(bool full = false); void ResetStrategies(bool load = false);
static bool IsTank(Player* player); void ReInitCurrentEngine();
static bool IsHeal(Player* player); void Reset(bool full = false);
static bool IsDps(Player* player); static bool IsTank(Player* player);
static bool IsRanged(Player* player); static bool IsHeal(Player* player);
static bool IsMelee(Player* player); static bool IsDps(Player* player);
static bool IsCaster(Player* player); static bool IsRanged(Player* player);
static bool IsCombo(Player* player); static bool IsMelee(Player* player);
static bool IsRangedDps(Player* player); static bool IsCaster(Player* player);
static bool IsMainTank(Player* player); static bool IsCombo(Player* player);
bool IsAssistTank(Player* player); static bool IsRangedDps(Player* player);
bool IsAssistTankOfIndex(Player* player, int index); static bool IsMainTank(Player* player);
bool IsHealAssistantOfIndex(Player* player, int index); bool IsAssistTank(Player* player);
bool IsRangedDpsAssistantOfIndex(Player* player, int index); bool IsAssistTankOfIndex(Player* player, int index);
bool HasAggro(Unit* unit); bool IsHealAssistantOfIndex(Player* player, int index);
int32 GetGroupSlotIndex(Player* player); bool IsRangedDpsAssistantOfIndex(Player* player, int index);
int32 GetRangedIndex(Player* player); bool HasAggro(Unit* unit);
int32 GetClassIndex(Player* player, uint8_t cls); int32 GetGroupSlotIndex(Player* player);
int32 GetRangedDpsIndex(Player* player); int32 GetRangedIndex(Player* player);
int32 GetMeleeIndex(Player* player); int32 GetClassIndex(Player* player, uint8_t cls);
int32 GetRangedDpsIndex(Player* player);
int32 GetMeleeIndex(Player* player);
Creature* GetCreature(ObjectGuid guid); Creature* GetCreature(ObjectGuid guid);
Unit* GetUnit(ObjectGuid guid); Unit* GetUnit(ObjectGuid guid);
Player* GetPlayer(ObjectGuid guid); Player* GetPlayer(ObjectGuid guid);
static Unit* GetUnit(CreatureData const* creatureData); static Unit* GetUnit(CreatureData const* creatureData);
GameObject* GetGameObject(ObjectGuid guid); GameObject* GetGameObject(ObjectGuid guid);
// static GameObject* GetGameObject(GameObjectData const* gameObjectData); // static GameObject* GetGameObject(GameObjectData const* gameObjectData);
WorldObject* GetWorldObject(ObjectGuid guid); WorldObject* GetWorldObject(ObjectGuid guid);
bool TellMaster(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); bool TellMaster(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
bool TellMaster(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); bool TellMaster(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
bool TellMasterNoFacing(std::ostringstream& stream, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); bool TellMasterNoFacing(std::ostringstream& stream,
bool TellMasterNoFacing(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
bool TellError(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); bool TellMasterNoFacing(std::string const text,
void SpellInterrupted(uint32 spellid); PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
int32 CalculateGlobalCooldown(uint32 spellid); bool TellError(std::string const text, PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
void InterruptSpell(); void SpellInterrupted(uint32 spellid);
void RemoveAura(std::string const name); int32 CalculateGlobalCooldown(uint32 spellid);
void RemoveShapeshift(); void InterruptSpell();
void WaitForSpellCast(Spell* spell); void RemoveAura(std::string const name);
bool PlaySound(uint32 emote); void RemoveShapeshift();
bool PlayEmote(uint32 emote); void WaitForSpellCast(Spell* spell);
void Ping(float x, float y); bool PlaySound(uint32 emote);
Item* FindPoison() const; bool PlayEmote(uint32 emote);
Item* FindBandage() const; void Ping(float x, float y);
Item* FindConsumable(uint32 displayId) const; Item* FindPoison() const;
Item* FindStoneFor(Item* weapon) const; Item* FindBandage() const;
Item* FindOilFor(Item* weapon) const; Item* FindConsumable(uint32 displayId) const;
void ImbueItem(Item* item, uint32 targetFlag, ObjectGuid targetGUID); Item* FindStoneFor(Item* weapon) const;
void ImbueItem(Item* item, uint8 targetInventorySlot); Item* FindOilFor(Item* weapon) const;
void ImbueItem(Item* item, Unit* target); void ImbueItem(Item* item, uint32 targetFlag, ObjectGuid targetGUID);
void ImbueItem(Item* item); void ImbueItem(Item* item, uint8 targetInventorySlot);
void EnchantItemT(uint32 spellid, uint8 slot); void ImbueItem(Item* item, Unit* target);
uint32 GetBuffedCount(Player* player, std::string const spellname); void ImbueItem(Item* item);
void EnchantItemT(uint32 spellid, uint8 slot);
uint32 GetBuffedCount(Player* player, std::string const spellname);
virtual bool CanCastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); virtual bool CanCastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr);
virtual bool CastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr); virtual bool CastSpell(std::string const name, Unit* target, Item* itemTarget = nullptr);
virtual bool HasAura(std::string const spellName, Unit* player, bool maxStack = false, bool checkIsOwner = false, int maxAmount = -1, bool checkDuration = false); virtual bool HasAura(std::string const spellName, Unit* player, bool maxStack = false, bool checkIsOwner = false,
virtual bool HasAnyAuraOf(Unit* player, ...); int maxAmount = -1, bool checkDuration = false);
virtual bool HasAnyAuraOf(Unit* player, ...);
virtual bool IsInterruptableSpellCasting(Unit* player, std::string const spell); virtual bool IsInterruptableSpellCasting(Unit* player, std::string const spell);
virtual bool HasAuraToDispel(Unit* player, uint32 dispelType); virtual bool HasAuraToDispel(Unit* player, uint32 dispelType);
bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr, Item* castItem = nullptr); bool CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell = true, Item* itemTarget = nullptr,
bool CanCastSpell(uint32 spellid, GameObject* goTarget, uint8 effectMask, bool checkHasSpell = true); Item* castItem = nullptr);
bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true, Item* itemTarget = nullptr); bool CanCastSpell(uint32 spellid, GameObject* goTarget, uint8 effectMask, bool checkHasSpell = true);
bool CanCastSpell(uint32 spellid, float x, float y, float z, uint8 effectMask, bool checkHasSpell = true,
Item* itemTarget = nullptr);
bool HasAura(uint32 spellId, Unit const* player); bool HasAura(uint32 spellId, Unit const* player);
Aura* GetAura(std::string const spellName, Unit* unit, bool checkIsOwner = false, bool checkDuration = false, int checkStack = -1); Aura* GetAura(std::string const spellName, Unit* unit, bool checkIsOwner = false, bool checkDuration = false,
bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = nullptr); int checkStack = -1);
bool CastSpell(uint32 spellId, float x, float y, float z, Item* itemTarget = nullptr); bool CastSpell(uint32 spellId, Unit* target, Item* itemTarget = nullptr);
bool canDispel(SpellInfo const* spellInfo, uint32 dispelType); bool CastSpell(uint32 spellId, float x, float y, float z, Item* itemTarget = nullptr);
bool canDispel(SpellInfo const* spellInfo, uint32 dispelType);
bool CanCastVehicleSpell(uint32 spellid, Unit* target); bool CanCastVehicleSpell(uint32 spellid, Unit* target);
bool CastVehicleSpell(uint32 spellId, Unit* target); bool CastVehicleSpell(uint32 spellId, Unit* target);
bool CastVehicleSpell(uint32 spellId, float x, float y, float z); bool CastVehicleSpell(uint32 spellId, float x, float y, float z);
bool IsInVehicle(bool canControl = false, bool canCast = false, bool canAttack = false, bool canTurn = false, bool fixed = false); bool IsInVehicle(bool canControl = false, bool canCast = false, bool canAttack = false, bool canTurn = false,
bool fixed = false);
uint32 GetEquipGearScore(Player* player, bool withBags, bool withBank); uint32 GetEquipGearScore(Player* player, bool withBags, bool withBank);
static uint32 GetMixedGearScore(Player* player, bool withBags, bool withBank, uint32 topN = 0); static uint32 GetMixedGearScore(Player* player, bool withBags, bool withBank, uint32 topN = 0);
bool HasSkill(SkillType skill); bool HasSkill(SkillType skill);
bool IsAllowedCommand(std::string const text); bool IsAllowedCommand(std::string const text);
float GetRange(std::string const type); float GetRange(std::string const type);
Player* GetBot() { return bot; } Player* GetBot() { return bot; }
Player* GetMaster() { return master; } Player* GetMaster() { return master; }
//Checks if the bot is really a player. Players always have themselves as master. // Checks if the bot is really a player. Players always have themselves as master.
bool IsRealPlayer() { return master ? (master == bot) : false; } bool IsRealPlayer() { return master ? (master == bot) : false; }
//Bot has a master that is a player. // Bot has a master that is a player.
bool HasRealPlayerMaster(); bool HasRealPlayerMaster();
//Bot has a master that is activly playing. // Bot has a master that is activly playing.
bool HasActivePlayerMaster(); bool HasActivePlayerMaster();
//Get the group leader or the master of the bot. // Get the group leader or the master of the bot.
//Checks if the bot is summoned as alt of a player // Checks if the bot is summoned as alt of a player
bool IsAlt(); bool IsAlt();
Player* GetGroupMaster(); Player* GetGroupMaster();
//Returns a semi-random (cycling) number that is fixed for each bot. // Returns a semi-random (cycling) number that is fixed for each bot.
uint32 GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum = 100, float cyclePerMin = 1); uint32 GetFixedBotNumer(BotTypeNumber typeNumber, uint32 maxNum = 100, float cyclePerMin = 1);
GrouperType GetGrouperType(); GrouperType GetGrouperType();
GuilderType GetGuilderType(); GuilderType GetGuilderType();
bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance); bool HasPlayerNearby(WorldPosition* pos, float range = sPlayerbotAIConfig->reactDistance);
bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance); bool HasPlayerNearby(float range = sPlayerbotAIConfig->reactDistance);
bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance); bool HasManyPlayersNearby(uint32 trigerrValue = 20, float range = sPlayerbotAIConfig->sightDistance);
bool AllowActive(ActivityType activityType); bool AllowActive(ActivityType activityType);
bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false); bool AllowActivity(ActivityType activityType = ALL_ACTIVITY, bool checkNow = false);
bool HasCheat(BotCheatMask mask) { return ((uint32)mask & (uint32)cheatMask) != 0 || ((uint32)mask & (uint32)sPlayerbotAIConfig->botCheatMask) != 0; } bool HasCheat(BotCheatMask mask)
BotCheatMask GetCheat() { return cheatMask; } {
void SetCheat(BotCheatMask mask) { cheatMask = mask; } return ((uint32)mask & (uint32)cheatMask) != 0 ||
((uint32)mask & (uint32)sPlayerbotAIConfig->botCheatMask) != 0;
}
BotCheatMask GetCheat() { return cheatMask; }
void SetCheat(BotCheatMask mask) { cheatMask = mask; }
void SetMaster(Player* newMaster) { master = newMaster; } void SetMaster(Player* newMaster) { master = newMaster; }
AiObjectContext* GetAiObjectContext() { return aiObjectContext; } AiObjectContext* GetAiObjectContext() { return aiObjectContext; }
ChatHelper* GetChatHelper() { return &chatHelper; } ChatHelper* GetChatHelper() { return &chatHelper; }
bool IsOpposing(Player* player); bool IsOpposing(Player* player);
static bool IsOpposing(uint8 race1, uint8 race2); static bool IsOpposing(uint8 race1, uint8 race2);
PlayerbotSecurity* GetSecurity() { return &security; } PlayerbotSecurity* GetSecurity() { return &security; }
Position GetJumpDestination() { return jumpDestination; } Position GetJumpDestination() { return jumpDestination; }
void SetJumpDestination(Position pos) { jumpDestination = pos; } void SetJumpDestination(Position pos) { jumpDestination = pos; }
void ResetJumpDestination() { jumpDestination = Position(); } void ResetJumpDestination() { jumpDestination = Position(); }
bool CanMove(); bool CanMove();
bool IsInRealGuild(); bool IsInRealGuild();
static std::vector<std::string> dispel_whitelist; static std::vector<std::string> dispel_whitelist;
bool EqualLowercaseName(std::string s1, std::string s2); bool EqualLowercaseName(std::string s1, std::string s2);
InventoryResult CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading = true) const; InventoryResult CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool swap, bool not_loading = true) const;
uint8 FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const; uint8 FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const;
private:
static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore, bool mixed = false); private:
bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL); static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore,
protected: bool mixed = false);
Player* bot; bool IsTellAllowed(PlayerbotSecurityLevel securityLevel = PLAYERBOT_SECURITY_ALLOW_ALL);
Player* master;
uint32 accountId; protected:
AiObjectContext* aiObjectContext; Player* bot;
Engine* currentEngine; Player* master;
Engine* engines[BOT_STATE_MAX]; uint32 accountId;
BotState currentState; AiObjectContext* aiObjectContext;
ChatHelper chatHelper; Engine* currentEngine;
std::queue<ChatCommandHolder> chatCommands; Engine* engines[BOT_STATE_MAX];
std::queue<ChatQueuedReply> chatReplies; BotState currentState;
PacketHandlingHelper botOutgoingPacketHandlers; ChatHelper chatHelper;
PacketHandlingHelper masterIncomingPacketHandlers; std::queue<ChatCommandHolder> chatCommands;
PacketHandlingHelper masterOutgoingPacketHandlers; std::queue<ChatQueuedReply> chatReplies;
CompositeChatFilter chatFilter; PacketHandlingHelper botOutgoingPacketHandlers;
PlayerbotSecurity security; PacketHandlingHelper masterIncomingPacketHandlers;
std::map<std::string, time_t> whispers; PacketHandlingHelper masterOutgoingPacketHandlers;
std::pair<ChatMsg, time_t> currentChat; CompositeChatFilter chatFilter;
static std::set<std::string> unsecuredCommands; PlayerbotSecurity security;
bool allowActive[MAX_ACTIVITY_TYPE]; std::map<std::string, time_t> whispers;
time_t allowActiveCheckTimer[MAX_ACTIVITY_TYPE]; std::pair<ChatMsg, time_t> currentChat;
bool inCombat = false; static std::set<std::string> unsecuredCommands;
BotCheatMask cheatMask = BotCheatMask::none; bool allowActive[MAX_ACTIVITY_TYPE];
Position jumpDestination = Position(); time_t allowActiveCheckTimer[MAX_ACTIVITY_TYPE];
bool inCombat = false;
BotCheatMask cheatMask = BotCheatMask::none;
Position jumpDestination = Position();
}; };
#endif #endif

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_PLAYERbotAIAWARE_H #ifndef _PLAYERBOT_PLAYERbotAIAWARE_H
@@ -9,11 +10,11 @@ class PlayerbotAI;
class PlayerbotAIAware class PlayerbotAIAware
{ {
public: public:
PlayerbotAIAware(PlayerbotAI* botAI) : botAI(botAI) { } PlayerbotAIAware(PlayerbotAI* botAI) : botAI(botAI) {}
protected: protected:
PlayerbotAI* botAI; PlayerbotAI* botAI;
}; };
#endif #endif

View File

@@ -1,13 +1,13 @@
/* /*
* 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. * 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 "PlayerbotAIBase.h" #include "PlayerbotAIBase.h"
#include "Playerbots.h" #include "Playerbots.h"
PlayerbotAIBase::PlayerbotAIBase(bool isBotAI) : nextAICheckDelay(0), _isBotAI(isBotAI) PlayerbotAIBase::PlayerbotAIBase(bool isBotAI) : nextAICheckDelay(0), _isBotAI(isBotAI) {}
{
}
void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal) void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal)
{ {
@@ -26,12 +26,12 @@ void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal)
void PlayerbotAIBase::SetNextCheckDelay(uint32 const delay) void PlayerbotAIBase::SetNextCheckDelay(uint32 const delay)
{ {
// if (nextAICheckDelay < delay) // if (nextAICheckDelay < delay)
// LOG_DEBUG("playerbots", "Setting lesser delay {} -> {}", nextAICheckDelay, delay); // LOG_DEBUG("playerbots", "Setting lesser delay {} -> {}", nextAICheckDelay, delay);
nextAICheckDelay = delay; nextAICheckDelay = delay;
// if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown) // if (nextAICheckDelay > sPlayerbotAIConfig->globalCoolDown)
// LOG_DEBUG("playerbots", "std::set next check delay: {}", nextAICheckDelay); // LOG_DEBUG("playerbots", "std::set next check delay: {}", nextAICheckDelay);
} }
void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay) void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay)
@@ -42,10 +42,7 @@ void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay)
// LOG_DEBUG("playerbots", "increase next check delay: {}", nextAICheckDelay); // LOG_DEBUG("playerbots", "increase next check delay: {}", nextAICheckDelay);
} }
bool PlayerbotAIBase::CanUpdateAI() bool PlayerbotAIBase::CanUpdateAI() { return nextAICheckDelay == 0; }
{
return nextAICheckDelay == 0;
}
void PlayerbotAIBase::YieldThread(bool delay) void PlayerbotAIBase::YieldThread(bool delay)
{ {
@@ -53,12 +50,6 @@ void PlayerbotAIBase::YieldThread(bool delay)
nextAICheckDelay = delay ? sPlayerbotAIConfig->reactDelay * 10 : sPlayerbotAIConfig->reactDelay; nextAICheckDelay = delay ? sPlayerbotAIConfig->reactDelay * 10 : sPlayerbotAIConfig->reactDelay;
} }
bool PlayerbotAIBase::IsActive() bool PlayerbotAIBase::IsActive() { return nextAICheckDelay < sPlayerbotAIConfig->maxWaitForMove; }
{
return nextAICheckDelay < sPlayerbotAIConfig->maxWaitForMove;
}
bool PlayerbotAIBase::IsBotAI() const bool PlayerbotAIBase::IsBotAI() const { return _isBotAI; }
{
return _isBotAI;
}

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_PLAYERBOTAIBASE_H #ifndef _PLAYERBOT_PLAYERBOTAIBASE_H
@@ -9,23 +10,23 @@
class PlayerbotAIBase class PlayerbotAIBase
{ {
public: public:
PlayerbotAIBase(bool isBotAI); PlayerbotAIBase(bool isBotAI);
bool CanUpdateAI(); bool CanUpdateAI();
void SetNextCheckDelay(uint32 const delay); void SetNextCheckDelay(uint32 const delay);
void IncreaseNextCheckDelay(uint32 delay); void IncreaseNextCheckDelay(uint32 delay);
void YieldThread(bool delay = false); void YieldThread(bool delay = false);
virtual void UpdateAI(uint32 elapsed, bool minimal = false); virtual void UpdateAI(uint32 elapsed, bool minimal = false);
virtual void UpdateAIInternal(uint32 elapsed, bool minimal = false) = 0; virtual void UpdateAIInternal(uint32 elapsed, bool minimal = false) = 0;
bool IsActive(); bool IsActive();
bool IsBotAI() const; bool IsBotAI() const;
protected: protected:
uint32 nextAICheckDelay; uint32 nextAICheckDelay;
private: private:
bool _isBotAI; bool _isBotAI;
}; };
#endif #endif

View File

@@ -1,17 +1,19 @@
/* /*
* 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. * 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 "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include <iostream>
#include "Config.h" #include "Config.h"
#include "Playerbots.h" #include "PlayerbotDungeonSuggestionMgr.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "RandomItemMgr.h" #include "RandomItemMgr.h"
#include "RandomPlayerbotFactory.h" #include "RandomPlayerbotFactory.h"
#include "Talentspec.h" #include "Talentspec.h"
#include "PlayerbotDungeonSuggestionMgr.h"
#include <iostream>
template <class T> template <class T>
void LoadList(std::string const value, T& list) void LoadList(std::string const value, T& list)
@@ -110,49 +112,71 @@ bool PlayerbotAIConfig::Initialize()
randomBotMapsAsString = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotMaps", "0,1,530,571"); randomBotMapsAsString = sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotMaps", "0,1,530,571");
LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps); LoadList<std::vector<uint32>>(randomBotMapsAsString, randomBotMaps);
probTeleToBankers = sConfigMgr->GetOption<float>("AiPlayerbot.ProbTeleToBankers", 0.25f); probTeleToBankers = sConfigMgr->GetOption<float>("AiPlayerbot.ProbTeleToBankers", 0.25f);
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestItems", "6948,5175,5176,5177,5178,16309,12382,13704,11000"), randomBotQuestItems); LoadList<std::vector<uint32>>(
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotSpellIds", "54197"), randomBotSpellIds); sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestItems",
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("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"), pvpProhibitedZoneIds); "6948,5175,5176,5177,5178,16309,12382,13704,11000"),
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.PvpProhibitedAreaIds", "976,35"), pvpProhibitedAreaIds); randomBotQuestItems);
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotSpellIds", "54197"),
randomBotSpellIds);
LoadList<std::vector<uint32>>(
sConfigMgr->GetOption<std::string>("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"),
pvpProhibitedZoneIds);
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.PvpProhibitedAreaIds", "976,35"),
pvpProhibitedAreaIds);
LoadList<std::vector<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761"), randomBotQuestIds); LoadList<std::vector<uint32>>(
sConfigMgr->GetOption<std::string>("AiPlayerbot.RandomBotQuestIds", "7848,3802,5505,6502,7761"),
randomBotQuestIds);
botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false); botAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.BotAutologin", false);
randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true); randomBotAutologin = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutologin", true);
minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50); minRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBots", 50);
maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200); maxRandomBots = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBots", 200);
randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", MINUTE); randomBotUpdateInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotUpdateInterval", MINUTE);
randomBotCountChangeMinInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE); randomBotCountChangeMinInterval =
randomBotCountChangeMaxInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMaxInterval", 2 * HOUR); sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMinInterval", 30 * MINUTE);
randomBotCountChangeMaxInterval =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotCountChangeMaxInterval", 2 * HOUR);
minRandomBotInWorldTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotInWorldTime", 2 * HOUR); minRandomBotInWorldTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotInWorldTime", 2 * HOUR);
maxRandomBotInWorldTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotInWorldTime", 12 * HOUR); maxRandomBotInWorldTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotInWorldTime", 12 * HOUR);
minRandomBotRandomizeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotRandomizeTime", 2 * HOUR); minRandomBotRandomizeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotRandomizeTime", 2 * HOUR);
maxRandomBotRandomizeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotRandomizeTime", 14 * 24 * HOUR); maxRandomBotRandomizeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotRandomizeTime", 14 * 24 * HOUR);
minRandomBotChangeStrategyTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotChangeStrategyTime", 30 * MINUTE); minRandomBotChangeStrategyTime =
maxRandomBotChangeStrategyTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotChangeStrategyTime", 2 * HOUR); sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotChangeStrategyTime", 30 * MINUTE);
maxRandomBotChangeStrategyTime =
sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotChangeStrategyTime", 2 * HOUR);
minRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotReviveTime", MINUTE); minRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotReviveTime", MINUTE);
maxRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE); maxRandomBotReviveTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotReviveTime", 5 * MINUTE);
minRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR); minRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotTeleportInterval", 1 * HOUR);
maxRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR); maxRandomBotTeleportInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotTeleportInterval", 5 * HOUR);
randomBotInWorldWithRotationDisabled = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotInWorldWithRotationDisabled", 1 * YEAR); randomBotInWorldWithRotationDisabled =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotInWorldWithRotationDisabled", 1 * YEAR);
randomBotTeleportDistance = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleportDistance", 100); randomBotTeleportDistance = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotTeleportDistance", 100);
randomBotsPerInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotsPerInterval", MINUTE); randomBotsPerInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotsPerInterval", MINUTE);
minRandomBotsPriceChangeInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR); minRandomBotsPriceChangeInterval =
maxRandomBotsPriceChangeInterval = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR); sConfigMgr->GetOption<int32>("AiPlayerbot.MinRandomBotsPriceChangeInterval", 2 * HOUR);
maxRandomBotsPriceChangeInterval =
sConfigMgr->GetOption<int32>("AiPlayerbot.MaxRandomBotsPriceChangeInterval", 48 * HOUR);
randomBotJoinLfg = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotJoinLfg", true); randomBotJoinLfg = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotJoinLfg", true);
randomBotTalk = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotTalk", false); randomBotTalk = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotTalk", false);
randomBotEmote = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotEmote", false); randomBotEmote = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotEmote", false);
randomBotSuggestDungeons = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotSuggestDungeons", true); randomBotSuggestDungeons = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotSuggestDungeons", true);
randomBotGuildTalk = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGuildTalk", false); randomBotGuildTalk = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotGuildTalk", false);
suggestDungeonsInLowerCaseRandomly = sConfigMgr->GetOption<bool>("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false); suggestDungeonsInLowerCaseRandomly =
sConfigMgr->GetOption<bool>("AiPlayerbot.SuggestDungeonsInLowerCaseRandomly", false);
randomBotJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotJoinBG", true); randomBotJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotJoinBG", true);
randomBotAutoJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutoJoinBG", false); randomBotAutoJoinBG = sConfigMgr->GetOption<bool>("AiPlayerbot.RandomBotAutoJoinBG", false);
randomBotAutoJoinWarsongBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinWarsongBracket", 14); randomBotAutoJoinWarsongBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinWarsongBracket", 14);
randomBotAutoJoinArenaBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7); randomBotAutoJoinArenaBracket = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinArenaBracket", 7);
randomBotAutoJoinBGWarsongCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGWarsongCount", 0); randomBotAutoJoinBGWarsongCount = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGWarsongCount", 0);
randomBotAutoJoinBGRatedArena2v2Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count", 0); randomBotAutoJoinBGRatedArena2v2Count =
randomBotAutoJoinBGRatedArena3v3Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena3v3Count", 0); sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena2v2Count", 0);
randomBotAutoJoinBGRatedArena5v5Count = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena5v5Count", 0); randomBotAutoJoinBGRatedArena3v3Count =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena3v3Count", 0);
randomBotAutoJoinBGRatedArena5v5Count =
sConfigMgr->GetOption<int32>("AiPlayerbot.RandomBotAutoJoinBGRatedArena5v5Count", 0);
logInGroupOnly = sConfigMgr->GetOption<bool>("AiPlayerbot.LogInGroupOnly", true); logInGroupOnly = sConfigMgr->GetOption<bool>("AiPlayerbot.LogInGroupOnly", true);
logValuesPerTick = sConfigMgr->GetOption<bool>("AiPlayerbot.LogValuesPerTick", false); logValuesPerTick = sConfigMgr->GetOption<bool>("AiPlayerbot.LogValuesPerTick", false);
fleeingEnabled = sConfigMgr->GetOption<bool>("AiPlayerbot.FleeingEnabled", true); fleeingEnabled = sConfigMgr->GetOption<bool>("AiPlayerbot.FleeingEnabled", true);
@@ -183,7 +207,8 @@ bool PlayerbotAIConfig::Initialize()
for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) for (uint32 cls = 1; cls < MAX_CLASSES; ++cls)
{ {
if (cls == 10) { if (cls == 10)
{
continue; continue;
} }
for (uint32 spec = 0; spec < MAX_SPECNO; ++spec) for (uint32 spec = 0; spec < MAX_SPECNO; ++spec)
@@ -196,12 +221,15 @@ bool PlayerbotAIConfig::Initialize()
os << "AiPlayerbot.PremadeSpecGlyph." << cls << "." << spec; os << "AiPlayerbot.PremadeSpecGlyph." << cls << "." << spec;
premadeSpecGlyph[cls][spec] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false); premadeSpecGlyph[cls][spec] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false);
std::vector<std::string> splitSpecGlyph = split(premadeSpecGlyph[cls][spec], ','); std::vector<std::string> splitSpecGlyph = split(premadeSpecGlyph[cls][spec], ',');
for (std::string &split : splitSpecGlyph) { for (std::string& split : splitSpecGlyph)
if (split.size() != 0) { {
if (split.size() != 0)
{
parsedSpecGlyph[cls][spec].push_back(atoi(split.c_str())); parsedSpecGlyph[cls][spec].push_back(atoi(split.c_str()));
} }
} }
for (uint32 level = 0; level < MAX_LEVEL; ++level) { for (uint32 level = 0; level < MAX_LEVEL; ++level)
{
std::ostringstream os; std::ostringstream os;
os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level; os << "AiPlayerbot.PremadeSpecLink." << cls << "." << spec << "." << level;
premadeSpecLink[cls][spec][level] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false); premadeSpecLink[cls][spec][level] = sConfigMgr->GetOption<std::string>(os.str().c_str(), "", false);
@@ -221,7 +249,8 @@ bool PlayerbotAIConfig::Initialize()
} }
botCheats.clear(); botCheats.clear();
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi"), botCheats); LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi"),
botCheats);
botCheatMask = 0; botCheatMask = 0;
@@ -236,7 +265,8 @@ bool PlayerbotAIConfig::Initialize()
if (std::find(botCheats.begin(), botCheats.end(), "power") != botCheats.end()) if (std::find(botCheats.begin(), botCheats.end(), "power") != botCheats.end())
botCheatMask |= (uint32)BotCheatMask::power; botCheatMask |= (uint32)BotCheatMask::power;
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AllowedLogFiles", ""), allowedLogFiles); LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AllowedLogFiles", ""),
allowedLogFiles);
worldBuffs.clear(); worldBuffs.clear();
@@ -264,7 +294,8 @@ bool PlayerbotAIConfig::Initialize()
minGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600); minGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskChangeTime", 3 * 24 * 3600);
maxGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600); maxGuildTaskChangeTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskChangeTime", 4 * 24 * 3600);
minGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskAdvertisementTime", 300); minGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskAdvertisementTime", 300);
maxGuildTaskAdvertisementTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600); maxGuildTaskAdvertisementTime =
sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskAdvertisementTime", 12 * 3600);
minGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskRewardTime", 300); minGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MinGuildTaskRewardTime", 300);
maxGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskRewardTime", 3600); maxGuildTaskRewardTime = sConfigMgr->GetOption<int32>("AiPlayerbot.MaxGuildTaskRewardTime", 3600);
guildTaskAdvertCleanupTime = sConfigMgr->GetOption<int32>("AiPlayerbot.GuildTaskAdvertCleanupTime", 300); guildTaskAdvertCleanupTime = sConfigMgr->GetOption<int32>("AiPlayerbot.GuildTaskAdvertCleanupTime", 300);
@@ -352,7 +383,8 @@ bool PlayerbotAIConfig::Initialize()
selfBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.SelfBotLevel", 1); selfBotLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.SelfBotLevel", 1);
RandomPlayerbotFactory::CreateRandomBots(); RandomPlayerbotFactory::CreateRandomBots();
if (World::IsStopped()) { if (World::IsStopped())
{
return true; return true;
} }
PlayerbotFactory::Init(); PlayerbotFactory::Init();
@@ -418,7 +450,8 @@ std::string const PlayerbotAIConfig::GetTimestampStr()
// MM minutes (2 digits 00-59) // MM minutes (2 digits 00-59)
// SS seconds (2 digits 00-59) // SS seconds (2 digits 00-59)
char buf[20]; char buf[20];
snprintf(buf, 20, "%04d-%02d-%02d %02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); snprintf(buf, 20, "%04d-%02d-%02d %02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour,
aTm->tm_min, aTm->tm_sec);
return std::string(buf); return std::string(buf);
} }
@@ -437,7 +470,7 @@ bool PlayerbotAIConfig::openLog(std::string const fileName, char const* mode)
FILE* file = logFileIt->second.first; FILE* file = logFileIt->second.first;
bool fileOpen = logFileIt->second.second; bool fileOpen = logFileIt->second.second;
if (fileOpen) //close log file if (fileOpen) // close log file
fclose(file); fclose(file);
std::string m_logsDir = sConfigMgr->GetOption<std::string>("LogsDir", "", false); std::string m_logsDir = sConfigMgr->GetOption<std::string>("LogsDir", "", false);
@@ -447,7 +480,6 @@ bool PlayerbotAIConfig::openLog(std::string const fileName, char const* mode)
m_logsDir.append("/"); m_logsDir.append("/");
} }
file = fopen((m_logsDir + fileName).c_str(), mode); file = fopen((m_logsDir + fileName).c_str(), mode);
fileOpen = true; fileOpen = true;
@@ -490,7 +522,7 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs) for (auto buff : buffs)
{ {
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 }; worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb); worldBuffs.push_back(wb);
} }
@@ -503,7 +535,7 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs) for (auto buff : buffs)
{ {
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 }; worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb); worldBuffs.push_back(wb);
} }
} }
@@ -517,7 +549,7 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs) for (auto buff : buffs)
{ {
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 }; worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb); worldBuffs.push_back(wb);
} }
} }
@@ -531,7 +563,7 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs) for (auto buff : buffs)
{ {
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 }; worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb); worldBuffs.push_back(wb);
} }
} }
@@ -545,34 +577,35 @@ void PlayerbotAIConfig::loadWorldBuf(uint32 factionId1, uint32 classId1, uint32
for (auto buff : buffs) for (auto buff : buffs)
{ {
worldBuff wb = { buff, factionId1, classId1, minLevel1, maxLevel1 }; worldBuff wb = {buff, factionId1, classId1, minLevel1, maxLevel1};
worldBuffs.push_back(wb); worldBuffs.push_back(wb);
} }
} }
} }
static std::vector<std::string> split(const std::string &str, const std::string &pattern) static std::vector<std::string> split(const std::string& str, const std::string& pattern)
{ {
std::vector<std::string> res; std::vector<std::string> res;
if(str == "") if (str == "")
return res; return res;
// Also add separators to string connections to facilitate intercepting the last paragraph. // Also add separators to string connections to facilitate intercepting the last paragraph.
std::string strs = str + pattern; std::string strs = str + pattern;
size_t pos = strs.find(pattern); size_t pos = strs.find(pattern);
while(pos != strs.npos) while (pos != strs.npos)
{ {
std::string temp = strs.substr(0, pos); std::string temp = strs.substr(0, pos);
res.push_back(temp); res.push_back(temp);
// Remove the split string and split the remaining string // Remove the split string and split the remaining string
strs = strs.substr(pos+1, strs.size()); strs = strs.substr(pos + 1, strs.size());
pos = strs.find(pattern); pos = strs.find(pattern);
} }
return res; return res;
} }
std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 cls, std::string tab_link) { std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32 cls, std::string tab_link)
{
// check bad link // check bad link
uint32 classMask = 1 << (cls - 1); uint32 classMask = 1 << (cls - 1);
std::vector<std::vector<uint32>> res; std::vector<std::vector<uint32>> res;
@@ -581,40 +614,44 @@ std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempTalentsOrder(uint32
std::vector<std::vector<std::vector<uint32>>> orders(3); std::vector<std::vector<std::vector<uint32>>> orders(3);
for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
{ {
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
if(!talentInfo) if (!talentInfo)
continue; continue;
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
if(!talentTabInfo) if (!talentTabInfo)
continue; continue;
if( (classMask & talentTabInfo->ClassMask) == 0 ) if ((classMask & talentTabInfo->ClassMask) == 0)
continue; continue;
spells[talentTabInfo->tabpage].push_back(talentInfo); spells[talentTabInfo->tabpage].push_back(talentInfo);
} }
for (int tab = 0; tab < 3; tab++) { for (int tab = 0; tab < 3; tab++)
if (tab_links.size() <= tab) { {
if (tab_links.size() <= tab)
{
break; break;
} }
std::sort(spells[tab].begin(), spells[tab].end(), [&](TalentEntry const* lhs, TalentEntry const* rhs) { std::sort(spells[tab].begin(), spells[tab].end(),
return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; [&](TalentEntry const* lhs, TalentEntry const* rhs)
}); { return lhs->Row != rhs->Row ? lhs->Row < rhs->Row : lhs->Col < rhs->Col; });
for (int i = 0; i < tab_links[tab].size(); i++) { for (int i = 0; i < tab_links[tab].size(); i++)
if (i >= spells[tab].size()) { {
if (i >= spells[tab].size())
{
break; break;
} }
int lvl = tab_links[tab][i] - '0'; int lvl = tab_links[tab][i] - '0';
if (lvl == 0) continue; if (lvl == 0)
continue;
orders[tab].push_back({(uint32)tab, spells[tab][i]->Row, spells[tab][i]->Col, (uint32)lvl}); orders[tab].push_back({(uint32)tab, spells[tab][i]->Row, spells[tab][i]->Col, (uint32)lvl});
} }
} }
// sort by talent tab size // sort by talent tab size
std::sort(orders.begin(), orders.end(), [&](auto &lhs, auto &rhs) { std::sort(orders.begin(), orders.end(), [&](auto& lhs, auto& rhs) { return lhs.size() > rhs.size(); });
return lhs.size() > rhs.size(); for (auto& order : orders)
}); {
for (auto &order : orders) {
res.insert(res.end(), order.begin(), order.end()); res.insert(res.end(), order.begin(), order.end());
} }
return res; return res;

View File

@@ -1,256 +1,262 @@
/* /*
* 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. * 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_PLAYERbotAICONFIG_H #ifndef _PLAYERBOT_PLAYERbotAICONFIG_H
#define _PLAYERBOT_PLAYERbotAICONFIG_H #define _PLAYERBOT_PLAYERbotAICONFIG_H
#include <mutex>
#include "Common.h" #include "Common.h"
#include "DBCEnums.h" #include "DBCEnums.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "Talentspec.h" #include "Talentspec.h"
#include <mutex>
enum class BotCheatMask : uint32 enum class BotCheatMask : uint32
{ {
none = 0, none = 0,
taxi = 1, taxi = 1,
gold = 2, gold = 2,
health = 4, health = 4,
mana = 8, mana = 8,
power = 16, power = 16,
maxMask = 32 maxMask = 32
}; };
enum class HealingManaEfficiency : uint8 enum class HealingManaEfficiency : uint8
{ {
VERY_LOW = 1, VERY_LOW = 1,
LOW = 2, LOW = 2,
MEDIUM = 4, MEDIUM = 4,
HIGH = 8, HIGH = 8,
VERY_HIGH = 16, VERY_HIGH = 16,
SUPERIOR = 32 SUPERIOR = 32
}; };
#define MAX_SPECNO 20 #define MAX_SPECNO 20
class PlayerbotAIConfig class PlayerbotAIConfig
{ {
public: public:
PlayerbotAIConfig() { }; PlayerbotAIConfig(){};
static PlayerbotAIConfig* instance() static PlayerbotAIConfig* instance()
{ {
static PlayerbotAIConfig instance; static PlayerbotAIConfig instance;
return &instance; return &instance;
} }
bool Initialize(); bool Initialize();
bool IsInRandomAccountList(uint32 id); bool IsInRandomAccountList(uint32 id);
bool IsInRandomQuestItemList(uint32 id); bool IsInRandomQuestItemList(uint32 id);
bool IsPvpProhibited(uint32 zoneId, uint32 areaId); bool IsPvpProhibited(uint32 zoneId, uint32 areaId);
bool IsInPvpProhibitedZone(uint32 id); bool IsInPvpProhibitedZone(uint32 id);
bool IsInPvpProhibitedArea(uint32 id); bool IsInPvpProhibitedArea(uint32 id);
bool enabled; bool enabled;
bool allowGuildBots, allowPlayerBots; bool allowGuildBots, allowPlayerBots;
uint32 globalCoolDown, reactDelay, maxWaitForMove, disableMoveSplinePath, maxMovementSearchTime, uint32 globalCoolDown, reactDelay, maxWaitForMove, disableMoveSplinePath, maxMovementSearchTime, expireActionTime,
expireActionTime, dispelAuraDuration, passiveDelay, repeatDelay, dispelAuraDuration, passiveDelay, repeatDelay, errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay;
errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay; float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance, fleeDistance,
float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, aoeRadius, rpgDistance,
fleeDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, targetPosRecalcDistance, farDistance, healDistance, aggroDistance;
aoeRadius, rpgDistance, targetPosRecalcDistance, farDistance, healDistance, aggroDistance; uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth;
uint32 criticalHealth, lowHealth, mediumHealth, almostFullHealth; uint32 lowMana, mediumMana;
uint32 lowMana, mediumMana; bool autoSaveMana;
bool autoSaveMana; uint32 saveManaThreshold;
uint32 saveManaThreshold; bool autoAvoidAoe;
bool autoAvoidAoe; bool tellWhenAvoidAoe;
bool tellWhenAvoidAoe;
uint32 openGoSpell; uint32 openGoSpell;
bool randomBotAutologin; bool randomBotAutologin;
bool botAutologin; bool botAutologin;
std::string randomBotMapsAsString; std::string randomBotMapsAsString;
float probTeleToBankers; float probTeleToBankers;
std::vector<uint32> randomBotMaps; std::vector<uint32> randomBotMaps;
std::vector<uint32> randomBotQuestItems; std::vector<uint32> randomBotQuestItems;
std::vector<uint32> randomBotAccounts; std::vector<uint32> randomBotAccounts;
std::vector<uint32> randomBotSpellIds; std::vector<uint32> randomBotSpellIds;
std::vector<uint32> randomBotQuestIds; std::vector<uint32> randomBotQuestIds;
uint32 randomBotTeleportDistance; uint32 randomBotTeleportDistance;
float randomGearLoweringChance; float randomGearLoweringChance;
int32 randomGearQualityLimit; int32 randomGearQualityLimit;
int32 randomGearScoreLimit; int32 randomGearScoreLimit;
float randomBotMaxLevelChance; float randomBotMaxLevelChance;
float randomBotRpgChance; float randomBotRpgChance;
uint32 minRandomBots, maxRandomBots; uint32 minRandomBots, maxRandomBots;
uint32 randomBotUpdateInterval, randomBotCountChangeMinInterval, randomBotCountChangeMaxInterval; uint32 randomBotUpdateInterval, randomBotCountChangeMinInterval, randomBotCountChangeMaxInterval;
uint32 minRandomBotInWorldTime, maxRandomBotInWorldTime; uint32 minRandomBotInWorldTime, maxRandomBotInWorldTime;
uint32 minRandomBotRandomizeTime, maxRandomBotRandomizeTime; uint32 minRandomBotRandomizeTime, maxRandomBotRandomizeTime;
uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime; uint32 minRandomBotChangeStrategyTime, maxRandomBotChangeStrategyTime;
uint32 minRandomBotReviveTime, maxRandomBotReviveTime; uint32 minRandomBotReviveTime, maxRandomBotReviveTime;
uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval; uint32 minRandomBotTeleportInterval, maxRandomBotTeleportInterval;
uint32 randomBotInWorldWithRotationDisabled; uint32 randomBotInWorldWithRotationDisabled;
uint32 minRandomBotPvpTime, maxRandomBotPvpTime; uint32 minRandomBotPvpTime, maxRandomBotPvpTime;
uint32 randomBotsPerInterval; uint32 randomBotsPerInterval;
uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval; uint32 minRandomBotsPriceChangeInterval, maxRandomBotsPriceChangeInterval;
bool randomBotJoinLfg; bool randomBotJoinLfg;
bool randomBotTalk; bool randomBotTalk;
bool randomBotEmote; bool randomBotEmote;
bool randomBotSuggestDungeons; bool randomBotSuggestDungeons;
bool randomBotGuildTalk; bool randomBotGuildTalk;
bool suggestDungeonsInLowerCaseRandomly; bool suggestDungeonsInLowerCaseRandomly;
bool randomBotJoinBG; bool randomBotJoinBG;
bool randomBotAutoJoinBG; bool randomBotAutoJoinBG;
uint32 randomBotAutoJoinWarsongBracket; uint32 randomBotAutoJoinWarsongBracket;
uint32 randomBotAutoJoinArenaBracket; uint32 randomBotAutoJoinArenaBracket;
uint32 randomBotAutoJoinBGWarsongCount; uint32 randomBotAutoJoinBGWarsongCount;
uint32 randomBotAutoJoinBGRatedArena2v2Count; uint32 randomBotAutoJoinBGRatedArena2v2Count;
uint32 randomBotAutoJoinBGRatedArena3v3Count; uint32 randomBotAutoJoinBGRatedArena3v3Count;
uint32 randomBotAutoJoinBGRatedArena5v5Count; uint32 randomBotAutoJoinBGRatedArena5v5Count;
bool randomBotLoginAtStartup; bool randomBotLoginAtStartup;
uint32 randomBotTeleLowerLevel, randomBotTeleHigherLevel; uint32 randomBotTeleLowerLevel, randomBotTeleHigherLevel;
bool logInGroupOnly, logValuesPerTick; bool logInGroupOnly, logValuesPerTick;
bool fleeingEnabled; bool fleeingEnabled;
bool summonAtInnkeepersEnabled; bool summonAtInnkeepersEnabled;
std::string combatStrategies, nonCombatStrategies; std::string combatStrategies, nonCombatStrategies;
std::string randomBotCombatStrategies, randomBotNonCombatStrategies; std::string randomBotCombatStrategies, randomBotNonCombatStrategies;
uint32 randomBotMinLevel, randomBotMaxLevel; uint32 randomBotMinLevel, randomBotMaxLevel;
float randomChangeMultiplier; float randomChangeMultiplier;
// std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100
// ClassSpecs classSpecs[MAX_CLASSES];
// std::string premadeLevelSpec[MAX_CLASSES][10][91]; //lvl 10 - 100 std::string premadeSpecName[MAX_CLASSES][MAX_SPECNO];
// ClassSpecs classSpecs[MAX_CLASSES]; std::string premadeSpecGlyph[MAX_CLASSES][MAX_SPECNO];
std::vector<uint32> parsedSpecGlyph[MAX_CLASSES][MAX_SPECNO];
std::string premadeSpecLink[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL];
std::vector<std::vector<uint32>> parsedSpecLinkOrder[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL];
uint32 randomClassSpecProb[MAX_CLASSES][MAX_SPECNO];
uint32 randomClassSpecIndex[MAX_CLASSES][MAX_SPECNO];
std::string premadeSpecName[MAX_CLASSES][MAX_SPECNO]; std::string commandPrefix, commandSeparator;
std::string premadeSpecGlyph[MAX_CLASSES][MAX_SPECNO]; std::string randomBotAccountPrefix;
std::vector<uint32> parsedSpecGlyph[MAX_CLASSES][MAX_SPECNO]; uint32 randomBotAccountCount;
std::string premadeSpecLink[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL]; bool randomBotRandomPassword;
std::vector<std::vector<uint32>> parsedSpecLinkOrder[MAX_CLASSES][MAX_SPECNO][MAX_LEVEL]; bool deleteRandomBotAccounts;
uint32 randomClassSpecProb[MAX_CLASSES][MAX_SPECNO]; uint32 randomBotGuildCount;
uint32 randomClassSpecIndex[MAX_CLASSES][MAX_SPECNO]; bool deleteRandomBotGuilds;
std::vector<uint32> randomBotGuilds;
std::vector<uint32> pvpProhibitedZoneIds;
std::vector<uint32> pvpProhibitedAreaIds;
std::string commandPrefix, commandSeparator; bool randombotsWalkingRPG;
std::string randomBotAccountPrefix; bool randombotsWalkingRPGInDoors;
uint32 randomBotAccountCount; uint32 minEnchantingBotLevel;
bool randomBotRandomPassword; uint32 limitEnchantExpansion;
bool deleteRandomBotAccounts; uint32 limitGearExpansion;
uint32 randomBotGuildCount; uint32 randombotStartingLevel;
bool deleteRandomBotGuilds; bool enableRotation;
std::vector<uint32> randomBotGuilds; uint32 rotationPoolSize;
std::vector<uint32> pvpProhibitedZoneIds; bool gearscorecheck;
std::vector<uint32> pvpProhibitedAreaIds; bool randomBotPreQuests;
bool randombotsWalkingRPG; bool guildTaskEnabled;
bool randombotsWalkingRPGInDoors; uint32 minGuildTaskChangeTime, maxGuildTaskChangeTime;
uint32 minEnchantingBotLevel; uint32 minGuildTaskAdvertisementTime, maxGuildTaskAdvertisementTime;
uint32 limitEnchantExpansion; uint32 minGuildTaskRewardTime, maxGuildTaskRewardTime;
uint32 limitGearExpansion; uint32 guildTaskAdvertCleanupTime;
uint32 randombotStartingLevel; uint32 guildTaskKillTaskDistance;
bool enableRotation;
uint32 rotationPoolSize;
bool gearscorecheck;
bool randomBotPreQuests;
bool guildTaskEnabled; uint32 iterationsPerTick;
uint32 minGuildTaskChangeTime, maxGuildTaskChangeTime;
uint32 minGuildTaskAdvertisementTime, maxGuildTaskAdvertisementTime;
uint32 minGuildTaskRewardTime, maxGuildTaskRewardTime;
uint32 guildTaskAdvertCleanupTime;
uint32 guildTaskKillTaskDistance;
uint32 iterationsPerTick; std::mutex m_logMtx;
std::vector<std::string> allowedLogFiles;
std::unordered_map<std::string, std::pair<FILE*, bool>> logFiles;
std::mutex m_logMtx; std::vector<std::string> botCheats;
std::vector<std::string> allowedLogFiles; uint32 botCheatMask = 0;
std::unordered_map<std::string, std::pair<FILE*, bool>> logFiles;
std::vector<std::string> botCheats; struct worldBuff
uint32 botCheatMask = 0; {
uint32 spellId;
uint32 factionId = 0;
uint32 classId = 0;
uint32 minLevel = 0;
uint32 maxLevel = 0;
};
struct worldBuff std::vector<worldBuff> worldBuffs;
{
uint32 spellId;
uint32 factionId = 0;
uint32 classId = 0;
uint32 minLevel = 0;
uint32 maxLevel = 0;
};
std::vector<worldBuff> worldBuffs; uint32 commandServerPort;
bool perfMonEnabled;
uint32 commandServerPort; bool enableGreet;
bool perfMonEnabled; bool summonWhenGroup;
bool randomBotShowHelmet;
bool randomBotShowCloak;
bool randomBotFixedLevel;
bool disableRandomLevels;
uint32 playerbotsXPrate;
bool disableDeathKnightLogin;
uint32 botActiveAlone;
bool enableGreet; uint32 enablePrototypePerformanceDiff;
bool summonWhenGroup; uint32 diffWithPlayer;
bool randomBotShowHelmet; uint32 diffEmpty;
bool randomBotShowCloak;
bool randomBotFixedLevel;
bool disableRandomLevels;
uint32 playerbotsXPrate;
bool disableDeathKnightLogin;
uint32 botActiveAlone;
uint32 enablePrototypePerformanceDiff; bool freeMethodLoot;
uint32 diffWithPlayer; int32 lootRollLevel;
uint32 diffEmpty; std::string autoPickReward;
bool autoEquipUpgradeLoot;
float equipUpgradeThreshold;
bool syncQuestWithPlayer;
bool syncQuestForPlayer;
std::string autoTrainSpells;
bool autoPickTalents;
bool autoUpgradeEquip;
bool autoLearnTrainerSpells;
bool autoDoQuests;
bool syncLevelWithPlayers;
bool freeFood;
bool autoLearnQuestSpells;
bool autoTeleportForLevel;
bool randomBotSayWithoutMaster;
bool sayWhenCollectingItems;
bool randomBotGroupNearby;
uint32 tweakValue; // Debugging config
bool freeMethodLoot; uint32 randomBotArenaTeamCount;
int32 lootRollLevel; uint32 randomBotArenaTeamMaxRating;
std::string autoPickReward; uint32 randomBotArenaTeamMinRating;
bool autoEquipUpgradeLoot; uint32 randomBotArenaTeam2v2Count;
float equipUpgradeThreshold; uint32 randomBotArenaTeam3v3Count;
bool syncQuestWithPlayer; uint32 randomBotArenaTeam5v5Count;
bool syncQuestForPlayer; bool deleteRandomBotArenaTeams;
std::string autoTrainSpells; std::vector<uint32> randomBotArenaTeams;
bool autoPickTalents;
bool autoUpgradeEquip;
bool autoLearnTrainerSpells;
bool autoDoQuests;
bool syncLevelWithPlayers;
bool freeFood;
bool autoLearnQuestSpells;
bool autoTeleportForLevel;
bool randomBotSayWithoutMaster;
bool sayWhenCollectingItems;
bool randomBotGroupNearby;
uint32 tweakValue; //Debugging config
uint32 randomBotArenaTeamCount; uint32 selfBotLevel;
uint32 randomBotArenaTeamMaxRating; bool downgradeMaxLevelBot;
uint32 randomBotArenaTeamMinRating; bool equipmentPersistence;
uint32 randomBotArenaTeam2v2Count; int32 equipmentPersistenceLevel;
uint32 randomBotArenaTeam3v3Count; int32 groupInvitationPermission;
uint32 randomBotArenaTeam5v5Count; bool allowSummonInCombat;
bool deleteRandomBotArenaTeams; bool allowSummonWhenMasterIsDead;
std::vector<uint32> randomBotArenaTeams; bool allowSummonWhenBotIsDead;
int reviveBotWhenSummoned;
bool botRepairWhenSummon;
bool autoInitOnly;
float autoInitEquipLevelLimitRatio;
int32 maxAddedBots, maxAddedBotsPerClass;
int32 addClassCommand;
int32 maintenanceCommand;
int32 autoGearCommand, autoGearQualityLimit, autoGearScoreLimit;
uint32 selfBotLevel; std::string const GetTimestampStr();
bool downgradeMaxLevelBot; bool hasLog(std::string const fileName)
bool equipmentPersistence; {
int32 equipmentPersistenceLevel; return std::find(allowedLogFiles.begin(), allowedLogFiles.end(), fileName) != allowedLogFiles.end();
int32 groupInvitationPermission; };
bool allowSummonInCombat; bool openLog(std::string const fileName, char const* mode = "a");
bool allowSummonWhenMasterIsDead; bool isLogOpen(std::string const fileName)
bool allowSummonWhenBotIsDead; {
int reviveBotWhenSummoned; auto it = logFiles.find(fileName);
bool botRepairWhenSummon; return it != logFiles.end() && it->second.second;
bool autoInitOnly; }
float autoInitEquipLevelLimitRatio; void log(std::string const fileName, const char* str, ...);
int32 maxAddedBots, maxAddedBotsPerClass;
int32 addClassCommand;
int32 maintenanceCommand;
int32 autoGearCommand, autoGearQualityLimit, autoGearScoreLimit;
std::string const GetTimestampStr(); void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
bool hasLog(std::string const fileName) { return std::find(allowedLogFiles.begin(), allowedLogFiles.end(), fileName) != allowedLogFiles.end(); }; static std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
bool openLog(std::string const fileName, char const* mode = "a");
bool isLogOpen(std::string const fileName) { auto it = logFiles.find(fileName); return it != logFiles.end() && it->second.second; }
void log(std::string const fileName, const char* str, ...);
void loadWorldBuf(uint32 factionId, uint32 classId, uint32 minLevel, uint32 maxLevel);
static std::vector<std::vector<uint32>> ParseTempTalentsOrder(uint32 cls, std::string temp_talents_order);
}; };
#define sPlayerbotAIConfig PlayerbotAIConfig::instance() #define sPlayerbotAIConfig PlayerbotAIConfig::instance()

View File

@@ -1,18 +1,19 @@
/* /*
* 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. * 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 "PlayerbotCommandServer.h" #include "PlayerbotCommandServer.h"
#include "IoContext.h"
#include "Playerbots.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/thread/thread.hpp>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <boost/bind.hpp> #include "IoContext.h"
#include <boost/smart_ptr.hpp> #include "Playerbots.h"
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
typedef boost::shared_ptr<tcp::socket> socket_ptr; typedef boost::shared_ptr<tcp::socket> socket_ptr;
@@ -29,7 +30,7 @@ bool ReadLine(socket_ptr sock, std::string* buffer, std::string* line)
if (n == -1 || error == boost::asio::error::eof) if (n == -1 || error == boost::asio::error::eof)
return false; return false;
else if (error) else if (error)
throw boost::system::system_error(error); // Some other error. throw boost::system::system_error(error); // Some other error.
buf[n] = 0; buf[n] = 0;
*buffer += buf; *buffer += buf;

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_PLAYERBOTCOMMANDSERVER_H #ifndef _PLAYERBOT_PLAYERBOTCOMMANDSERVER_H
@@ -7,16 +8,16 @@
class PlayerbotCommandServer class PlayerbotCommandServer
{ {
public: public:
PlayerbotCommandServer() { } PlayerbotCommandServer() {}
virtual ~PlayerbotCommandServer() { } virtual ~PlayerbotCommandServer() {}
static PlayerbotCommandServer* instance() static PlayerbotCommandServer* instance()
{ {
static PlayerbotCommandServer instance; static PlayerbotCommandServer instance;
return &instance; return &instance;
} }
void Start(); void Start();
}; };
#define sPlayerbotCommandServer PlayerbotCommandServer::instance() #define sPlayerbotCommandServer PlayerbotCommandServer::instance()

View File

@@ -1,12 +1,14 @@
/* /*
* 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. * 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 "PlayerbotDbStore.h" #include "PlayerbotDbStore.h"
#include "Playerbots.h"
#include <iostream> #include <iostream>
#include "Playerbots.h"
void PlayerbotDbStore::Load(PlayerbotAI* botAI) void PlayerbotDbStore::Load(PlayerbotAI* botAI)
{ {
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter(); ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
@@ -35,8 +37,7 @@ void PlayerbotDbStore::Load(PlayerbotAI* botAI)
botAI->ChangeStrategy(value, BOT_STATE_NON_COMBAT); botAI->ChangeStrategy(value, BOT_STATE_NON_COMBAT);
else if (key == "dead") else if (key == "dead")
botAI->ChangeStrategy(value, BOT_STATE_DEAD); botAI->ChangeStrategy(value, BOT_STATE_DEAD);
} } while (result->NextRow());
while (result->NextRow());
botAI->GetAiObjectContext()->Load(values); botAI->GetAiObjectContext()->Load(values);
} }

View File

@@ -1,34 +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. * 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_PLAYERBOTDBSTORE_H #ifndef _PLAYERBOT_PLAYERBOTDBSTORE_H
#define _PLAYERBOT_PLAYERBOTDBSTORE_H #define _PLAYERBOT_PLAYERBOTDBSTORE_H
#include "Common.h"
#include <vector> #include <vector>
#include "Common.h"
class PlayerbotAI; class PlayerbotAI;
class PlayerbotDbStore class PlayerbotDbStore
{ {
public: public:
PlayerbotDbStore() { } PlayerbotDbStore() {}
virtual ~PlayerbotDbStore() { } virtual ~PlayerbotDbStore() {}
static PlayerbotDbStore* instance() static PlayerbotDbStore* instance()
{ {
static PlayerbotDbStore instance; static PlayerbotDbStore instance;
return &instance; return &instance;
} }
void Save(PlayerbotAI* botAI); void Save(PlayerbotAI* botAI);
void Load(PlayerbotAI* botAI); void Load(PlayerbotAI* botAI);
void Reset(PlayerbotAI* botAI); void Reset(PlayerbotAI* botAI);
private: private:
void SaveValue(uint32 guid, std::string const key, std::string const value); void SaveValue(uint32 guid, std::string const key, std::string const value);
std::string const FormatStrategies(std::string const type, std::vector<std::string> strategies); std::string const FormatStrategies(std::string const type, std::vector<std::string> strategies);
}; };
#define sPlayerbotDbStore PlayerbotDbStore::instance() #define sPlayerbotDbStore PlayerbotDbStore::instance()

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "PlayerbotDungeonSuggestionMgr.h" #include "PlayerbotDungeonSuggestionMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
std::vector<DungeonSuggestion> const PlayerbotDungeonSuggestionMgr::GetDungeonSuggestions() std::vector<DungeonSuggestion> const PlayerbotDungeonSuggestionMgr::GetDungeonSuggestions()
@@ -33,22 +35,14 @@ void PlayerbotDungeonSuggestionMgr::LoadDungeonSuggestions()
std::string const abbrevation = fields[4].Get<std::string>(); std::string const abbrevation = fields[4].Get<std::string>();
std::string const strategy = fields[5].Get<std::string>(); std::string const strategy = fields[5].Get<std::string>();
DungeonSuggestion const row = DungeonSuggestion const row = {
{ name, static_cast<Difficulty>(difficulty), min_level, max_level, abbrevation, strategy};
name,
static_cast<Difficulty>(difficulty),
min_level,
max_level,
abbrevation,
strategy
};
m_dungeonSuggestions.push_back(row); m_dungeonSuggestions.push_back(row);
++count; ++count;
} } while (result->NextRow());
while (result->NextRow());
} }
LOG_INFO("server.loading", "{} playerbots dungeon suggestions loaded in {} ms", LOG_INFO("server.loading", "{} playerbots dungeon suggestions loaded in {} ms", count,
count, GetMSTimeDiffToNow(oldMSTime)); GetMSTimeDiffToNow(oldMSTime));
} }

View File

@@ -1,16 +1,17 @@
/* /*
* 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. * 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_PLAYERBOTDUNGEONSUGGESTIONMGR_H #ifndef _PLAYERBOT_PLAYERBOTDUNGEONSUGGESTIONMGR_H
#define _PLAYERBOT_PLAYERBOTDUNGEONSUGGESTIONMGR_H #define _PLAYERBOT_PLAYERBOTDUNGEONSUGGESTIONMGR_H
#include "Common.h"
#include "DBCEnums.h"
#include <map> #include <map>
#include <vector> #include <vector>
#include "Common.h"
#include "DBCEnums.h"
struct DungeonSuggestion struct DungeonSuggestion
{ {
std::string name; std::string name;
@@ -23,20 +24,20 @@ struct DungeonSuggestion
class PlayerbotDungeonSuggestionMgr class PlayerbotDungeonSuggestionMgr
{ {
public: public:
PlayerbotDungeonSuggestionMgr() { }; PlayerbotDungeonSuggestionMgr(){};
~PlayerbotDungeonSuggestionMgr() { }; ~PlayerbotDungeonSuggestionMgr(){};
static PlayerbotDungeonSuggestionMgr* instance() static PlayerbotDungeonSuggestionMgr* instance()
{ {
static PlayerbotDungeonSuggestionMgr instance; static PlayerbotDungeonSuggestionMgr instance;
return &instance; return &instance;
} }
void LoadDungeonSuggestions(); void LoadDungeonSuggestions();
std::vector<DungeonSuggestion> const GetDungeonSuggestions(); std::vector<DungeonSuggestion> const GetDungeonSuggestions();
private: private:
std::vector<DungeonSuggestion> m_dungeonSuggestions; std::vector<DungeonSuggestion> m_dungeonSuggestions;
}; };
#define sPlayerbotDungeonSuggestionMgr PlayerbotDungeonSuggestionMgr::instance() #define sPlayerbotDungeonSuggestionMgr PlayerbotDungeonSuggestionMgr::instance()

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_PLAYERBOTFACTORY_H #ifndef _PLAYERBOT_PLAYERBOTFACTORY_H
@@ -15,15 +16,15 @@ struct ItemTemplate;
struct EnchantTemplate struct EnchantTemplate
{ {
uint8 ClassId; uint8 ClassId;
uint8 SpecId; uint8 SpecId;
uint32 SpellId; uint32 SpellId;
uint8 SlotId; uint8 SlotId;
}; };
typedef std::vector<EnchantTemplate> EnchantContainer; typedef std::vector<EnchantTemplate> EnchantContainer;
//TODO: more spec/role // TODO: more spec/role
/* classid+talenttree /* classid+talenttree
enum spec : uint8 enum spec : uint8
{ {
@@ -46,158 +47,160 @@ enum spec : uint8
enum PriorizedConsumables enum PriorizedConsumables
{ {
CONSUM_ID_ROUGH_WEIGHTSTONE = 3239, CONSUM_ID_ROUGH_WEIGHTSTONE = 3239,
CONSUM_ID_COARSE_WEIGHTSTONE = 3239, CONSUM_ID_COARSE_WEIGHTSTONE = 3239,
CONSUM_ID_HEAVY_WEIGHTSTONE = 3241, CONSUM_ID_HEAVY_WEIGHTSTONE = 3241,
CONSUM_ID_SOLID_WEIGHTSTONE = 7965, CONSUM_ID_SOLID_WEIGHTSTONE = 7965,
CONSUM_ID_DENSE_WEIGHTSTONE = 12643, CONSUM_ID_DENSE_WEIGHTSTONE = 12643,
CONSUM_ID_FEL_WEIGHTSTONE = 28420, CONSUM_ID_FEL_WEIGHTSTONE = 28420,
CONSUM_ID_ADAMANTITE_WEIGHTSTONE = 28421, CONSUM_ID_ADAMANTITE_WEIGHTSTONE = 28421,
CONSUM_ID_ROUGH_SHARPENING_STONE = 2862, CONSUM_ID_ROUGH_SHARPENING_STONE = 2862,
CONSUM_ID_COARSE_SHARPENING_STONE = 2863, CONSUM_ID_COARSE_SHARPENING_STONE = 2863,
CONSUM_ID_HEAVY_SHARPENING_STONE = 2871, CONSUM_ID_HEAVY_SHARPENING_STONE = 2871,
CONSUM_ID_SOL_SHARPENING_STONE = 7964, CONSUM_ID_SOL_SHARPENING_STONE = 7964,
CONSUM_ID_DENSE_SHARPENING_STONE = 12404, CONSUM_ID_DENSE_SHARPENING_STONE = 12404,
CONSUM_ID_ELEMENTAL_SHARPENING_STONE = 18262, CONSUM_ID_ELEMENTAL_SHARPENING_STONE = 18262,
CONSUM_ID_CONSECRATED_SHARPENING_STONE = 23122, CONSUM_ID_CONSECRATED_SHARPENING_STONE = 23122,
CONSUM_ID_FEL_SHARPENING_STONE = 23528, CONSUM_ID_FEL_SHARPENING_STONE = 23528,
CONSUM_ID_ADAMANTITE_SHARPENING_STONE = 23529, CONSUM_ID_ADAMANTITE_SHARPENING_STONE = 23529,
CONSUM_ID_LINEN_BANDAGE = 1251, CONSUM_ID_LINEN_BANDAGE = 1251,
CONSUM_ID_HEAVY_LINEN_BANDAGE = 2581, CONSUM_ID_HEAVY_LINEN_BANDAGE = 2581,
CONSUM_ID_WOOL_BANDAGE = 3530, CONSUM_ID_WOOL_BANDAGE = 3530,
CONSUM_ID_HEAVY_WOOL_BANDAGE = 3531, CONSUM_ID_HEAVY_WOOL_BANDAGE = 3531,
CONSUM_ID_SILK_BANDAGE = 6450, CONSUM_ID_SILK_BANDAGE = 6450,
CONSUM_ID_HEAVY_SILK_BANDAGE = 6451, CONSUM_ID_HEAVY_SILK_BANDAGE = 6451,
CONSUM_ID_MAGEWEAVE_BANDAGE = 8544, CONSUM_ID_MAGEWEAVE_BANDAGE = 8544,
CONSUM_ID_HEAVY_MAGEWEAVE_BANDAGE = 8545, CONSUM_ID_HEAVY_MAGEWEAVE_BANDAGE = 8545,
CONSUM_ID_RUNECLOTH_BANDAGE = 14529, CONSUM_ID_RUNECLOTH_BANDAGE = 14529,
CONSUM_ID_HEAVY_RUNECLOTH_BANDAGE = 14530, CONSUM_ID_HEAVY_RUNECLOTH_BANDAGE = 14530,
CONSUM_ID_NETHERWEAVE_BANDAGE = 21990, CONSUM_ID_NETHERWEAVE_BANDAGE = 21990,
CONSUM_ID_HEAVY_NETHERWEAVE_BANDAGE = 21991, CONSUM_ID_HEAVY_NETHERWEAVE_BANDAGE = 21991,
CONSUM_ID_BRILLIANT_MANA_OIL = 20748, CONSUM_ID_BRILLIANT_MANA_OIL = 20748,
CONSUM_ID_MINOR_MANA_OIL = 20745, CONSUM_ID_MINOR_MANA_OIL = 20745,
CONSUM_ID_SUPERIOR_MANA_OIL = 22521, CONSUM_ID_SUPERIOR_MANA_OIL = 22521,
CONSUM_ID_LESSER_MANA_OIL = 20747, CONSUM_ID_LESSER_MANA_OIL = 20747,
CONSUM_ID_BRILLIANT_WIZARD_OIL = 20749, CONSUM_ID_BRILLIANT_WIZARD_OIL = 20749,
CONSUM_ID_MINOR_WIZARD_OIL = 20744, CONSUM_ID_MINOR_WIZARD_OIL = 20744,
CONSUM_ID_SUPERIOR_WIZARD_OIL = 22522, CONSUM_ID_SUPERIOR_WIZARD_OIL = 22522,
CONSUM_ID_WIZARD_OIL = 20750, CONSUM_ID_WIZARD_OIL = 20750,
CONSUM_ID_LESSER_WIZARD_OIL = 20746, CONSUM_ID_LESSER_WIZARD_OIL = 20746,
CONSUM_ID_INSTANT_POISON = 6947, CONSUM_ID_INSTANT_POISON = 6947,
CONSUM_ID_INSTANT_POISON_II = 6949, CONSUM_ID_INSTANT_POISON_II = 6949,
CONSUM_ID_INSTANT_POISON_III = 6950, CONSUM_ID_INSTANT_POISON_III = 6950,
CONSUM_ID_INSTANT_POISON_IV = 8926, CONSUM_ID_INSTANT_POISON_IV = 8926,
CONSUM_ID_INSTANT_POISON_V = 8927, CONSUM_ID_INSTANT_POISON_V = 8927,
CONSUM_ID_INSTANT_POISON_VI = 8928, CONSUM_ID_INSTANT_POISON_VI = 8928,
CONSUM_ID_INSTANT_POISON_VII = 21927, CONSUM_ID_INSTANT_POISON_VII = 21927,
CONSUM_ID_DEADLY_POISON = 2892, CONSUM_ID_DEADLY_POISON = 2892,
CONSUM_ID_DEADLY_POISON_II = 2893, CONSUM_ID_DEADLY_POISON_II = 2893,
CONSUM_ID_DEADLY_POISON_III = 8984, CONSUM_ID_DEADLY_POISON_III = 8984,
CONSUM_ID_DEADLY_POISON_IV = 8985, CONSUM_ID_DEADLY_POISON_IV = 8985,
CONSUM_ID_DEADLY_POISON_V = 20844, CONSUM_ID_DEADLY_POISON_V = 20844,
CONSUM_ID_DEADLY_POISON_VI = 22053, CONSUM_ID_DEADLY_POISON_VI = 22053,
CONSUM_ID_DEADLY_POISON_VII = 22054 CONSUM_ID_DEADLY_POISON_VII = 22054
}; };
#define MAX_CONSUM_ID 28 #define MAX_CONSUM_ID 28
class PlayerbotFactory class PlayerbotFactory
{ {
public: public:
PlayerbotFactory(Player* bot, uint32 level, uint32 itemQuality = 0, uint32 gearScoreLimit = 0); PlayerbotFactory(Player* bot, uint32 level, uint32 itemQuality = 0, uint32 gearScoreLimit = 0);
static ObjectGuid GetRandomBot(); static ObjectGuid GetRandomBot();
static void Init(); static void Init();
void Refresh(); void Refresh();
void Randomize(bool incremental); void Randomize(bool incremental);
static std::list<uint32> classQuestIds; static std::list<uint32> classQuestIds;
void ClearEverything(); void ClearEverything();
void InitSkills(); void InitSkills();
static uint32 tradeSkills[]; static uint32 tradeSkills[];
static float CalculateItemScore(uint32 item_id, Player* bot); static float CalculateItemScore(uint32 item_id, Player* bot);
static float CalculateEnchantScore(uint32 enchant_id, Player* bot); static float CalculateEnchantScore(uint32 enchant_id, Player* bot);
static float CalculateSpellScore(uint32 spell_id, Player* bot, uint32 trigger = ITEM_SPELLTRIGGER_ON_EQUIP); static float CalculateSpellScore(uint32 spell_id, Player* bot, uint32 trigger = ITEM_SPELLTRIGGER_ON_EQUIP);
void InitTalentsTree(bool incremental = false, bool use_template = true, bool reset = false); void InitTalentsTree(bool incremental = false, bool use_template = true, bool reset = false);
static void InitTalentsBySpecNo(Player* bot, int specNo, bool reset); static void InitTalentsBySpecNo(Player* bot, int specNo, bool reset);
static void InitTalentsByParsedSpecLink(Player* bot, std::vector<std::vector<uint32>> parsedSpecLink, bool reset); static void InitTalentsByParsedSpecLink(Player* bot, std::vector<std::vector<uint32>> parsedSpecLink, bool reset);
void InitAvailableSpells(); void InitAvailableSpells();
void InitClassSpells(); void InitClassSpells();
void InitEquipment(bool incremental); void InitEquipment(bool incremental);
void InitPet(); void InitPet();
void InitAmmo(); void InitAmmo();
static uint32 CalcMixedGearScore(uint32 gs, uint32 quality); static uint32 CalcMixedGearScore(uint32 gs, uint32 quality);
void InitPetTalents(); void InitPetTalents();
void InitReagents(); void InitReagents();
void InitGlyphs(bool increment = false); void InitGlyphs(bool increment = false);
void InitFood(); void InitFood();
void InitMounts(); void InitMounts();
void InitBags(bool destroyOld = true); void InitBags(bool destroyOld = true);
void ApplyEnchantAndGemsNew(bool destoryOld = true); void ApplyEnchantAndGemsNew(bool destoryOld = true);
void InitInstanceQuests(); void InitInstanceQuests();
void UnbindInstance(); void UnbindInstance();
private:
void Prepare();
// void InitSecondEquipmentSet();
// void InitEquipmentNew(bool incremental);
bool CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality);
bool CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item);
void InitTradeSkills();
void UpdateTradeSkills();
void SetRandomSkill(uint16 id);
void InitSpells();
void ClearSpells();
void ClearSkills();
void InitSpecialSpells();
void InitTalents(uint32 specNo);
void InitTalentsByTemplate(uint32 specNo);
void InitQuests(std::list<uint32>& questMap);
void ClearInventory();
void ClearAllItems();
void ResetQuests();
void InitPotions();
bool CanEquipArmor(ItemTemplate const* proto); private:
bool CanEquipWeapon(ItemTemplate const* proto); void Prepare();
void EnchantItem(Item* item); // void InitSecondEquipmentSet();
void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank); // void InitEquipmentNew(bool incremental);
bool CheckItemStats(uint8 sp, uint8 ap, uint8 tank); bool CanEquipItem(ItemTemplate const* proto, uint32 desiredQuality);
void CancelAuras(); bool CanEquipUnseenItem(uint8 slot, uint16& dest, uint32 item);
bool IsDesiredReplacement(Item* item); void InitTradeSkills();
void InitInventory(); void UpdateTradeSkills();
void InitInventoryTrade(); void SetRandomSkill(uint16 id);
void InitInventoryEquip(); void InitSpells();
void InitInventorySkill(); void ClearSpells();
Item* StoreItem(uint32 itemId, uint32 count); void ClearSkills();
void InitGuild(); void InitSpecialSpells();
void InitArenaTeam(); void InitTalents(uint32 specNo);
void InitImmersive(); void InitTalentsByTemplate(uint32 specNo);
void AddConsumables(); void InitQuests(std::list<uint32>& questMap);
static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds); void ClearInventory();
void LoadEnchantContainer(); void ClearAllItems();
void ApplyEnchantTemplate(); void ResetQuests();
void ApplyEnchantTemplate(uint8 spec); void InitPotions();
std::vector<InventoryType> GetPossibleInventoryTypeListBySlot(EquipmentSlots slot);
static bool IsShieldTank(Player* bot); bool CanEquipArmor(ItemTemplate const* proto);
static bool NotSameArmorType(uint32 item_subclass_armor, Player* bot); bool CanEquipWeapon(ItemTemplate const* proto);
void IterateItems(IterateItemsVisitor* visitor, IterateItemsMask mask = ITERATE_ITEMS_IN_BAGS); void EnchantItem(Item* item);
void IterateItemsInBags(IterateItemsVisitor* visitor); void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank);
void IterateItemsInEquip(IterateItemsVisitor* visitor); bool CheckItemStats(uint8 sp, uint8 ap, uint8 tank);
void IterateItemsInBank(IterateItemsVisitor* visitor); void CancelAuras();
EnchantContainer::const_iterator GetEnchantContainerBegin() { return m_EnchantContainer.begin(); } bool IsDesiredReplacement(Item* item);
EnchantContainer::const_iterator GetEnchantContainerEnd() { return m_EnchantContainer.end(); } void InitInventory();
uint32 level; void InitInventoryTrade();
uint32 itemQuality; void InitInventoryEquip();
uint32 gearScoreLimit; void InitInventorySkill();
static std::list<uint32> specialQuestIds; Item* StoreItem(uint32 itemId, uint32 count);
std::vector<uint32> trainerIdCache; void InitGuild();
static std::vector<uint32> enchantSpellIdCache; void InitArenaTeam();
static std::vector<uint32> enchantGemIdCache; void InitImmersive();
protected: void AddConsumables();
EnchantContainer m_EnchantContainer; static void AddPrevQuests(uint32 questId, std::list<uint32>& questIds);
Player* bot; void LoadEnchantContainer();
PlayerbotAI* botAI; void ApplyEnchantTemplate();
void ApplyEnchantTemplate(uint8 spec);
std::vector<InventoryType> GetPossibleInventoryTypeListBySlot(EquipmentSlots slot);
static bool IsShieldTank(Player* bot);
static bool NotSameArmorType(uint32 item_subclass_armor, Player* bot);
void IterateItems(IterateItemsVisitor* visitor, IterateItemsMask mask = ITERATE_ITEMS_IN_BAGS);
void IterateItemsInBags(IterateItemsVisitor* visitor);
void IterateItemsInEquip(IterateItemsVisitor* visitor);
void IterateItemsInBank(IterateItemsVisitor* visitor);
EnchantContainer::const_iterator GetEnchantContainerBegin() { return m_EnchantContainer.begin(); }
EnchantContainer::const_iterator GetEnchantContainerEnd() { return m_EnchantContainer.end(); }
uint32 level;
uint32 itemQuality;
uint32 gearScoreLimit;
static std::list<uint32> specialQuestIds;
std::vector<uint32> trainerIdCache;
static std::vector<uint32> enchantSpellIdCache;
static std::vector<uint32> enchantGemIdCache;
protected:
EnchantContainer m_EnchantContainer;
Player* bot;
PlayerbotAI* botAI;
}; };
#endif #endif

View File

@@ -1,7 +1,16 @@
/* /*
* 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. * 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 "PlayerbotMgr.h"
#include <cstdio>
#include <cstring>
#include <istream>
#include <string>
#include "ChannelMgr.h"
#include "CharacterCache.h" #include "CharacterCache.h"
#include "CharacterPackets.h" #include "CharacterPackets.h"
#include "Common.h" #include "Common.h"
@@ -11,35 +20,29 @@
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "PlayerbotMgr.h"
#include "PlayerbotSecurity.h"
#include "Playerbots.h"
#include "PlayerbotDbStore.h" #include "PlayerbotDbStore.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "PlayerbotSecurity.h"
#include "Playerbots.h"
#include "SharedDefines.h" #include "SharedDefines.h"
#include "WorldSession.h" #include "WorldSession.h"
#include "ChannelMgr.h"
#include <cstdio>
#include <cstring>
#include <istream>
#include <string>
PlayerbotHolder::PlayerbotHolder() : PlayerbotAIBase(false) PlayerbotHolder::PlayerbotHolder() : PlayerbotAIBase(false) {}
{
}
class PlayerbotLoginQueryHolder : public LoginQueryHolder class PlayerbotLoginQueryHolder : public LoginQueryHolder
{ {
private: private:
uint32 masterAccountId; uint32 masterAccountId;
PlayerbotHolder* playerbotHolder; PlayerbotHolder* playerbotHolder;
public: public:
PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid) PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid)
: LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder) { } : LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder)
{
}
uint32 GetMasterAccountId() const { return masterAccountId; } uint32 GetMasterAccountId() const { return masterAccountId; }
PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; } PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; }
}; };
void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId) void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId)
@@ -53,7 +56,8 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
if (!accountId) if (!accountId)
return; return;
std::shared_ptr<PlayerbotLoginQueryHolder> holder = std::make_shared<PlayerbotLoginQueryHolder>(this, masterAccountId, accountId, playerGuid); std::shared_ptr<PlayerbotLoginQueryHolder> holder =
std::make_shared<PlayerbotLoginQueryHolder>(this, masterAccountId, accountId, playerGuid);
if (!holder->Initialize()) if (!holder->Initialize())
{ {
return; return;
@@ -61,17 +65,15 @@ void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId
if (WorldSession* masterSession = sWorld->FindSession(masterAccountId)) if (WorldSession* masterSession = sWorld->FindSession(masterAccountId))
{ {
masterSession->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder) masterSession->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder))
{ .AfterComplete([this](SQLQueryHolderBase const& holder)
HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); { HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); });
});
} }
else else
{ {
sWorld->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase const& holder) sWorld->AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder))
{ .AfterComplete([this](SQLQueryHolderBase const& holder)
HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); { HandlePlayerBotLoginCallback(static_cast<PlayerbotLoginQueryHolder const&>(holder)); });
});
} }
} }
@@ -79,23 +81,27 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
{ {
// has bot already been added? // has bot already been added?
Player* loginBot = ObjectAccessor::FindConnectedPlayer(holder.GetGuid()); Player* loginBot = ObjectAccessor::FindConnectedPlayer(holder.GetGuid());
if (loginBot && loginBot->IsInWorld()) { if (loginBot && loginBot->IsInWorld())
{
return; return;
} }
uint32 botAccountId = holder.GetAccountId(); uint32 botAccountId = holder.GetAccountId();
// At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this allows channels to work as intended) // At login DBC locale should be what the server is set to use by default (as spells etc are hardcoded to ENUS this
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), sWorld->GetDefaultDbcLocale(), 0, false, false, 0, true); // allows channels to work as intended)
WorldSession* botSession = new WorldSession(botAccountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
time_t(0), sWorld->GetDefaultDbcLocale(), 0, false, false, 0, true);
botSession->HandlePlayerLoginFromDB(holder); // will delete lqh botSession->HandlePlayerLoginFromDB(holder); // will delete lqh
Player* bot = botSession->GetPlayer(); Player* bot = botSession->GetPlayer();
if (!bot) if (!bot)
{ {
botSession->LogoutPlayer(true); botSession->LogoutPlayer(true);
delete botSession; delete botSession;
// LOG_ERROR("playerbots", "Error logging in bot {}, please try to reset all random bots", holder.GetGuid().ToString().c_str()); // LOG_ERROR("playerbots", "Error logging in bot {}, please try to reset all random bots",
// holder.GetGuid().ToString().c_str());
return; return;
} }
@@ -103,25 +109,37 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
WorldSession* masterSession = masterAccount ? sWorld->FindSession(masterAccount) : nullptr; WorldSession* masterSession = masterAccount ? sWorld->FindSession(masterAccount) : nullptr;
std::ostringstream out; std::ostringstream out;
bool allowed = false; bool allowed = false;
if (botAccountId == masterAccount) { if (botAccountId == masterAccount)
{
allowed = true; 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; allowed = true;
} else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId)) { }
else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId))
{
allowed = true; allowed = true;
} else { }
else
{
allowed = false; allowed = false;
out << "Failure: You are not allowed to control bot " << bot->GetName().c_str(); out << "Failure: You are not allowed to control bot " << bot->GetName().c_str();
} }
if (allowed && masterSession) { if (allowed && masterSession)
{
Player* player = masterSession->GetPlayer(); Player* player = masterSession->GetPlayer();
PlayerbotMgr *mgr = GET_PLAYERBOT_MGR(player); PlayerbotMgr* mgr = GET_PLAYERBOT_MGR(player);
uint32 count = mgr->GetPlayerbotsCount(); uint32 count = mgr->GetPlayerbotsCount();
uint32 cls_count = mgr->GetPlayerbotsCountByClass(bot->getClass()); uint32 cls_count = mgr->GetPlayerbotsCountByClass(bot->getClass());
if (count >= sPlayerbotAIConfig->maxAddedBots) { if (count >= sPlayerbotAIConfig->maxAddedBots)
{
allowed = false; allowed = false;
out << "Failure: You have added too many bots"; out << "Failure: You have added too many bots";
} else if (cls_count >= sPlayerbotAIConfig->maxAddedBotsPerClass) { }
else if (cls_count >= sPlayerbotAIConfig->maxAddedBotsPerClass)
{
allowed = false; allowed = false;
out << "Failure: You have added too many bots for this class"; out << "Failure: You have added too many bots for this class";
} }
@@ -143,7 +161,8 @@ void PlayerbotHolder::HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder con
// OnBotLogin(bot); // OnBotLogin(bot);
// LogoutPlayerBot(bot->GetGUID()); // LogoutPlayerBot(bot->GetGUID());
// LOG_ERROR("playerbots", "Attempt to add not allowed bot {}, please try to reset all random bots", bot->GetName()); // LOG_ERROR("playerbots", "Attempt to add not allowed bot {}, please try to reset all random bots",
// bot->GetName());
} }
} }
@@ -155,7 +174,8 @@ void PlayerbotHolder::UpdateSessions()
if (bot->IsBeingTeleported()) if (bot->IsBeingTeleported())
{ {
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (botAI) { if (botAI)
{
botAI->HandleTeleportAck(); botAI->HandleTeleportAck();
} }
} }
@@ -229,7 +249,8 @@ void PlayerbotMgr::CancelLogout()
} }
} }
for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin();
it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -289,14 +310,16 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
logout = true; logout = true;
} }
if (master && (master->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || master->HasUnitState(UNIT_STATE_IN_FLIGHT) || if (master &&
(masterWorldSessionPtr && masterWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT)))) (master->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || master->HasUnitState(UNIT_STATE_IN_FLIGHT) ||
(masterWorldSessionPtr &&
masterWorldSessionPtr->GetSecurity() >= (AccountTypes)sWorld->getIntConfig(CONFIG_INSTANT_LOGOUT))))
{ {
logout = true; logout = true;
} }
TravelTarget* target = nullptr; TravelTarget* target = nullptr;
if (botAI->GetAiObjectContext()) //Maybe some day re-write to delate all pointer values. if (botAI->GetAiObjectContext()) // Maybe some day re-write to delate all pointer values.
{ {
target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get(); target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get();
} }
@@ -325,19 +348,19 @@ void PlayerbotHolder::LogoutPlayerBot(ObjectGuid guid)
} }
else else
{ {
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
delete botWorldSessionPtr; // finally delete the bot's WorldSession delete botWorldSessionPtr; // finally delete the bot's WorldSession
if (target) if (target)
delete target; delete target;
} }
return; return;
} // if instant logout possible, do it } // if instant logout possible, do it
else if (bot && (logout || !botWorldSessionPtr->isLogingOut())) else if (bot && (logout || !botWorldSessionPtr->isLogingOut()))
{ {
botAI->TellMaster("Goodbye!"); botAI->TellMaster("Goodbye!");
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
botWorldSessionPtr->LogoutPlayer(true); // this will delete the bot Player object and PlayerbotAI object botWorldSessionPtr->LogoutPlayer(true); // this will delete the bot Player object and PlayerbotAI object
delete botWorldSessionPtr; // finally delete the bot's WorldSession delete botWorldSessionPtr; // finally delete the bot's WorldSession
} }
} }
} }
@@ -347,7 +370,8 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid)
if (Player* bot = GetPlayerBot(guid)) if (Player* bot = GetPlayerBot(guid))
{ {
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
botAI->TellMaster("Goodbye!"); botAI->TellMaster("Goodbye!");
@@ -364,14 +388,14 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid)
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
if (botAI->GetAiObjectContext()) //Maybe some day re-write to delate all pointer values. if (botAI->GetAiObjectContext()) // Maybe some day re-write to delate all pointer values.
{ {
TravelTarget* target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get(); TravelTarget* target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get();
if (target) if (target)
delete target; delete target;
} }
playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap playerBots.erase(guid); // deletes bot player ptr inside this WorldSession PlayerBotMap
delete botAI; delete botAI;
} }
@@ -393,7 +417,8 @@ Player* PlayerbotHolder::GetPlayerBot(ObjectGuid::LowType lowGuid) const
void PlayerbotHolder::OnBotLogin(Player* const bot) void PlayerbotHolder::OnBotLogin(Player* const bot)
{ {
// Prevent duplicate login // Prevent duplicate login
if (playerBots.find(bot->GetGUID()) != playerBots.end()) { if (playerBots.find(bot->GetGUID()) != playerBots.end())
{
return; return;
} }
@@ -401,16 +426,16 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
playerBots[bot->GetGUID()] = bot; playerBots[bot->GetGUID()] = bot;
OnBotLoginInternal(bot); OnBotLoginInternal(bot);
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
Player* master = botAI->GetMaster(); Player* master = botAI->GetMaster();
if (master) if (master)
{ {
ObjectGuid masterGuid = master->GetGUID(); ObjectGuid masterGuid = master->GetGUID();
if (master->GetGroup() && ! master->GetGroup()->IsLeader(masterGuid)) if (master->GetGroup() && !master->GetGroup()->IsLeader(masterGuid))
master->GetGroup()->ChangeLeader(masterGuid); master->GetGroup()->ChangeLeader(masterGuid);
} }
@@ -475,19 +500,27 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
botAI->TellMaster("Hello!", PLAYERBOT_SECURITY_TALK); botAI->TellMaster("Hello!", PLAYERBOT_SECURITY_TALK);
if (master && master->GetGroup() && !group) { if (master && master->GetGroup() && !group)
{
Group* mgroup = master->GetGroup(); Group* mgroup = master->GetGroup();
if (mgroup->GetMembersCount() >= 5) { if (mgroup->GetMembersCount() >= 5)
if (!mgroup->isRaidGroup() && !mgroup->isLFGGroup() && !mgroup->isBGGroup() && !mgroup->isBFGroup()) { {
if (!mgroup->isRaidGroup() && !mgroup->isLFGGroup() && !mgroup->isBGGroup() && !mgroup->isBFGroup())
{
mgroup->ConvertToRaid(); mgroup->ConvertToRaid();
} }
if (mgroup->isRaidGroup()) { if (mgroup->isRaidGroup())
{
mgroup->AddMember(bot); mgroup->AddMember(bot);
} }
} else { }
else
{
mgroup->AddMember(bot); mgroup->AddMember(bot);
} }
} else if (master && !group) { }
else if (master && !group)
{
Group* newGroup = new Group(); Group* newGroup = new Group();
newGroup->Create(master); newGroup->Create(master);
sGroupMgr->AddGroup(newGroup); sGroupMgr->AddGroup(newGroup);
@@ -497,30 +530,36 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
uint32 accountId = bot->GetSession()->GetAccountId(); uint32 accountId = bot->GetSession()->GetAccountId();
bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId); bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId);
if (isRandomAccount && sPlayerbotAIConfig->randomBotFixedLevel) { if (isRandomAccount && sPlayerbotAIConfig->randomBotFixedLevel)
{
bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN);
} else if (isRandomAccount && !sPlayerbotAIConfig->randomBotFixedLevel) { }
else if (isRandomAccount && !sPlayerbotAIConfig->randomBotFixedLevel)
{
bot->RemovePlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); bot->RemovePlayerFlag(PLAYER_FLAGS_NO_XP_GAIN);
} }
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) { if (master && isRandomAccount && master->GetLevel() < bot->GetLevel())
{
// PlayerbotFactory factory(bot, master->GetLevel()); // PlayerbotFactory factory(bot, master->GetLevel());
// factory.Randomize(false); // factory.Randomize(false);
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; uint32 mixedGearScore =
PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore); PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
factory.Randomize(false); factory.Randomize(false);
} }
// bots join World chat if not solo oriented // bots join World chat if not solo oriented
if (bot->GetLevel() >= 10 && sRandomPlayerbotMgr->IsRandomBot(bot) && GET_PLAYERBOT_AI(bot) && GET_PLAYERBOT_AI(bot)->GetGrouperType() != GrouperType::SOLO) if (bot->GetLevel() >= 10 && sRandomPlayerbotMgr->IsRandomBot(bot) && GET_PLAYERBOT_AI(bot) &&
GET_PLAYERBOT_AI(bot)->GetGrouperType() != GrouperType::SOLO)
{ {
// TODO make action/config // TODO make action/config
// Make the bot join the world channel for chat // Make the bot join the world channel for chat
WorldPacket pkt(CMSG_JOIN_CHANNEL); WorldPacket pkt(CMSG_JOIN_CHANNEL);
pkt << uint32(0) << uint8(0) << uint8(0); pkt << uint32(0) << uint8(0) << uint8(0);
pkt << std::string("World"); pkt << std::string("World");
pkt << ""; // Pass pkt << ""; // Pass
bot->GetSession()->HandleJoinChannel(pkt); bot->GetSession()->HandleJoinChannel(pkt);
} }
// join standard channels // join standard channels
@@ -533,7 +572,8 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i) for (uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
{ {
ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i); ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i);
if (!channel) continue; if (!channel)
continue;
bool isLfg = (channel->flags & CHANNEL_DBC_FLAG_LFG) != 0; bool isLfg = (channel->flags & CHANNEL_DBC_FLAG_LFG) != 0;
@@ -551,7 +591,8 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
else else
{ {
char new_channel_name_buf[100]; char new_channel_name_buf[100];
snprintf(new_channel_name_buf, 100, channel->pattern[sWorld->GetDefaultDbcLocale()], current_zone_name.c_str()); snprintf(new_channel_name_buf, 100, channel->pattern[sWorld->GetDefaultDbcLocale()],
current_zone_name.c_str());
new_channel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID); new_channel = cMgr->GetJoinChannel(new_channel_name_buf, channel->ChannelID);
} }
if (new_channel && new_channel->GetName().length() > 0) if (new_channel && new_channel->GetName().length() > 0)
@@ -560,7 +601,8 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
} }
} }
std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin, uint32 masterAccountId, uint32 masterGuildId) std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid,
bool admin, uint32 masterAccountId, uint32 masterGuildId)
{ {
if (!sPlayerbotAIConfig->enabled || guid.IsEmpty()) if (!sPlayerbotAIConfig->enabled || guid.IsEmpty())
return "bot system is disabled"; return "bot system is disabled";
@@ -573,7 +615,8 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
if (!isRandomAccount && !isMasterAccount && !admin && masterguid) if (!isRandomAccount && !isMasterAccount && !admin && masterguid)
{ {
Player* master = ObjectAccessor::FindConnectedPlayer(masterguid); Player* master = ObjectAccessor::FindConnectedPlayer(masterguid);
if (master && (!sPlayerbotAIConfig->allowGuildBots || !masterGuildId || (masterGuildId && sCharacterCache->GetCharacterGuildIdByGuid(guid) != masterGuildId))) if (master && (!sPlayerbotAIConfig->allowGuildBots || !masterGuildId ||
(masterGuildId && sCharacterCache->GetCharacterGuildIdByGuid(guid) != masterGuildId)))
return "not in your guild or account"; return "not in your guild or account";
} }
@@ -609,21 +652,27 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
if (!bot) if (!bot)
return "bot not found"; return "bot not found";
if (!isRandomAccount || isRandomBot) { if (!isRandomAccount || isRandomBot)
{
return "ERROR: You can not use this command on non-summoned random bot."; return "ERROR: You can not use this command on non-summoned random bot.";
} }
if (!admin) { if (!admin)
{
Player* master = ObjectAccessor::FindConnectedPlayer(masterguid); Player* master = ObjectAccessor::FindConnectedPlayer(masterguid);
if (master && (master->IsInCombat() || bot->IsInCombat())) { if (master && (master->IsInCombat() || bot->IsInCombat()))
{
return "ERROR: You can not use this command during combat."; return "ERROR: You can not use this command during combat.";
} }
} }
if (GET_PLAYERBOT_AI(bot)) { if (GET_PLAYERBOT_AI(bot))
{
if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster())
{ {
if (master->GetSession()->GetSecurity() <= SEC_PLAYER && sPlayerbotAIConfig->autoInitOnly && cmd != "init=auto") { if (master->GetSession()->GetSecurity() <= SEC_PLAYER && sPlayerbotAIConfig->autoInitOnly &&
cmd != "init=auto")
{
return "The command is not allowed, use init=auto instead."; return "The command is not allowed, use init=auto instead.";
} }
int gs; int gs;
@@ -659,10 +708,12 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
} }
else if (cmd == "init=auto") else if (cmd == "init=auto")
{ {
uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) *
sPlayerbotAIConfig->autoInitEquipLevelLimitRatio;
PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore); PlayerbotFactory factory(bot, master->GetLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore);
factory.Randomize(false); factory.Randomize(false);
return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) + "(for epic)"; return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) +
"(for epic)";
} }
else if (cmd.starts_with("init=") && sscanf(cmd.c_str(), "init=%d", &gs) != -1) else if (cmd.starts_with("init=") && sscanf(cmd.c_str(), "init=%d", &gs) != -1)
{ {
@@ -673,7 +724,7 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
} }
if (cmd == "refresh=raid") if (cmd == "refresh=raid")
{ // TODO: This function is not perfect yet. If you are already in a raid, { // TODO: This function is not perfect yet. If you are already in a raid,
// after the command is executed, the AI needs to go back online or exit the raid and re-enter. // after the command is executed, the AI needs to go back online or exit the raid and re-enter.
PlayerbotFactory factory(bot, bot->GetLevel()); PlayerbotFactory factory(bot, bot->GetLevel());
factory.UnbindInstance(); factory.UnbindInstance();
@@ -698,7 +749,8 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje
sRandomPlayerbotMgr->Randomize(bot); sRandomPlayerbotMgr->Randomize(bot);
return "ok"; return "ok";
} }
else if (cmd == "quests"){ else if (cmd == "quests")
{
PlayerbotFactory factory(bot, bot->GetLevel()); PlayerbotFactory factory(bot, bot->GetLevel());
factory.InitInstanceQuests(); factory.InitInstanceQuests();
return "Initialization quests"; return "Initialization quests";
@@ -754,61 +806,78 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
return messages; return messages;
} }
char* cmd = strtok ((char*)args, " "); char* cmd = strtok((char*)args, " ");
char* charname = strtok (nullptr, " "); char* charname = strtok(nullptr, " ");
if (!cmd) if (!cmd)
{ {
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME or addclass CLASSNAME"); messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME or addclass CLASSNAME");
return messages; return messages;
} }
if (!strcmp(cmd, "initself")) { if (!strcmp(cmd, "initself"))
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) { {
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
{
// OnBotLogin(master); // OnBotLogin(master);
PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC);
factory.Randomize(false); factory.Randomize(false);
messages.push_back("initself ok"); messages.push_back("initself ok");
return messages; return messages;
} else { }
else
{
messages.push_back("ERROR: Only GM can use this command."); messages.push_back("ERROR: Only GM can use this command.");
return messages; return messages;
} }
} }
if (!strncmp(cmd, "initself=", 9)) { if (!strncmp(cmd, "initself=", 9))
if (!strcmp(cmd, "initself=rare")) { {
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) { if (!strcmp(cmd, "initself=rare"))
{
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
{
// OnBotLogin(master); // OnBotLogin(master);
PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_RARE); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_RARE);
factory.Randomize(false); factory.Randomize(false);
messages.push_back("initself ok"); messages.push_back("initself ok");
return messages; return messages;
} else { }
else
{
messages.push_back("ERROR: Only GM can use this command."); messages.push_back("ERROR: Only GM can use this command.");
return messages; return messages;
} }
} }
if (!strcmp(cmd, "initself=epic")) { if (!strcmp(cmd, "initself=epic"))
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) { {
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
{
// OnBotLogin(master); // OnBotLogin(master);
PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_EPIC);
factory.Randomize(false); factory.Randomize(false);
messages.push_back("initself ok"); messages.push_back("initself ok");
return messages; return messages;
} else { }
else
{
messages.push_back("ERROR: Only GM can use this command."); messages.push_back("ERROR: Only GM can use this command.");
return messages; return messages;
} }
} }
int32 gs; int32 gs;
if (sscanf(cmd, "initself=%d", &gs) != -1) { if (sscanf(cmd, "initself=%d", &gs) != -1)
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER) { {
if (master->GetSession()->GetSecurity() >= SEC_GAMEMASTER)
{
// OnBotLogin(master); // OnBotLogin(master);
PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_LEGENDARY, gs); PlayerbotFactory factory(master, master->GetLevel(), ITEM_QUALITY_LEGENDARY, gs);
factory.Randomize(false); factory.Randomize(false);
messages.push_back("initself ok, gs = " + std::to_string(gs)); messages.push_back("initself ok, gs = " + std::to_string(gs));
return messages; return messages;
} else { }
else
{
messages.push_back("ERROR: Only GM can use this command."); messages.push_back("ERROR: Only GM can use this command.");
return messages; return messages;
} }
@@ -867,12 +936,15 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
if (!strcmp(cmd, "addclass")) if (!strcmp(cmd, "addclass"))
{ {
if (sPlayerbotAIConfig->addClassCommand == 0 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER) { if (sPlayerbotAIConfig->addClassCommand == 0 && master->GetSession()->GetSecurity() < SEC_GAMEMASTER)
{
messages.push_back("You do not have permission to create bot by addclass command"); messages.push_back("You do not have permission to create bot by addclass command");
return messages; return messages;
} }
if (!charname) { if (!charname)
messages.push_back("addclass: invalid CLASSNAME(warrior/paladin/hunter/rogue/priest/shaman/mage/warlock/druid/dk)"); {
messages.push_back(
"addclass: invalid CLASSNAME(warrior/paladin/hunter/rogue/priest/shaman/mage/warlock/druid/dk)");
return messages; return messages;
} }
uint8 claz; uint8 claz;
@@ -942,10 +1014,13 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
} }
uint32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back(); uint32 maxAccountId = sPlayerbotAIConfig->randomBotAccounts.back();
// find a bot fit conditions and not in any guild // find a bot fit conditions and not in any guild
QueryResult results = CharacterDatabase.Query("SELECT guid FROM characters " QueryResult results = CharacterDatabase.Query(
"WHERE name IN (SELECT name FROM playerbots_names) AND class = '{}' AND online = 0 AND race IN ({}) AND guid NOT IN ( SELECT guid FROM guild_member ) " "SELECT guid FROM characters "
"WHERE name IN (SELECT name FROM playerbots_names) AND class = '{}' AND online = 0 AND race IN ({}) AND "
"guid NOT IN ( SELECT guid FROM guild_member ) "
"AND account <= {} " "AND account <= {} "
"ORDER BY account DESC LIMIT 1", claz, race_limit, maxAccountId); "ORDER BY account DESC LIMIT 1",
claz, race_limit, maxAccountId);
if (results) if (results)
{ {
Field* fields = results->Fetch(); Field* fields = results->Fetch();
@@ -966,13 +1041,18 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
std::string name; std::string name;
bool isPlayer = sCharacterCache->GetCharacterNameByGuid(master->GetTarget(), name); bool isPlayer = sCharacterCache->GetCharacterNameByGuid(master->GetTarget(), name);
// Player* tPlayer = ObjectAccessor::FindConnectedPlayer(master->GetTarget()); // Player* tPlayer = ObjectAccessor::FindConnectedPlayer(master->GetTarget());
if (isPlayer) { if (isPlayer)
{
charnameStr = name; charnameStr = name;
} else { }
else
{
messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME"); messages.push_back("usage: list/reload/tweak/self or add/init/remove PLAYERNAME");
return messages; return messages;
} }
} else { }
else
{
charnameStr = charname; charnameStr = charname;
} }
@@ -1050,7 +1130,9 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
} }
else if (master && member != master->GetGUID()) else if (master && member != master->GetGUID())
{ {
out << ProcessBotCommand(cmdStr, member, master->GetGUID(), master->GetSession()->GetSecurity() >= SEC_GAMEMASTER, master->GetSession()->GetAccountId(), master->GetGuildId()); out << ProcessBotCommand(cmdStr, member, master->GetGUID(),
master->GetSession()->GetSecurity() >= SEC_GAMEMASTER,
master->GetSession()->GetAccountId(), master->GetGuildId());
} }
else if (!master) else if (!master)
{ {
@@ -1063,10 +1145,7 @@ std::vector<std::string> PlayerbotHolder::HandlePlayerbotCommand(char const* arg
return messages; return messages;
} }
uint32 PlayerbotHolder::GetAccountId(std::string const name) uint32 PlayerbotHolder::GetAccountId(std::string const name) { return AccountMgr::GetId(name); }
{
return AccountMgr::GetId(name);
}
uint32 PlayerbotHolder::GetAccountId(ObjectGuid guid) uint32 PlayerbotHolder::GetAccountId(ObjectGuid guid)
{ {
@@ -1122,7 +1201,8 @@ std::string const PlayerbotHolder::ListBots(Player* master)
if (master) if (master)
{ {
QueryResult results = CharacterDatabase.Query("SELECT class, name FROM characters WHERE account = {}", master->GetSession()->GetAccountId()); QueryResult results = CharacterDatabase.Query("SELECT class, name FROM characters WHERE account = {}",
master->GetSession()->GetAccountId());
if (results) if (results)
{ {
do do
@@ -1147,7 +1227,7 @@ std::string const PlayerbotHolder::ListBots(Player* master)
Group::MemberSlotList const& groupSlot = group->GetMemberSlots(); Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++) for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
{ {
Player *member = ObjectAccessor::FindPlayer(itr->guid); Player* member = ObjectAccessor::FindPlayer(itr->guid);
if (member && sRandomPlayerbotMgr->IsRandomBot(member)) if (member && sRandomPlayerbotMgr->IsRandomBot(member))
{ {
std::string const name = member->GetName(); std::string const name = member->GetName();
@@ -1192,7 +1272,8 @@ std::string const PlayerbotHolder::LookupBots(Player* master)
messages.push_back("DK"); messages.push_back("DK");
messages.push_back("(Usage: .bot lookup CLASS)"); messages.push_back("(Usage: .bot lookup CLASS)");
std::string ret_msg; std::string ret_msg;
for (std::string msg: messages) { for (std::string msg : messages)
{
ret_msg += msg + "\n"; ret_msg += msg + "\n";
} }
return ret_msg; return ret_msg;
@@ -1204,16 +1285,15 @@ uint32 PlayerbotHolder::GetPlayerbotsCountByClass(uint32 cls)
for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
if (bot->getClass() == cls) { if (bot->getClass() == cls)
{
count++; count++;
} }
} }
return count; return count;
} }
PlayerbotMgr::PlayerbotMgr(Player* const master) : PlayerbotHolder(), master(master), lastErrorTell(0) PlayerbotMgr::PlayerbotMgr(Player* const master) : PlayerbotHolder(), master(master), lastErrorTell(0) {}
{
}
PlayerbotMgr::~PlayerbotMgr() PlayerbotMgr::~PlayerbotMgr()
{ {
@@ -1253,7 +1333,8 @@ void PlayerbotMgr::HandleCommand(uint32 type, std::string const text)
botAI->HandleCommand(type, text, master); botAI->HandleCommand(type, text, master);
} }
for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin();
it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -1274,7 +1355,8 @@ void PlayerbotMgr::HandleMasterIncomingPacket(WorldPacket const& packet)
botAI->HandleMasterIncomingPacket(packet); botAI->HandleMasterIncomingPacket(packet);
} }
for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin();
it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -1309,7 +1391,8 @@ void PlayerbotMgr::HandleMasterOutgoingPacket(WorldPacket const& packet)
botAI->HandleMasterOutgoingPacket(packet); botAI->HandleMasterOutgoingPacket(packet);
} }
for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin();
it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
@@ -1326,7 +1409,8 @@ void PlayerbotMgr::SaveToDB()
bot->SaveToDB(false, false); bot->SaveToDB(false, false);
} }
for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin(); it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it) for (PlayerBotMap::const_iterator it = sRandomPlayerbotMgr->GetPlayerBotsBegin();
it != sRandomPlayerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
Player* const bot = it->second; Player* const bot = it->second;
if (GET_PLAYERBOT_AI(bot) && GET_PLAYERBOT_AI(bot)->GetMaster() == GetMaster()) if (GET_PLAYERBOT_AI(bot) && GET_PLAYERBOT_AI(bot)->GetMaster() == GetMaster())
@@ -1334,10 +1418,11 @@ void PlayerbotMgr::SaveToDB()
} }
} }
void PlayerbotMgr::OnBotLoginInternal(Player * const bot) void PlayerbotMgr::OnBotLoginInternal(Player* const bot)
{ {
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return; return;
} }
botAI->SetMaster(master); botAI->SetMaster(master);
@@ -1458,13 +1543,16 @@ void PlayerbotsMgr::AddPlayerbotData(Player* player, bool isBotAI)
void PlayerbotsMgr::RemovePlayerBotData(ObjectGuid const& guid, bool is_AI) void PlayerbotsMgr::RemovePlayerBotData(ObjectGuid const& guid, bool is_AI)
{ {
if (is_AI) { if (is_AI)
{
std::unordered_map<ObjectGuid, PlayerbotAIBase*>::iterator itr = _playerbotsAIMap.find(guid); std::unordered_map<ObjectGuid, PlayerbotAIBase*>::iterator itr = _playerbotsAIMap.find(guid);
if (itr != _playerbotsAIMap.end()) if (itr != _playerbotsAIMap.end())
{ {
_playerbotsAIMap.erase(itr); _playerbotsAIMap.erase(itr);
} }
} else { }
else
{
std::unordered_map<ObjectGuid, PlayerbotAIBase*>::iterator itr = _playerbotsMgrMap.find(guid); std::unordered_map<ObjectGuid, PlayerbotAIBase*>::iterator itr = _playerbotsMgrMap.find(guid);
if (itr != _playerbotsMgrMap.end()) if (itr != _playerbotsMgrMap.end())
{ {

View File

@@ -1,15 +1,16 @@
/* /*
* 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. * 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_PLAYERBOTMGR_H #ifndef _PLAYERBOT_PLAYERBOTMGR_H
#define _PLAYERBOT_PLAYERBOTMGR_H #define _PLAYERBOT_PLAYERBOTMGR_H
#include "Common.h" #include "Common.h"
#include "QueryHolder.h"
#include "QueryResult.h"
#include "Player.h" #include "Player.h"
#include "PlayerbotAIBase.h" #include "PlayerbotAIBase.h"
#include "QueryHolder.h"
#include "QueryResult.h"
class ChatHandler; class ChatHandler;
class PlayerbotAI; class PlayerbotAI;
@@ -21,92 +22,94 @@ typedef std::map<std::string, std::set<std::string> > PlayerBotErrorMap;
class PlayerbotHolder : public PlayerbotAIBase class PlayerbotHolder : public PlayerbotAIBase
{ {
public: public:
PlayerbotHolder(); PlayerbotHolder();
virtual ~PlayerbotHolder() { }; virtual ~PlayerbotHolder(){};
void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId); void AddPlayerBot(ObjectGuid guid, uint32 masterAccountId);
void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder); void HandlePlayerBotLoginCallback(PlayerbotLoginQueryHolder const& holder);
void LogoutPlayerBot(ObjectGuid guid); void LogoutPlayerBot(ObjectGuid guid);
void DisablePlayerBot(ObjectGuid guid); void DisablePlayerBot(ObjectGuid guid);
Player* GetPlayerBot(ObjectGuid guid) const; Player* GetPlayerBot(ObjectGuid guid) const;
Player* GetPlayerBot(ObjectGuid::LowType lowGuid) const; Player* GetPlayerBot(ObjectGuid::LowType lowGuid) const;
PlayerBotMap::const_iterator GetPlayerBotsBegin() const { return playerBots.begin(); } PlayerBotMap::const_iterator GetPlayerBotsBegin() const { return playerBots.begin(); }
PlayerBotMap::const_iterator GetPlayerBotsEnd() const { return playerBots.end(); } PlayerBotMap::const_iterator GetPlayerBotsEnd() const { return playerBots.end(); }
void UpdateAIInternal([[maybe_unused]] uint32 elapsed, [[maybe_unused]] bool minimal = false) override { }; void UpdateAIInternal([[maybe_unused]] uint32 elapsed, [[maybe_unused]] bool minimal = false) override{};
void UpdateSessions(); void UpdateSessions();
void HandleBotPackets(WorldSession* session); void HandleBotPackets(WorldSession* session);
void LogoutAllBots(); void LogoutAllBots();
void OnBotLogin(Player* const bot); void OnBotLogin(Player* const bot);
std::vector<std::string> HandlePlayerbotCommand(char const* args, Player* master = nullptr); std::vector<std::string> HandlePlayerbotCommand(char const* args, Player* master = nullptr);
std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin, uint32 masterAccountId, uint32 masterGuildId); std::string const ProcessBotCommand(std::string const cmd, ObjectGuid guid, ObjectGuid masterguid, bool admin,
uint32 GetAccountId(std::string const name); uint32 masterAccountId, uint32 masterGuildId);
uint32 GetAccountId(ObjectGuid guid); uint32 GetAccountId(std::string const name);
std::string const ListBots(Player* master); uint32 GetAccountId(ObjectGuid guid);
std::string const LookupBots(Player* master); std::string const ListBots(Player* master);
uint32 GetPlayerbotsCount() { return playerBots.size(); } std::string const LookupBots(Player* master);
uint32 GetPlayerbotsCountByClass(uint32 cls); uint32 GetPlayerbotsCount() { return playerBots.size(); }
protected: uint32 GetPlayerbotsCountByClass(uint32 cls);
virtual void OnBotLoginInternal(Player* const bot) = 0;
PlayerBotMap playerBots; protected:
virtual void OnBotLoginInternal(Player* const bot) = 0;
PlayerBotMap playerBots;
}; };
class PlayerbotMgr : public PlayerbotHolder class PlayerbotMgr : public PlayerbotHolder
{ {
public: public:
PlayerbotMgr(Player* const master); PlayerbotMgr(Player* const master);
virtual ~PlayerbotMgr(); virtual ~PlayerbotMgr();
static bool HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args); static bool HandlePlayerbotMgrCommand(ChatHandler* handler, char const* args);
void HandleMasterIncomingPacket(WorldPacket const& packet); void HandleMasterIncomingPacket(WorldPacket const& packet);
void HandleMasterOutgoingPacket(WorldPacket const& packet); void HandleMasterOutgoingPacket(WorldPacket const& packet);
void HandleCommand(uint32 type, std::string const text); void HandleCommand(uint32 type, std::string const text);
void OnPlayerLogin(Player* player); void OnPlayerLogin(Player* player);
void CancelLogout(); void CancelLogout();
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override; void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
void TellError(std::string const botName, std::string const text); void TellError(std::string const botName, std::string const text);
Player* GetMaster() const { return master; }; Player* GetMaster() const { return master; };
void SaveToDB(); void SaveToDB();
protected: protected:
void OnBotLoginInternal(Player* const bot) override; void OnBotLoginInternal(Player* const bot) override;
void CheckTellErrors(uint32 elapsed); void CheckTellErrors(uint32 elapsed);
private: private:
Player* const master; Player* const master;
PlayerBotErrorMap errors; PlayerBotErrorMap errors;
time_t lastErrorTell; time_t lastErrorTell;
}; };
class PlayerbotsMgr class PlayerbotsMgr
{ {
public: public:
PlayerbotsMgr() { } PlayerbotsMgr() {}
~PlayerbotsMgr() { } ~PlayerbotsMgr() {}
static PlayerbotsMgr* instance() static PlayerbotsMgr* instance()
{ {
static PlayerbotsMgr instance; static PlayerbotsMgr instance;
return &instance; return &instance;
} }
void AddPlayerbotData(Player* player, bool isBotAI); void AddPlayerbotData(Player* player, bool isBotAI);
void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI); void RemovePlayerBotData(ObjectGuid const& guid, bool is_AI);
PlayerbotAI* GetPlayerbotAI(Player* player); PlayerbotAI* GetPlayerbotAI(Player* player);
PlayerbotMgr* GetPlayerbotMgr(Player* player); PlayerbotMgr* GetPlayerbotMgr(Player* player);
private: private:
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsAIMap; std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsAIMap;
std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMgrMap; std::unordered_map<ObjectGuid, PlayerbotAIBase*> _playerbotsMgrMap;
}; };
#define sPlayerbotsMgr PlayerbotsMgr::instance() #define sPlayerbotsMgr PlayerbotsMgr::instance()

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "PlayerbotSecurity.h" #include "PlayerbotSecurity.h"
#include "LFGMgr.h" #include "LFGMgr.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -19,7 +21,8 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
return PLAYERBOT_SECURITY_ALLOW_ALL; return PLAYERBOT_SECURITY_ALLOW_ALL;
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot); PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI) { if (!botAI)
{
return PLAYERBOT_SECURITY_DENY_ALL; return PLAYERBOT_SECURITY_DENY_ALL;
} }
if (botAI->IsOpposing(from)) if (botAI->IsOpposing(from))
@@ -62,7 +65,8 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
} }
} }
if (sPlayerbotAIConfig->groupInvitationPermission <= 0) { if (sPlayerbotAIConfig->groupInvitationPermission <= 0)
{
if (reason) if (reason)
*reason = PLAYERBOT_DENY_NONE; *reason = PLAYERBOT_DENY_NONE;
@@ -85,9 +89,11 @@ PlayerbotSecurityLevel PlayerbotSecurity::LevelFor(Player* from, DenyReason* rea
if (sPlayerbotAIConfig->gearscorecheck) if (sPlayerbotAIConfig->gearscorecheck)
{ {
if (botGS && bot->GetLevel() > 15 && botGS > fromGS && if (botGS && bot->GetLevel() > 15 && botGS > fromGS &&
static_cast<float>(100 * (botGS - fromGS) / botGS) >= static_cast<float>(12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel())) static_cast<float>(100 * (botGS - fromGS) / botGS) >=
static_cast<float>(12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel()))
{ {
if (reason) *reason = PLAYERBOT_DENY_GEARSCORE; if (reason)
*reason = PLAYERBOT_DENY_GEARSCORE;
return PLAYERBOT_SECURITY_TALK; return PLAYERBOT_SECURITY_TALK;
} }
} }
@@ -195,37 +201,39 @@ bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent,
case PLAYERBOT_SECURITY_TALK: case PLAYERBOT_SECURITY_TALK:
switch (reason) switch (reason)
{ {
case PLAYERBOT_DENY_NONE: case PLAYERBOT_DENY_NONE:
out << "I'll do it later"; out << "I'll do it later";
break; break;
case PLAYERBOT_DENY_LOW_LEVEL: case PLAYERBOT_DENY_LOW_LEVEL:
out << "You are too low level: |cffff0000" << (uint32)from->GetLevel() << "|cffffffff/|cff00ff00" << (uint32)bot->GetLevel(); out << "You are too low level: |cffff0000" << (uint32)from->GetLevel() << "|cffffffff/|cff00ff00"
break; << (uint32)bot->GetLevel();
case PLAYERBOT_DENY_GEARSCORE: break;
case PLAYERBOT_DENY_GEARSCORE:
{ {
int botGS = (int)botAI->GetEquipGearScore(bot, false, false); int botGS = (int)botAI->GetEquipGearScore(bot, false, false);
int fromGS = (int)botAI->GetEquipGearScore(from, false, false); int fromGS = (int)botAI->GetEquipGearScore(from, false, false);
int diff = (100 * (botGS - fromGS) / botGS); int diff = (100 * (botGS - fromGS) / botGS);
int req = 12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel(); int req = 12 * sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) / from->GetLevel();
out << "Your gearscore is too low: |cffff0000" << fromGS << "|cffffffff/|cff00ff00" << botGS << " |cffff0000" << diff << "%|cffffffff/|cff00ff00" << req << "%"; out << "Your gearscore is too low: |cffff0000" << fromGS << "|cffffffff/|cff00ff00" << botGS
<< " |cffff0000" << diff << "%|cffffffff/|cff00ff00" << req << "%";
} }
break; break;
case PLAYERBOT_DENY_NOT_YOURS: case PLAYERBOT_DENY_NOT_YOURS:
out << "I have a master already"; out << "I have a master already";
break; break;
case PLAYERBOT_DENY_IS_BOT: case PLAYERBOT_DENY_IS_BOT:
out << "You are a bot"; out << "You are a bot";
break; break;
case PLAYERBOT_DENY_OPPOSING: case PLAYERBOT_DENY_OPPOSING:
out << "You are the enemy"; out << "You are the enemy";
break; break;
case PLAYERBOT_DENY_DEAD: case PLAYERBOT_DENY_DEAD:
out << "I'm dead. Will do it later"; out << "I'm dead. Will do it later";
break; break;
case PLAYERBOT_DENY_INVITE: case PLAYERBOT_DENY_INVITE:
out << "Invite me to your group first"; out << "Invite me to your group first";
break; break;
case PLAYERBOT_DENY_FAR: case PLAYERBOT_DENY_FAR:
{ {
out << "You must be closer to invite me to your group. I am in "; out << "You must be closer to invite me to your group. I am in ";
@@ -235,31 +243,32 @@ bool PlayerbotSecurity::CheckLevelFor(PlayerbotSecurityLevel level, bool silent,
} }
} }
break; break;
case PLAYERBOT_DENY_FULL_GROUP: case PLAYERBOT_DENY_FULL_GROUP:
out << "I am in a full group. Will do it later"; out << "I am in a full group. Will do it later";
break; break;
case PLAYERBOT_DENY_IS_LEADER: case PLAYERBOT_DENY_IS_LEADER:
out << "I am currently leading a group. I can invite you if you want."; out << "I am currently leading a group. I can invite you if you want.";
break; break;
case PLAYERBOT_DENY_NOT_LEADER: case PLAYERBOT_DENY_NOT_LEADER:
if (botAI->GetGroupMaster()) if (botAI->GetGroupMaster())
{ {
out << "I am in a group with " << botAI->GetGroupMaster()->GetName() << ". You can ask him for invite."; out << "I am in a group with " << botAI->GetGroupMaster()->GetName()
} << ". You can ask him for invite.";
else }
{ else
out << "I am in a group with someone else. You can ask him for invite."; {
} out << "I am in a group with someone else. You can ask him for invite.";
break; }
case PLAYERBOT_DENY_BG: break;
out << "I am in a queue for BG. Will do it later"; case PLAYERBOT_DENY_BG:
break; out << "I am in a queue for BG. Will do it later";
case PLAYERBOT_DENY_LFG: break;
out << "I am in a queue for dungeon. Will do it later"; case PLAYERBOT_DENY_LFG:
break; out << "I am in a queue for dungeon. Will do it later";
default: break;
out << "I can't do that"; default:
break; out << "I can't do that";
break;
} }
break; break;
case PLAYERBOT_SECURITY_INVITE: case PLAYERBOT_SECURITY_INVITE:

View File

@@ -1,23 +1,24 @@
/* /*
* 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. * 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_PLAYERBOTSECURITY_H #ifndef _PLAYERBOT_PLAYERBOTSECURITY_H
#define _PLAYERBOT_PLAYERBOTSECURITY_H #define _PLAYERBOT_PLAYERBOTSECURITY_H
#include <map>
#include "Common.h" #include "Common.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include <map>
class Player; class Player;
enum PlayerbotSecurityLevel : uint32 enum PlayerbotSecurityLevel : uint32
{ {
PLAYERBOT_SECURITY_DENY_ALL = 0, PLAYERBOT_SECURITY_DENY_ALL = 0,
PLAYERBOT_SECURITY_TALK = 1, PLAYERBOT_SECURITY_TALK = 1,
PLAYERBOT_SECURITY_INVITE = 2, PLAYERBOT_SECURITY_INVITE = 2,
PLAYERBOT_SECURITY_ALLOW_ALL = 3 PLAYERBOT_SECURITY_ALLOW_ALL = 3
}; };
enum DenyReason enum DenyReason
@@ -40,16 +41,16 @@ enum DenyReason
class PlayerbotSecurity class PlayerbotSecurity
{ {
public: public:
PlayerbotSecurity(Player* const bot); PlayerbotSecurity(Player* const bot);
PlayerbotSecurityLevel LevelFor(Player* from, DenyReason* reason = nullptr, bool ignoreGroup = false); PlayerbotSecurityLevel LevelFor(Player* from, DenyReason* reason = nullptr, bool ignoreGroup = false);
bool CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* from, bool ignoreGroup = false); bool CheckLevelFor(PlayerbotSecurityLevel level, bool silent, Player* from, bool ignoreGroup = false);
private: private:
Player* const bot; Player* const bot;
uint32 account; uint32 account;
std::map<ObjectGuid, std::map<std::string, time_t> > whispers; std::map<ObjectGuid, std::map<std::string, time_t> > whispers;
}; };
#endif #endif

View File

@@ -1,17 +1,21 @@
/* /*
* 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. * 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 "PlayerbotTextMgr.h" #include "PlayerbotTextMgr.h"
#include "Playerbots.h" #include "Playerbots.h"
void PlayerbotTextMgr::replaceAll(std::string & str, const std::string & from, const std::string & to) { void PlayerbotTextMgr::replaceAll(std::string& str, const std::string& from, const std::string& to)
{
if (from.empty()) if (from.empty())
return; return;
size_t start_pos = 0; size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos) { while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to); str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
} }
} }
@@ -20,7 +24,8 @@ void PlayerbotTextMgr::LoadBotTexts()
LOG_INFO("playerbots", "Loading playerbots texts..."); LOG_INFO("playerbots", "Loading playerbots texts...");
uint32 count = 0; uint32 count = 0;
if (PreparedQueryResult result = PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_TEXT))) if (PreparedQueryResult result =
PlayerbotsDatabase.Query(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_TEXT)))
{ {
do do
{ {
@@ -37,8 +42,7 @@ void PlayerbotTextMgr::LoadBotTexts()
botTexts[name].push_back(BotTextEntry(name, text, sayType, replyType)); botTexts[name].push_back(BotTextEntry(name, text, sayType, replyType));
++count; ++count;
} } while (result->NextRow());
while (result->NextRow());
} }
LOG_INFO("playerbots", "{} playerbots texts loaded", count); LOG_INFO("playerbots", "{} playerbots texts loaded", count);
@@ -123,14 +127,14 @@ std::string PlayerbotTextMgr::GetBotText(ChatReplyType replyType, std::map<std::
return ""; return "";
BotTextEntry textEntry = proper_list[urand(0, proper_list.size() - 1)]; BotTextEntry textEntry = proper_list[urand(0, proper_list.size() - 1)];
std::string botText = !textEntry.m_text[GetLocalePriority()].empty() ? textEntry.m_text[GetLocalePriority()] : textEntry.m_text[0]; std::string botText =
for (auto & placeholder : placeholders) !textEntry.m_text[GetLocalePriority()].empty() ? textEntry.m_text[GetLocalePriority()] : textEntry.m_text[0];
for (auto& placeholder : placeholders)
replaceAll(botText, placeholder.first, placeholder.second); replaceAll(botText, placeholder.first, placeholder.second);
return botText; return botText;
} }
std::string PlayerbotTextMgr::GetBotText(ChatReplyType replyType, std::string name) std::string PlayerbotTextMgr::GetBotText(ChatReplyType replyType, std::string name)
{ {
std::map<std::string, std::string> placeholders; std::map<std::string, std::string> placeholders;
@@ -149,7 +153,7 @@ bool PlayerbotTextMgr::rollTextChance(std::string name)
return urand(0, 100) < botTextChance[name]; return urand(0, 100) < botTextChance[name];
} }
bool PlayerbotTextMgr::GetBotText(std::string name, std::string &text) bool PlayerbotTextMgr::GetBotText(std::string name, std::string& text)
{ {
if (!rollTextChance(name)) if (!rollTextChance(name))
return false; return false;
@@ -167,7 +171,6 @@ bool PlayerbotTextMgr::GetBotText(std::string name, std::string& text, std::map<
return !text.empty(); return !text.empty();
} }
void PlayerbotTextMgr::AddLocalePriority(uint32 locale) void PlayerbotTextMgr::AddLocalePriority(uint32 locale)
{ {
if (!locale) if (!locale)

View File

@@ -1,21 +1,25 @@
/* /*
* 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. * 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_PLAYERBOTTEXTMGR_H #ifndef _PLAYERBOT_PLAYERBOTTEXTMGR_H
#define _PLAYERBOT_PLAYERBOTTEXTMGR_H #define _PLAYERBOT_PLAYERBOTTEXTMGR_H
#include "Common.h"
#include <map> #include <map>
#include <vector> #include <vector>
#include "Common.h"
#define BOT_TEXT1(name) sPlayerbotTextMgr->GetBotText(name) #define BOT_TEXT1(name) sPlayerbotTextMgr->GetBotText(name)
#define BOT_TEXT2(name, replace) sPlayerbotTextMgr->GetBotText(name, replace) #define BOT_TEXT2(name, replace) sPlayerbotTextMgr->GetBotText(name, replace)
struct BotTextEntry struct BotTextEntry
{ {
BotTextEntry(std::string name, std::map<uint32, std::string> text, uint32 say_type, uint32 reply_type) : m_name(name), m_text(text), m_sayType(say_type), m_replyType(reply_type) {} BotTextEntry(std::string name, std::map<uint32, std::string> text, uint32 say_type, uint32 reply_type)
: m_name(name), m_text(text), m_sayType(say_type), m_replyType(reply_type)
{
}
std::string m_name; std::string m_name;
std::map<uint32, std::string> m_text; std::map<uint32, std::string> m_text;
uint32 m_sayType; uint32 m_sayType;
@@ -31,7 +35,11 @@ struct ChatReplyData
struct ChatQueuedReply struct ChatQueuedReply
{ {
ChatQueuedReply(uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name, time_t time) : m_type(type), m_guid1(guid1), m_guid2(guid2), m_msg(msg), m_chanName(chanName), m_name(name), m_time(time) {} ChatQueuedReply(uint32 type, uint32 guid1, uint32 guid2, std::string msg, std::string chanName, std::string name,
time_t time)
: m_type(type), m_guid1(guid1), m_guid2(guid2), m_msg(msg), m_chanName(chanName), m_name(name), m_time(time)
{
}
uint32 m_type; uint32 m_type;
uint32 m_guid1; uint32 m_guid1;
uint32 m_guid2; uint32 m_guid2;
@@ -54,39 +62,40 @@ enum ChatReplyType
class PlayerbotTextMgr class PlayerbotTextMgr
{ {
public: public:
PlayerbotTextMgr() { PlayerbotTextMgr()
for (uint8 i = 0; i < MAX_LOCALES; ++i) {
{ for (uint8 i = 0; i < MAX_LOCALES; ++i)
botTextLocalePriority[i] = 0;
}
};
virtual ~PlayerbotTextMgr() { };
static PlayerbotTextMgr* instance()
{ {
static PlayerbotTextMgr instance; botTextLocalePriority[i] = 0;
return &instance;
} }
};
virtual ~PlayerbotTextMgr(){};
static PlayerbotTextMgr* instance()
{
static PlayerbotTextMgr instance;
return &instance;
}
std::string GetBotText(std::string name, std::map<std::string, std::string> placeholders); std::string GetBotText(std::string name, std::map<std::string, std::string> placeholders);
std::string GetBotText(std::string name); std::string GetBotText(std::string name);
std::string GetBotText(ChatReplyType replyType, std::map<std::string, std::string> placeholders); std::string GetBotText(ChatReplyType replyType, std::map<std::string, std::string> placeholders);
std::string GetBotText(ChatReplyType replyType, std::string name); std::string GetBotText(ChatReplyType replyType, std::string name);
bool GetBotText(std::string name, std::string& text); bool GetBotText(std::string name, std::string& text);
bool GetBotText(std::string name, std::string& text, std::map<std::string, std::string> placeholders); bool GetBotText(std::string name, std::string& text, std::map<std::string, std::string> placeholders);
void LoadBotTexts(); void LoadBotTexts();
void LoadBotTextChance(); void LoadBotTextChance();
static void replaceAll(std::string& str, const std::string& from, const std::string& to); static void replaceAll(std::string& str, const std::string& from, const std::string& to);
bool rollTextChance(std::string text); bool rollTextChance(std::string text);
uint32 GetLocalePriority(); uint32 GetLocalePriority();
void AddLocalePriority(uint32 locale); void AddLocalePriority(uint32 locale);
void ResetLocalePriority(); void ResetLocalePriority();
private: private:
std::map<std::string, std::vector<BotTextEntry>> botTexts; std::map<std::string, std::vector<BotTextEntry>> botTexts;
std::map<std::string, uint32 > botTextChance; std::map<std::string, uint32> botTextChance;
uint32 botTextLocalePriority[MAX_LOCALES]; uint32 botTextLocalePriority[MAX_LOCALES];
}; };
#define sPlayerbotTextMgr PlayerbotTextMgr::instance() #define sPlayerbotTextMgr PlayerbotTextMgr::instance()

View File

@@ -15,327 +15,320 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "cs_playerbots.h" #include "Playerbots.h"
#include "Channel.h" #include "Channel.h"
#include "Config.h" #include "Config.h"
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "DatabaseLoader.h" #include "DatabaseLoader.h"
#include "GuildTaskMgr.h" #include "GuildTaskMgr.h"
#include "Metric.h" #include "Metric.h"
#include "Playerbots.h"
#include "RandomPlayerbotMgr.h" #include "RandomPlayerbotMgr.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "cs_playerbots.h"
class PlayerbotsDatabaseScript : public DatabaseScript class PlayerbotsDatabaseScript : public DatabaseScript
{ {
public: public:
PlayerbotsDatabaseScript() : DatabaseScript("PlayerbotsDatabaseScript") { } PlayerbotsDatabaseScript() : DatabaseScript("PlayerbotsDatabaseScript") {}
bool OnDatabasesLoading() override bool OnDatabasesLoading() override
{
DatabaseLoader playerbotLoader("server.playerbots");
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("Playerbots.Updates.EnableDatabases", true)
? DatabaseLoader::DATABASE_PLAYERBOTS
: 0);
playerbotLoader.AddDatabase(PlayerbotsDatabase, "Playerbots");
return playerbotLoader.Load();
}
void OnDatabasesKeepAlive() override { PlayerbotsDatabase.KeepAlive(); }
void OnDatabasesClosing() override { PlayerbotsDatabase.Close(); }
void OnDatabaseWarnAboutSyncQueries(bool apply) override { PlayerbotsDatabase.WarnAboutSyncQueries(apply); }
void OnDatabaseSelectIndexLogout(Player* player, uint32& statementIndex, uint32& statementParam) override
{
statementIndex = CHAR_UPD_CHAR_ONLINE;
statementParam = player->GetGUID().GetCounter();
}
void OnDatabaseGetDBRevision(std::string& revision) override
{
if (QueryResult resultPlayerbot =
PlayerbotsDatabase.Query("SELECT date FROM version_db_playerbots ORDER BY date DESC LIMIT 1"))
{ {
DatabaseLoader playerbotLoader("server.playerbots"); Field* fields = resultPlayerbot->Fetch();
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("Playerbots.Updates.EnableDatabases", true) ? DatabaseLoader::DATABASE_PLAYERBOTS : 0); revision = fields[0].Get<std::string>();
playerbotLoader.AddDatabase(PlayerbotsDatabase, "Playerbots");
return playerbotLoader.Load();
} }
void OnDatabasesKeepAlive() override if (revision.empty())
{ {
PlayerbotsDatabase.KeepAlive(); revision = "Unknown Playerbots Database Revision";
}
void OnDatabasesClosing() override
{
PlayerbotsDatabase.Close();
}
void OnDatabaseWarnAboutSyncQueries(bool apply) override
{
PlayerbotsDatabase.WarnAboutSyncQueries(apply);
}
void OnDatabaseSelectIndexLogout(Player* player, uint32& statementIndex, uint32& statementParam) override
{
statementIndex = CHAR_UPD_CHAR_ONLINE;
statementParam = player->GetGUID().GetCounter();
}
void OnDatabaseGetDBRevision(std::string& revision) override
{
if (QueryResult resultPlayerbot = PlayerbotsDatabase.Query("SELECT date FROM version_db_playerbots ORDER BY date DESC LIMIT 1"))
{
Field* fields = resultPlayerbot->Fetch();
revision = fields[0].Get<std::string>();
}
if (revision.empty())
{
revision = "Unknown Playerbots Database Revision";
}
} }
}
}; };
class PlayerbotsMetricScript : public MetricScript class PlayerbotsMetricScript : public MetricScript
{ {
public: public:
PlayerbotsMetricScript() : MetricScript("PlayerbotsMetricScript") { } PlayerbotsMetricScript() : MetricScript("PlayerbotsMetricScript") {}
void OnMetricLogging() override void OnMetricLogging() override
{
if (sMetric->IsEnabled())
{ {
if (sMetric->IsEnabled()) sMetric->LogValue("db_queue_playerbots", uint64(PlayerbotsDatabase.QueueSize()), {});
{
sMetric->LogValue("db_queue_playerbots", uint64(PlayerbotsDatabase.QueueSize()), {});
}
} }
}
}; };
class PlayerbotsPlayerScript : public PlayerScript class PlayerbotsPlayerScript : public PlayerScript
{ {
public: public:
PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript") { } PlayerbotsPlayerScript() : PlayerScript("PlayerbotsPlayerScript") {}
void OnLogin(Player* player) override void OnLogin(Player* player) override
{
if (!player->GetSession()->IsBot())
{ {
if (!player->GetSession()->IsBot()) sPlayerbotsMgr->AddPlayerbotData(player, false);
sRandomPlayerbotMgr->OnPlayerLogin(player);
}
}
void OnAfterUpdate(Player* player, uint32 diff) override
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{
botAI->UpdateAI(diff);
}
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
playerbotMgr->UpdateAI(diff);
}
}
bool CanPlayerUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
{
if (type == CHAT_MSG_WHISPER)
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver))
{ {
sPlayerbotsMgr->AddPlayerbotData(player, false); botAI->HandleCommand(type, msg, player);
sRandomPlayerbotMgr->OnPlayerLogin(player);
return false;
} }
} }
void OnAfterUpdate(Player* player, uint32 diff) override return true;
{ }
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{
botAI->UpdateAI(diff);
}
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
{ {
playerbotMgr->UpdateAI(diff); for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
}
}
bool CanPlayerUseChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Player* receiver) override
{ {
if (type == CHAT_MSG_WHISPER) if (Player* member = itr->GetSource())
{ {
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(receiver)) if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member))
{ {
botAI->HandleCommand(type, msg, player); botAI->HandleCommand(type, msg, player);
return false;
}
}
return true;
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Group* group) override
{
for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
{
if (Player* member = itr->GetSource())
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(member))
{
botAI->HandleCommand(type, msg, player);
}
} }
} }
} }
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg) override
{
if (type == CHAT_MSG_GUILD)
{ {
if (type == CHAT_MSG_GUILD) if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{ {
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin();
it != playerbotMgr->GetPlayerBotsEnd(); ++it)
{ {
for (PlayerBotMap::const_iterator it = playerbotMgr->GetPlayerBotsBegin(); it != playerbotMgr->GetPlayerBotsEnd(); ++it) if (Player* const bot = it->second)
{ {
if (Player* const bot = it->second) if (bot->GetGuildId() == player->GetGuildId())
{ {
if (bot->GetGuildId() == player->GetGuildId()) GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player);
{
GET_PLAYERBOT_AI(bot)->HandleCommand(type, msg, player);
}
} }
} }
} }
} }
} }
}
void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override void OnChat(Player* player, uint32 type, uint32 /*lang*/, std::string& msg, Channel* channel) override
{
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{ {
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) if (channel->GetFlags() & 0x18)
{ {
if (channel->GetFlags() & 0x18) playerbotMgr->HandleCommand(type, msg);
{
playerbotMgr->HandleCommand(type, msg);
}
} }
sRandomPlayerbotMgr->HandleCommand(type, msg, player);
} }
bool OnBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override sRandomPlayerbotMgr->HandleCommand(type, msg, player);
{ }
if (sRandomPlayerbotMgr->IsRandomBot(player))
{
return false;
}
return true;
}
bool OnBeforeAchiComplete(Player* player, AchievementEntry const* /*achievement*/) override bool OnBeforeCriteriaProgress(Player* player, AchievementCriteriaEntry const* /*criteria*/) override
{
if (sRandomPlayerbotMgr->IsRandomBot(player))
{ {
if (sRandomPlayerbotMgr->IsRandomBot(player)) return false;
{
return false;
}
return true;
} }
return true;
}
bool OnBeforeAchiComplete(Player* player, AchievementEntry const* /*achievement*/) override
{
if (sRandomPlayerbotMgr->IsRandomBot(player))
{
return false;
}
return true;
}
}; };
class PlayerbotsMiscScript : public MiscScript class PlayerbotsMiscScript : public MiscScript
{ {
public: public:
PlayerbotsMiscScript() : MiscScript("PlayerbotsMiscScript", {MISCHOOK_ON_DESTRUCT_PLAYER}) { } PlayerbotsMiscScript() : MiscScript("PlayerbotsMiscScript", {MISCHOOK_ON_DESTRUCT_PLAYER}) {}
void OnDestructPlayer(Player* player) override void OnDestructPlayer(Player* player) override
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{ {
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) delete botAI;
{
delete botAI;
}
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
delete playerbotMgr;
}
} }
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
delete playerbotMgr;
}
}
}; };
class PlayerbotsServerScript : public ServerScript class PlayerbotsServerScript : public ServerScript
{ {
public: public:
PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript") { } PlayerbotsServerScript() : ServerScript("PlayerbotsServerScript") {}
void OnPacketReceived(WorldSession* session, WorldPacket const& packet) override void OnPacketReceived(WorldSession* session, WorldPacket const& packet) override
{ {
if (Player* player = session->GetPlayer()) if (Player* player = session->GetPlayer())
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
playerbotMgr->HandleMasterIncomingPacket(packet); playerbotMgr->HandleMasterIncomingPacket(packet);
} }
}; };
class PlayerbotsWorldScript : public WorldScript class PlayerbotsWorldScript : public WorldScript
{ {
public: public:
PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript") { } PlayerbotsWorldScript() : WorldScript("PlayerbotsWorldScript") {}
void OnBeforeWorldInitialized() override void OnBeforeWorldInitialized() override
{ {
uint32 oldMSTime = getMSTime(); uint32 oldMSTime = getMSTime();
LOG_INFO("server.loading", " "); LOG_INFO("server.loading", " ");
LOG_INFO("server.loading", "Load Playerbots Config..."); LOG_INFO("server.loading", "Load Playerbots Config...");
sPlayerbotAIConfig->Initialize(); sPlayerbotAIConfig->Initialize();
LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " "); LOG_INFO("server.loading", " ");
} }
}; };
class PlayerbotsScript : public PlayerbotScript class PlayerbotsScript : public PlayerbotScript
{ {
public: public:
PlayerbotsScript() : PlayerbotScript("PlayerbotsScript") { } PlayerbotsScript() : PlayerbotScript("PlayerbotsScript") {}
bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override bool OnPlayerbotCheckLFGQueue(lfg::Lfg5Guids const& guidsList) override
{
bool nonBotFound = false;
for (ObjectGuid const& guid : guidsList.guids)
{ {
bool nonBotFound = false; Player* player = ObjectAccessor::FindPlayer(guid);
for (ObjectGuid const& guid : guidsList.guids) if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player)))
{ {
Player* player = ObjectAccessor::FindPlayer(guid); nonBotFound = true;
if (guid.IsGroup() || (player && !GET_PLAYERBOT_AI(player))) break;
{
nonBotFound = true;
break;
}
} }
return nonBotFound;
} }
void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override return nonBotFound;
}
void OnPlayerbotCheckKillTask(Player* player, Unit* victim) override
{
if (player)
sGuildTaskMgr->CheckKillTask(player, victim);
}
void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override
{
if (found && GET_PLAYERBOT_AI(player))
found = false;
}
bool OnPlayerbotCheckUpdatesToSend(Player* player) override
{
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
return botAI->IsRealPlayer();
return true;
}
void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override
{
if (!player)
return;
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{ {
if (player) botAI->HandleBotOutgoingPacket(*packet);
sGuildTaskMgr->CheckKillTask(player, victim);
} }
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
void OnPlayerbotCheckPetitionAccount(Player* player, bool& found) override
{ {
if (found && GET_PLAYERBOT_AI(player)) playerbotMgr->HandleMasterOutgoingPacket(*packet);
found = false;
} }
}
bool OnPlayerbotCheckUpdatesToSend(Player* player) override void OnPlayerbotUpdate(uint32 diff) override
{ {
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player)) sRandomPlayerbotMgr->UpdateAI(diff);
return botAI->IsRealPlayer(); sRandomPlayerbotMgr->UpdateSessions();
}
return true; void OnPlayerbotUpdateSessions(Player* player) override
} {
if (player)
void OnPlayerbotPacketSent(Player* player, WorldPacket const* packet) override
{
if (!player)
return;
if (PlayerbotAI* botAI = GET_PLAYERBOT_AI(player))
{
botAI->HandleBotOutgoingPacket(*packet);
}
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player)) if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
playerbotMgr->UpdateSessions();
}
void OnPlayerbotLogout(Player* player) override
{
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
if (!botAI || botAI->IsRealPlayer())
{ {
playerbotMgr->HandleMasterOutgoingPacket(*packet); playerbotMgr->LogoutAllBots();
} }
} }
void OnPlayerbotUpdate(uint32 diff) override sRandomPlayerbotMgr->OnPlayerLogout(player);
{ }
sRandomPlayerbotMgr->UpdateAI(diff);
sRandomPlayerbotMgr->UpdateSessions();
}
void OnPlayerbotUpdateSessions(Player* player) override void OnPlayerbotLogoutBots() override { sRandomPlayerbotMgr->LogoutAllBots(); }
{
if (player)
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
playerbotMgr->UpdateSessions();
}
void OnPlayerbotLogout(Player* player) override
{
if (PlayerbotMgr* playerbotMgr = GET_PLAYERBOT_MGR(player))
{
PlayerbotAI* botAI = GET_PLAYERBOT_AI(player);
if (!botAI || botAI->IsRealPlayer())
{
playerbotMgr->LogoutAllBots();
}
}
sRandomPlayerbotMgr->OnPlayerLogout(player);
}
void OnPlayerbotLogoutBots() override
{
sRandomPlayerbotMgr->LogoutAllBots();
}
}; };
void AddPlayerbotsScripts() void AddPlayerbotsScripts()

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_H #ifndef _PLAYERBOT_H
@@ -43,7 +44,8 @@ int strcmpi(char const* s1, char const* s2);
#define RESET_AI_VALUE2(type, name, param) context->GetValue<type>(name, param)->Reset() #define RESET_AI_VALUE2(type, name, param) context->GetValue<type>(name, param)->Reset()
#define PAI_VALUE(type, name) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name)->Get() #define PAI_VALUE(type, name) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name)->Get()
#define PAI_VALUE2(type, name, param) sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name, param)->Get() #define PAI_VALUE2(type, name, param) \
sPlayerbotsMgr->GetPlayerbotAI(player)->GetAiObjectContext()->GetValue<type>(name, param)->Get()
#define GAI_VALUE(type, name) sSharedValueContext->getGlobalValue<type>(name)->Get() #define GAI_VALUE(type, name) sSharedValueContext->getGlobalValue<type>(name)->Get()
#define GAI_VALUE2(type, name, param) sSharedValueContext->getGlobalValue<type>(name, param)->Get() #define GAI_VALUE2(type, name, param) sSharedValueContext->getGlobalValue<type>(name, param)->Get()

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,19 @@
/* /*
* 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. * 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_RANDOMITEMMGR_H #ifndef _PLAYERBOT_RANDOMITEMMGR_H
#define _PLAYERBOT_RANDOMITEMMGR_H #define _PLAYERBOT_RANDOMITEMMGR_H
#include "AiFactory.h"
#include "Common.h"
#include "ItemTemplate.h"
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
#include "AiFactory.h"
#include "Common.h"
#include "ItemTemplate.h"
class ChatHandler; class ChatHandler;
struct ItemTemplate; struct ItemTemplate;
@@ -60,7 +61,8 @@ struct StatWeight
struct ItemInfoEntry struct ItemInfoEntry
{ {
ItemInfoEntry() : minLevel(0), source(0), sourceId(0), team(0), repRank(0), repFaction(0), quality(0), slot(0), itemId(0) ItemInfoEntry()
: minLevel(0), source(0), sourceId(0), team(0), repRank(0), repFaction(0), quality(0), slot(0), itemId(0)
{ {
for (uint8 i = 1; i <= MAX_STAT_SCALES; ++i) for (uint8 i = 1; i <= MAX_STAT_SCALES; ++i)
{ {
@@ -81,7 +83,7 @@ struct ItemInfoEntry
}; };
typedef std::vector<WeightScaleStat> WeightScaleStats; typedef std::vector<WeightScaleStat> WeightScaleStats;
//typedef std::map<WeightScaleInfo, WeightScaleStats> WeightScaleList; // typedef std::map<WeightScaleInfo, WeightScaleStats> WeightScaleList;
struct WeightScale struct WeightScale
{ {
@@ -89,14 +91,14 @@ struct WeightScale
WeightScaleStats stats; WeightScaleStats stats;
}; };
//typedef map<uint32, WeightScale> WeightScales; // typedef map<uint32, WeightScale> WeightScales;
class RandomItemPredicate class RandomItemPredicate
{ {
public: public:
virtual ~RandomItemPredicate() { }; virtual ~RandomItemPredicate(){};
virtual bool Apply(ItemTemplate const* proto) = 0; virtual bool Apply(ItemTemplate const* proto) = 0;
}; };
typedef std::vector<uint32> RandomItemList; typedef std::vector<uint32> RandomItemList;
@@ -104,102 +106,107 @@ typedef std::map<RandomItemType, RandomItemList> RandomItemCache;
class BotEquipKey class BotEquipKey
{ {
public: public:
BotEquipKey() : level(0), clazz(0), slot(0), quality(0), key(GetKey()) { } BotEquipKey() : level(0), clazz(0), slot(0), quality(0), key(GetKey()) {}
BotEquipKey(uint32 level, uint8 clazz, uint8 slot, uint32 quality) : level(level), clazz(clazz), slot(slot), quality(quality), key(GetKey()) { } BotEquipKey(uint32 level, uint8 clazz, uint8 slot, uint32 quality)
BotEquipKey(BotEquipKey const& other) : level(other.level), clazz(other.clazz), slot(other.slot), quality(other.quality), key(GetKey()) { } : level(level), clazz(clazz), slot(slot), quality(quality), key(GetKey())
{
}
BotEquipKey(BotEquipKey const& other)
: level(other.level), clazz(other.clazz), slot(other.slot), quality(other.quality), key(GetKey())
{
}
bool operator<(BotEquipKey const& other) const bool operator<(BotEquipKey const& other) const { return other.key < this->key; }
{
return other.key < this->key;
}
uint32 level; uint32 level;
uint8 clazz; uint8 clazz;
uint8 slot; uint8 slot;
uint32 quality; uint32 quality;
uint64 key; uint64 key;
private: private:
uint64 GetKey(); uint64 GetKey();
}; };
typedef std::map<BotEquipKey, RandomItemList> BotEquipCache; typedef std::map<BotEquipKey, RandomItemList> BotEquipCache;
class RandomItemMgr class RandomItemMgr
{ {
public: public:
RandomItemMgr(); RandomItemMgr();
virtual ~RandomItemMgr(); virtual ~RandomItemMgr();
static RandomItemMgr* instance() static RandomItemMgr* instance()
{ {
static RandomItemMgr instance; static RandomItemMgr instance;
return &instance; return &instance;
} }
public: public:
void Init(); void Init();
void InitAfterAhBot(); void InitAfterAhBot();
static bool HandleConsoleCommand(ChatHandler* handler, char const* args); static bool HandleConsoleCommand(ChatHandler* handler, char const* args);
RandomItemList Query(uint32 level, RandomItemType type, RandomItemPredicate* predicate); RandomItemList Query(uint32 level, RandomItemType type, RandomItemPredicate* predicate);
RandomItemList Query(uint32 level, uint8 clazz, uint8 slot, uint32 quality); RandomItemList Query(uint32 level, uint8 clazz, uint8 slot, uint32 quality);
uint32 GetUpgrade(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId); uint32 GetUpgrade(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId);
std::vector<uint32> GetUpgradeList(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId, uint32 amount = 1); std::vector<uint32> GetUpgradeList(Player* player, std::string spec, uint8 slot, uint32 quality, uint32 itemId,
bool HasStatWeight(uint32 itemId); uint32 amount = 1);
uint32 GetMinLevelFromCache(uint32 itemId); bool HasStatWeight(uint32 itemId);
uint32 GetStatWeight(Player* player, uint32 itemId); uint32 GetMinLevelFromCache(uint32 itemId);
uint32 GetLiveStatWeight(Player* player, uint32 itemId); uint32 GetStatWeight(Player* player, uint32 itemId);
uint32 GetRandomItem(uint32 level, RandomItemType type, RandomItemPredicate* predicate = nullptr); uint32 GetLiveStatWeight(Player* player, uint32 itemId);
uint32 GetAmmo(uint32 level, uint32 subClass); uint32 GetRandomItem(uint32 level, RandomItemType type, RandomItemPredicate* predicate = nullptr);
uint32 GetRandomPotion(uint32 level, uint32 effect); uint32 GetAmmo(uint32 level, uint32 subClass);
uint32 GetRandomFood(uint32 level, uint32 category); uint32 GetRandomPotion(uint32 level, uint32 effect);
uint32 GetFood(uint32 level, uint32 category); uint32 GetRandomFood(uint32 level, uint32 category);
uint32 GetRandomTrade(uint32 level); uint32 GetFood(uint32 level, uint32 category);
uint32 CalculateStatWeight(uint8 playerclass, uint8 spec, ItemTemplate const* proto); uint32 GetRandomTrade(uint32 level);
uint32 CalculateSingleStatWeight(uint8 playerclass, uint8 spec, std::string stat, uint32 value); uint32 CalculateStatWeight(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
bool CanEquipArmor(uint8 clazz, uint32 level, ItemTemplate const* proto); uint32 CalculateSingleStatWeight(uint8 playerclass, uint8 spec, std::string stat, uint32 value);
bool ShouldEquipArmorForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto); bool CanEquipArmor(uint8 clazz, uint32 level, ItemTemplate const* proto);
bool CanEquipWeapon(uint8 clazz, ItemTemplate const* proto); bool ShouldEquipArmorForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
bool ShouldEquipWeaponForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto); bool CanEquipWeapon(uint8 clazz, ItemTemplate const* proto);
float GetItemRarity(uint32 itemId); bool ShouldEquipWeaponForSpec(uint8 playerclass, uint8 spec, ItemTemplate const* proto);
uint32 GetQuestIdForItem(uint32 itemId); float GetItemRarity(uint32 itemId);
std::vector<uint32> GetQuestIdsForItem(uint32 itemId); uint32 GetQuestIdForItem(uint32 itemId);
static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId); std::vector<uint32> GetQuestIdsForItem(uint32 itemId);
bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); } static bool IsUsedBySkill(ItemTemplate const* proto, uint32 skillId);
std::vector<uint32> GetCachedEquipments(uint32 requiredLevel, uint32 inventoryType); bool IsTestItem(uint32 itemId) { return itemForTest.find(itemId) != itemForTest.end(); }
std::vector<uint32> GetCachedEquipments(uint32 requiredLevel, uint32 inventoryType);
private: private:
void BuildRandomItemCache(); void BuildRandomItemCache();
void BuildEquipCache(); void BuildEquipCache();
void BuildEquipCacheNew(); void BuildEquipCacheNew();
void BuildItemInfoCache(); void BuildItemInfoCache();
void BuildAmmoCache(); void BuildAmmoCache();
void BuildFoodCache(); void BuildFoodCache();
void BuildPotionCache(); void BuildPotionCache();
void BuildTradeCache(); void BuildTradeCache();
void BuildRarityCache(); void BuildRarityCache();
bool CanEquipItem(BotEquipKey key, ItemTemplate const* proto); bool CanEquipItem(BotEquipKey key, ItemTemplate const* proto);
bool CanEquipItemNew(ItemTemplate const* proto); bool CanEquipItemNew(ItemTemplate const* proto);
void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank); void AddItemStats(uint32 mod, uint8& sp, uint8& ap, uint8& tank);
bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank); bool CheckItemStats(uint8 clazz, uint8 sp, uint8 ap, uint8 tank);
private:
std::map<uint32, RandomItemCache> randomItemCache; private:
std::map<RandomItemType, RandomItemPredicate*> predicates; std::map<uint32, RandomItemCache> randomItemCache;
BotEquipCache equipCache; std::map<RandomItemType, RandomItemPredicate*> predicates;
std::map<EquipmentSlots, std::set<InventoryType>> viableSlots; BotEquipCache equipCache;
std::map<uint32, std::map<uint32, uint32> > ammoCache; std::map<EquipmentSlots, std::set<InventoryType>> viableSlots;
std::map<uint32, std::map<uint32, std::vector<uint32> > > potionCache; std::map<uint32, std::map<uint32, uint32>> ammoCache;
std::map<uint32, std::map<uint32, std::vector<uint32> > > foodCache; std::map<uint32, std::map<uint32, std::vector<uint32>>> potionCache;
std::map<uint32, std::vector<uint32> > tradeCache; std::map<uint32, std::map<uint32, std::vector<uint32>>> foodCache;
std::map<uint32, float> rarityCache; std::map<uint32, std::vector<uint32>> tradeCache;
std::map<uint8, WeightScale> m_weightScales[MAX_CLASSES]; std::map<uint32, float> rarityCache;
std::map<std::string, uint32 > weightStatLink; std::map<uint8, WeightScale> m_weightScales[MAX_CLASSES];
std::map<std::string, uint32 > weightRatingLink; std::map<std::string, uint32> weightStatLink;
std::map<uint32, ItemInfoEntry> itemInfoCache; std::map<std::string, uint32> weightRatingLink;
std::set<uint32> itemForTest; std::map<uint32, ItemInfoEntry> itemInfoCache;
static std::set<uint32> itemCache; std::set<uint32> itemForTest;
// equipCacheNew[RequiredLevel][InventoryType] static std::set<uint32> itemCache;
std::map<uint32, std::map<uint32, std::vector<uint32>>> equipCacheNew; // equipCacheNew[RequiredLevel][InventoryType]
std::map<uint32, std::map<uint32, std::vector<uint32>>> equipCacheNew;
}; };
#define sRandomItemMgr RandomItemMgr::instance() #define sRandomItemMgr RandomItemMgr::instance()

View File

@@ -1,14 +1,16 @@
/* /*
* 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. * 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 "RandomPlayerbotFactory.h" #include "RandomPlayerbotFactory.h"
#include "ArenaTeamMgr.h"
#include "AccountMgr.h" #include "AccountMgr.h"
#include "ArenaTeamMgr.h"
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "GuildMgr.h" #include "GuildMgr.h"
#include "Playerbots.h"
#include "PlayerbotFactory.h" #include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "SocialMgr.h" #include "SocialMgr.h"
@@ -26,14 +28,14 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_WARRIOR].push_back(RACE_UNDEAD_PLAYER); availableRaces[CLASS_WARRIOR].push_back(RACE_UNDEAD_PLAYER);
availableRaces[CLASS_WARRIOR].push_back(RACE_TAUREN); availableRaces[CLASS_WARRIOR].push_back(RACE_TAUREN);
availableRaces[CLASS_WARRIOR].push_back(RACE_TROLL); availableRaces[CLASS_WARRIOR].push_back(RACE_TROLL);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_WARRIOR].push_back(RACE_DRAENEI); availableRaces[CLASS_WARRIOR].push_back(RACE_DRAENEI);
} }
availableRaces[CLASS_PALADIN].push_back(RACE_HUMAN); availableRaces[CLASS_PALADIN].push_back(RACE_HUMAN);
availableRaces[CLASS_PALADIN].push_back(RACE_DWARF); availableRaces[CLASS_PALADIN].push_back(RACE_DWARF);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_PALADIN].push_back(RACE_DRAENEI); availableRaces[CLASS_PALADIN].push_back(RACE_DRAENEI);
availableRaces[CLASS_PALADIN].push_back(RACE_BLOODELF); availableRaces[CLASS_PALADIN].push_back(RACE_BLOODELF);
@@ -45,7 +47,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_ROGUE].push_back(RACE_GNOME); availableRaces[CLASS_ROGUE].push_back(RACE_GNOME);
availableRaces[CLASS_ROGUE].push_back(RACE_ORC); availableRaces[CLASS_ROGUE].push_back(RACE_ORC);
availableRaces[CLASS_ROGUE].push_back(RACE_TROLL); availableRaces[CLASS_ROGUE].push_back(RACE_TROLL);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_ROGUE].push_back(RACE_BLOODELF); availableRaces[CLASS_ROGUE].push_back(RACE_BLOODELF);
} }
@@ -55,7 +57,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_PRIEST].push_back(RACE_NIGHTELF); availableRaces[CLASS_PRIEST].push_back(RACE_NIGHTELF);
availableRaces[CLASS_PRIEST].push_back(RACE_TROLL); availableRaces[CLASS_PRIEST].push_back(RACE_TROLL);
availableRaces[CLASS_PRIEST].push_back(RACE_UNDEAD_PLAYER); availableRaces[CLASS_PRIEST].push_back(RACE_UNDEAD_PLAYER);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_PRIEST].push_back(RACE_DRAENEI); availableRaces[CLASS_PRIEST].push_back(RACE_DRAENEI);
availableRaces[CLASS_PRIEST].push_back(RACE_BLOODELF); availableRaces[CLASS_PRIEST].push_back(RACE_BLOODELF);
@@ -65,7 +67,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_MAGE].push_back(RACE_GNOME); availableRaces[CLASS_MAGE].push_back(RACE_GNOME);
availableRaces[CLASS_MAGE].push_back(RACE_UNDEAD_PLAYER); availableRaces[CLASS_MAGE].push_back(RACE_UNDEAD_PLAYER);
availableRaces[CLASS_MAGE].push_back(RACE_TROLL); availableRaces[CLASS_MAGE].push_back(RACE_TROLL);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_MAGE].push_back(RACE_DRAENEI); availableRaces[CLASS_MAGE].push_back(RACE_DRAENEI);
availableRaces[CLASS_MAGE].push_back(RACE_BLOODELF); availableRaces[CLASS_MAGE].push_back(RACE_BLOODELF);
@@ -75,7 +77,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_WARLOCK].push_back(RACE_GNOME); availableRaces[CLASS_WARLOCK].push_back(RACE_GNOME);
availableRaces[CLASS_WARLOCK].push_back(RACE_UNDEAD_PLAYER); availableRaces[CLASS_WARLOCK].push_back(RACE_UNDEAD_PLAYER);
availableRaces[CLASS_WARLOCK].push_back(RACE_ORC); availableRaces[CLASS_WARLOCK].push_back(RACE_ORC);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_WARLOCK].push_back(RACE_BLOODELF); availableRaces[CLASS_WARLOCK].push_back(RACE_BLOODELF);
} }
@@ -83,7 +85,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_SHAMAN].push_back(RACE_ORC); availableRaces[CLASS_SHAMAN].push_back(RACE_ORC);
availableRaces[CLASS_SHAMAN].push_back(RACE_TAUREN); availableRaces[CLASS_SHAMAN].push_back(RACE_TAUREN);
availableRaces[CLASS_SHAMAN].push_back(RACE_TROLL); availableRaces[CLASS_SHAMAN].push_back(RACE_TROLL);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_SHAMAN].push_back(RACE_DRAENEI); availableRaces[CLASS_SHAMAN].push_back(RACE_DRAENEI);
} }
@@ -93,7 +95,7 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
availableRaces[CLASS_HUNTER].push_back(RACE_ORC); availableRaces[CLASS_HUNTER].push_back(RACE_ORC);
availableRaces[CLASS_HUNTER].push_back(RACE_TAUREN); availableRaces[CLASS_HUNTER].push_back(RACE_TAUREN);
availableRaces[CLASS_HUNTER].push_back(RACE_TROLL); availableRaces[CLASS_HUNTER].push_back(RACE_TROLL);
if(expansion >= EXPANSION_THE_BURNING_CRUSADE) if (expansion >= EXPANSION_THE_BURNING_CRUSADE)
{ {
availableRaces[CLASS_HUNTER].push_back(RACE_DRAENEI); availableRaces[CLASS_HUNTER].push_back(RACE_DRAENEI);
availableRaces[CLASS_HUNTER].push_back(RACE_BLOODELF); availableRaces[CLASS_HUNTER].push_back(RACE_BLOODELF);
@@ -119,27 +121,30 @@ RandomPlayerbotFactory::RandomPlayerbotFactory(uint32 accountId) : accountId(acc
Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls) Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls)
{ {
LOG_DEBUG("playerbots", "Creating new random bot for class {}", cls); LOG_DEBUG("playerbots", "Creating new random bot for class {}", cls);
uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE; uint8 gender = rand() % 2 ? GENDER_MALE : GENDER_FEMALE;
uint8 alliance = rand() % 2; uint8 alliance = rand() % 2;
uint8 race; uint8 race;
for (int attempt = 0; attempt < 15; attempt++) { for (int attempt = 0; attempt < 15; attempt++)
{
race = availableRaces[cls][urand(0, availableRaces[cls].size() - 1)]; race = availableRaces[cls][urand(0, availableRaces[cls].size() - 1)];
if ((alliance && IsAlliance(race)) || (!alliance && !IsAlliance(race))) { if ((alliance && IsAlliance(race)) || (!alliance && !IsAlliance(race)))
{
break; break;
} }
} }
std::string name = CreateRandomBotName(gender); std::string name = CreateRandomBotName(gender);
if (name.empty()) { if (name.empty())
{
LOG_ERROR("playerbots", "Unable to get random bot name!"); LOG_ERROR("playerbots", "Unable to get random bot name!");
return nullptr; return nullptr;
} }
CharacterDatabase.DirectExecute("UPDATE playerbots_names SET in_use=1 WHERE name='{}'", name); CharacterDatabase.DirectExecute("UPDATE playerbots_names SET in_use=1 WHERE name='{}'", name);
std::vector<uint8> skinColors, facialHairTypes; std::vector<uint8> skinColors, facialHairTypes;
std::vector<std::pair<uint8,uint8>> faces, hairs; std::vector<std::pair<uint8, uint8>> faces, hairs;
for (CharSectionsEntry const* charSection : sCharSectionsStore) for (CharSectionsEntry const* charSection : sCharSectionsStore)
{ {
if (charSection->Race != race || charSection->Gender != gender) if (charSection->Race != race || charSection->Gender != gender)
@@ -166,19 +171,22 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
std::pair<uint8, uint8> face = faces[urand(0, faces.size() - 1)]; std::pair<uint8, uint8> face = faces[urand(0, faces.size() - 1)];
std::pair<uint8, uint8> hair = hairs[urand(0, hairs.size() - 1)]; std::pair<uint8, uint8> hair = hairs[urand(0, hairs.size() - 1)];
bool excludeCheck = (race == RACE_TAUREN) || (race == RACE_DRAENEI) || (gender == GENDER_FEMALE && race != RACE_NIGHTELF && race != RACE_UNDEAD_PLAYER); bool excludeCheck = (race == RACE_TAUREN) || (race == RACE_DRAENEI) ||
uint8 facialHair = excludeCheck ? 0 : facialHairTypes[urand(0, facialHairTypes.size() - 1)]; (gender == GENDER_FEMALE && race != RACE_NIGHTELF && race != RACE_UNDEAD_PLAYER);
uint8 facialHair = excludeCheck ? 0 : facialHairTypes[urand(0, facialHairTypes.size() - 1)];
std::unique_ptr<CharacterCreateInfo> characterInfo = std::make_unique<CharacterCreateInfo>(name, race, cls, gender, face.second, face.first, hair.first, hair.second, facialHair); std::unique_ptr<CharacterCreateInfo> characterInfo = std::make_unique<CharacterCreateInfo>(
name, race, cls, gender, face.second, face.first, hair.first, hair.second, facialHair);
Player* player = new Player(session); Player* player = new Player(session);
player->GetMotionMaster()->Initialize(); player->GetMotionMaster()->Initialize();
if (!player->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), characterInfo.get())) if (!player->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), characterInfo.get()))
{ {
player->CleanupsBeforeDelete(); player->CleanupsBeforeDelete();
delete player; delete player;
LOG_ERROR("playerbots", "Unable to create random bot for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls); LOG_ERROR("playerbots", "Unable to create random bot for account {} - name: \"{}\"; race: {}; class: {}",
accountId, name.c_str(), race, cls);
return nullptr; return nullptr;
} }
@@ -186,12 +194,13 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls
player->SetAtLoginFlag(AT_LOGIN_NONE); player->SetAtLoginFlag(AT_LOGIN_NONE);
if (player->getClass() == CLASS_DEATH_KNIGHT) if (player->getClass() == CLASS_DEATH_KNIGHT)
{ {
player->learnSpell(50977, false); player->learnSpell(50977, false);
} }
// player->SaveToDB(true, false); // player->SaveToDB(true, false);
// player->RewardQuest(const Quest *quest, uint32 reward, Object *questGiver) // player->RewardQuest(const Quest *quest, uint32 reward, Object *questGiver)
LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls); LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId,
name.c_str(), race, cls);
return player; return player;
} }
@@ -200,9 +209,12 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender)
{ {
std::string botName = ""; std::string botName = "";
int tries = 10; int tries = 10;
while(--tries) { while (--tries)
QueryResult result = CharacterDatabase.Query("SELECT name FROM playerbots_names " {
"WHERE in_use = 0 AND gender = {} ORDER BY RAND() LIMIT 1", gender); QueryResult result = CharacterDatabase.Query(
"SELECT name FROM playerbots_names "
"WHERE in_use = 0 AND gender = {} ORDER BY RAND() LIMIT 1",
gender);
if (!result) if (!result)
{ {
break; break;
@@ -215,66 +227,57 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender)
} }
} }
//CONLANG NAME GENERATION // CONLANG NAME GENERATION
LOG_ERROR("playerbots", "No more names left for random bots. Attempting 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 groupCategory = "SCVKRU";
const std::string groupFormStart[2][4] = { const std::string groupFormStart[2][4] = {{"SV", "SV", "VK", "RV"}, {"V", "SU", "VS", "RV"}};
{"SV","SV","VK","RV"}, const std::string groupFormMid[2][6] = {{"CV", "CVC", "CVC", "CVK", "VC", "VK"},
{"V" ,"SU","VS","RV"} {"CV", "CVC", "CVK", "KVC", "VC", "KV"}};
}; const std::string groupFormEnd[2][4] = {{"CV", "VC", "VK", "CV"}, {"RU", "UR", "VR", "V"}};
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] = { const std::string groupLetter[2][6] = {
//S C V K R U // S C V K R U
{"dtspkThfS","bcCdfghjkmnNqqrrlsStTvwxyz","aaeeiouA" ,"ppttkkbdg","lmmnrr" ,"AEO" }, {"dtspkThfS", "bcCdfghjkmnNqqrrlsStTvwxyz", "aaeeiouA", "ppttkkbdg", "lmmnrr", "AEO"},
{"dtskThfS" ,"bcCdfghjkmmnNqrrlssStTvwyz","aaaeeiiuAAEIO","ppttkbbdg","lmmnrrr","AEOy"} {"dtskThfS", "bcCdfghjkmmnNqrrlssStTvwyz", "aaaeeiiuAAEIO", "ppttkbbdg", "lmmnrrr", "AEOy"}};
};
const std::string replaceRule[2][17] = { const std::string replaceRule[2][17] = {
{"ST" ,"ka","ko","ku","kr","S" ,"T" ,"C" ,"N" ,"jj","AA","AI" ,"A" ,"E" ,"O" ,"I" ,"aa"}, {"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"} {"sth", "ca", "co", "cu", "cr", "sh", "th", "ch", "ng", "dg", "A", "ayu", "ai", "ei", "ou", "iu", "ae"}};
};
tries = 10; tries = 10;
while (--tries) while (--tries)
{ {
botName.clear(); botName.clear();
//Build name from groupForms // Build name from groupForms
//Pick random start group // Pick random start group
botName = groupFormStart[gender][rand()%4]; botName = groupFormStart[gender][rand() % 4];
//Pick up to 2 and then up to 1 additional middle group // Pick up to 2 and then up to 1 additional middle group
for (int i = 0; i < rand()%3 + rand()%2; i++) for (int i = 0; i < rand() % 3 + rand() % 2; i++)
{ {
botName += groupFormMid[gender][rand()%6]; botName += groupFormMid[gender][rand() % 6];
} }
//Pick up to 1 end group // Pick up to 1 end group
botName += rand()%2 ? groupFormEnd[gender][rand()%4] : ""; botName += rand() % 2 ? groupFormEnd[gender][rand() % 4] : "";
//If name is single letter add random end group // If name is single letter add random end group
botName += (botName.size() < 2) ? groupFormEnd[gender][rand()%4] : ""; 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 // 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++) for (int i = 0; i < botName.size(); i++)
{ {
botName[i] = groupLetter[gender][groupCategory.find(botName[i])][rand()%groupLetter[gender][groupCategory.find(botName[i])].size()]; botName[i] = groupLetter[gender][groupCategory.find(botName[i])]
} [rand() % groupLetter[gender][groupCategory.find(botName[i])].size()];
}
//Itterate over replace rules // Itterate over replace rules
for (int i = 0; i < 17; i++) for (int i = 0; i < 17; i++)
{ {
int j = botName.find(replaceRule[0][i]); int j = botName.find(replaceRule[0][i]);
while ( j > -1) while (j > -1)
{ {
botName.replace(j,replaceRule[0][i].size(),replaceRule[1][i]); botName.replace(j, replaceRule[0][i].size(), replaceRule[1][i]);
j = botName.find(replaceRule[0][i]); j = botName.find(replaceRule[0][i]);
} }
} }
//Capitalize first letter // Capitalize first letter
botName[0] -= 32; botName[0] -= 32;
if (ObjectMgr::CheckPlayerName(botName) != CHAR_NAME_SUCCESS || if (ObjectMgr::CheckPlayerName(botName) != CHAR_NAME_SUCCESS ||
@@ -286,11 +289,13 @@ std::string const RandomPlayerbotFactory::CreateRandomBotName(uint8 gender)
return std::move(botName); return std::move(botName);
} }
//TRUE RANDOM NAME GENERATION // TRUE RANDOM NAME GENERATION
LOG_ERROR("playerbots", "Conlang name generation failed. True random name fallback."); LOG_ERROR("playerbots", "Conlang name generation failed. True random name fallback.");
tries = 10; tries = 10;
while(--tries) { while (--tries)
for (uint8 i = 0; i < 10; i++) { {
for (uint8 i = 0; i < 10; i++)
{
botName += (i == 0 ? 'A' : 'a') + rand() % 26; botName += (i == 0 ? 'A' : 'a') + rand() % 26;
} }
if (ObjectMgr::CheckPlayerName(botName) != CHAR_NAME_SUCCESS || if (ObjectMgr::CheckPlayerName(botName) != CHAR_NAME_SUCCESS ||
@@ -325,7 +330,8 @@ void RandomPlayerbotFactory::CreateRandomBots()
} }
LOG_INFO("playerbots", "Deleting all random bot characters, {} accounts collected...", botAccounts.size()); LOG_INFO("playerbots", "Deleting all random bot characters, {} accounts collected...", botAccounts.size());
QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'", sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'",
sPlayerbotAIConfig->randomBotAccountPrefix.c_str());
int32 deletion_count = 0; int32 deletion_count = 0;
if (results) if (results)
{ {
@@ -340,8 +346,8 @@ void RandomPlayerbotFactory::CreateRandomBots()
PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS)); PlayerbotsDatabase.Execute(PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_DEL_RANDOM_BOTS));
CharacterDatabase.DirectExecute("UPDATE playerbots_names SET in_use = 0 WHERE in_use = 1"); CharacterDatabase.DirectExecute("UPDATE playerbots_names SET in_use = 0 WHERE in_use = 1");
/* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created correctly /* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created
the better way is turning the async db operation to sync db operation */ correctly the better way is turning the async db operation to sync db operation */
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount); std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
LOG_INFO("playerbots", "Random bot characters deleted."); LOG_INFO("playerbots", "Random bot characters deleted.");
LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server..."); LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server...");
@@ -374,7 +380,7 @@ void RandomPlayerbotFactory::CreateRandomBots()
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
password += (char) urand('!', 'z'); password += (char)urand('!', 'z');
} }
} }
else else
@@ -385,7 +391,8 @@ void RandomPlayerbotFactory::CreateRandomBots()
LOG_DEBUG("playerbots", "Account {} created for random bots", accountName.c_str()); LOG_DEBUG("playerbots", "Account {} created for random bots", accountName.c_str());
} }
if (account_creation) { if (account_creation)
{
/* wait for async accounts create to make character create correctly, same as account delete */ /* wait for async accounts create to make character create correctly, same as account delete */
LOG_INFO("playerbots", "Waiting for {} accounts loading into database...", account_creation); LOG_INFO("playerbots", "Waiting for {} accounts loading into database...", account_creation);
std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount); std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount);
@@ -420,10 +427,12 @@ void RandomPlayerbotFactory::CreateRandomBots()
{ {
continue; continue;
} }
LOG_INFO("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1, sPlayerbotAIConfig->randomBotAccountCount); LOG_INFO("playerbots", "Creating random bot characters for account: [{}/{}]", accountNumber + 1,
sPlayerbotAIConfig->randomBotAccountCount);
RandomPlayerbotFactory factory(accountId); RandomPlayerbotFactory factory(accountId);
WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, 0, false, false, 0, true); WorldSession* session = new WorldSession(accountId, "", nullptr, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING,
time_t(0), LOCALE_enUS, 0, false, false, 0, true);
sessionBots.push_back(session); sessionBots.push_back(session);
for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES - count; ++cls) for (uint8 cls = CLASS_WARRIOR; cls < MAX_CLASSES - count; ++cls)
@@ -433,29 +442,33 @@ void RandomPlayerbotFactory::CreateRandomBots()
continue; continue;
if (bool const isClassDeathKnight = cls == CLASS_DEATH_KNIGHT; if (bool const isClassDeathKnight = cls == CLASS_DEATH_KNIGHT;
isClassDeathKnight && isClassDeathKnight && sWorld->getIntConfig(CONFIG_EXPANSION) != EXPANSION_WRATH_OF_THE_LICH_KING)
sWorld->getIntConfig(CONFIG_EXPANSION) !=
EXPANSION_WRATH_OF_THE_LICH_KING)
{ {
continue; continue;
} }
if (cls != 10) { if (cls != 10)
if (Player* playerBot = factory.CreateRandomBot(session, cls)) { {
if (Player* playerBot = factory.CreateRandomBot(session, cls))
{
playerBot->SaveToDB(true, false); playerBot->SaveToDB(true, false);
sCharacterCache->AddCharacterCacheEntry(playerBot->GetGUID(), accountId, playerBot->GetName(), sCharacterCache->AddCharacterCacheEntry(playerBot->GetGUID(), accountId, playerBot->GetName(),
playerBot->getGender(), playerBot->getRace(), playerBot->getClass(), playerBot->GetLevel()); playerBot->getGender(), playerBot->getRace(),
playerBot->getClass(), playerBot->GetLevel());
playerBot->CleanupsBeforeDelete(); playerBot->CleanupsBeforeDelete();
delete playerBot; delete playerBot;
bot_creation++; bot_creation++;
} else { }
else
{
LOG_ERROR("playerbots", "Fail to create character for account {}", accountId); LOG_ERROR("playerbots", "Fail to create character for account {}", accountId);
} }
} }
} }
} }
if (bot_creation) { if (bot_creation)
{
LOG_INFO("playerbots", "Waiting for {} characters loading into database...", bot_creation); LOG_INFO("playerbots", "Waiting for {} characters loading into database...", bot_creation);
/* wait for characters load into database, or characters will fail to loggin */ /* wait for characters load into database, or characters will fail to loggin */
std::this_thread::sleep_for(10s); std::this_thread::sleep_for(10s);
@@ -464,11 +477,13 @@ void RandomPlayerbotFactory::CreateRandomBots()
for (WorldSession* session : sessionBots) for (WorldSession* session : sessionBots)
delete session; delete session;
for (uint32 accountId : sPlayerbotAIConfig->randomBotAccounts) { for (uint32 accountId : sPlayerbotAIConfig->randomBotAccounts)
{
totalRandomBotChars += AccountMgr::GetCharactersCount(accountId); totalRandomBotChars += AccountMgr::GetCharactersCount(accountId);
} }
LOG_INFO("server.loading", "{} random bot accounts with {} characters available", sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars); LOG_INFO("server.loading", "{} random bot accounts with {} characters available",
sPlayerbotAIConfig->randomBotAccounts.size(), totalRandomBotChars);
} }
void RandomPlayerbotFactory::CreateRandomGuilds() void RandomPlayerbotFactory::CreateRandomGuilds()
@@ -484,8 +499,7 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 bot = fields[0].Get<uint32>(); uint32 bot = fields[0].Get<uint32>();
randomBots.push_back(bot); randomBots.push_back(bot);
} } while (result->NextRow());
while (result->NextRow());
} }
if (sPlayerbotAIConfig->deleteRandomBotGuilds) if (sPlayerbotAIConfig->deleteRandomBotGuilds)
@@ -538,7 +552,8 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
Player* player = ObjectAccessor::FindPlayer(leader); Player* player = ObjectAccessor::FindPlayer(leader);
if (!player) if (!player)
{ {
LOG_ERROR("playerbots", "ObjectAccessor Cannot find player to set leader for guild {} . Skipped...", guildName.c_str()); LOG_ERROR("playerbots", "ObjectAccessor Cannot find player to set leader for guild {} . Skipped...",
guildName.c_str());
continue; continue;
} }
@@ -548,7 +563,8 @@ void RandomPlayerbotFactory::CreateRandomGuilds()
Guild* guild = new Guild(); Guild* guild = new Guild();
if (!guild->Create(player, guildName)) if (!guild->Create(player, guildName))
{ {
LOG_ERROR("playerbots", "Error creating guild [ {} ] with leader [ {} ]", guildName.c_str(), player->GetName().c_str()); LOG_ERROR("playerbots", "Error creating guild [ {} ] with leader [ {} ]", guildName.c_str(),
player->GetName().c_str());
delete guild; delete guild;
continue; continue;
} }
@@ -586,8 +602,10 @@ std::string const RandomPlayerbotFactory::CreateRandomGuildName()
uint32 maxId = fields[0].Get<uint32>(); uint32 maxId = fields[0].Get<uint32>();
uint32 id = urand(0, maxId); uint32 id = urand(0, maxId);
result = CharacterDatabase.Query("SELECT n.name FROM playerbots_guild_names n " result = CharacterDatabase.Query(
"LEFT OUTER JOIN guild e ON e.name = n.name WHERE e.guildid IS NULL AND n.name_id >= {} LIMIT 1", id); "SELECT n.name FROM playerbots_guild_names n "
"LEFT OUTER JOIN guild e ON e.name = n.name WHERE e.guildid IS NULL AND n.name_id >= {} LIMIT 1",
id);
if (!result) if (!result)
{ {
LOG_ERROR("playerbots", "No more names left for random guilds"); LOG_ERROR("playerbots", "No more names left for random guilds");
@@ -613,8 +631,7 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
Field* fields = result->Fetch(); Field* fields = result->Fetch();
uint32 bot = fields[0].Get<uint32>(); uint32 bot = fields[0].Get<uint32>();
randomBots.push_back(bot); randomBots.push_back(bot);
} } while (result->NextRow());
while (result->NextRow());
} }
uint32 arenaTeamNumber = 0; uint32 arenaTeamNumber = 0;
@@ -664,10 +681,10 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
continue; continue;
} }
// Below query no longer required as now user has control over the number of each type of arena team they want to create. // Below query no longer required as now user has control over the number of each type of arena team they want
// Keeping commented for potential future reference. // to create. Keeping commented for potential future reference. QueryResult results =
// QueryResult results = CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'", arenaTeamName.c_str()); // CharacterDatabase.Query("SELECT `type` FROM playerbots_arena_team_names WHERE name = '{}'",
// if (!results) // arenaTeamName.c_str()); if (!results)
// { // {
// LOG_ERROR("playerbots", "No valid types for arena teams"); // LOG_ERROR("playerbots", "No valid types for arena teams");
// return; // return;
@@ -686,7 +703,8 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
arenateam->SetCaptain(player->GetGUID()); arenateam->SetCaptain(player->GetGUID());
// set random rating // set random rating
arenateam->SetRatingForAll(urand(sPlayerbotAIConfig->randomBotArenaTeamMinRating, sPlayerbotAIConfig->randomBotArenaTeamMaxRating)); arenateam->SetRatingForAll(
urand(sPlayerbotAIConfig->randomBotArenaTeamMinRating, sPlayerbotAIConfig->randomBotArenaTeamMaxRating));
// set random emblem // set random emblem
uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF); uint32 backgroundColor = urand(0xFF000000, 0xFFFFFFFF);
@@ -697,10 +715,11 @@ void RandomPlayerbotFactory::CreateRandomArenaTeams(ArenaType type, uint32 count
arenateam->SetEmblem(backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor); arenateam->SetEmblem(backgroundColor, emblemStyle, emblemColor, borderStyle, borderColor);
// set random kills (wip) // set random kills (wip)
//arenateam->SetStats(STAT_TYPE_GAMES_WEEK, urand(0, 30)); // arenateam->SetStats(STAT_TYPE_GAMES_WEEK, urand(0, 30));
//arenateam->SetStats(STAT_TYPE_WINS_WEEK, urand(0, arenateam->GetStats().games_week)); // arenateam->SetStats(STAT_TYPE_WINS_WEEK, urand(0, arenateam->GetStats().games_week));
//arenateam->SetStats(STAT_TYPE_GAMES_SEASON, urand(arenateam->GetStats().games_week, arenateam->GetStats().games_week * 5)); // arenateam->SetStats(STAT_TYPE_GAMES_SEASON, urand(arenateam->GetStats().games_week,
//arenateam->SetStats(STAT_TYPE_WINS_SEASON, urand(arenateam->GetStats().wins_week, arenateam->GetStats().games // arenateam->GetStats().games_week * 5)); arenateam->SetStats(STAT_TYPE_WINS_SEASON,
// urand(arenateam->GetStats().wins_week, arenateam->GetStats().games
arenateam->SaveToDB(); arenateam->SaveToDB();
sArenaTeamMgr->AddArenaTeam(arenateam); sArenaTeamMgr->AddArenaTeam(arenateam);
@@ -725,8 +744,10 @@ std::string const RandomPlayerbotFactory::CreateRandomArenaTeamName()
uint32 maxId = fields[0].Get<uint32>(); uint32 maxId = fields[0].Get<uint32>();
uint32 id = urand(0, maxId); uint32 id = urand(0, maxId);
result = CharacterDatabase.Query("SELECT n.name FROM playerbots_arena_team_names n LEFT OUTER JOIN arena_team e ON e.name = n.name " result = CharacterDatabase.Query(
"WHERE e.arenateamid IS NULL AND n.name_id >= {} LIMIT 1", id); "SELECT n.name FROM playerbots_arena_team_names n LEFT OUTER JOIN arena_team e ON e.name = n.name "
"WHERE e.arenateamid IS NULL AND n.name_id >= {} LIMIT 1",
id);
if (!result) if (!result)
{ {

View File

@@ -1,15 +1,16 @@
/* /*
* 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. * 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_RANDOMPLAYERBOTFACTORY_H #ifndef _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H
#define _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H #define _PLAYERBOT_RANDOMPLAYERBOTFACTORY_H
#include "Common.h"
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "Common.h"
#include "DBCEnums.h" #include "DBCEnums.h"
class Player; class Player;
@@ -19,22 +20,22 @@ enum ArenaType : uint8;
class RandomPlayerbotFactory class RandomPlayerbotFactory
{ {
public: public:
RandomPlayerbotFactory(uint32 accountId); RandomPlayerbotFactory(uint32 accountId);
virtual ~RandomPlayerbotFactory() { } virtual ~RandomPlayerbotFactory() {}
Player* CreateRandomBot(WorldSession* session, uint8 cls); Player* CreateRandomBot(WorldSession* session, uint8 cls);
static void CreateRandomBots(); static void CreateRandomBots();
static void CreateRandomGuilds(); static void CreateRandomGuilds();
static void CreateRandomArenaTeams(ArenaType slot, uint32 count); static void CreateRandomArenaTeams(ArenaType slot, uint32 count);
static std::string const CreateRandomGuildName(); static std::string const CreateRandomGuildName();
private: private:
std::string const CreateRandomBotName(uint8 gender); std::string const CreateRandomBotName(uint8 gender);
static std::string const CreateRandomArenaTeamName(); static std::string const CreateRandomArenaTeamName();
uint32 accountId; uint32 accountId;
static std::map<uint8, std::vector<uint8>> availableRaces; static std::map<uint8, std::vector<uint8>> availableRaces;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_RANDOMPLAYERBOTMGR_H #ifndef _PLAYERBOT_RANDOMPLAYERBOTMGR_H
@@ -7,7 +8,8 @@
#include "PlayerbotMgr.h" #include "PlayerbotMgr.h"
struct BattlegroundInfo { struct BattlegroundInfo
{
std::vector<uint32> bgInstances; std::vector<uint32> bgInstances;
std::vector<uint32> ratedArenaInstances; std::vector<uint32> ratedArenaInstances;
std::vector<uint32> skirmishArenaInstances; std::vector<uint32> skirmishArenaInstances;
@@ -16,9 +18,9 @@ struct BattlegroundInfo {
uint32 skirmishArenaInstanceCount = 0; uint32 skirmishArenaInstanceCount = 0;
uint32 minLevel = 0; uint32 minLevel = 0;
uint32 maxLevel = 0; uint32 maxLevel = 0;
uint32 activeRatedArenaQueue = 0; // 0 = Inactive, 1 = Active uint32 activeRatedArenaQueue = 0; // 0 = Inactive, 1 = Active
uint32 activeSkirmishArenaQueue = 0; // 0 = Inactive, 1 = Active uint32 activeSkirmishArenaQueue = 0; // 0 = Inactive, 1 = Active
uint32 activeBgQueue = 0; // 0 = Inactive, 1 = Active uint32 activeBgQueue = 0; // 0 = Inactive, 1 = Active
// Bots (Arena) // Bots (Arena)
uint32 ratedArenaBotCount = 0; uint32 ratedArenaBotCount = 0;
@@ -43,21 +45,27 @@ class WorldLocation;
class CachedEvent class CachedEvent
{ {
public: public:
CachedEvent() : value(0), lastChangeTime(0), validIn(0), data("") { } CachedEvent() : value(0), lastChangeTime(0), validIn(0), data("") {}
CachedEvent(const CachedEvent& other) : value(other.value), lastChangeTime(other.lastChangeTime), validIn(other.validIn), data(other.data) { } CachedEvent(const CachedEvent& other)
CachedEvent(uint32 value, uint32 lastChangeTime, uint32 validIn, std::string const data = "") : value(value), lastChangeTime(lastChangeTime), validIn(validIn), data(data) { } : value(other.value), lastChangeTime(other.lastChangeTime), validIn(other.validIn), data(other.data)
{
}
CachedEvent(uint32 value, uint32 lastChangeTime, uint32 validIn, std::string const data = "")
: value(value), lastChangeTime(lastChangeTime), validIn(validIn), data(data)
{
}
bool IsEmpty() { return !lastChangeTime; } bool IsEmpty() { return !lastChangeTime; }
public: public:
uint32 value; uint32 value;
uint32 lastChangeTime; uint32 lastChangeTime;
uint32 validIn; uint32 validIn;
std::string data; std::string data;
}; };
//https://gist.github.com/bradley219/5373998 // https://gist.github.com/bradley219/5373998
class botPIDImpl; class botPIDImpl;
class botPID class botPID
@@ -82,117 +90,121 @@ private:
class RandomPlayerbotMgr : public PlayerbotHolder class RandomPlayerbotMgr : public PlayerbotHolder
{ {
public: public:
RandomPlayerbotMgr(); RandomPlayerbotMgr();
virtual ~RandomPlayerbotMgr(); virtual ~RandomPlayerbotMgr();
static RandomPlayerbotMgr* instance() static RandomPlayerbotMgr* instance()
{ {
static RandomPlayerbotMgr instance; static RandomPlayerbotMgr instance;
return &instance; return &instance;
} }
void LogPlayerLocation(); void LogPlayerLocation();
void UpdateAIInternal(uint32 elapsed, bool minimal = false) override; void UpdateAIInternal(uint32 elapsed, bool minimal = false) override;
private: private:
void ScaleBotActivity(); void ScaleBotActivity();
public: public:
uint32 activeBots = 0; uint32 activeBots = 0;
static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args); static bool HandlePlayerbotConsoleCommand(ChatHandler* handler, char const* args);
bool IsRandomBot(Player* bot); bool IsRandomBot(Player* bot);
bool IsRandomBot(ObjectGuid::LowType bot); bool IsRandomBot(ObjectGuid::LowType bot);
void Randomize(Player* bot); void Randomize(Player* bot);
void Clear(Player* bot); void Clear(Player* bot);
void RandomizeFirst(Player* bot); void RandomizeFirst(Player* bot);
void RandomizeMin(Player* bot); void RandomizeMin(Player* bot);
void IncreaseLevel(Player* bot); void IncreaseLevel(Player* bot);
void ScheduleTeleport(uint32 bot, uint32 time = 0); void ScheduleTeleport(uint32 bot, uint32 time = 0);
void ScheduleChangeStrategy(uint32 bot, uint32 time = 0); void ScheduleChangeStrategy(uint32 bot, uint32 time = 0);
void HandleCommand(uint32 type, std::string const text, Player* fromPlayer, std::string channelName = ""); void HandleCommand(uint32 type, std::string const text, Player* fromPlayer, std::string channelName = "");
std::string const HandleRemoteCommand(std::string const request); std::string const HandleRemoteCommand(std::string const request);
void OnPlayerLogout(Player* player); void OnPlayerLogout(Player* player);
void OnPlayerLogin(Player* player); void OnPlayerLogin(Player* player);
void OnPlayerLoginError(uint32 bot); void OnPlayerLoginError(uint32 bot);
Player* GetRandomPlayer(); Player* GetRandomPlayer();
std::vector<Player*> GetPlayers() { return players; }; std::vector<Player*> GetPlayers() { return players; };
PlayerBotMap GetAllBots() { return playerBots; }; PlayerBotMap GetAllBots() { return playerBots; };
void PrintStats(); void PrintStats();
double GetBuyMultiplier(Player* bot); double GetBuyMultiplier(Player* bot);
double GetSellMultiplier(Player* bot); double GetSellMultiplier(Player* bot);
void AddTradeDiscount(Player* bot, Player* master, int32 value); void AddTradeDiscount(Player* bot, Player* master, int32 value);
void SetTradeDiscount(Player* bot, Player* master, uint32 value); void SetTradeDiscount(Player* bot, Player* master, uint32 value);
uint32 GetTradeDiscount(Player* bot, Player* master); uint32 GetTradeDiscount(Player* bot, Player* master);
void Refresh(Player* bot); void Refresh(Player* bot);
void RandomTeleportForLevel(Player* bot); void RandomTeleportForLevel(Player* bot);
void RandomTeleportGrindForLevel(Player* bot); void RandomTeleportGrindForLevel(Player* bot);
void RandomTeleportForRpg(Player* bot); void RandomTeleportForRpg(Player* bot);
uint32 GetMaxAllowedBotCount(); uint32 GetMaxAllowedBotCount();
bool ProcessBot(Player* player); bool ProcessBot(Player* player);
void Revive(Player* player); void Revive(Player* player);
void ChangeStrategy(Player* player); void ChangeStrategy(Player* player);
void ChangeStrategyOnce(Player* player); void ChangeStrategyOnce(Player* player);
uint32 GetValue(Player* bot, std::string const type); uint32 GetValue(Player* bot, std::string const type);
uint32 GetValue(uint32 bot, std::string const type); uint32 GetValue(uint32 bot, std::string const type);
std::string const GetData(uint32 bot, std::string const type); std::string const GetData(uint32 bot, std::string const type);
void SetValue(uint32 bot, std::string const type, uint32 value, std::string const data = ""); void SetValue(uint32 bot, std::string const type, uint32 value, std::string const data = "");
void SetValue(Player* bot, std::string const type, uint32 value, std::string const data = ""); void SetValue(Player* bot, std::string const type, uint32 value, std::string const data = "");
void Remove(Player* bot); void Remove(Player* bot);
ObjectGuid const GetBattleMasterGUID(Player* bot, BattlegroundTypeId bgTypeId); ObjectGuid const GetBattleMasterGUID(Player* bot, BattlegroundTypeId bgTypeId);
CreatureData const* GetCreatureDataByEntry(uint32 entry); CreatureData const* GetCreatureDataByEntry(uint32 entry);
void LoadBattleMastersCache(); void LoadBattleMastersCache();
std::map<uint32, std::map<uint32, BattlegroundInfo>> BattlegroundData; std::map<uint32, std::map<uint32, BattlegroundInfo>> BattlegroundData;
std::map<uint32, std::map<uint32, std::map<TeamId, uint32>>> VisualBots; std::map<uint32, std::map<uint32, std::map<TeamId, uint32>>> VisualBots;
std::map<uint32, std::map<uint32, std::map<uint32, uint32>>> Supporters; std::map<uint32, std::map<uint32, std::map<uint32, uint32>>> Supporters;
std::map<TeamId, std::vector<uint32>> LfgDungeons; std::map<TeamId, std::vector<uint32>> LfgDungeons;
void CheckBgQueue(); void CheckBgQueue();
void CheckLfgQueue(); void CheckLfgQueue();
void CheckPlayers(); void CheckPlayers();
void LogBattlegroundInfo(); void LogBattlegroundInfo();
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> getBattleMastersCache() { return BattleMastersCache; } std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> getBattleMastersCache()
{
return BattleMastersCache;
}
float getActivityMod() { return activityMod; } float getActivityMod() { return activityMod; }
float getActivityPercentage() { return activityMod * 100.0f; } float getActivityPercentage() { return activityMod * 100.0f; }
void setActivityPercentage(float percentage) { activityMod = percentage / 100.0f; } void setActivityPercentage(float percentage) { activityMod = percentage / 100.0f; }
protected: protected:
void OnBotLoginInternal(Player* const bot) override; void OnBotLoginInternal(Player* const bot) override;
private: private:
//pid values are set in constructor // pid values are set in constructor
botPID pid = botPID(1, 50, -50, 0, 0, 0); botPID pid = botPID(1, 50, -50, 0, 0, 0);
float activityMod = 0.25; float activityMod = 0.25;
uint32 GetEventValue(uint32 bot, std::string const event); uint32 GetEventValue(uint32 bot, std::string const event);
std::string const GetEventData(uint32 bot, std::string const event); std::string const GetEventData(uint32 bot, std::string const event);
uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn, std::string const data = ""); uint32 SetEventValue(uint32 bot, std::string const event, uint32 value, uint32 validIn,
void GetBots(); std::string const data = "");
std::vector<uint32> GetBgBots(uint32 bracket); void GetBots();
time_t BgCheckTimer; std::vector<uint32> GetBgBots(uint32 bracket);
time_t LfgCheckTimer; time_t BgCheckTimer;
time_t PlayersCheckTimer; time_t LfgCheckTimer;
uint32 AddRandomBots(); time_t PlayersCheckTimer;
bool ProcessBot(uint32 bot); uint32 AddRandomBots();
void ScheduleRandomize(uint32 bot, uint32 time); bool ProcessBot(uint32 bot);
void RandomTeleport(Player* bot); void ScheduleRandomize(uint32 bot, uint32 time);
void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false); void RandomTeleport(Player* bot);
uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ); void RandomTeleport(Player* bot, std::vector<WorldLocation>& locs, bool hearth = false);
void PrepareTeleportCache(); uint32 GetZoneLevel(uint16 mapId, float teleX, float teleY, float teleZ);
typedef void(RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*); void PrepareTeleportCache();
typedef void (RandomPlayerbotMgr::*ConsoleCommandHandler)(Player*);
std::vector<Player*> players; std::vector<Player*> players;
uint32 processTicks; uint32 processTicks;
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache; std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache; std::map<uint8, std::vector<WorldLocation>> bankerLocsPerLevelCache;
// std::map<uint32, std::vector<WorldLocation>> rpgLocsCache; // std::map<uint32, std::vector<WorldLocation>> rpgLocsCache;
std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel; std::map<uint32, std::map<uint32, std::vector<WorldLocation>>> rpgLocsCacheLevel;
std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> BattleMastersCache; std::map<TeamId, std::map<BattlegroundTypeId, std::vector<uint32>>> BattleMastersCache;
std::map<uint32, std::map<std::string, CachedEvent>> eventCache; std::map<uint32, std::map<std::string, CachedEvent>> eventCache;
std::list<uint32> currentBots; std::list<uint32> currentBots;
uint32 bgBotsCount; uint32 bgBotsCount;
uint32 playersLevel; uint32 playersLevel;
PerformanceMonitorOperation* totalPmo; PerformanceMonitorOperation* totalPmo;
}; };
#define sRandomPlayerbotMgr RandomPlayerbotMgr::instance() #define sRandomPlayerbotMgr RandomPlayerbotMgr::instance()

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "ServerFacade.h" #include "ServerFacade.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "TargetedMovementGenerator.h" #include "TargetedMovementGenerator.h"
@@ -15,7 +17,7 @@ float ServerFacade::GetDistance2d(Unit* unit, WorldObject* wo)
return std::round(dist * 10.0f) / 10.0f; return std::round(dist * 10.0f) / 10.0f;
} }
float ServerFacade::GetDistance2d(Unit *unit, float x, float y) float ServerFacade::GetDistance2d(Unit* unit, float x, float y)
{ {
float dist = unit->GetDistance2d(x, y); float dist = unit->GetDistance2d(x, y);
return std::round(dist * 10.0f) / 10.0f; return std::round(dist * 10.0f) / 10.0f;
@@ -23,25 +25,19 @@ float ServerFacade::GetDistance2d(Unit *unit, float x, float y)
bool ServerFacade::IsDistanceLessThan(float dist1, float dist2) bool ServerFacade::IsDistanceLessThan(float dist1, float dist2)
{ {
//return dist1 - dist2 < sPlayerbotAIConfig->targetPosRecalcDistance; // return dist1 - dist2 < sPlayerbotAIConfig->targetPosRecalcDistance;
return dist1 < dist2; return dist1 < dist2;
} }
bool ServerFacade::IsDistanceGreaterThan(float dist1, float dist2) bool ServerFacade::IsDistanceGreaterThan(float dist1, float dist2)
{ {
//return dist1 - dist2 > sPlayerbotAIConfig->targetPosRecalcDistance; // return dist1 - dist2 > sPlayerbotAIConfig->targetPosRecalcDistance;
return dist1 > dist2; return dist1 > dist2;
} }
bool ServerFacade::IsDistanceGreaterOrEqualThan(float dist1, float dist2) bool ServerFacade::IsDistanceGreaterOrEqualThan(float dist1, float dist2) { return !IsDistanceLessThan(dist1, dist2); }
{
return !IsDistanceLessThan(dist1, dist2);
}
bool ServerFacade::IsDistanceLessOrEqualThan(float dist1, float dist2) bool ServerFacade::IsDistanceLessOrEqualThan(float dist1, float dist2) { return !IsDistanceGreaterThan(dist1, dist2); }
{
return !IsDistanceGreaterThan(dist1, dist2);
}
void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force) void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force)
{ {
@@ -50,8 +46,8 @@ void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force)
// bot->SetFacingTo(bot->GetAngle(wo)); // bot->SetFacingTo(bot->GetAngle(wo));
// else // else
// { // {
bot->SetOrientation(angle); bot->SetOrientation(angle);
bot->SendMovementFlagUpdate(); bot->SendMovementFlagUpdate();
// } // }
} }

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_SERVERFACADE_H #ifndef _PLAYERBOT_SERVERFACADE_H
@@ -13,26 +14,26 @@ class WorldObject;
class ServerFacade class ServerFacade
{ {
public: public:
ServerFacade() { }; ServerFacade(){};
virtual ~ServerFacade() { }; virtual ~ServerFacade(){};
static ServerFacade* instance() static ServerFacade* instance()
{ {
static ServerFacade instance; static ServerFacade instance;
return &instance; return &instance;
} }
public: public:
float GetDistance2d(Unit* unit, WorldObject* wo); float GetDistance2d(Unit* unit, WorldObject* wo);
float GetDistance2d(Unit* unit, float x, float y); float GetDistance2d(Unit* unit, float x, float y);
bool IsDistanceLessThan(float dist1, float dist2); bool IsDistanceLessThan(float dist1, float dist2);
bool IsDistanceGreaterThan(float dist1, float dist2); bool IsDistanceGreaterThan(float dist1, float dist2);
bool IsDistanceGreaterOrEqualThan(float dist1, float dist2); bool IsDistanceGreaterOrEqualThan(float dist1, float dist2);
bool IsDistanceLessOrEqualThan(float dist1, float dist2); bool IsDistanceLessOrEqualThan(float dist1, float dist2);
void SetFacingTo(Player* bot, WorldObject* wo, bool force = false); void SetFacingTo(Player* bot, WorldObject* wo, bool force = false);
Unit* GetChaseTarget(Unit* target); Unit* GetChaseTarget(Unit* target);
}; };
#define sServerFacade ServerFacade::instance() #define sServerFacade ServerFacade::instance()

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "Talentspec.h" #include "Talentspec.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -11,7 +13,7 @@ uint32 TalentSpec::TalentListEntry::tabPage() const
return talentTabInfo->TalentTabID == 41 ? 1 : talentTabInfo->tabpage; return talentTabInfo->TalentTabID == 41 ? 1 : talentTabInfo->tabpage;
} }
//Checks a talent link on basic validity. // Checks a talent link on basic validity.
bool TalentSpec::CheckTalentLink(std::string const link, std::ostringstream* out) bool TalentSpec::CheckTalentLink(std::string const link, std::ostringstream* out)
{ {
std::string const validChar = "-"; std::string const validChar = "-";
@@ -50,10 +52,7 @@ uint32 TalentSpec::PointstoLevel(uint32 points) const
return uint32(ceil(points / sWorld->getRate(RATE_TALENT))) + 9; return uint32(ceil(points / sWorld->getRate(RATE_TALENT))) + 9;
} }
TalentSpec::TalentSpec(uint32 classMask) TalentSpec::TalentSpec(uint32 classMask) { GetTalents(classMask); }
{
GetTalents(classMask);
}
TalentSpec::TalentSpec(TalentSpec* base, std::string const link) TalentSpec::TalentSpec(TalentSpec* base, std::string const link)
{ {
@@ -73,7 +72,7 @@ TalentSpec::TalentSpec(Player* bot, std::string const link)
ReadTalents(link); ReadTalents(link);
} }
//Check the talentspec for errors. // Check the talentspec for errors.
bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out) bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
{ {
for (auto& entry : talents) for (auto& entry : talents)
@@ -81,7 +80,8 @@ bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
if (entry.rank > entry.maxRank) if (entry.rank > entry.maxRank)
{ {
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
*out << "spec is not for this class. " << spellInfo->SpellName[0] << " has " << (entry.rank - entry.maxRank) << " points above max rank."; *out << "spec is not for this class. " << spellInfo->SpellName[0] << " has " << (entry.rank - entry.maxRank)
<< " points above max rank.";
return false; return false;
} }
@@ -103,7 +103,8 @@ bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
if (!found) if (!found)
{ {
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
*out << "spec is invalid. Talent:" << spellInfo->SpellName[0] << " needs: " << spellInfodep->SpellName[0] << " at rank: " << entry.talentInfo->DependsOnRank; *out << "spec is invalid. Talent:" << spellInfo->SpellName[0]
<< " needs: " << spellInfodep->SpellName[0] << " at rank: " << entry.talentInfo->DependsOnRank;
return false; return false;
} }
} }
@@ -120,7 +121,8 @@ bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
if (entry.rank > 0 && entry.talentInfo->Row * 5 > points) if (entry.rank > 0 && entry.talentInfo->Row * 5 > points)
{ {
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(entry.talentInfo->RankID[0]);
*out << "spec is is invalid. Talent " << spellInfo->SpellName[0] << " is selected with only " << points << " in row below it."; *out << "spec is is invalid. Talent " << spellInfo->SpellName[0] << " is selected with only " << points
<< " in row below it.";
return false; return false;
} }
@@ -137,17 +139,18 @@ bool TalentSpec::CheckTalents(uint32 level, std::ostringstream* out)
return true; return true;
} }
//Set the talents for the bots to the current spec. // Set the talents for the bots to the current spec.
void TalentSpec::ApplyTalents(Player* bot, std::ostringstream* out) void TalentSpec::ApplyTalents(Player* bot, std::ostringstream* out)
{ {
for (auto& entry : talents) { for (auto& entry : talents)
{
if (entry.rank == 0) if (entry.rank == 0)
continue; continue;
bot->LearnTalent(entry.talentInfo->TalentID, entry.rank - 1); bot->LearnTalent(entry.talentInfo->TalentID, entry.rank - 1);
} }
} }
//Returns a base talentlist for a class. // Returns a base talentlist for a class.
void TalentSpec::GetTalents(uint32 classMask) void TalentSpec::GetTalents(uint32 classMask)
{ {
TalentListEntry entry; TalentListEntry entry;
@@ -185,7 +188,7 @@ void TalentSpec::GetTalents(uint32 classMask)
SortTalents(talents, SORT_BY_DEFAULT); SortTalents(talents, SORT_BY_DEFAULT);
} }
//Sorts a talent list by page, row, column. // Sorts a talent list by page, row, column.
bool sortTalentMap(TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j, uint32* tabSort) bool sortTalentMap(TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j, uint32* tabSort)
{ {
uint32 itab = i.tabPage(); uint32 itab = i.tabPage();
@@ -208,38 +211,35 @@ bool sortTalentMap(TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j,
return false; return false;
} }
void TalentSpec::SortTalents(uint32 sortBy) void TalentSpec::SortTalents(uint32 sortBy) { SortTalents(talents, sortBy); }
{
SortTalents(talents, sortBy);
}
//Sort the talents. // Sort the talents.
void TalentSpec::SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy) void TalentSpec::SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy)
{ {
switch (sortBy) switch (sortBy)
{ {
case SORT_BY_DEFAULT: case SORT_BY_DEFAULT:
{ {
uint32 tabSort[] = { 0, 1, 2 }; uint32 tabSort[] = {0, 1, 2};
std::sort(talents.begin(), talents.end(), [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j) std::sort(talents.begin(), talents.end(),
{ [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j)
return sortTalentMap(i, j, tabSort); { return sortTalentMap(i, j, tabSort); });
});
break; break;
} }
case SORT_BY_POINTS_TREE: case SORT_BY_POINTS_TREE:
{ {
uint32 tabSort[] = { GetTalentPoints(talents, 0) * 100 - urand(0, 99), GetTalentPoints(talents, 1) * 100 - urand(0, 99), GetTalentPoints(talents, 2) * 100 - urand(0, 99) }; uint32 tabSort[] = {GetTalentPoints(talents, 0) * 100 - urand(0, 99),
std::sort(talents.begin(), talents.end(), [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j) GetTalentPoints(talents, 1) * 100 - urand(0, 99),
{ GetTalentPoints(talents, 2) * 100 - urand(0, 99)};
return sortTalentMap(i, j, tabSort); std::sort(talents.begin(), talents.end(),
}); [&tabSort](TalentSpec::TalentListEntry i, TalentSpec::TalentListEntry j)
{ return sortTalentMap(i, j, tabSort); });
break; break;
} }
} }
} }
//Set the talent ranks to the current rank of the player. // Set the talent ranks to the current rank of the player.
void TalentSpec::ReadTalents(Player* bot) void TalentSpec::ReadTalents(Player* bot)
{ {
for (auto& entry : talents) for (auto& entry : talents)
@@ -257,7 +257,7 @@ void TalentSpec::ReadTalents(Player* bot)
} }
} }
//Set the talent ranks to the ranks of the link. // Set the talent ranks to the ranks of the link.
void TalentSpec::ReadTalents(std::string const link) void TalentSpec::ReadTalents(std::string const link)
{ {
uint32 rank = 0; uint32 rank = 0;
@@ -308,7 +308,7 @@ void TalentSpec::ReadTalents(std::string const link)
} }
} }
//Returns only a specific tree from a talent list. // Returns only a specific tree from a talent list.
std::vector<TalentSpec::TalentListEntry> TalentSpec::GetTalentTree(uint32 tabpage) std::vector<TalentSpec::TalentListEntry> TalentSpec::GetTalentTree(uint32 tabpage)
{ {
std::vector<TalentListEntry> retList; std::vector<TalentListEntry> retList;
@@ -320,12 +320,9 @@ std::vector<TalentSpec::TalentListEntry> TalentSpec::GetTalentTree(uint32 tabpag
return std::move(retList); return std::move(retList);
} }
uint32 TalentSpec::GetTalentPoints(int32 tabpage) uint32 TalentSpec::GetTalentPoints(int32 tabpage) { return GetTalentPoints(talents, tabpage); };
{
return GetTalentPoints(talents, tabpage);
};
//Counts the point in a talent list. // Counts the point in a talent list.
uint32 TalentSpec::GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage) uint32 TalentSpec::GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage)
{ {
if (tabpage == -1) if (tabpage == -1)
@@ -339,7 +336,7 @@ uint32 TalentSpec::GetTalentPoints(std::vector<TalentListEntry>& talents, int32
return tPoints; return tPoints;
} }
//Generates a wow-head link from a talent list. // Generates a wow-head link from a talent list.
std::string const TalentSpec::GetTalentLink() std::string const TalentSpec::GetTalentLink()
{ {
std::string link = ""; std::string link = "";
@@ -403,7 +400,7 @@ std::string const TalentSpec::FormatSpec(Player* bot)
uint8 cls = bot->getClass(); uint8 cls = bot->getClass();
std::ostringstream out; std::ostringstream out;
//out << chathelper:: specs[cls][highestTree()] << " ("; // out << chathelper:: specs[cls][highestTree()] << " (";
uint32 c0 = GetTalentPoints(0); uint32 c0 = GetTalentPoints(0);
uint32 c1 = GetTalentPoints(1); uint32 c1 = GetTalentPoints(1);
@@ -416,7 +413,7 @@ std::string const TalentSpec::FormatSpec(Player* bot)
return out.str(); return out.str();
} }
//Removes talentpoints to match the level // Removes talentpoints to match the level
void TalentSpec::CropTalents(uint32 level) void TalentSpec::CropTalents(uint32 level)
{ {
if (points <= LeveltoPoints(level)) if (points <= LeveltoPoints(level))
@@ -436,8 +433,10 @@ void TalentSpec::CropTalents(uint32 level)
SortTalents(talents, SORT_BY_DEFAULT); SortTalents(talents, SORT_BY_DEFAULT);
} }
//Substracts ranks. Follows the sorting of the newList. // Substracts ranks. Follows the sorting of the newList.
std::vector<TalentSpec::TalentListEntry> TalentSpec::SubTalentList(std::vector<TalentListEntry>& oldList, std::vector<TalentListEntry>& newList, uint32 reverse = SUBSTRACT_OLD_NEW) std::vector<TalentSpec::TalentListEntry> TalentSpec::SubTalentList(std::vector<TalentListEntry>& oldList,
std::vector<TalentListEntry>& newList,
uint32 reverse = SUBSTRACT_OLD_NEW)
{ {
std::vector<TalentSpec::TalentListEntry> deltaList = newList; std::vector<TalentSpec::TalentListEntry> deltaList = newList;
@@ -466,35 +465,35 @@ bool TalentSpec::isEarlierVersionOf(TalentSpec& newSpec)
return true; return true;
} }
//Modifies current talents towards new talents up to a maxium of points. // Modifies current talents towards new talents up to a maxium of points.
void TalentSpec::ShiftTalents(TalentSpec* currentSpec, uint32 level) void TalentSpec::ShiftTalents(TalentSpec* currentSpec, uint32 level)
{ {
uint32 currentPoints = currentSpec->GetTalentPoints(); uint32 currentPoints = currentSpec->GetTalentPoints();
if (points >= LeveltoPoints(level)) //We have no more points to spend. Better reset and crop if (points >= LeveltoPoints(level)) // We have no more points to spend. Better reset and crop
{ {
CropTalents(level); CropTalents(level);
return; return;
} }
SortTalents(SORT_BY_POINTS_TREE); //Apply points first to the largest new tree. SortTalents(SORT_BY_POINTS_TREE); // Apply points first to the largest new tree.
std::vector<TalentSpec::TalentListEntry> deltaList = SubTalentList(currentSpec->talents, talents); std::vector<TalentSpec::TalentListEntry> deltaList = SubTalentList(currentSpec->talents, talents);
for (auto& entry : deltaList) for (auto& entry : deltaList)
{ {
if (entry.rank < 0) //We have to remove talents. Might as well reset and crop the new list. if (entry.rank < 0) // We have to remove talents. Might as well reset and crop the new list.
{ {
CropTalents(level); CropTalents(level);
return; return;
} }
} }
//Start from the current spec. // Start from the current spec.
talents = currentSpec->talents; talents = currentSpec->talents;
for (auto& entry : deltaList) for (auto& entry : deltaList)
{ {
if (entry.rank + points > LeveltoPoints(level)) //Running out of points. Only apply what we have left. if (entry.rank + points > LeveltoPoints(level)) // Running out of points. Only apply what we have left.
entry.rank = std::max(0, std::abs(int32(LeveltoPoints(level) - points))); entry.rank = std::max(0, std::abs(int32(LeveltoPoints(level) - points)));
for (auto& subentry : talents) for (auto& subentry : talents)

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_TALENTSPEC_H #ifndef _PLAYERBOT_TALENTSPEC_H
@@ -21,85 +22,86 @@ struct TalentTabEntry;
// unused currently // unused currently
class TalentSpec class TalentSpec
{ {
public: public:
struct TalentListEntry struct TalentListEntry
{ {
uint32 entry; uint32 entry;
uint32 rank; uint32 rank;
uint32 maxRank; uint32 maxRank;
TalentEntry const* talentInfo; TalentEntry const* talentInfo;
TalentTabEntry const* talentTabInfo; TalentTabEntry const* talentTabInfo;
uint32 tabPage() const; uint32 tabPage() const;
}; };
TalentSpec() { }; TalentSpec(){};
virtual ~TalentSpec() { } virtual ~TalentSpec() {}
TalentSpec(uint32 classMask); TalentSpec(uint32 classMask);
TalentSpec(TalentSpec* base, std::string const link); TalentSpec(TalentSpec* base, std::string const link);
TalentSpec(Player* bot); TalentSpec(Player* bot);
TalentSpec(Player* bot, std::string const link); TalentSpec(Player* bot, std::string const link);
uint32 points = 0; uint32 points = 0;
std::vector<TalentListEntry> talents; std::vector<TalentListEntry> talents;
bool CheckTalentLink(std::string const link, std::ostringstream* out); bool CheckTalentLink(std::string const link, std::ostringstream* out);
virtual bool CheckTalents(uint32 maxPoints, std::ostringstream* out); virtual bool CheckTalents(uint32 maxPoints, std::ostringstream* out);
void CropTalents(uint32 level); void CropTalents(uint32 level);
void ShiftTalents(TalentSpec* oldTalents, uint32 level); void ShiftTalents(TalentSpec* oldTalents, uint32 level);
void ApplyTalents(Player* bot, std::ostringstream* out); void ApplyTalents(Player* bot, std::ostringstream* out);
uint32 GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage = -1); uint32 GetTalentPoints(std::vector<TalentListEntry>& talents, int32 tabpage = -1);
uint32 GetTalentPoints(int32 tabpage = -1); uint32 GetTalentPoints(int32 tabpage = -1);
bool isEarlierVersionOf(TalentSpec& newSpec); bool isEarlierVersionOf(TalentSpec& newSpec);
std::string const GetTalentLink(); std::string const GetTalentLink();
uint32 highestTree(); uint32 highestTree();
std::string const FormatSpec(Player* bot); std::string const FormatSpec(Player* bot);
protected: protected:
uint32 LeveltoPoints(uint32 level) const; uint32 LeveltoPoints(uint32 level) const;
uint32 PointstoLevel(uint32 points) const; uint32 PointstoLevel(uint32 points) const;
void GetTalents(uint32 classMask); void GetTalents(uint32 classMask);
void SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy); void SortTalents(std::vector<TalentListEntry>& talents, uint32 sortBy);
void SortTalents(uint32 sortBy); void SortTalents(uint32 sortBy);
void ReadTalents(Player* bot); void ReadTalents(Player* bot);
void ReadTalents(std::string const link); void ReadTalents(std::string const link);
std::vector<TalentListEntry> GetTalentTree(uint32 tabpage); std::vector<TalentListEntry> GetTalentTree(uint32 tabpage);
std::vector<TalentListEntry> SubTalentList(std::vector<TalentListEntry>& oldList, std::vector<TalentListEntry>& newList, uint32 reverse); std::vector<TalentListEntry> SubTalentList(std::vector<TalentListEntry>& oldList,
std::vector<TalentListEntry>& newList, uint32 reverse);
}; };
class TalentPath class TalentPath
{ {
public: public:
TalentPath(uint32 pathId, std::string const pathName, uint32 pathProbability) TalentPath(uint32 pathId, std::string const pathName, uint32 pathProbability)
{ {
id = pathId; id = pathId;
name = pathName; name = pathName;
probability = pathProbability; probability = pathProbability;
}; };
uint32 id = 0; uint32 id = 0;
std::string name = ""; std::string name = "";
uint32 probability = 100; uint32 probability = 100;
std::vector<TalentSpec> talentSpec; std::vector<TalentSpec> talentSpec;
}; };
class ClassSpecs class ClassSpecs
{ {
public: public:
ClassSpecs() { }; ClassSpecs(){};
ClassSpecs(uint32 specsClassMask) ClassSpecs(uint32 specsClassMask)
{ {
classMask = specsClassMask; classMask = specsClassMask;
baseSpec = TalentSpec(specsClassMask); baseSpec = TalentSpec(specsClassMask);
} }
uint32 classMask = 0; uint32 classMask = 0;
TalentSpec baseSpec; TalentSpec baseSpec;
std::vector<TalentPath> talentPath; std::vector<TalentPath> talentPath;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,39 +13,36 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BattleGroundTactics.h"
#include "Chat.h" #include "Chat.h"
#include "GuildTaskMgr.h" #include "GuildTaskMgr.h"
#include "PerformanceMonitor.h" #include "PerformanceMonitor.h"
#include "PlayerbotMgr.h" #include "PlayerbotMgr.h"
#include "RandomPlayerbotMgr.h" #include "RandomPlayerbotMgr.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "BattleGroundTactics.h"
using namespace Acore::ChatCommands; using namespace Acore::ChatCommands;
class playerbots_commandscript : public CommandScript class playerbots_commandscript : public CommandScript
{ {
public: public:
playerbots_commandscript() : CommandScript("playerbots_commandscript") { } playerbots_commandscript() : CommandScript("playerbots_commandscript") {}
ChatCommandTable GetCommands() const override ChatCommandTable GetCommands() const override
{ {
static ChatCommandTable playerbotsDebugCommandTable = static ChatCommandTable playerbotsDebugCommandTable = {
{ {"bg", HandleDebugBGCommand, SEC_GAMEMASTER, Console::Yes},
{ "bg", HandleDebugBGCommand, SEC_GAMEMASTER, Console::Yes },
}; };
static ChatCommandTable playerbotsCommandTable = static ChatCommandTable playerbotsCommandTable = {
{ {"bot", HandlePlayerbotCommand, SEC_PLAYER, Console::No},
{ "bot", HandlePlayerbotCommand, SEC_PLAYER, Console::No }, {"gtask", HandleGuildTaskCommand, SEC_GAMEMASTER, Console::Yes},
{ "gtask", HandleGuildTaskCommand, SEC_GAMEMASTER, Console::Yes }, {"pmon", HandlePerfMonCommand, SEC_GAMEMASTER, Console::Yes},
{ "pmon", HandlePerfMonCommand, SEC_GAMEMASTER, Console::Yes }, {"rndbot", HandleRandomPlayerbotCommand, SEC_GAMEMASTER, Console::Yes},
{ "rndbot", HandleRandomPlayerbotCommand, SEC_GAMEMASTER, Console::Yes }, {"debug", playerbotsDebugCommandTable},
{ "debug", playerbotsDebugCommandTable },
}; };
static ChatCommandTable commandTable = static ChatCommandTable commandTable = {
{ {"playerbots", playerbotsCommandTable},
{ "playerbots", playerbotsCommandTable },
}; };
return commandTable; return commandTable;
@@ -96,7 +93,4 @@ public:
} }
}; };
void AddSC_playerbots_commandscript() void AddSC_playerbots_commandscript() { new playerbots_commandscript(); }
{
new playerbots_commandscript();
}

View File

@@ -19,7 +19,4 @@
void AddPlayerbotsScripts(); void AddPlayerbotsScripts();
// Add all // Add all
void Addmod_playerbotsScripts() void Addmod_playerbotsScripts() { AddPlayerbotsScripts(); }
{
AddPlayerbotsScripts();
}

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "Action.h" #include "Action.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Timer.h" #include "Timer.h"
@@ -66,8 +68,7 @@ NextAction** NextAction::array(uint32 nil, ...)
{ {
cur = va_arg(vl, NextAction*); cur = va_arg(vl, NextAction*);
++size; ++size;
} } while (cur);
while (cur);
va_end(vl); va_end(vl);
@@ -85,28 +86,19 @@ void NextAction::destroy(NextAction** actions)
if (!actions) if (!actions)
return; return;
for (uint32 i=0; actions[i]; i++) for (uint32 i = 0; actions[i]; i++)
delete actions[i]; delete actions[i];
delete[] actions; delete[] actions;
} }
Value<Unit*>* Action::GetTargetValue() Value<Unit*>* Action::GetTargetValue() { return context->GetValue<Unit*>(GetTargetName()); }
{
return context->GetValue<Unit*>(GetTargetName());
}
Unit* Action::GetTarget() Unit* Action::GetTarget() { return GetTargetValue()->Get(); }
{
return GetTargetValue()->Get();
}
ActionBasket::ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event) : ActionBasket::ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event)
action(action), relevance(relevance), skipPrerequisites(skipPrerequisites), event(event), created(getMSTime()) : action(action), relevance(relevance), skipPrerequisites(skipPrerequisites), event(event), created(getMSTime())
{ {
} }
bool ActionBasket::isExpired(uint32 msecs) bool ActionBasket::isExpired(uint32 msecs) { return getMSTime() - created >= msecs; }
{
return getMSTime() - created >= msecs;
}

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ACTION_H #ifndef _PLAYERBOT_ACTION_H
@@ -15,108 +16,119 @@ class Unit;
class NextAction class NextAction
{ {
public: public:
NextAction(std::string const name, float relevance = 0.0f) : relevance(relevance), name(name) { } // name after relevance - whipowill NextAction(std::string const name, float relevance = 0.0f)
NextAction(NextAction const& o) : relevance(o.relevance), name(o.name) { } // name after relevance - whipowill : relevance(relevance), name(name) {} // name after relevance - whipowill
NextAction(NextAction const& o) : relevance(o.relevance), name(o.name) {} // name after relevance - whipowill
std::string const getName() { return name; } std::string const getName() { return name; }
float getRelevance() {return relevance;} float getRelevance() { return relevance; }
static uint32 size(NextAction** actions); static uint32 size(NextAction** actions);
static NextAction** clone(NextAction** actions); static NextAction** clone(NextAction** actions);
static NextAction** merge(NextAction** what, NextAction** with); static NextAction** merge(NextAction** what, NextAction** with);
static NextAction** array(uint32 nil,...); static NextAction** array(uint32 nil, ...);
static void destroy(NextAction** actions); static void destroy(NextAction** actions);
private: private:
float relevance; float relevance;
std::string const name; std::string const name;
}; };
class Action : public AiNamedObject class Action : public AiNamedObject
{ {
public: public:
enum class ActionThreatType enum class ActionThreatType
{ {
None = 0, None = 0,
Single = 1, Single = 1,
Aoe = 2 Aoe = 2
}; };
Action(PlayerbotAI* botAI, std::string const name = "action") : AiNamedObject(botAI, name), verbose(false) { } // verbose after ainamedobject - whipowill Action(PlayerbotAI* botAI, std::string const name = "action")
virtual ~Action(void) { } : AiNamedObject(botAI, name), verbose(false) {} // verbose after ainamedobject - whipowill
virtual ~Action(void) {}
virtual bool Execute([[maybe_unused]] Event event) { return true; } virtual bool Execute([[maybe_unused]] Event event) { return true; }
virtual bool isPossible() { return true; } virtual bool isPossible() { return true; }
virtual bool isUseful() { return true; } virtual bool isUseful() { return true; }
virtual NextAction** getPrerequisites() { return nullptr; } virtual NextAction** getPrerequisites() { return nullptr; }
virtual NextAction** getAlternatives() { return nullptr; } virtual NextAction** getAlternatives() { return nullptr; }
virtual NextAction** getContinuers() { return nullptr; } virtual NextAction** getContinuers() { return nullptr; }
virtual ActionThreatType getThreatType() { return ActionThreatType::None; } virtual ActionThreatType getThreatType() { return ActionThreatType::None; }
void Update() { } void Update() {}
void Reset() { } void Reset() {}
virtual Unit* GetTarget(); virtual Unit* GetTarget();
virtual Value<Unit*>* GetTargetValue(); virtual Value<Unit*>* GetTargetValue();
virtual std::string const GetTargetName() { return "self target"; } virtual std::string const GetTargetName() { return "self target"; }
void MakeVerbose() { verbose = true; } void MakeVerbose() { verbose = true; }
void setRelevance(uint32 relevance1) { relevance = relevance1; }; void setRelevance(uint32 relevance1) { relevance = relevance1; };
virtual float getRelevance() { return relevance; } virtual float getRelevance() { return relevance; }
protected: protected:
bool verbose; bool verbose;
float relevance = 0; float relevance = 0;
}; };
class ActionNode class ActionNode
{ {
public: public:
ActionNode(std::string const name, NextAction** prerequisites = nullptr, NextAction** alternatives = nullptr, NextAction** continuers = nullptr) : ActionNode(std::string const name, NextAction** prerequisites = nullptr, NextAction** alternatives = nullptr,
name(name), action(nullptr), continuers(continuers), alternatives(alternatives), prerequisites(prerequisites) { } // reorder arguments - whipowill NextAction** continuers = nullptr)
: name(name), action(nullptr), continuers(continuers), alternatives(alternatives), prerequisites(prerequisites)
{
} // reorder arguments - whipowill
virtual ~ActionNode() virtual ~ActionNode()
{ {
NextAction::destroy(prerequisites); NextAction::destroy(prerequisites);
NextAction::destroy(alternatives); NextAction::destroy(alternatives);
NextAction::destroy(continuers); NextAction::destroy(continuers);
} }
Action* getAction() { return action; } Action* getAction() { return action; }
void setAction(Action* action) { this->action = action; } void setAction(Action* action) { this->action = action; }
std::string const getName() { return name; } std::string const getName() { return name; }
NextAction** getContinuers() { return NextAction::merge(NextAction::clone(continuers), action->getContinuers()); } NextAction** getContinuers() { return NextAction::merge(NextAction::clone(continuers), action->getContinuers()); }
NextAction** getAlternatives() { return NextAction::merge(NextAction::clone(alternatives), action->getAlternatives()); } NextAction** getAlternatives()
NextAction** getPrerequisites() { return NextAction::merge(NextAction::clone(prerequisites), action->getPrerequisites()); } {
return NextAction::merge(NextAction::clone(alternatives), action->getAlternatives());
}
NextAction** getPrerequisites()
{
return NextAction::merge(NextAction::clone(prerequisites), action->getPrerequisites());
}
private: private:
std::string const name; std::string const name;
Action* action; Action* action;
NextAction** continuers; NextAction** continuers;
NextAction** alternatives; NextAction** alternatives;
NextAction** prerequisites; NextAction** prerequisites;
}; };
class ActionBasket class ActionBasket
{ {
public: public:
ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event); ActionBasket(ActionNode* action, float relevance, bool skipPrerequisites, Event event);
virtual ~ActionBasket(void) { } virtual ~ActionBasket(void) {}
float getRelevance() {return relevance;} float getRelevance() { return relevance; }
ActionNode* getAction() {return action;} ActionNode* getAction() { return action; }
Event getEvent() { return event; } Event getEvent() { return event; }
bool isSkipPrerequisites() { return skipPrerequisites; } bool isSkipPrerequisites() { return skipPrerequisites; }
void AmendRelevance(float k) { relevance *= k; } void AmendRelevance(float k) { relevance *= k; }
void setRelevance(float relevance) { this->relevance = relevance; } void setRelevance(float relevance) { this->relevance = relevance; }
bool isExpired(uint32 msecs); bool isExpired(uint32 msecs);
private: private:
ActionNode* action; ActionNode* action;
float relevance; float relevance;
bool skipPrerequisites; bool skipPrerequisites;
Event event; Event event;
uint32 created; uint32 created;
}; };
#endif #endif

View File

@@ -1,15 +1,15 @@
/* /*
* 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. * 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 "AiObject.h" #include "AiObject.h"
#include "Playerbots.h" #include "Playerbots.h"
AiObject::AiObject(PlayerbotAI* botAI) : PlayerbotAIAware(botAI), bot(botAI->GetBot()), context(botAI->GetAiObjectContext()), chat(botAI->GetChatHelper()) AiObject::AiObject(PlayerbotAI* botAI)
: PlayerbotAIAware(botAI), bot(botAI->GetBot()), context(botAI->GetAiObjectContext()), chat(botAI->GetChatHelper())
{ {
} }
Player* AiObject::GetMaster() Player* AiObject::GetMaster() { return botAI->GetMaster(); }
{
return botAI->GetMaster();
}

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_AIOBJECT_H #ifndef _PLAYERBOT_AIOBJECT_H
@@ -15,26 +16,26 @@ class PlayerbotAI;
class AiObject : public PlayerbotAIAware class AiObject : public PlayerbotAIAware
{ {
public: public:
AiObject(PlayerbotAI* botAI); AiObject(PlayerbotAI* botAI);
protected: protected:
Player* bot; Player* bot;
Player* GetMaster(); Player* GetMaster();
AiObjectContext* context; AiObjectContext* context;
ChatHelper* chat; ChatHelper* chat;
}; };
class AiNamedObject : public AiObject class AiNamedObject : public AiObject
{ {
public: public:
AiNamedObject(PlayerbotAI* botAI, std::string const name) : AiObject(botAI), name(name) { } AiNamedObject(PlayerbotAI* botAI, std::string const name) : AiObject(botAI), name(name) {}
public: public:
virtual std::string const getName() { return name; } virtual std::string const getName() { return name; }
protected: protected:
std::string const name; std::string const name;
}; };
// //
@@ -44,475 +45,469 @@ class AiNamedObject : public AiObject
#define NEXT_TRIGGERS(name, relevance) \ #define NEXT_TRIGGERS(name, relevance) \
virtual NextAction* getNextAction() { return new NextAction(name, relevance); } virtual NextAction* getNextAction() { return new NextAction(name, relevance); }
#define BEGIN_TRIGGER(clazz, super) \ #define BEGIN_TRIGGER(clazz, super) \
class clazz : public super \ class clazz : public super \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : super(botAI) { } \ clazz(PlayerbotAI* botAI) : super(botAI) {} \
bool IsActive() override; \ bool IsActive() override;
#define END_TRIGGER() \ #define END_TRIGGER() \
}; } \
;
#define BUFF_TRIGGER(clazz, spell) \ #define BUFF_TRIGGER(clazz, spell) \
class clazz : public BuffTrigger \ class clazz : public BuffTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BuffTrigger(botAI, spell) {} \
} }
#define BUFF_TRIGGER_A(clazz, spell) \ #define BUFF_TRIGGER_A(clazz, spell) \
class clazz : public BuffTrigger \ class clazz : public BuffTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BuffTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define BUFF_PARTY_TRIGGER(clazz, spell) \ #define BUFF_PARTY_TRIGGER(clazz, spell) \
class clazz : public BuffOnPartyTrigger \ class clazz : public BuffOnPartyTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) {} \
} }
#define BUFF_PARTY_TRIGGER_A(clazz, spell) \ #define BUFF_PARTY_TRIGGER_A(clazz, spell) \
class clazz : public BuffOnPartyTrigger \ class clazz : public BuffOnPartyTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define DEBUFF_TRIGGER(clazz, spell) \ #define DEBUFF_TRIGGER(clazz, spell) \
class clazz : public DebuffTrigger \ class clazz : public DebuffTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell) {} \
} }
#define DEBUFF_CHECKISOWNER_TRIGGER(clazz, spell) \ #define DEBUFF_CHECKISOWNER_TRIGGER(clazz, spell) \
class clazz : public DebuffTrigger \ class clazz : public DebuffTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell, 1, true) { } \ clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell, 1, true) {} \
} }
#define DEBUFF_TRIGGER_A(clazz, spell) \ #define DEBUFF_TRIGGER_A(clazz, spell) \
class clazz : public DebuffTrigger \ class clazz : public DebuffTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : DebuffTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define DEBUFF_ENEMY_TRIGGER(clazz, spell) \ #define DEBUFF_ENEMY_TRIGGER(clazz, spell) \
class clazz : public DebuffOnAttackerTrigger \ class clazz : public DebuffOnAttackerTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, spell) {} \
} }
#define DEBUFF_ENEMY_TRIGGER_A(clazz, spell) \ #define DEBUFF_ENEMY_TRIGGER_A(clazz, spell) \
class clazz : public DebuffOnAttackerTrigger \ class clazz : public DebuffOnAttackerTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : DebuffOnAttackerTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define CURE_TRIGGER(clazz, spell, dispel) \ #define CURE_TRIGGER(clazz, spell, dispel) \
class clazz : public NeedCureTrigger \ class clazz : public NeedCureTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : NeedCureTrigger(botAI, spell, dispel) { } \ clazz(PlayerbotAI* botAI) : NeedCureTrigger(botAI, spell, dispel) {} \
} }
#define CURE_PARTY_TRIGGER(clazz, spell, dispel) \ #define CURE_PARTY_TRIGGER(clazz, spell, dispel) \
class clazz : public PartyMemberNeedCureTrigger \ class clazz : public PartyMemberNeedCureTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : PartyMemberNeedCureTrigger(botAI, spell, dispel) { } \ clazz(PlayerbotAI* botAI) : PartyMemberNeedCureTrigger(botAI, spell, dispel) {} \
} }
#define CAN_CAST_TRIGGER(clazz, spell) \ #define CAN_CAST_TRIGGER(clazz, spell) \
class clazz : public SpellCanBeCastTrigger \ class clazz : public SpellCanBeCastTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : SpellCanBeCastTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : SpellCanBeCastTrigger(botAI, spell) {} \
} }
#define CAN_CAST_TRIGGER_A(clazz, spell) \ #define CAN_CAST_TRIGGER_A(clazz, spell) \
class clazz : public SpellCanBeCastTrigger \ class clazz : public SpellCanBeCastTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : SpellCanBeCastTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : SpellCanBeCastTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define CD_TRIGGER(clazz, spell) \ #define CD_TRIGGER(clazz, spell) \
class clazz : public SpellNoCooldownTrigger \ class clazz : public SpellNoCooldownTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : SpellNoCooldownTrigger(botAI, spell) {} \ clazz(PlayerbotAI* botAI) : SpellNoCooldownTrigger(botAI, spell) {} \
} }
#define INTERRUPT_TRIGGER(clazz, spell) \ #define INTERRUPT_TRIGGER(clazz, spell) \
class clazz : public InterruptSpellTrigger \ class clazz : public InterruptSpellTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, spell) {} \
} }
#define INTERRUPT_TRIGGER_A(clazz, spell) \ #define INTERRUPT_TRIGGER_A(clazz, spell) \
class clazz : public InterruptSpellTrigger \ class clazz : public InterruptSpellTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define HAS_AURA_TRIGGER(clazz, spell) \ #define HAS_AURA_TRIGGER(clazz, spell) \
class clazz : public HasAuraTrigger \ class clazz : public HasAuraTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : HasAuraTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : HasAuraTrigger(botAI, spell) {} \
} }
#define HAS_AURA_TRIGGER_A(clazz, spell) \ #define HAS_AURA_TRIGGER_A(clazz, spell) \
class clazz : public HasAuraTrigger \ class clazz : public HasAuraTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : HasAuraTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : HasAuraTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define SNARE_TRIGGER(clazz, spell) \ #define SNARE_TRIGGER(clazz, spell) \
class clazz : public SnareTargetTrigger \ class clazz : public SnareTargetTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, spell) {} \
} }
#define SNARE_TRIGGER_A(clazz, spell) \ #define SNARE_TRIGGER_A(clazz, spell) \
class clazz : public SnareTargetTrigger \ class clazz : public SnareTargetTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define PROTECT_TRIGGER(clazz, spell) \ #define PROTECT_TRIGGER(clazz, spell) \
class clazz : public ProtectPartyMemberTrigger \ class clazz : public ProtectPartyMemberTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : ProtectPartyMemberTrigger(botAI) { } \ clazz(PlayerbotAI* botAI) : ProtectPartyMemberTrigger(botAI) {} \
} }
#define DEFLECT_TRIGGER(clazz, spell) \ #define DEFLECT_TRIGGER(clazz, spell) \
class clazz : public DeflectSpellTrigger \ class clazz : public DeflectSpellTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : DeflectSpellTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : DeflectSpellTrigger(botAI, spell) {} \
} }
#define BOOST_TRIGGER(clazz, spell) \ #define BOOST_TRIGGER(clazz, spell) \
class clazz : public BoostTrigger \ class clazz : public BoostTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BoostTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BoostTrigger(botAI, spell) {} \
} }
#define BOOST_TRIGGER_A(clazz, spell) \ #define BOOST_TRIGGER_A(clazz, spell) \
class clazz : public BoostTrigger \ class clazz : public BoostTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BoostTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BoostTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define INTERRUPT_HEALER_TRIGGER(clazz, spell) \ #define INTERRUPT_HEALER_TRIGGER(clazz, spell) \
class clazz : public InterruptEnemyHealerTrigger \ class clazz : public InterruptEnemyHealerTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, spell) {} \
} }
#define INTERRUPT_HEALER_TRIGGER_A(clazz, spell) \ #define INTERRUPT_HEALER_TRIGGER_A(clazz, spell) \
class clazz : public InterruptEnemyHealerTrigger \ class clazz : public InterruptEnemyHealerTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, spell) {} \
bool IsActive() override; \ bool IsActive() override; \
} }
#define CC_TRIGGER(clazz, spell) \ #define CC_TRIGGER(clazz, spell) \
class clazz : public HasCcTargetTrigger \ class clazz : public HasCcTargetTrigger \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : HasCcTargetTrigger(botAI, spell) {} \
} }
// //
// ACTIONS // ACTIONS
// //
#define MELEE_ACTION(clazz, spell) \ #define MELEE_ACTION(clazz, spell) \
class clazz : public CastMeleeSpellAction \ class clazz : public CastMeleeSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, spell) {} \
} }
#define MELEE_ACTION_U(clazz, spell, useful) \ #define MELEE_ACTION_U(clazz, spell, useful) \
class clazz : public CastMeleeSpellAction \ class clazz : public CastMeleeSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define SPELL_ACTION(clazz, spell) \ #define SPELL_ACTION(clazz, spell) \
class clazz : public CastSpellAction \ class clazz : public CastSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, spell) {} \
} }
#define SPELL_ACTION_U(clazz, spell, useful) \ #define SPELL_ACTION_U(clazz, spell, useful) \
class clazz : public CastSpellAction \ class clazz : public CastSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define HEAL_ACTION(clazz, spell) \ #define HEAL_ACTION(clazz, spell) \
class clazz : public CastHealingSpellAction \ class clazz : public CastHealingSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) {} \
} }
#define HEAL_ACTION_U(clazz, spell, useful) \ #define HEAL_ACTION_U(clazz, spell, useful) \
class clazz : public CastHealingSpellAction \ class clazz : public CastHealingSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastHealingSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define HEAL_PARTY_ACTION(clazz, spell, estAmount, manaEfficiency) \ #define HEAL_PARTY_ACTION(clazz, spell, estAmount, manaEfficiency) \
class clazz : public HealPartyMemberAction \ class clazz : public HealPartyMemberAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, spell, estAmount, manaEfficiency) { } \ clazz(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, spell, estAmount, manaEfficiency) {} \
} }
#define AOE_HEAL_ACTION(clazz, spell, estAmount, manaEfficiency) \ #define AOE_HEAL_ACTION(clazz, spell, estAmount, manaEfficiency) \
class clazz : public CastAoeHealSpellAction \ class clazz : public CastAoeHealSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastAoeHealSpellAction(botAI, spell) {} \
} }
#define BUFF_ACTION(clazz, spell) \ #define BUFF_ACTION(clazz, spell) \
class clazz : public CastBuffSpellAction \ class clazz : public CastBuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, spell) {} \
} }
#define BUFF_ACTION_U(clazz, spell, useful) \ #define BUFF_ACTION_U(clazz, spell, useful) \
class clazz : public CastBuffSpellAction \ class clazz : public CastBuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define BUFF_PARTY_ACTION(clazz, spell) \ #define BUFF_PARTY_ACTION(clazz, spell) \
class clazz : public BuffOnPartyAction \ class clazz : public BuffOnPartyAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, spell) {} \
} }
#define CURE_ACTION(clazz, spell) \ #define CURE_ACTION(clazz, spell) \
class clazz : public CastCureSpellAction \ class clazz : public CastCureSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastCureSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastCureSpellAction(botAI, spell) {} \
} }
#define CURE_PARTY_ACTION(clazz, spell, dispel) \ #define CURE_PARTY_ACTION(clazz, spell, dispel) \
class clazz : public CurePartyMemberAction \ class clazz : public CurePartyMemberAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CurePartyMemberAction(botAI, spell, dispel) { } \ clazz(PlayerbotAI* botAI) : CurePartyMemberAction(botAI, spell, dispel) {} \
} }
#define RESS_ACTION(clazz, spell) \ #define RESS_ACTION(clazz, spell) \
class clazz : public ResurrectPartyMemberAction \ class clazz : public ResurrectPartyMemberAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : ResurrectPartyMemberAction(botAI, spell) {} \
} }
#define DEBUFF_ACTION(clazz, spell) \ #define DEBUFF_ACTION(clazz, spell) \
class clazz : public CastDebuffSpellAction \ class clazz : public CastDebuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) {} \
} }
#define DEBUFF_CHECKISOWNER_ACTION(clazz, spell) \ #define DEBUFF_CHECKISOWNER_ACTION(clazz, spell) \
class clazz : public CastDebuffSpellAction \ class clazz : public CastDebuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell, true) { } \ clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell, true) {} \
} }
#define DEBUFF_ACTION_U(clazz, spell, useful) \ #define DEBUFF_ACTION_U(clazz, spell, useful) \
class clazz : public CastDebuffSpellAction \ class clazz : public CastDebuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define DEBUFF_ACTION_R(clazz, spell, distance) \ #define DEBUFF_ACTION_R(clazz, spell, distance) \
class clazz : public CastDebuffSpellAction \ class clazz : public CastDebuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) \ clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, spell) { range = distance; } \
{ \ }
range = distance; \
} \
}
#define DEBUFF_ENEMY_ACTION(clazz, spell) \ #define DEBUFF_ENEMY_ACTION(clazz, spell) \
class clazz : public CastDebuffSpellOnAttackerAction \ class clazz : public CastDebuffSpellOnAttackerAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, spell) {} \
} }
#define REACH_ACTION(clazz, spell, range) \ #define REACH_ACTION(clazz, spell, range) \
class clazz : public CastReachTargetSpellAction \ class clazz : public CastReachTargetSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) { } \ clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) {} \
} }
#define REACH_ACTION_U(clazz, spell, range, useful) \ #define REACH_ACTION_U(clazz, spell, range, useful) \
class clazz : public CastReachTargetSpellAction \ class clazz : public CastReachTargetSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) { } \ clazz(PlayerbotAI* botAI) : CastReachTargetSpellAction(botAI, spell, range) {} \
bool isUseful() override { return useful; } \ bool isUseful() override { return useful; } \
} }
#define ENEMY_HEALER_ACTION(clazz, spell) \ #define ENEMY_HEALER_ACTION(clazz, spell) \
class clazz : public CastSpellOnEnemyHealerAction \ class clazz : public CastSpellOnEnemyHealerAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSpellOnEnemyHealerAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastSpellOnEnemyHealerAction(botAI, spell) {} \
} }
#define SNARE_ACTION(clazz, spell) \
class clazz : public CastSnareSpellAction \
{ \
public: \
clazz(PlayerbotAI* botAI) : CastSnareSpellAction(botAI, spell) {} \
}
#define SNARE_ACTION(clazz, spell) \ #define CC_ACTION(clazz, spell) \
class clazz : public CastSnareSpellAction \ class clazz : public CastCrowdControlSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSnareSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastCrowdControlSpellAction(botAI, spell) {} \
} }
#define CC_ACTION(clazz, spell) \ #define PROTECT_ACTION(clazz, spell) \
class clazz : public CastCrowdControlSpellAction \ class clazz : public CastProtectSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastCrowdControlSpellAction(botAI, spell) { } \ clazz(PlayerbotAI* botAI) : CastProtectSpellAction(botAI, spell) {} \
} }
#define PROTECT_ACTION(clazz, spell) \
class clazz : public CastProtectSpellAction \
{ \
public: \
clazz(PlayerbotAI* botAI) : CastProtectSpellAction(botAI, spell) { } \
}
#define END_RANGED_SPELL_ACTION() \ #define END_RANGED_SPELL_ACTION() \
}; } \
;
#define BEGIN_SPELL_ACTION(clazz, name) \ #define BEGIN_SPELL_ACTION(clazz, name) \
class clazz : public CastSpellAction \ class clazz : public CastSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, name) { } \ clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, name) {}
#define END_SPELL_ACTION() \ #define END_SPELL_ACTION() \
}; } \
;
#define BEGIN_DEBUFF_ACTION(clazz, name) \ #define BEGIN_DEBUFF_ACTION(clazz, name) \
class clazz : public CastDebuffSpellAction \ class clazz : public CastDebuffSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, name) { } \ clazz(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, name) {}
#define BEGIN_RANGED_SPELL_ACTION(clazz, name) \ #define BEGIN_RANGED_SPELL_ACTION(clazz, name) \
class clazz : public CastSpellAction \ class clazz : public CastSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, name) { } \ clazz(PlayerbotAI* botAI) : CastSpellAction(botAI, name) {}
#define BEGIN_MELEE_SPELL_ACTION(clazz, name) \ #define BEGIN_MELEE_SPELL_ACTION(clazz, name) \
class clazz : public CastMeleeSpellAction \ class clazz : public CastMeleeSpellAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, name) { } \ clazz(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, name) {}
#define END_RANGED_SPELL_ACTION() \ #define END_RANGED_SPELL_ACTION() \
}; } \
;
#define BEGIN_BUFF_ON_PARTY_ACTION(clazz, name) \ #define BEGIN_BUFF_ON_PARTY_ACTION(clazz, name) \
class clazz : public BuffOnPartyAction \ class clazz : public BuffOnPartyAction \
{ \ { \
public: \ public: \
clazz(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, name) { } clazz(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, name) {}
// //
// Action node // Action node
// //
// node_name , action, prerequisite // node_name , action, prerequisite
#define ACTION_NODE_P(name, spell, pre) \ #define ACTION_NODE_P(name, spell, pre) \
static ActionNode* name(PlayerbotAI* botAI) \ static ActionNode* name(PlayerbotAI* botAI) \
{ \ { \
return new ActionNode(spell, \ return new ActionNode(spell, /*P*/ NextAction::array(0, new NextAction(pre), nullptr), /*A*/ nullptr, \
/*P*/ NextAction::array(0, new NextAction(pre), nullptr), \ /*C*/ nullptr); \
/*A*/ nullptr, \ }
/*C*/ nullptr); \
}
// node_name , action, alternative // node_name , action, alternative
#define ACTION_NODE_A(name, spell, alt) \ #define ACTION_NODE_A(name, spell, alt) \
static ActionNode* name(PlayerbotAI* botAI) \ static ActionNode* name(PlayerbotAI* botAI) \
{ \ { \
return new ActionNode(spell, \ return new ActionNode(spell, /*P*/ nullptr, /*A*/ NextAction::array(0, new NextAction(alt), nullptr), \
/*P*/ nullptr, \ /*C*/ nullptr); \
/*A*/ NextAction::array(0, new NextAction(alt), nullptr), \ }
/*C*/ nullptr); \
}
// node_name , action, continuer // node_name , action, continuer
#define ACTION_NODE_C(name, spell, con) \ #define ACTION_NODE_C(name, spell, con) \
static ActionNode* name(PlayerbotAI* botAI) \ static ActionNode* name(PlayerbotAI* botAI) \
{ \ { \
return new ActionNode(spell, \ return new ActionNode(spell, /*P*/ nullptr, /*A*/ nullptr, \
/*P*/ nullptr, \ /*C*/ NextAction::array(0, new NextAction(con), nullptr)); \
/*A*/ nullptr, \ }
/*C*/ NextAction::array(0, new NextAction(con), nullptr)); \
}
#endif #endif

View File

@@ -1,21 +1,23 @@
/* /*
* 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. * 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 "AiObjectContext.h" #include "AiObjectContext.h"
#include "StrategyContext.h"
#include "ActionContext.h" #include "ActionContext.h"
#include "ChatActionContext.h" #include "ChatActionContext.h"
#include "WorldPacketActionContext.h"
#include "ChatTriggerContext.h" #include "ChatTriggerContext.h"
#include "TriggerContext.h"
#include "SharedValueContext.h"
#include "WorldPacketTriggerContext.h"
#include "ValueContext.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "raids/RaidTriggerContext.h" #include "SharedValueContext.h"
#include "StrategyContext.h"
#include "TriggerContext.h"
#include "ValueContext.h"
#include "WorldPacketActionContext.h"
#include "WorldPacketTriggerContext.h"
#include "raids/RaidActionContext.h" #include "raids/RaidActionContext.h"
#include "raids/RaidStrategyContext.h" #include "raids/RaidStrategyContext.h"
#include "raids/RaidTriggerContext.h"
#include "raids/naxxramas/RaidNaxxActionContext.h" #include "raids/naxxramas/RaidNaxxActionContext.h"
#include "raids/naxxramas/RaidNaxxTriggerContext.h" #include "raids/naxxramas/RaidNaxxTriggerContext.h"
@@ -116,35 +118,20 @@ std::set<std::string> AiObjectContext::GetSiblingStrategy(std::string const name
return strategyContexts.GetSiblings(name); return strategyContexts.GetSiblings(name);
} }
Trigger* AiObjectContext::GetTrigger(std::string const name) Trigger* AiObjectContext::GetTrigger(std::string const name) { return triggerContexts.GetContextObject(name, botAI); }
{
return triggerContexts.GetContextObject(name, botAI);
}
Action* AiObjectContext::GetAction(std::string const name) Action* AiObjectContext::GetAction(std::string const name) { return actionContexts.GetContextObject(name, botAI); }
{
return actionContexts.GetContextObject(name, botAI);
}
UntypedValue* AiObjectContext::GetUntypedValue(std::string const name) UntypedValue* AiObjectContext::GetUntypedValue(std::string const name)
{ {
return valueContexts.GetContextObject(name, botAI); return valueContexts.GetContextObject(name, botAI);
} }
std::set<std::string> AiObjectContext::GetValues() std::set<std::string> AiObjectContext::GetValues() { return valueContexts.GetCreated(); }
{
return valueContexts.GetCreated();
}
std::set<std::string> AiObjectContext::GetSupportedStrategies() std::set<std::string> AiObjectContext::GetSupportedStrategies() { return strategyContexts.supports(); }
{
return strategyContexts.supports();
}
std::set<std::string> AiObjectContext::GetSupportedActions() std::set<std::string> AiObjectContext::GetSupportedActions() { return actionContexts.supports(); }
{
return actionContexts.supports();
}
std::string const AiObjectContext::FormatValues() std::string const AiObjectContext::FormatValues()
{ {
@@ -166,7 +153,4 @@ std::string const AiObjectContext::FormatValues()
return out.str(); return out.str();
} }
void AiObjectContext::AddShared(NamedObjectContext<UntypedValue>* sharedValues) void AiObjectContext::AddShared(NamedObjectContext<UntypedValue>* sharedValues) { valueContexts.Add(sharedValues); }
{
valueContexts.Add(sharedValues);
}

View File

@@ -1,10 +1,14 @@
/* /*
* 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. * 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_AIOBJECTCONTEXT_H #ifndef _PLAYERBOT_AIOBJECTCONTEXT_H
#define _PLAYERBOT_AIOBJECTCONTEXT_H #define _PLAYERBOT_AIOBJECTCONTEXT_H
#include <sstream>
#include <string>
#include "Common.h" #include "Common.h"
#include "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "PlayerbotAIAware.h" #include "PlayerbotAIAware.h"
@@ -12,62 +16,59 @@
#include "Trigger.h" #include "Trigger.h"
#include "Value.h" #include "Value.h"
#include <sstream>
#include <string>
class PlayerbotAI; class PlayerbotAI;
class AiObjectContext : public PlayerbotAIAware class AiObjectContext : public PlayerbotAIAware
{ {
public: public:
AiObjectContext(PlayerbotAI* botAI); AiObjectContext(PlayerbotAI* botAI);
virtual ~AiObjectContext() { } virtual ~AiObjectContext() {}
virtual Strategy* GetStrategy(std::string const name); virtual Strategy* GetStrategy(std::string const name);
virtual std::set<std::string> GetSiblingStrategy(std::string const name); virtual std::set<std::string> GetSiblingStrategy(std::string const name);
virtual Trigger* GetTrigger(std::string const name); virtual Trigger* GetTrigger(std::string const name);
virtual Action* GetAction(std::string const name); virtual Action* GetAction(std::string const name);
virtual UntypedValue* GetUntypedValue(std::string const name); virtual UntypedValue* GetUntypedValue(std::string const name);
template<class T> template <class T>
Value<T>* GetValue(std::string const name) Value<T>* GetValue(std::string const name)
{ {
return dynamic_cast<Value<T>*>(GetUntypedValue(name)); return dynamic_cast<Value<T>*>(GetUntypedValue(name));
} }
template<class T> template <class T>
Value<T>* GetValue(std::string const name, std::string const param) Value<T>* GetValue(std::string const name, std::string const param)
{ {
return GetValue<T>((std::string(name) + "::" + param)); return GetValue<T>((std::string(name) + "::" + param));
} }
template<class T> template <class T>
Value<T>* GetValue(std::string const name, int32 param) Value<T>* GetValue(std::string const name, int32 param)
{ {
std::ostringstream out; std::ostringstream out;
out << param; out << param;
return GetValue<T>(name, out.str()); return GetValue<T>(name, out.str());
} }
std::set<std::string> GetValues(); std::set<std::string> GetValues();
std::set<std::string> GetSupportedStrategies(); std::set<std::string> GetSupportedStrategies();
std::set<std::string> GetSupportedActions(); std::set<std::string> GetSupportedActions();
std::string const FormatValues(); std::string const FormatValues();
virtual void Update(); virtual void Update();
virtual void Reset(); virtual void Reset();
virtual void AddShared(NamedObjectContext<UntypedValue>* sharedValues); virtual void AddShared(NamedObjectContext<UntypedValue>* sharedValues);
std::vector<std::string> Save(); std::vector<std::string> Save();
void Load(std::vector<std::string> data); void Load(std::vector<std::string> data);
std::vector<std::string> performanceStack; std::vector<std::string> performanceStack;
protected: protected:
NamedObjectContextList<Strategy> strategyContexts; NamedObjectContextList<Strategy> strategyContexts;
NamedObjectContextList<Action> actionContexts; NamedObjectContextList<Action> actionContexts;
NamedObjectContextList<Trigger> triggerContexts; NamedObjectContextList<Trigger> triggerContexts;
NamedObjectContextList<UntypedValue> valueContexts; NamedObjectContextList<UntypedValue> valueContexts;
}; };
#endif #endif

View File

@@ -1,12 +1,14 @@
/* /*
* 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. * 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 "CustomStrategy.h" #include "CustomStrategy.h"
#include "Playerbots.h"
#include <regex> #include <regex>
#include "Playerbots.h"
std::map<std::string, std::string> CustomStrategy::actionLinesCache; std::map<std::string, std::string> CustomStrategy::actionLinesCache;
NextAction* toNextAction(std::string const action) NextAction* toNextAction(std::string const action)
@@ -33,7 +35,7 @@ NextAction** toNextActionArray(std::string const actions)
res[index++] = na; res[index++] = na;
} }
res[index++] = nullptr; res[index++] = nullptr;
return res; return res;
} }
@@ -47,11 +49,9 @@ TriggerNode* toTriggerNode(std::string const actionLine)
return nullptr; return nullptr;
} }
CustomStrategy::CustomStrategy(PlayerbotAI* botAI) : Strategy(botAI), Qualified() CustomStrategy::CustomStrategy(PlayerbotAI* botAI) : Strategy(botAI), Qualified() {}
{
}
void CustomStrategy::InitTriggers(std::vector<TriggerNode*> &triggers) void CustomStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
if (actionLines.empty()) if (actionLines.empty())
{ {
@@ -68,7 +68,8 @@ void CustomStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
for (std::vector<std::string>::iterator i = tokens.begin(); i != tokens.end(); ++i) for (std::vector<std::string>::iterator i = tokens.begin(); i != tokens.end(); ++i)
{ {
std::string const line = *i; std::string const line = *i;
for (std::sregex_iterator j = std::sregex_iterator(line.begin(), line.end(), tpl); j != std::sregex_iterator(); ++j) for (std::sregex_iterator j = std::sregex_iterator(line.begin(), line.end(), tpl);
j != std::sregex_iterator(); ++j)
{ {
std::smatch match = *j; std::smatch match = *j;
std::string const actionLine = match[1].str(); std::string const actionLine = match[1].str();
@@ -88,7 +89,8 @@ void CustomStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
void CustomStrategy::LoadActionLines(uint32 owner) void CustomStrategy::LoadActionLines(uint32 owner)
{ {
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_CUSTOM_STRATEGY_BY_OWNER_AND_NAME); PlayerbotsDatabasePreparedStatement* stmt =
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_CUSTOM_STRATEGY_BY_OWNER_AND_NAME);
stmt->SetData(0, owner); stmt->SetData(0, owner);
stmt->SetData(1, qualifier); stmt->SetData(1, qualifier);
PreparedQueryResult result = PlayerbotsDatabase.Query(stmt); PreparedQueryResult result = PlayerbotsDatabase.Query(stmt);
@@ -99,8 +101,7 @@ void CustomStrategy::LoadActionLines(uint32 owner)
Field* fields = result->Fetch(); Field* fields = result->Fetch();
std::string const action = fields[1].Get<std::string>(); std::string const action = fields[1].Get<std::string>();
actionLines.push_back(action); actionLines.push_back(action);
} } while (result->NextRow());
while (result->NextRow());
} }
} }

View File

@@ -1,30 +1,31 @@
/* /*
* 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. * 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_CUSTOMSTRATEGY_H #ifndef _PLAYERBOT_CUSTOMSTRATEGY_H
#define _PLAYERBOT_CUSTOMSTRATEGY_H #define _PLAYERBOT_CUSTOMSTRATEGY_H
#include "Strategy.h"
#include <map> #include <map>
#include "Strategy.h"
class PlayerbotAI; class PlayerbotAI;
class CustomStrategy : public Strategy, public Qualified class CustomStrategy : public Strategy, public Qualified
{ {
public: public:
CustomStrategy(PlayerbotAI* botAI); CustomStrategy(PlayerbotAI* botAI);
void InitTriggers(std::vector<TriggerNode*> &triggers) override; void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return std::string("custom::" + qualifier); } std::string const getName() override { return std::string("custom::" + qualifier); }
void Reset(); void Reset();
static std::map<std::string, std::string> actionLinesCache; static std::map<std::string, std::string> actionLinesCache;
private: private:
std::vector<std::string> actionLines; std::vector<std::string> actionLines;
void LoadActionLines(uint32 owner); void LoadActionLines(uint32 owner);
}; };
#endif #endif

View File

@@ -1,13 +1,15 @@
/* /*
* 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. * 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 "Engine.h" #include "Engine.h"
#include "Action.h" #include "Action.h"
#include "Event.h" #include "Event.h"
#include "Queue.h"
#include "PerformanceMonitor.h" #include "PerformanceMonitor.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Queue.h"
#include "Strategy.h" #include "Strategy.h"
Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory) Engine::Engine(PlayerbotAI* botAI, AiObjectContext* factory) : PlayerbotAIAware(botAI), aiObjectContext(factory)
@@ -125,12 +127,12 @@ void Engine::Init()
MultiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent, "default"); MultiplyAndPush(strategy->getDefaultActions(), 0.0f, false, emptyEvent, "default");
} }
if (testMode) if (testMode)
{ {
FILE* file = fopen("test.log", "w"); FILE* file = fopen("test.log", "w");
fprintf(file, "\n"); fprintf(file, "\n");
fclose(file); fclose(file);
} }
} }
bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
@@ -156,7 +158,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
if (basket) if (basket)
{ {
float relevance = basket->getRelevance(); // just for reference float relevance = basket->getRelevance(); // just for reference
bool skipPrerequisites = basket->isSkipPrerequisites(); bool skipPrerequisites = basket->isSkipPrerequisites();
if (minimal && (relevance < 100)) if (minimal && (relevance < 100))
@@ -172,12 +174,13 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
if (!action) if (!action)
{ {
//LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(), botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel()); // LOG_ERROR("playerbots", "Action: {} - is UNKNOWN - c:{} l:{}", actionNode->getName().c_str(),
// botAI->GetBot()->getClass(), botAI->GetBot()->GetLevel());
LogAction("A:%s - UNKNOWN", actionNode->getName().c_str()); LogAction("A:%s - UNKNOWN", actionNode->getName().c_str());
} }
else if (action->isUseful()) else if (action->isUseful())
{ {
for (std::vector<Multiplier*>::iterator i = multipliers.begin(); i!= multipliers.end(); i++) for (std::vector<Multiplier*>::iterator i = multipliers.begin(); i != multipliers.end(); i++)
{ {
Multiplier* multiplier = *i; Multiplier* multiplier = *i;
relevance *= multiplier->GetValue(action); relevance *= multiplier->GetValue(action);
@@ -185,7 +188,8 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
if (!relevance) if (!relevance)
{ {
LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(), action->getName().c_str()); LogAction("Multiplier %s made action %s useless", multiplier->getName().c_str(),
action->getName().c_str());
break; break;
} }
} }
@@ -203,7 +207,8 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
} }
} }
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_ACTION, action->getName(), &aiObjectContext->performanceStack); PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_ACTION, action->getName(),
&aiObjectContext->performanceStack);
actionExecuted = ListenAndExecute(action, event); actionExecuted = ListenAndExecute(action, event);
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
@@ -264,8 +269,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
delete actionNode; delete actionNode;
} }
} } while (basket && ++iterations <= iterationsPerTick);
while (basket && ++iterations <= iterationsPerTick);
// if (!basket) // if (!basket)
// { // {
@@ -312,13 +316,14 @@ ActionNode* Engine::CreateActionNode(std::string const name)
return node; return node;
} }
return new ActionNode (name, return new ActionNode(name,
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event, char const* pushType) bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event,
char const* pushType)
{ {
bool pushed = false; bool pushed = false;
if (actions) if (actions)
@@ -361,7 +366,7 @@ bool Engine::MultiplyAndPush(NextAction** actions, float forceRelevance, bool sk
ActionResult Engine::ExecuteAction(std::string const name, Event event, std::string const qualifier) ActionResult Engine::ExecuteAction(std::string const name, Event event, std::string const qualifier)
{ {
bool result = false; bool result = false;
ActionNode* actionNode = CreateActionNode(name); ActionNode* actionNode = CreateActionNode(name);
if (!actionNode) if (!actionNode)
@@ -399,7 +404,7 @@ ActionResult Engine::ExecuteAction(std::string const name, Event event, std::str
delete actionNode; delete actionNode;
return result ? ACTION_RESULT_OK : ACTION_RESULT_FAILED; return result ? ACTION_RESULT_OK : ACTION_RESULT_FAILED;
} }
void Engine::addStrategy(std::string const name) void Engine::addStrategy(std::string const name)
@@ -421,21 +426,20 @@ void Engine::addStrategy(std::string const name)
void Engine::addStrategies(std::string first, ...) void Engine::addStrategies(std::string first, ...)
{ {
addStrategy(first); addStrategy(first);
va_list vl; va_list vl;
va_start(vl, first); va_start(vl, first);
const char* cur; const char* cur;
do do
{ {
cur = va_arg(vl, const char*); cur = va_arg(vl, const char*);
if (cur) if (cur)
addStrategy(cur); addStrategy(cur);
} } while (cur);
while (cur);
va_end(vl); va_end(vl);
} }
bool Engine::removeStrategy(std::string const name) bool Engine::removeStrategy(std::string const name)
@@ -463,10 +467,7 @@ void Engine::toggleStrategy(std::string const name)
addStrategy(name); addStrategy(name);
} }
bool Engine::HasStrategy(std::string const name) bool Engine::HasStrategy(std::string const name) { return strategies.find(name) != strategies.end(); }
{
return strategies.find(name) != strategies.end();
}
void Engine::ProcessTriggers(bool minimal) void Engine::ProcessTriggers(bool minimal)
{ {
@@ -495,7 +496,8 @@ void Engine::ProcessTriggers(bool minimal)
if (minimal && node->getFirstRelevance() < 100) if (minimal && node->getFirstRelevance() < 100)
continue; continue;
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack); PerformanceMonitorOperation* pmo =
sPerformanceMonitor->start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack);
Event event = trigger->Check(); Event event = trigger->Check();
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
@@ -574,12 +576,12 @@ void Engine::PushAgain(ActionNode* actionNode, float relevance, Event event)
bool Engine::ContainsStrategy(StrategyType type) bool Engine::ContainsStrategy(StrategyType type)
{ {
for (std::map<std::string, Strategy*>::iterator i = strategies.begin(); i != strategies.end(); i++) for (std::map<std::string, Strategy*>::iterator i = strategies.begin(); i != strategies.end(); i++)
{ {
if (i->second->GetType() & type) if (i->second->GetType() & type)
return true; return true;
} }
return false; return false;
} }
Action* Engine::InitializeAction(ActionNode* actionNode) Action* Engine::InitializeAction(ActionNode* actionNode)
@@ -658,7 +660,7 @@ void Engine::LogAction(char const* format, ...)
} }
else else
{ {
LOG_DEBUG("playerbots", "{} {}", bot->GetName().c_str(), buf); LOG_DEBUG("playerbots", "{} {}", bot->GetName().c_str(), buf);
} }
} }
@@ -671,13 +673,13 @@ void Engine::ChangeStrategy(std::string const names)
switch (name[0]) switch (name[0])
{ {
case '+': case '+':
addStrategy(name+1); addStrategy(name + 1);
break; break;
case '-': case '-':
removeStrategy(name+1); removeStrategy(name + 1);
break; break;
case '~': case '~':
toggleStrategy(name+1); toggleStrategy(name + 1);
break; break;
case '?': case '?':
botAI->TellMaster(ListStrategies()); botAI->TellMaster(ListStrategies());
@@ -696,5 +698,5 @@ void Engine::LogValues()
return; return;
std::string const text = botAI->GetAiObjectContext()->FormatValues(); std::string const text = botAI->GetAiObjectContext()->FormatValues();
LOG_DEBUG("playerbots", "Values for {}: {}", bot->GetName().c_str(), text.c_str()); LOG_DEBUG("playerbots", "Values for {}: {}", bot->GetName().c_str(), text.c_str());
} }

View File

@@ -1,18 +1,19 @@
/* /*
* 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. * 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_ENGINE_H #ifndef _PLAYERBOT_ENGINE_H
#define _PLAYERBOT_ENGINE_H #define _PLAYERBOT_ENGINE_H
#include <map>
#include "Multiplier.h" #include "Multiplier.h"
#include "Queue.h"
#include "PlayerbotAIAware.h" #include "PlayerbotAIAware.h"
#include "Queue.h"
#include "Strategy.h" #include "Strategy.h"
#include "Trigger.h" #include "Trigger.h"
#include <map>
class Action; class Action;
class ActionNode; class ActionNode;
class AiObjectContext; class AiObjectContext;
@@ -31,97 +32,86 @@ enum ActionResult
class ActionExecutionListener class ActionExecutionListener
{ {
public: public:
virtual ~ActionExecutionListener() { }; virtual ~ActionExecutionListener(){};
virtual bool Before(Action* action, Event event) = 0; virtual bool Before(Action* action, Event event) = 0;
virtual bool AllowExecution(Action* action, Event event) = 0; virtual bool AllowExecution(Action* action, Event event) = 0;
virtual void After(Action* action, bool executed, Event event) = 0; virtual void After(Action* action, bool executed, Event event) = 0;
virtual bool OverrideResult(Action* action, bool executed, Event event) = 0; virtual bool OverrideResult(Action* action, bool executed, Event event) = 0;
}; };
class ActionExecutionListeners : public ActionExecutionListener class ActionExecutionListeners : public ActionExecutionListener
{ {
public: public:
virtual ~ActionExecutionListeners(); virtual ~ActionExecutionListeners();
bool Before(Action* action, Event event) override; bool Before(Action* action, Event event) override;
bool AllowExecution(Action* action, Event event) override; bool AllowExecution(Action* action, Event event) override;
void After(Action* action, bool executed, Event event) override; void After(Action* action, bool executed, Event event) override;
bool OverrideResult(Action* action, bool executed, Event event) override; bool OverrideResult(Action* action, bool executed, Event event) override;
void Add(ActionExecutionListener* listener) void Add(ActionExecutionListener* listener) { listeners.push_back(listener); }
{
listeners.push_back(listener);
}
void Remove(ActionExecutionListener* listener) void Remove(ActionExecutionListener* listener) { listeners.remove(listener); }
{
listeners.remove(listener);
}
private: private:
std::list<ActionExecutionListener*> listeners; std::list<ActionExecutionListener*> listeners;
}; };
class Engine : public PlayerbotAIAware class Engine : public PlayerbotAIAware
{ {
public: public:
Engine(PlayerbotAI* botAI, AiObjectContext* factory); Engine(PlayerbotAI* botAI, AiObjectContext* factory);
void Init(); void Init();
void addStrategy(std::string const name); void addStrategy(std::string const name);
void addStrategies(std::string first, ...); void addStrategies(std::string first, ...);
bool removeStrategy(std::string const name); bool removeStrategy(std::string const name);
bool HasStrategy(std::string const name); bool HasStrategy(std::string const name);
void removeAllStrategies(); void removeAllStrategies();
void toggleStrategy(std::string const name); void toggleStrategy(std::string const name);
std::string const ListStrategies(); std::string const ListStrategies();
std::vector<std::string> GetStrategies(); std::vector<std::string> GetStrategies();
bool ContainsStrategy(StrategyType type); bool ContainsStrategy(StrategyType type);
void ChangeStrategy(std::string const names); void ChangeStrategy(std::string const names);
std::string const GetLastAction() { return lastAction; } std::string const GetLastAction() { return lastAction; }
virtual bool DoNextAction(Unit*, uint32 depth = 0, bool minimal = false); virtual bool DoNextAction(Unit*, uint32 depth = 0, bool minimal = false);
ActionResult ExecuteAction(std::string const name, Event event = Event(), std::string const qualifier = ""); ActionResult ExecuteAction(std::string const name, Event event = Event(), std::string const qualifier = "");
void AddActionExecutionListener(ActionExecutionListener* listener) void AddActionExecutionListener(ActionExecutionListener* listener) { actionExecutionListeners.Add(listener); }
{
actionExecutionListeners.Add(listener);
}
void removeActionExecutionListener(ActionExecutionListener* listener) void removeActionExecutionListener(ActionExecutionListener* listener) { actionExecutionListeners.Remove(listener); }
{
actionExecutionListeners.Remove(listener);
}
virtual ~Engine(void); virtual ~Engine(void);
bool testMode; bool testMode;
private: private:
bool MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event, const char* pushType); bool MultiplyAndPush(NextAction** actions, float forceRelevance, bool skipPrerequisites, Event event,
void Reset(); const char* pushType);
void ProcessTriggers(bool minimal); void Reset();
void PushDefaultActions(); void ProcessTriggers(bool minimal);
void PushAgain(ActionNode* actionNode, float relevance, Event event); void PushDefaultActions();
ActionNode* CreateActionNode(std::string const name); void PushAgain(ActionNode* actionNode, float relevance, Event event);
Action* InitializeAction(ActionNode* actionNode); ActionNode* CreateActionNode(std::string const name);
bool ListenAndExecute(Action* action, Event event); Action* InitializeAction(ActionNode* actionNode);
bool ListenAndExecute(Action* action, Event event);
void LogAction(char const* format, ...); void LogAction(char const* format, ...);
void LogValues(); void LogValues();
ActionExecutionListeners actionExecutionListeners; ActionExecutionListeners actionExecutionListeners;
protected: protected:
Queue queue; Queue queue;
std::vector<TriggerNode*> triggers; std::vector<TriggerNode*> triggers;
std::vector<Multiplier*> multipliers; std::vector<Multiplier*> multipliers;
AiObjectContext* aiObjectContext; AiObjectContext* aiObjectContext;
std::map<std::string, Strategy*> strategies; std::map<std::string, Strategy*> strategies;
float lastRelevance; float lastRelevance;
std::string lastAction; std::string lastAction;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
Event::Event(std::string const source, ObjectGuid object, Player* owner) : source(source), owner(owner) Event::Event(std::string const source, ObjectGuid object, Player* owner) : source(source), owner(owner)

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_EVENT_H #ifndef _PLAYERBOT_EVENT_H
@@ -12,27 +13,33 @@ class Player;
class Event class Event
{ {
public: public:
Event(Event const& other) : source(other.source), param(other.param), packet(other.packet), owner(other.owner) { } Event(Event const& other) : source(other.source), param(other.param), packet(other.packet), owner(other.owner) {}
Event() { } Event() {}
Event(std::string const source) : source(source) { } Event(std::string const source) : source(source) {}
Event(std::string const source, std::string const param, Player* owner = nullptr) : source(source), param(param), owner(owner) { } Event(std::string const source, std::string const param, Player* owner = nullptr)
Event(std::string const source, WorldPacket& packet, Player* owner = nullptr) : source(source), packet(packet), owner(owner) { } : source(source), param(param), owner(owner)
Event(std::string const source, ObjectGuid object, Player* owner = nullptr); {
virtual ~Event() { } }
Event(std::string const source, WorldPacket& packet, Player* owner = nullptr)
: source(source), packet(packet), owner(owner)
{
}
Event(std::string const source, ObjectGuid object, Player* owner = nullptr);
virtual ~Event() {}
std::string const GetSource() { return source; } std::string const GetSource() { return source; }
std::string const getParam() { return param; } std::string const getParam() { return param; }
WorldPacket& getPacket() { return packet; } WorldPacket& getPacket() { return packet; }
ObjectGuid getObject(); ObjectGuid getObject();
Player* getOwner() { return owner; } Player* getOwner() { return owner; }
bool operator! () const { return source.empty(); } bool operator!() const { return source.empty(); }
protected: protected:
std::string source; std::string source;
std::string param; std::string param;
WorldPacket packet; WorldPacket packet;
Player* owner = nullptr; Player* owner = nullptr;
}; };
#endif #endif

View File

@@ -1,11 +1,13 @@
/* /*
* 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. * 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 "ExternalEventHelper.h" #include "ExternalEventHelper.h"
#include "Trigger.h"
#include "ChatHelper.h" #include "ChatHelper.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Trigger.h"
bool ExternalEventHelper::ParseChatCommand(std::string const command, Player* owner) bool ExternalEventHelper::ParseChatCommand(std::string const command, Player* owner)
{ {
@@ -37,7 +39,8 @@ bool ExternalEventHelper::ParseChatCommand(std::string const command, Player* ow
return true; return true;
} }
void ExternalEventHelper::HandlePacket(std::map<uint16, std::string>& handlers, WorldPacket const& packet, Player* owner) void ExternalEventHelper::HandlePacket(std::map<uint16, std::string>& handlers, WorldPacket const& packet,
Player* owner)
{ {
uint16 opcode = packet.GetOpcode(); uint16 opcode = packet.GetOpcode();
std::string const name = handlers[opcode]; std::string const name = handlers[opcode];

View File

@@ -1,29 +1,30 @@
/* /*
* 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. * 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_EXTERNALEVENTHELPER_H #ifndef _PLAYERBOT_EXTERNALEVENTHELPER_H
#define _PLAYERBOT_EXTERNALEVENTHELPER_H #define _PLAYERBOT_EXTERNALEVENTHELPER_H
#include "Common.h"
#include <map> #include <map>
#include "Common.h"
class AiObjectContext; class AiObjectContext;
class Player; class Player;
class WorldPacket; class WorldPacket;
class ExternalEventHelper class ExternalEventHelper
{ {
public: public:
ExternalEventHelper(AiObjectContext* aiObjectContext) : aiObjectContext(aiObjectContext) { } ExternalEventHelper(AiObjectContext* aiObjectContext) : aiObjectContext(aiObjectContext) {}
bool ParseChatCommand(std::string const command, Player* owner = nullptr); bool ParseChatCommand(std::string const command, Player* owner = nullptr);
void HandlePacket(std::map<uint16, std::string>& handlers, WorldPacket const& packet, Player* owner = nullptr); void HandlePacket(std::map<uint16, std::string>& handlers, WorldPacket const& packet, Player* owner = nullptr);
bool HandleCommand(std::string const name, std::string const param, Player* owner = nullptr); bool HandleCommand(std::string const name, std::string const param, Player* owner = nullptr);
private: private:
AiObjectContext* aiObjectContext; AiObjectContext* aiObjectContext;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "ItemVisitors.h" #include "ItemVisitors.h"
#include "Playerbots.h" #include "Playerbots.h"
bool FindUsableItemVisitor::Visit(Item* item) bool FindUsableItemVisitor::Visit(Item* item)
@@ -15,7 +17,8 @@ bool FindUsableItemVisitor::Visit(Item* item)
bool FindPotionVisitor::Accept(ItemTemplate const* proto) bool FindPotionVisitor::Accept(ItemTemplate const* proto)
{ {
if (proto->Class == ITEM_CLASS_CONSUMABLE && (proto->SubClass == ITEM_SUBCLASS_POTION || proto->SubClass == ITEM_SUBCLASS_FLASK)) if (proto->Class == ITEM_CLASS_CONSUMABLE &&
(proto->SubClass == ITEM_SUBCLASS_POTION || proto->SubClass == ITEM_SUBCLASS_FLASK))
{ {
for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; j++) for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; j++)
{ {

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ITEMVISITORS_H #ifndef _PLAYERBOT_ITEMVISITORS_H
@@ -17,407 +18,401 @@ char* strstri(char const* str1, char const* str2);
enum IterateItemsMask : uint32 enum IterateItemsMask : uint32
{ {
ITERATE_ITEMS_IN_BAGS = 1, ITERATE_ITEMS_IN_BAGS = 1,
ITERATE_ITEMS_IN_EQUIP = 2, ITERATE_ITEMS_IN_EQUIP = 2,
ITERATE_ITEMS_IN_BANK = 4, ITERATE_ITEMS_IN_BANK = 4,
ITERATE_ALL_ITEMS = 255 ITERATE_ALL_ITEMS = 255
}; };
class IterateItemsVisitor class IterateItemsVisitor
{ {
public: public:
IterateItemsVisitor() { } IterateItemsVisitor() {}
virtual bool Visit(Item* item) = 0; virtual bool Visit(Item* item) = 0;
}; };
class FindItemVisitor : public IterateItemsVisitor class FindItemVisitor : public IterateItemsVisitor
{ {
public: public:
FindItemVisitor() : IterateItemsVisitor(), result() { } FindItemVisitor() : IterateItemsVisitor(), result() {}
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
if (!Accept(item->GetTemplate())) if (!Accept(item->GetTemplate()))
return true;
result.push_back(item);
return true; return true;
}
std::vector<Item*>& GetResult() { return result; } result.push_back(item);
return true;
}
protected: std::vector<Item*>& GetResult() { return result; }
virtual bool Accept(ItemTemplate const* proto) = 0;
private: protected:
std::vector<Item*> result; virtual bool Accept(ItemTemplate const* proto) = 0;
private:
std::vector<Item*> result;
}; };
class FindUsableItemVisitor : public FindItemVisitor class FindUsableItemVisitor : public FindItemVisitor
{ {
public: public:
FindUsableItemVisitor(Player* bot) : FindItemVisitor(), bot(bot) { } FindUsableItemVisitor(Player* bot) : FindItemVisitor(), bot(bot) {}
bool Visit(Item* item) override; bool Visit(Item* item) override;
private: private:
Player* bot; Player* bot;
}; };
class FindItemsByQualityVisitor : public IterateItemsVisitor class FindItemsByQualityVisitor : public IterateItemsVisitor
{ {
public: public:
FindItemsByQualityVisitor(uint32 quality, uint32 count) : IterateItemsVisitor(), quality(quality), count(count) { } FindItemsByQualityVisitor(uint32 quality, uint32 count) : IterateItemsVisitor(), quality(quality), count(count) {}
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
if (item->GetTemplate()->Quality != quality) if (item->GetTemplate()->Quality != quality)
return true;
if (result.size() >= (size_t)count)
return false;
result.push_back(item);
return true; return true;
}
std::vector<Item*>& GetResult() if (result.size() >= (size_t)count)
{ return false;
return result;
}
private: result.push_back(item);
uint32 quality; return true;
uint32 count; }
std::vector<Item*> result;
std::vector<Item*>& GetResult() { return result; }
private:
uint32 quality;
uint32 count;
std::vector<Item*> result;
}; };
class FindItemsToTradeByQualityVisitor : public FindItemsByQualityVisitor class FindItemsToTradeByQualityVisitor : public FindItemsByQualityVisitor
{ {
public: public:
FindItemsToTradeByQualityVisitor(uint32 quality, uint32 count) : FindItemsByQualityVisitor(quality, count) { } FindItemsToTradeByQualityVisitor(uint32 quality, uint32 count) : FindItemsByQualityVisitor(quality, count) {}
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
if (item->IsSoulBound()) if (item->IsSoulBound())
return true; return true;
return FindItemsByQualityVisitor::Visit(item); return FindItemsByQualityVisitor::Visit(item);
} }
}; };
class FindItemsToTradeByClassVisitor : public IterateItemsVisitor class FindItemsToTradeByClassVisitor : public IterateItemsVisitor
{ {
public: public:
FindItemsToTradeByClassVisitor(uint32 itemClass, uint32 itemSubClass, uint32 count) FindItemsToTradeByClassVisitor(uint32 itemClass, uint32 itemSubClass, uint32 count)
: IterateItemsVisitor(), itemClass(itemClass), itemSubClass(itemSubClass), count(count) { } // reorder args - whipowill : IterateItemsVisitor(), itemClass(itemClass), itemSubClass(itemSubClass), count(count)
{
} // reorder args - whipowill
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
if (item->IsSoulBound()) if (item->IsSoulBound())
return true;
if (item->GetTemplate()->Class != itemClass || item->GetTemplate()->SubClass != itemSubClass)
return true;
if (result.size() >= (size_t)count)
return false;
result.push_back(item);
return true; return true;
}
std::vector<Item*>& GetResult() if (item->GetTemplate()->Class != itemClass || item->GetTemplate()->SubClass != itemSubClass)
{ return true;
return result;
}
private: if (result.size() >= (size_t)count)
uint32 itemClass; return false;
uint32 itemSubClass;
uint32 count; result.push_back(item);
std::vector<Item*> result; return true;
}
std::vector<Item*>& GetResult() { return result; }
private:
uint32 itemClass;
uint32 itemSubClass;
uint32 count;
std::vector<Item*> result;
}; };
class QueryItemCountVisitor : public IterateItemsVisitor class QueryItemCountVisitor : public IterateItemsVisitor
{ {
public: public:
QueryItemCountVisitor(uint32 itemId) : count(0), itemId(itemId) { } QueryItemCountVisitor(uint32 itemId) : count(0), itemId(itemId) {}
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
if (item->GetTemplate()->ItemId == itemId) if (item->GetTemplate()->ItemId == itemId)
count += item->GetCount(); count += item->GetCount();
return true; return true;
} }
uint32 GetCount() { return count; } uint32 GetCount() { return count; }
protected: protected:
uint32 count; uint32 count;
uint32 itemId; uint32 itemId;
}; };
class QueryNamedItemCountVisitor : public QueryItemCountVisitor class QueryNamedItemCountVisitor : public QueryItemCountVisitor
{ {
public: public:
QueryNamedItemCountVisitor(std::string const name) : QueryItemCountVisitor(0), name(name) { } QueryNamedItemCountVisitor(std::string const name) : QueryItemCountVisitor(0), name(name) {}
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
ItemTemplate const* proto = item->GetTemplate(); ItemTemplate const* proto = item->GetTemplate();
if (proto && proto->Name1.c_str() && strstri(proto->Name1.c_str(), name.c_str())) if (proto && proto->Name1.c_str() && strstri(proto->Name1.c_str(), name.c_str()))
count += item->GetCount(); count += item->GetCount();
return true; return true;
} }
private: private:
std::string const name; std::string const name;
}; };
class FindNamedItemVisitor : public FindItemVisitor class FindNamedItemVisitor : public FindItemVisitor
{ {
public: public:
FindNamedItemVisitor([[maybe_unused]] Player* bot, std::string const name) : FindItemVisitor(), name(name) { } FindNamedItemVisitor([[maybe_unused]] Player* bot, std::string const name) : FindItemVisitor(), name(name) {}
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override
{ {
return proto && proto->Name1.c_str() && strstri(proto->Name1.c_str(), name.c_str()); return proto && proto->Name1.c_str() && strstri(proto->Name1.c_str(), name.c_str());
} }
private: private:
std::string const name; std::string const name;
}; };
class FindItemByIdVisitor : public FindItemVisitor class FindItemByIdVisitor : public FindItemVisitor
{ {
public: public:
FindItemByIdVisitor(uint32 id) : FindItemVisitor(), id(id) { } FindItemByIdVisitor(uint32 id) : FindItemVisitor(), id(id) {}
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override { return proto->ItemId == id; }
{
return proto->ItemId == id;
}
private: private:
uint32 id; uint32 id;
}; };
class FindItemByIdsVisitor : public FindItemVisitor class FindItemByIdsVisitor : public FindItemVisitor
{ {
public: public:
FindItemByIdsVisitor(ItemIds ids) : FindItemVisitor(), ids(ids) { } FindItemByIdsVisitor(ItemIds ids) : FindItemVisitor(), ids(ids) {}
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override { return ids.find(proto->ItemId) != ids.end(); }
{
return ids.find(proto->ItemId) != ids.end();
}
private: private:
ItemIds ids; ItemIds ids;
}; };
class ListItemsVisitor : public IterateItemsVisitor class ListItemsVisitor : public IterateItemsVisitor
{ {
public: public:
ListItemsVisitor() : IterateItemsVisitor() { } ListItemsVisitor() : IterateItemsVisitor() {}
std::map<uint32, uint32> items; std::map<uint32, uint32> items;
std::map<uint32, bool> soulbound; std::map<uint32, bool> soulbound;
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
uint32 id = item->GetTemplate()->ItemId; uint32 id = item->GetTemplate()->ItemId;
if (items.find(id) == items.end()) if (items.find(id) == items.end())
items[id] = 0; items[id] = 0;
items[id] += item->GetCount(); items[id] += item->GetCount();
soulbound[id] = item->IsSoulBound(); soulbound[id] = item->IsSoulBound();
return true; return true;
} }
}; };
class ItemCountByQuality : public IterateItemsVisitor class ItemCountByQuality : public IterateItemsVisitor
{ {
public: public:
ItemCountByQuality() : IterateItemsVisitor() ItemCountByQuality() : IterateItemsVisitor()
{ {
for (uint32 i = 0; i < MAX_ITEM_QUALITY; ++i) for (uint32 i = 0; i < MAX_ITEM_QUALITY; ++i)
count[i] = 0; count[i] = 0;
} }
bool Visit(Item* item) override bool Visit(Item* item) override
{ {
++count[item->GetTemplate()->Quality]; ++count[item->GetTemplate()->Quality];
return true; return true;
} }
public: public:
std::map<uint32, uint32> count; std::map<uint32, uint32> count;
}; };
class FindPotionVisitor : public FindUsableItemVisitor class FindPotionVisitor : public FindUsableItemVisitor
{ {
public: public:
FindPotionVisitor(Player* bot, uint32 effectId) : FindUsableItemVisitor(bot), effectId(effectId) { } FindPotionVisitor(Player* bot, uint32 effectId) : FindUsableItemVisitor(bot), effectId(effectId) {}
bool Accept(ItemTemplate const* proto) override; bool Accept(ItemTemplate const* proto) override;
private: private:
uint32 effectId; uint32 effectId;
}; };
class FindFoodVisitor : public FindUsableItemVisitor class FindFoodVisitor : public FindUsableItemVisitor
{ {
public: public:
FindFoodVisitor(Player* bot, uint32 spellCategory, bool conjured = false) : FindUsableItemVisitor(bot), FindFoodVisitor(Player* bot, uint32 spellCategory, bool conjured = false)
spellCategory(spellCategory), conjured(conjured) { } : FindUsableItemVisitor(bot), spellCategory(spellCategory), conjured(conjured)
{
}
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override
{ {
return proto->Class == ITEM_CLASS_CONSUMABLE && (proto->SubClass == ITEM_SUBCLASS_CONSUMABLE || proto->SubClass == ITEM_SUBCLASS_FOOD) && return proto->Class == ITEM_CLASS_CONSUMABLE &&
proto->Spells[0].SpellCategory == spellCategory && (!conjured || proto->IsConjuredConsumable()); (proto->SubClass == ITEM_SUBCLASS_CONSUMABLE || proto->SubClass == ITEM_SUBCLASS_FOOD) &&
} proto->Spells[0].SpellCategory == spellCategory && (!conjured || proto->IsConjuredConsumable());
}
private: private:
uint32 spellCategory; uint32 spellCategory;
bool conjured; bool conjured;
}; };
class FindMountVisitor : public FindUsableItemVisitor class FindMountVisitor : public FindUsableItemVisitor
{ {
public: public:
FindMountVisitor(Player* bot) : FindUsableItemVisitor(bot) { } FindMountVisitor(Player* bot) : FindUsableItemVisitor(bot) {}
bool Accept(ItemTemplate const* proto) override; bool Accept(ItemTemplate const* proto) override;
private: private:
uint32 effectId; uint32 effectId;
}; };
class FindPetVisitor : public FindUsableItemVisitor class FindPetVisitor : public FindUsableItemVisitor
{ {
public: public:
FindPetVisitor(Player* bot) : FindUsableItemVisitor(bot) { } FindPetVisitor(Player* bot) : FindUsableItemVisitor(bot) {}
bool Accept(ItemTemplate const* proto) override; bool Accept(ItemTemplate const* proto) override;
}; };
class FindAmmoVisitor : public FindUsableItemVisitor class FindAmmoVisitor : public FindUsableItemVisitor
{ {
public: public:
FindAmmoVisitor(Player* bot, uint32 weaponType) : FindUsableItemVisitor(bot), weaponType(weaponType) { } FindAmmoVisitor(Player* bot, uint32 weaponType) : FindUsableItemVisitor(bot), weaponType(weaponType) {}
bool Accept(ItemTemplate const* proto)override bool Accept(ItemTemplate const* proto) override
{
if (proto->Class == ITEM_CLASS_PROJECTILE)
{ {
if (proto->Class == ITEM_CLASS_PROJECTILE) uint32 subClass = 0;
switch (weaponType)
{ {
uint32 subClass = 0; case ITEM_SUBCLASS_WEAPON_GUN:
switch (weaponType) subClass = ITEM_SUBCLASS_BULLET;
{ break;
case ITEM_SUBCLASS_WEAPON_GUN: case ITEM_SUBCLASS_WEAPON_BOW:
subClass = ITEM_SUBCLASS_BULLET; case ITEM_SUBCLASS_WEAPON_CROSSBOW:
break; subClass = ITEM_SUBCLASS_ARROW;
case ITEM_SUBCLASS_WEAPON_BOW: break;
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
subClass = ITEM_SUBCLASS_ARROW;
break;
}
if (!subClass)
return false;
if (proto->SubClass == subClass)
return true;
} }
return false; if (!subClass)
return false;
if (proto->SubClass == subClass)
return true;
} }
private: return false;
uint32 weaponType; }
private:
uint32 weaponType;
}; };
class FindQuestItemVisitor : public FindUsableItemVisitor class FindQuestItemVisitor : public FindUsableItemVisitor
{ {
public: public:
FindQuestItemVisitor(Player* bot) : FindUsableItemVisitor(bot) { } FindQuestItemVisitor(Player* bot) : FindUsableItemVisitor(bot) {}
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override
{
if (proto->Class == ITEM_CLASS_QUEST)
{ {
if (proto->Class == ITEM_CLASS_QUEST) return true;
{
return true;
}
return false;
} }
return false;
}
}; };
class FindRecipeVisitor : public FindUsableItemVisitor class FindRecipeVisitor : public FindUsableItemVisitor
{ {
public: public:
FindRecipeVisitor(Player* bot, SkillType skill = SKILL_NONE) : FindUsableItemVisitor(bot), skill(skill) { }; FindRecipeVisitor(Player* bot, SkillType skill = SKILL_NONE) : FindUsableItemVisitor(bot), skill(skill){};
bool Accept(ItemTemplate const* proto) override bool Accept(ItemTemplate const* proto) override
{
if (proto->Class == ITEM_CLASS_RECIPE)
{ {
if (proto->Class == ITEM_CLASS_RECIPE) if (skill == SKILL_NONE)
return true;
switch (proto->SubClass)
{ {
if (skill == SKILL_NONE) case ITEM_SUBCLASS_LEATHERWORKING_PATTERN:
return true; return skill == SKILL_LEATHERWORKING;
case ITEM_SUBCLASS_TAILORING_PATTERN:
switch (proto->SubClass) return skill == SKILL_TAILORING;
{ case ITEM_SUBCLASS_ENGINEERING_SCHEMATIC:
case ITEM_SUBCLASS_LEATHERWORKING_PATTERN: return skill == SKILL_ENGINEERING;
return skill == SKILL_LEATHERWORKING; case ITEM_SUBCLASS_BLACKSMITHING:
case ITEM_SUBCLASS_TAILORING_PATTERN: return skill == SKILL_BLACKSMITHING;
return skill == SKILL_TAILORING; case ITEM_SUBCLASS_COOKING_RECIPE:
case ITEM_SUBCLASS_ENGINEERING_SCHEMATIC: return skill == SKILL_COOKING;
return skill == SKILL_ENGINEERING; case ITEM_SUBCLASS_ALCHEMY_RECIPE:
case ITEM_SUBCLASS_BLACKSMITHING: return skill == SKILL_ALCHEMY;
return skill == SKILL_BLACKSMITHING; case ITEM_SUBCLASS_FIRST_AID_MANUAL:
case ITEM_SUBCLASS_COOKING_RECIPE: return skill == SKILL_FIRST_AID;
return skill == SKILL_COOKING; case ITEM_SUBCLASS_ENCHANTING_FORMULA:
case ITEM_SUBCLASS_ALCHEMY_RECIPE: return skill == SKILL_ENCHANTING;
return skill == SKILL_ALCHEMY; case ITEM_SUBCLASS_FISHING_MANUAL:
case ITEM_SUBCLASS_FIRST_AID_MANUAL: return skill == SKILL_FISHING;
return skill == SKILL_FIRST_AID;
case ITEM_SUBCLASS_ENCHANTING_FORMULA:
return skill == SKILL_ENCHANTING;
case ITEM_SUBCLASS_FISHING_MANUAL:
return skill == SKILL_FISHING;
}
} }
return false;
} }
private: return false;
SkillType skill; }
private:
SkillType skill;
}; };
class FindItemUsageVisitor : public FindUsableItemVisitor class FindItemUsageVisitor : public FindUsableItemVisitor
{ {
public: public:
FindItemUsageVisitor(Player* bot, ItemUsage usage = ITEM_USAGE_NONE); FindItemUsageVisitor(Player* bot, ItemUsage usage = ITEM_USAGE_NONE);
bool Accept(ItemTemplate const* proto) override; bool Accept(ItemTemplate const* proto) override;
private: private:
AiObjectContext* context; AiObjectContext* context;
ItemUsage usage; ItemUsage usage;
}; };
class FindUsableNamedItemVisitor : public FindUsableItemVisitor class FindUsableNamedItemVisitor : public FindUsableItemVisitor
{ {
public: public:
FindUsableNamedItemVisitor(Player* bot, std::string name): FindUsableItemVisitor(bot), name(name) {} FindUsableNamedItemVisitor(Player* bot, std::string name) : FindUsableItemVisitor(bot), name(name) {}
bool Accept(ItemTemplate const* proto) override; bool Accept(ItemTemplate const* proto) override;
private:
std::string name; private:
std::string name;
}; };
#endif #endif

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_MULTIPLIER_H #ifndef _PLAYERBOT_MULTIPLIER_H
@@ -12,11 +13,11 @@ class PlayerbotAI;
class Multiplier : public AiNamedObject class Multiplier : public AiNamedObject
{ {
public: public:
Multiplier(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) {} Multiplier(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) {}
virtual ~Multiplier() { } virtual ~Multiplier() {}
virtual float GetValue([[maybe_unused]] Action* action) { return 1.0f; } virtual float GetValue([[maybe_unused]] Action* action) { return 1.0f; }
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "NamedObjectContext.h" #include "NamedObjectContext.h"
#include "Playerbots.h" #include "Playerbots.h"
void Qualified::Qualify(int qual) void Qualified::Qualify(int qual)
@@ -24,7 +26,7 @@ std::string const Qualified::MultiQualify(std::vector<std::string> qualifiers)
std::vector<std::string> Qualified::getMultiQualifiers(std::string const qualifier1) std::vector<std::string> Qualified::getMultiQualifiers(std::string const qualifier1)
{ {
std::istringstream iss(qualifier1); std::istringstream iss(qualifier1);
return { std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{} }; return {std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};
} }
int32 Qualified::getMultiQualifier(std::string const qualifier1, uint32 pos) int32 Qualified::getMultiQualifier(std::string const qualifier1, uint32 pos)

View File

@@ -1,283 +1,272 @@
/* /*
* 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. * 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_NAMEDOBJECTCONEXT_H #ifndef _PLAYERBOT_NAMEDOBJECTCONEXT_H
#define _PLAYERBOT_NAMEDOBJECTCONEXT_H #define _PLAYERBOT_NAMEDOBJECTCONEXT_H
#include "Common.h"
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <list> #include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
#include "Common.h"
class PlayerbotAI; class PlayerbotAI;
class Qualified class Qualified
{ {
public: public:
Qualified() { }; Qualified(){};
Qualified(std::string const qualifier) : qualifier(qualifier) { } Qualified(std::string const qualifier) : qualifier(qualifier) {}
Qualified(int32 qualifier1) Qualified(int32 qualifier1) { Qualify(qualifier1); }
{
Qualify(qualifier1);
}
virtual void Qualify(int qual); virtual void Qualify(int qual);
virtual void Qualify(std::string const qual) virtual void Qualify(std::string const qual) { qualifier = qual; }
{
qualifier = qual;
}
std::string const getQualifier() { return qualifier; } std::string const getQualifier() { return qualifier; }
static std::string const MultiQualify(std::vector<std::string> qualifiers); static std::string const MultiQualify(std::vector<std::string> qualifiers);
static std::vector<std::string> getMultiQualifiers(std::string const qualifier1); static std::vector<std::string> getMultiQualifiers(std::string const qualifier1);
static int32 getMultiQualifier(std::string const qualifier1, uint32 pos); static int32 getMultiQualifier(std::string const qualifier1, uint32 pos);
protected: protected:
std::string qualifier; std::string qualifier;
}; };
template <class T> template <class T>
class NamedObjectFactory class NamedObjectFactory
{ {
protected: protected:
typedef T*(*ActionCreator)(PlayerbotAI* botAI); typedef T* (*ActionCreator)(PlayerbotAI* botAI);
std::unordered_map<std::string, ActionCreator> creators; std::unordered_map<std::string, ActionCreator> creators;
public: public:
T* create(std::string name, PlayerbotAI* botAI) T* create(std::string name, PlayerbotAI* botAI)
{
size_t found = name.find("::");
std::string qualifier;
if (found != std::string::npos)
{ {
size_t found = name.find("::"); qualifier = name.substr(found + 2);
std::string qualifier; name = name.substr(0, found);
if (found != std::string::npos)
{
qualifier = name.substr(found + 2);
name = name.substr(0, found);
}
if (creators.find(name) == creators.end())
return nullptr;
ActionCreator creator = creators[name];
if (!creator)
return nullptr;
T* object = (*creator)(botAI);
Qualified* q = dynamic_cast<Qualified*>(object);
if (q && found != std::string::npos)
q->Qualify(qualifier);
return object;
} }
std::set<std::string> supports() if (creators.find(name) == creators.end())
{ return nullptr;
std::set<std::string> keys;
for (typename std::unordered_map<std::string, ActionCreator>::iterator it = creators.begin(); it != creators.end(); it++)
keys.insert(it->first);
return keys; ActionCreator creator = creators[name];
} if (!creator)
return nullptr;
T* object = (*creator)(botAI);
Qualified* q = dynamic_cast<Qualified*>(object);
if (q && found != std::string::npos)
q->Qualify(qualifier);
return object;
}
std::set<std::string> supports()
{
std::set<std::string> keys;
for (typename std::unordered_map<std::string, ActionCreator>::iterator it = creators.begin();
it != creators.end(); it++)
keys.insert(it->first);
return keys;
}
}; };
template <class T> template <class T>
class NamedObjectContext : public NamedObjectFactory<T> class NamedObjectContext : public NamedObjectFactory<T>
{ {
public: public:
NamedObjectContext(bool shared = false, bool supportsSiblings = false) : NamedObjectContext(bool shared = false, bool supportsSiblings = false)
NamedObjectFactory<T>(), shared(shared), supportsSiblings(supportsSiblings) { } : NamedObjectFactory<T>(), shared(shared), supportsSiblings(supportsSiblings)
{
}
virtual ~NamedObjectContext() virtual ~NamedObjectContext() { Clear(); }
T* create(std::string const name, PlayerbotAI* botAI)
{
if (created.find(name) == created.end())
return created[name] = NamedObjectFactory<T>::create(name, botAI);
return created[name];
}
void Clear()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{ {
Clear(); if (i->second)
delete i->second;
} }
T* create(std::string const name, PlayerbotAI* botAI) created.clear();
}
void Update()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{ {
if (created.find(name) == created.end()) if (i->second)
return created[name] = NamedObjectFactory<T>::create(name, botAI); i->second->Update();
return created[name];
} }
}
void Clear() void Reset()
{
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{ {
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++) if (i->second)
{ i->second->Reset();
if (i->second)
delete i->second;
}
created.clear();
} }
}
void Update() bool IsShared() { return shared; }
{ bool IsSupportsSiblings() { return supportsSiblings; }
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++)
{
if (i->second)
i->second->Update();
}
}
void Reset() std::set<std::string> GetCreated()
{ {
for (typename std::unordered_map<std::string, T*>::iterator i = created.begin(); i != created.end(); i++) std::set<std::string> keys;
{ for (typename std::unordered_map<std::string, T*>::iterator it = created.begin(); it != created.end(); it++)
if (i->second) keys.insert(it->first);
i->second->Reset();
}
}
bool IsShared() { return shared; } return keys;
bool IsSupportsSiblings() { return supportsSiblings; } }
std::set<std::string> GetCreated() protected:
{ std::unordered_map<std::string, T*> created;
std::set<std::string> keys; bool shared;
for (typename std::unordered_map<std::string, T*>::iterator it = created.begin(); it != created.end(); it++) bool supportsSiblings;
keys.insert(it->first);
return keys;
}
protected:
std::unordered_map<std::string, T*> created;
bool shared;
bool supportsSiblings;
}; };
template <class T> template <class T>
class NamedObjectContextList class NamedObjectContextList
{ {
public: public:
virtual ~NamedObjectContextList() virtual ~NamedObjectContextList()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{ {
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) NamedObjectContext<T>* context = *i;
{ if (!context->IsShared())
NamedObjectContext<T>* context = *i; delete context;
if (!context->IsShared()) }
delete context; }
}
void Add(NamedObjectContext<T>* context) { contexts.push_back(context); }
T* GetContextObject(std::string const name, PlayerbotAI* botAI)
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
if (T* object = (*i)->create(name, botAI))
return object;
} }
void Add(NamedObjectContext<T>* context) return nullptr;
}
void Update()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{ {
contexts.push_back(context); if (!(*i)->IsShared())
(*i)->Update();
}
}
void Reset()
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
(*i)->Reset();
}
}
std::set<std::string> GetSiblings(std::string const name)
{
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
if (!(*i)->IsSupportsSiblings())
continue;
std::set<std::string> supported = (*i)->supports();
std::set<std::string>::iterator found = supported.find(name);
if (found == supported.end())
continue;
supported.erase(found);
return supported;
} }
T* GetContextObject(std::string const name, PlayerbotAI* botAI) return std::set<std::string>();
{ }
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
if (T* object = (*i)->create(name, botAI))
return object;
}
return nullptr; std::set<std::string> supports()
{
std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
std::set<std::string> supported = (*i)->supports();
for (std::set<std::string>::iterator j = supported.begin(); j != supported.end(); j++)
result.insert(*j);
} }
void Update() return result;
}
std::set<std::string> GetCreated()
{
std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{ {
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++) std::set<std::string> createdKeys = (*i)->GetCreated();
{
if (!(*i)->IsShared()) for (std::set<std::string>::iterator j = createdKeys.begin(); j != createdKeys.end(); j++)
(*i)->Update(); result.insert(*j);
}
} }
void Reset() return result;
{ }
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
(*i)->Reset();
}
}
std::set<std::string> GetSiblings(std::string const name) private:
{ std::vector<NamedObjectContext<T>*> contexts;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
if (!(*i)->IsSupportsSiblings())
continue;
std::set<std::string> supported = (*i)->supports();
std::set<std::string>::iterator found = supported.find(name);
if (found == supported.end())
continue;
supported.erase(found);
return supported;
}
return std::set<std::string>();
}
std::set<std::string> supports()
{
std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
std::set<std::string> supported = (*i)->supports();
for (std::set<std::string>::iterator j = supported.begin(); j != supported.end(); j++)
result.insert(*j);
}
return result;
}
std::set<std::string> GetCreated()
{
std::set<std::string> result;
for (typename std::vector<NamedObjectContext<T>*>::iterator i = contexts.begin(); i != contexts.end(); i++)
{
std::set<std::string> createdKeys = (*i)->GetCreated();
for (std::set<std::string>::iterator j = createdKeys.begin(); j != createdKeys.end(); j++)
result.insert(*j);
}
return result;
}
private:
std::vector<NamedObjectContext<T>*> contexts;
}; };
template <class T> template <class T>
class NamedObjectFactoryList class NamedObjectFactoryList
{ {
public: public:
virtual ~NamedObjectFactoryList() virtual ~NamedObjectFactoryList()
{
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++)
delete *i;
}
void Add(NamedObjectFactory<T>* context) { factories.push_front(context); }
T* GetContextObject(std::string const& name, PlayerbotAI* botAI)
{
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++)
{ {
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++) if (T* object = (*i)->create(name, botAI))
delete *i; return object;
} }
void Add(NamedObjectFactory<T>* context) return nullptr;
{ }
factories.push_front(context);
}
T* GetContextObject(std::string const &name, PlayerbotAI* botAI) private:
{ std::list<NamedObjectFactory<T>*> factories;
for (typename std::list<NamedObjectFactory<T>*>::iterator i = factories.begin(); i != factories.end(); i++)
{
if (T* object = (*i)->create(name, botAI))
return object;
}
return nullptr;
}
private:
std::list<NamedObjectFactory<T>*> factories;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "PassiveMultiplier.h" #include "PassiveMultiplier.h"
#include "Action.h" #include "Action.h"
#include "AiObjectContext.h" #include "AiObjectContext.h"
@@ -30,7 +32,7 @@ PassiveMultiplier::PassiveMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "pa
float PassiveMultiplier::GetValue(Action* action) float PassiveMultiplier::GetValue(Action* action)
{ {
if (!action) if (!action)
return 1.0f; return 1.0f;
std::string const name = action->getName(); std::string const name = action->getName();

View File

@@ -1,27 +1,28 @@
/* /*
* 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. * 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_PASSIVEMULTIPLIER_H #ifndef _PLAYERBOT_PASSIVEMULTIPLIER_H
#define _PLAYERBOT_PASSIVEMULTIPLIER_H #define _PLAYERBOT_PASSIVEMULTIPLIER_H
#include "Multiplier.h"
#include <vector> #include <vector>
#include "Multiplier.h"
class Action; class Action;
class PlayerbotAI; class PlayerbotAI;
class PassiveMultiplier : public Multiplier class PassiveMultiplier : public Multiplier
{ {
public: public:
PassiveMultiplier(PlayerbotAI* botAI); PassiveMultiplier(PlayerbotAI* botAI);
float GetValue(Action* action) override; float GetValue(Action* action) override;
private: private:
static std::vector<std::string> allowedActions; static std::vector<std::string> allowedActions;
static std::vector<std::string> allowedParts; static std::vector<std::string> allowedParts;
}; };
#endif #endif

View File

@@ -1,26 +1,28 @@
/* /*
* 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. * 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 "Queue.h" #include "Queue.h"
#include "AiObjectContext.h" #include "AiObjectContext.h"
#include "Log.h" #include "Log.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
void Queue::Push(ActionBasket *action) void Queue::Push(ActionBasket* action)
{ {
if (action) if (action)
{ {
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++) for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{ {
ActionBasket* basket = *iter; ActionBasket* basket = *iter;
if (action->getAction()->getName() == basket->getAction()->getName()) if (action->getAction()->getName() == basket->getAction()->getName())
{ {
if (basket->getRelevance() < action->getRelevance()) if (basket->getRelevance() < action->getRelevance())
basket->setRelevance(action->getRelevance()); basket->setRelevance(action->getRelevance());
if (ActionNode* actionNode = action->getAction()) if (ActionNode* actionNode = action->getAction())
delete actionNode; delete actionNode;
delete action; delete action;
@@ -28,34 +30,34 @@ void Queue::Push(ActionBasket *action)
} }
} }
actions.push_back(action); actions.push_back(action);
} }
} }
ActionNode* Queue::Pop() ActionNode* Queue::Pop()
{ {
float max = -1; float max = -1;
ActionBasket* selection = nullptr; ActionBasket* selection = nullptr;
for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++) for (std::list<ActionBasket*>::iterator iter = actions.begin(); iter != actions.end(); iter++)
{ {
ActionBasket* basket = *iter; ActionBasket* basket = *iter;
if (basket->getRelevance() > max) if (basket->getRelevance() > max)
{ {
max = basket->getRelevance(); max = basket->getRelevance();
selection = basket; selection = basket;
} }
} }
if (selection != nullptr) if (selection != nullptr)
{ {
ActionNode* action = selection->getAction(); ActionNode* action = selection->getAction();
actions.remove(selection); actions.remove(selection);
delete selection; delete selection;
return action; return action;
} }
return nullptr; return nullptr;
} }
ActionBasket* Queue::Peek() ActionBasket* Queue::Peek()
@@ -75,10 +77,7 @@ ActionBasket* Queue::Peek()
return selection; return selection;
} }
uint32 Queue::Size() uint32 Queue::Size() { return actions.size(); }
{
return actions.size();
}
void Queue::RemoveExpired() void Queue::RemoveExpired()
{ {

View File

@@ -1,27 +1,28 @@
/* /*
* 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. * 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_QUEUE_H #ifndef _PLAYERBOT_QUEUE_H
#define _PLAYERBOT_QUEUE_H #define _PLAYERBOT_QUEUE_H
#include "Common.h"
#include "Action.h" #include "Action.h"
#include "Common.h"
class Queue class Queue
{ {
public: public:
Queue(void) { } Queue(void) {}
~Queue(void) { } ~Queue(void) {}
void Push(ActionBasket *action); void Push(ActionBasket* action);
ActionNode* Pop(); ActionNode* Pop();
ActionBasket* Peek(); ActionBasket* Peek();
uint32 Size(); uint32 Size();
void RemoveExpired(); void RemoveExpired();
private: private:
std::list<ActionBasket*> actions; std::list<ActionBasket*> actions;
}; };
#endif #endif

View File

@@ -1,116 +1,118 @@
/* /*
* 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. * 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 "Strategy.h" #include "Strategy.h"
#include "Playerbots.h" #include "Playerbots.h"
class ActionNodeFactoryInternal : public NamedObjectFactory<ActionNode> class ActionNodeFactoryInternal : public NamedObjectFactory<ActionNode>
{ {
public: public:
ActionNodeFactoryInternal() ActionNodeFactoryInternal()
{ {
creators["melee"] = &melee; creators["melee"] = &melee;
creators["healthstone"] = &healthstone; creators["healthstone"] = &healthstone;
creators["be near"] = &follow_master_random; creators["be near"] = &follow_master_random;
creators["attack anything"] = &attack_anything; creators["attack anything"] = &attack_anything;
creators["move random"] = &move_random; creators["move random"] = &move_random;
creators["move to loot"] = &move_to_loot; creators["move to loot"] = &move_to_loot;
creators["food"] = &food; creators["food"] = &food;
creators["drink"] = &drink; creators["drink"] = &drink;
creators["mana potion"] = &mana_potion; creators["mana potion"] = &mana_potion;
creators["healing potion"] = &healing_potion; creators["healing potion"] = &healing_potion;
creators["flee"] = &flee; creators["flee"] = &flee;
} }
private: private:
static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* melee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("melee", return new ActionNode("melee",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healthstone([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("healthstone", return new ActionNode("healthstone",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("healing potion"), nullptr), /*A*/ NextAction::array(0, new NextAction("healing potion"), nullptr),
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* follow_master_random([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("be near", return new ActionNode("be near",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("follow"), nullptr), /*A*/ NextAction::array(0, new NextAction("follow"), nullptr),
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* attack_anything([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("attack anything", return new ActionNode("attack anything",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* move_random([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("move random", return new ActionNode("move random",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("stay line"), nullptr), /*A*/ NextAction::array(0, new NextAction("stay line"), nullptr),
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* move_to_loot([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("move to loot", return new ActionNode("move to loot",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* food([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("food", return new ActionNode("food",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* drink([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("drink", return new ActionNode("drink",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* mana_potion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("mana potion", return new ActionNode("mana potion",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("drink"), nullptr), /*A*/ NextAction::array(0, new NextAction("drink"), nullptr),
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* healing_potion([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("healing potion", return new ActionNode("healing potion",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("food"), nullptr), /*A*/ NextAction::array(0, new NextAction("food"), nullptr),
/*C*/ nullptr); /*C*/ nullptr);
} }
static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* flee([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode ("flee", return new ActionNode("flee",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ nullptr, /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
}; };
Strategy::Strategy(PlayerbotAI* botAI) : PlayerbotAIAware(botAI) Strategy::Strategy(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
@@ -118,8 +120,4 @@ Strategy::Strategy(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionNodeFactories.Add(new ActionNodeFactoryInternal()); actionNodeFactories.Add(new ActionNodeFactoryInternal());
} }
ActionNode* Strategy::GetAction(std::string const name) ActionNode* Strategy::GetAction(std::string const name) { return actionNodeFactories.GetContextObject(name, botAI); }
{
return actionNodeFactories.GetContextObject(name, botAI);
}

View File

@@ -1,26 +1,27 @@
/* /*
* 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. * 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_STRATEGY_H #ifndef _PLAYERBOT_STRATEGY_H
#define _PLAYERBOT_STRATEGY_H #define _PLAYERBOT_STRATEGY_H
#include "Action.h" #include "Action.h"
#include "NamedObjectContext.h"
#include "Multiplier.h" #include "Multiplier.h"
#include "Trigger.h" #include "NamedObjectContext.h"
#include "PlayerbotAIAware.h" #include "PlayerbotAIAware.h"
#include "Trigger.h"
enum StrategyType : uint32 enum StrategyType : uint32
{ {
STRATEGY_TYPE_GENERIC = 0, STRATEGY_TYPE_GENERIC = 0,
STRATEGY_TYPE_COMBAT = 1, STRATEGY_TYPE_COMBAT = 1,
STRATEGY_TYPE_NONCOMBAT = 2, STRATEGY_TYPE_NONCOMBAT = 2,
STRATEGY_TYPE_TANK = 4, STRATEGY_TYPE_TANK = 4,
STRATEGY_TYPE_DPS = 8, STRATEGY_TYPE_DPS = 8,
STRATEGY_TYPE_HEAL = 16, STRATEGY_TYPE_HEAL = 16,
STRATEGY_TYPE_RANGED = 32, STRATEGY_TYPE_RANGED = 32,
STRATEGY_TYPE_MELEE = 64 STRATEGY_TYPE_MELEE = 64
}; };
// enum ActionPriority // enum ActionPriority
@@ -54,21 +55,21 @@ static float ACTION_EMERGENCY = 90.0f;
class Strategy : public PlayerbotAIAware class Strategy : public PlayerbotAIAware
{ {
public: public:
Strategy(PlayerbotAI* botAI); Strategy(PlayerbotAI* botAI);
virtual ~Strategy() { } virtual ~Strategy() {}
virtual NextAction** getDefaultActions() { return nullptr; } virtual NextAction** getDefaultActions() { return nullptr; }
virtual void InitTriggers([[maybe_unused]] std::vector<TriggerNode*> &triggers) { } virtual void InitTriggers([[maybe_unused]] std::vector<TriggerNode*>& triggers) {}
virtual void InitMultipliers([[maybe_unused]] std::vector<Multiplier*> &multipliers) { } virtual void InitMultipliers([[maybe_unused]] std::vector<Multiplier*>& multipliers) {}
virtual std::string const getName() = 0; virtual std::string const getName() = 0;
virtual uint32 GetType() const { return STRATEGY_TYPE_GENERIC; } virtual uint32 GetType() const { return STRATEGY_TYPE_GENERIC; }
virtual ActionNode* GetAction(std::string const name); virtual ActionNode* GetAction(std::string const name);
void Update() { } void Update() {}
void Reset() { } void Reset() {}
protected: protected:
NamedObjectFactoryList<ActionNode> actionNodeFactories; NamedObjectFactoryList<ActionNode> actionNodeFactories;
}; };
#endif #endif

View File

@@ -1,17 +1,17 @@
/* /*
* 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. * 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_STRATEGYCONTEXT_H #ifndef _PLAYERBOT_STRATEGYCONTEXT_H
#define _PLAYERBOT_STRATEGYCONTEXT_H #define _PLAYERBOT_STRATEGYCONTEXT_H
#include "CustomStrategy.h"
#include "NamedObjectContext.h"
#include "AttackEnemyPlayersStrategy.h" #include "AttackEnemyPlayersStrategy.h"
#include "BattlegroundStrategy.h" #include "BattlegroundStrategy.h"
#include "CastTimeStrategy.h" #include "CastTimeStrategy.h"
#include "ChatCommandHandlerStrategy.h" #include "ChatCommandHandlerStrategy.h"
#include "ConserveManaStrategy.h" #include "ConserveManaStrategy.h"
#include "CustomStrategy.h"
#include "DeadStrategy.h" #include "DeadStrategy.h"
#include "DebugStrategy.h" #include "DebugStrategy.h"
#include "DpsAssistStrategy.h" #include "DpsAssistStrategy.h"
@@ -29,15 +29,16 @@
#include "MaintenanceStrategy.h" #include "MaintenanceStrategy.h"
#include "MarkRtiStrategy.h" #include "MarkRtiStrategy.h"
#include "MeleeCombatStrategy.h" #include "MeleeCombatStrategy.h"
#include "NamedObjectContext.h"
#include "NonCombatStrategy.h" #include "NonCombatStrategy.h"
#include "QuestStrategies.h"
#include "PassiveStrategy.h" #include "PassiveStrategy.h"
#include "PullStrategy.h" #include "PullStrategy.h"
#include "QuestStrategies.h"
#include "RTSCStrategy.h"
#include "RacialsStrategy.h" #include "RacialsStrategy.h"
#include "RangedCombatStrategy.h" #include "RangedCombatStrategy.h"
#include "ReturnStrategy.h" #include "ReturnStrategy.h"
#include "RpgStrategy.h" #include "RpgStrategy.h"
#include "RTSCStrategy.h"
#include "RunawayStrategy.h" #include "RunawayStrategy.h"
#include "StayStrategy.h" #include "StayStrategy.h"
#include "TankAssistStrategy.h" #include "TankAssistStrategy.h"
@@ -50,184 +51,182 @@
class StrategyContext : public NamedObjectContext<Strategy> class StrategyContext : public NamedObjectContext<Strategy>
{ {
public: public:
StrategyContext() StrategyContext()
{ {
creators["racials"] = &StrategyContext::racials; creators["racials"] = &StrategyContext::racials;
creators["loot"] = &StrategyContext::loot; creators["loot"] = &StrategyContext::loot;
creators["gather"] = &StrategyContext::gather; creators["gather"] = &StrategyContext::gather;
creators["emote"] = &StrategyContext::emote; creators["emote"] = &StrategyContext::emote;
creators["passive"] = &StrategyContext::passive; creators["passive"] = &StrategyContext::passive;
// creators["conserve mana"] = &StrategyContext::conserve_mana; // creators["conserve mana"] = &StrategyContext::conserve_mana;
creators["auto save mana"] = &StrategyContext::auto_save_mana; creators["auto save mana"] = &StrategyContext::auto_save_mana;
creators["food"] = &StrategyContext::food; creators["food"] = &StrategyContext::food;
creators["chat"] = &StrategyContext::chat; creators["chat"] = &StrategyContext::chat;
creators["default"] = &StrategyContext::world_packet; creators["default"] = &StrategyContext::world_packet;
creators["ready check"] = &StrategyContext::ready_check; creators["ready check"] = &StrategyContext::ready_check;
creators["dead"] = &StrategyContext::dead; creators["dead"] = &StrategyContext::dead;
creators["flee"] = &StrategyContext::flee; creators["flee"] = &StrategyContext::flee;
creators["duel"] = &StrategyContext::duel; creators["duel"] = &StrategyContext::duel;
creators["start duel"] = &StrategyContext::start_duel; creators["start duel"] = &StrategyContext::start_duel;
creators["kite"] = &StrategyContext::kite; creators["kite"] = &StrategyContext::kite;
creators["potions"] = &StrategyContext::potions; creators["potions"] = &StrategyContext::potions;
creators["cast time"] = &StrategyContext::cast_time; creators["cast time"] = &StrategyContext::cast_time;
creators["threat"] = &StrategyContext::threat; creators["threat"] = &StrategyContext::threat;
creators["focus"] = &StrategyContext::focus; creators["focus"] = &StrategyContext::focus;
creators["tell target"] = &StrategyContext::tell_target; creators["tell target"] = &StrategyContext::tell_target;
creators["pvp"] = &StrategyContext::pvp; creators["pvp"] = &StrategyContext::pvp;
creators["return"] = &StrategyContext::_return; creators["return"] = &StrategyContext::_return;
creators["lfg"] = &StrategyContext::lfg; creators["lfg"] = &StrategyContext::lfg;
creators["custom"] = &StrategyContext::custom; creators["custom"] = &StrategyContext::custom;
creators["reveal"] = &StrategyContext::reveal; creators["reveal"] = &StrategyContext::reveal;
creators["collision"] = &StrategyContext::collision; creators["collision"] = &StrategyContext::collision;
creators["rpg"] = &StrategyContext::rpg; creators["rpg"] = &StrategyContext::rpg;
creators["travel"] = &StrategyContext::travel; creators["travel"] = &StrategyContext::travel;
creators["explore"] = &StrategyContext::explore; creators["explore"] = &StrategyContext::explore;
creators["map"] = &StrategyContext::map; creators["map"] = &StrategyContext::map;
creators["map full"] = &StrategyContext::map_full; creators["map full"] = &StrategyContext::map_full;
creators["sit"] = &StrategyContext::sit; creators["sit"] = &StrategyContext::sit;
creators["mark rti"] = &StrategyContext::mark_rti; creators["mark rti"] = &StrategyContext::mark_rti;
creators["adds"] = &StrategyContext::possible_adds; creators["adds"] = &StrategyContext::possible_adds;
creators["close"] = &StrategyContext::close; creators["close"] = &StrategyContext::close;
creators["ranged"] = &StrategyContext::ranged; creators["ranged"] = &StrategyContext::ranged;
creators["behind"] = &StrategyContext::behind; creators["behind"] = &StrategyContext::behind;
creators["bg"] = &StrategyContext::bg; creators["bg"] = &StrategyContext::bg;
creators["battleground"] = &StrategyContext::battleground; creators["battleground"] = &StrategyContext::battleground;
creators["warsong"] = &StrategyContext::warsong; creators["warsong"] = &StrategyContext::warsong;
creators["alterac"] = &StrategyContext::alterac; creators["alterac"] = &StrategyContext::alterac;
creators["arathi"] = &StrategyContext::arathi; creators["arathi"] = &StrategyContext::arathi;
creators["eye"] = &StrategyContext::eye; creators["eye"] = &StrategyContext::eye;
creators["isle"] = &StrategyContext::isle; creators["isle"] = &StrategyContext::isle;
creators["arena"] = &StrategyContext::arena; creators["arena"] = &StrategyContext::arena;
creators["mount"] = &StrategyContext::mount; creators["mount"] = &StrategyContext::mount;
creators["rtsc"] = &StrategyContext::rtsc; creators["rtsc"] = &StrategyContext::rtsc;
creators["attack tagged"] = &StrategyContext::attack_tagged; creators["attack tagged"] = &StrategyContext::attack_tagged;
creators["debug"] = &StrategyContext::debug; creators["debug"] = &StrategyContext::debug;
creators["debug move"] = &StrategyContext::debug_move; creators["debug move"] = &StrategyContext::debug_move;
creators["debug rpg"] = &StrategyContext::debug_rpg; creators["debug rpg"] = &StrategyContext::debug_rpg;
creators["debug spell"] = &StrategyContext::debug_spell; creators["debug spell"] = &StrategyContext::debug_spell;
creators["maintenance"] = &StrategyContext::maintenance; creators["maintenance"] = &StrategyContext::maintenance;
creators["group"] = &StrategyContext::group; creators["group"] = &StrategyContext::group;
creators["guild"] = &StrategyContext::guild; creators["guild"] = &StrategyContext::guild;
creators["grind"] = &StrategyContext::grind; creators["grind"] = &StrategyContext::grind;
creators["avoid aoe"] = &StrategyContext::avoid_aoe; creators["avoid aoe"] = &StrategyContext::avoid_aoe;
creators["move random"] = &StrategyContext::move_random; creators["move random"] = &StrategyContext::move_random;
creators["combat formation"] = &StrategyContext::combat_formation; creators["combat formation"] = &StrategyContext::combat_formation;
} }
private: private:
static Strategy* behind(PlayerbotAI* botAI) { return new SetBehindCombatStrategy(botAI); } static Strategy* behind(PlayerbotAI* botAI) { return new SetBehindCombatStrategy(botAI); }
static Strategy* ranged(PlayerbotAI* botAI) { return new RangedCombatStrategy(botAI); } static Strategy* ranged(PlayerbotAI* botAI) { return new RangedCombatStrategy(botAI); }
static Strategy* close(PlayerbotAI* botAI) { return new MeleeCombatStrategy(botAI); } static Strategy* close(PlayerbotAI* botAI) { return new MeleeCombatStrategy(botAI); }
static Strategy* mark_rti(PlayerbotAI* botAI) { return new MarkRtiStrategy(botAI); } static Strategy* mark_rti(PlayerbotAI* botAI) { return new MarkRtiStrategy(botAI); }
static Strategy* tell_target(PlayerbotAI* botAI) { return new TellTargetStrategy(botAI); } static Strategy* tell_target(PlayerbotAI* botAI) { return new TellTargetStrategy(botAI); }
static Strategy* threat(PlayerbotAI* botAI) { return new ThreatStrategy(botAI); } static Strategy* threat(PlayerbotAI* botAI) { return new ThreatStrategy(botAI); }
static Strategy* focus(PlayerbotAI* botAI) { return new FocusStrategy(botAI); } static Strategy* focus(PlayerbotAI* botAI) { return new FocusStrategy(botAI); }
static Strategy* cast_time(PlayerbotAI* botAI) { return new CastTimeStrategy(botAI); } static Strategy* cast_time(PlayerbotAI* botAI) { return new CastTimeStrategy(botAI); }
static Strategy* potions(PlayerbotAI* botAI) { return new UsePotionsStrategy(botAI); } static Strategy* potions(PlayerbotAI* botAI) { return new UsePotionsStrategy(botAI); }
static Strategy* kite(PlayerbotAI* botAI) { return new KiteStrategy(botAI); } static Strategy* kite(PlayerbotAI* botAI) { return new KiteStrategy(botAI); }
static Strategy* duel(PlayerbotAI* botAI) { return new DuelStrategy(botAI); } static Strategy* duel(PlayerbotAI* botAI) { return new DuelStrategy(botAI); }
static Strategy* start_duel(PlayerbotAI* botAI) { return new StartDuelStrategy(botAI); } static Strategy* start_duel(PlayerbotAI* botAI) { return new StartDuelStrategy(botAI); }
static Strategy* flee(PlayerbotAI* botAI) { return new FleeStrategy(botAI); } static Strategy* flee(PlayerbotAI* botAI) { return new FleeStrategy(botAI); }
static Strategy* dead(PlayerbotAI* botAI) { return new DeadStrategy(botAI); } static Strategy* dead(PlayerbotAI* botAI) { return new DeadStrategy(botAI); }
static Strategy* racials(PlayerbotAI* botAI) { return new RacialsStrategy(botAI); } static Strategy* racials(PlayerbotAI* botAI) { return new RacialsStrategy(botAI); }
static Strategy* loot(PlayerbotAI* botAI) { return new LootNonCombatStrategy(botAI); } static Strategy* loot(PlayerbotAI* botAI) { return new LootNonCombatStrategy(botAI); }
static Strategy* gather(PlayerbotAI* botAI) { return new GatherStrategy(botAI); } static Strategy* gather(PlayerbotAI* botAI) { return new GatherStrategy(botAI); }
static Strategy* emote(PlayerbotAI* botAI) { return new EmoteStrategy(botAI); } static Strategy* emote(PlayerbotAI* botAI) { return new EmoteStrategy(botAI); }
static Strategy* passive(PlayerbotAI* botAI) { return new PassiveStrategy(botAI); } static Strategy* passive(PlayerbotAI* botAI) { return new PassiveStrategy(botAI); }
// static Strategy* conserve_mana(PlayerbotAI* botAI) { return new ConserveManaStrategy(botAI); } // static Strategy* conserve_mana(PlayerbotAI* botAI) { return new ConserveManaStrategy(botAI); }
static Strategy* auto_save_mana(PlayerbotAI* botAI) { return new HealerAutoSaveManaStrategy(botAI); } static Strategy* auto_save_mana(PlayerbotAI* botAI) { return new HealerAutoSaveManaStrategy(botAI); }
static Strategy* food(PlayerbotAI* botAI) { return new UseFoodStrategy(botAI); } static Strategy* food(PlayerbotAI* botAI) { return new UseFoodStrategy(botAI); }
static Strategy* chat(PlayerbotAI* botAI) { return new ChatCommandHandlerStrategy(botAI); } static Strategy* chat(PlayerbotAI* botAI) { return new ChatCommandHandlerStrategy(botAI); }
static Strategy* world_packet(PlayerbotAI* botAI) { return new WorldPacketHandlerStrategy(botAI); } static Strategy* world_packet(PlayerbotAI* botAI) { return new WorldPacketHandlerStrategy(botAI); }
static Strategy* ready_check(PlayerbotAI* botAI) { return new ReadyCheckStrategy(botAI); } static Strategy* ready_check(PlayerbotAI* botAI) { return new ReadyCheckStrategy(botAI); }
static Strategy* pvp(PlayerbotAI* botAI) { return new AttackEnemyPlayersStrategy(botAI); } static Strategy* pvp(PlayerbotAI* botAI) { return new AttackEnemyPlayersStrategy(botAI); }
static Strategy* _return(PlayerbotAI* botAI) { return new ReturnStrategy(botAI); } static Strategy* _return(PlayerbotAI* botAI) { return new ReturnStrategy(botAI); }
static Strategy* lfg(PlayerbotAI* botAI) { return new LfgStrategy(botAI); } static Strategy* lfg(PlayerbotAI* botAI) { return new LfgStrategy(botAI); }
static Strategy* custom(PlayerbotAI* botAI) { return new CustomStrategy(botAI); } static Strategy* custom(PlayerbotAI* botAI) { return new CustomStrategy(botAI); }
static Strategy* reveal(PlayerbotAI* botAI) { return new RevealStrategy(botAI); } static Strategy* reveal(PlayerbotAI* botAI) { return new RevealStrategy(botAI); }
static Strategy* collision(PlayerbotAI* botAI) { return new CollisionStrategy(botAI); } static Strategy* collision(PlayerbotAI* botAI) { return new CollisionStrategy(botAI); }
static Strategy* rpg(PlayerbotAI* botAI) { return new RpgStrategy(botAI); } static Strategy* rpg(PlayerbotAI* botAI) { return new RpgStrategy(botAI); }
static Strategy* travel(PlayerbotAI* botAI) { return new TravelStrategy(botAI); } static Strategy* travel(PlayerbotAI* botAI) { return new TravelStrategy(botAI); }
static Strategy* explore(PlayerbotAI* botAI) { return new ExploreStrategy(botAI); } static Strategy* explore(PlayerbotAI* botAI) { return new ExploreStrategy(botAI); }
static Strategy* map(PlayerbotAI* botAI) { return new MapStrategy(botAI); } static Strategy* map(PlayerbotAI* botAI) { return new MapStrategy(botAI); }
static Strategy* map_full(PlayerbotAI* botAI) { return new MapFullStrategy(botAI); } static Strategy* map_full(PlayerbotAI* botAI) { return new MapFullStrategy(botAI); }
static Strategy* sit(PlayerbotAI* botAI) { return new SitStrategy(botAI); } static Strategy* sit(PlayerbotAI* botAI) { return new SitStrategy(botAI); }
static Strategy* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsStrategy(botAI); } static Strategy* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsStrategy(botAI); }
static Strategy* mount(PlayerbotAI* botAI) { return new MountStrategy(botAI); } static Strategy* mount(PlayerbotAI* botAI) { return new MountStrategy(botAI); }
static Strategy* bg(PlayerbotAI* botAI) { return new BGStrategy(botAI); } static Strategy* bg(PlayerbotAI* botAI) { return new BGStrategy(botAI); }
static Strategy* battleground(PlayerbotAI* botAI) { return new BattlegroundStrategy(botAI); } static Strategy* battleground(PlayerbotAI* botAI) { return new BattlegroundStrategy(botAI); }
static Strategy* warsong(PlayerbotAI* botAI) { return new WarsongStrategy(botAI); } static Strategy* warsong(PlayerbotAI* botAI) { return new WarsongStrategy(botAI); }
static Strategy* alterac(PlayerbotAI* botAI) { return new AlteracStrategy(botAI); } static Strategy* alterac(PlayerbotAI* botAI) { return new AlteracStrategy(botAI); }
static Strategy* arathi(PlayerbotAI* botAI) { return new ArathiStrategy(botAI); } static Strategy* arathi(PlayerbotAI* botAI) { return new ArathiStrategy(botAI); }
static Strategy* eye(PlayerbotAI* botAI) { return new EyeStrategy(botAI); } static Strategy* eye(PlayerbotAI* botAI) { return new EyeStrategy(botAI); }
static Strategy* isle(PlayerbotAI* botAI) { return new IsleStrategy(botAI); } static Strategy* isle(PlayerbotAI* botAI) { return new IsleStrategy(botAI); }
static Strategy* arena(PlayerbotAI* botAI) { return new ArenaStrategy(botAI); } static Strategy* arena(PlayerbotAI* botAI) { return new ArenaStrategy(botAI); }
static Strategy* rtsc(PlayerbotAI* botAI) { return new RTSCStrategy(botAI); } static Strategy* rtsc(PlayerbotAI* botAI) { return new RTSCStrategy(botAI); }
static Strategy* attack_tagged(PlayerbotAI* botAI) { return new AttackTaggedStrategy(botAI); } static Strategy* attack_tagged(PlayerbotAI* botAI) { return new AttackTaggedStrategy(botAI); }
static Strategy* debug(PlayerbotAI* botAI) { return new DebugStrategy(botAI); } static Strategy* debug(PlayerbotAI* botAI) { return new DebugStrategy(botAI); }
static Strategy* debug_move(PlayerbotAI* botAI) { return new DebugMoveStrategy(botAI); } static Strategy* debug_move(PlayerbotAI* botAI) { return new DebugMoveStrategy(botAI); }
static Strategy* debug_rpg(PlayerbotAI* botAI) { return new DebugRpgStrategy(botAI); } static Strategy* debug_rpg(PlayerbotAI* botAI) { return new DebugRpgStrategy(botAI); }
static Strategy* debug_spell(PlayerbotAI* botAI) { return new DebugSpellStrategy(botAI); } static Strategy* debug_spell(PlayerbotAI* botAI) { return new DebugSpellStrategy(botAI); }
static Strategy* maintenance(PlayerbotAI* botAI) { return new MaintenanceStrategy(botAI); } static Strategy* maintenance(PlayerbotAI* botAI) { return new MaintenanceStrategy(botAI); }
static Strategy* group(PlayerbotAI* botAI) { return new GroupStrategy(botAI); } static Strategy* group(PlayerbotAI* botAI) { return new GroupStrategy(botAI); }
static Strategy* guild (PlayerbotAI* botAI) { return new GuildStrategy(botAI); } static Strategy* guild(PlayerbotAI* botAI) { return new GuildStrategy(botAI); }
static Strategy* grind(PlayerbotAI* botAI) { return new GrindingStrategy(botAI); } static Strategy* grind(PlayerbotAI* botAI) { return new GrindingStrategy(botAI); }
static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); } static Strategy* avoid_aoe(PlayerbotAI* botAI) { return new AvoidAoeStrategy(botAI); }
static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); } static Strategy* move_random(PlayerbotAI* ai) { return new MoveRandomStrategy(ai); }
static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); } static Strategy* combat_formation(PlayerbotAI* ai) { return new CombatFormationStrategy(ai); }
}; };
class MovementStrategyContext : public NamedObjectContext<Strategy> class MovementStrategyContext : public NamedObjectContext<Strategy>
{ {
public: public:
MovementStrategyContext() : NamedObjectContext<Strategy>(false, true) MovementStrategyContext() : NamedObjectContext<Strategy>(false, true)
{
creators["follow"] = &MovementStrategyContext::follow_master;
creators["stay"] = &MovementStrategyContext::stay;
creators["runaway"] = &MovementStrategyContext::runaway;
creators["flee from adds"] = &MovementStrategyContext::flee_from_adds;
creators["guard"] = &MovementStrategyContext::guard;
}
private:
static Strategy* guard(PlayerbotAI* botAI) { return new GuardStrategy(botAI); }
static Strategy* follow_master(PlayerbotAI* botAI) { return new FollowMasterStrategy(botAI); }
static Strategy* stay(PlayerbotAI* botAI) { return new StayStrategy(botAI); }
static Strategy* runaway(PlayerbotAI* botAI) { return new RunawayStrategy(botAI); }
static Strategy* flee_from_adds(PlayerbotAI* botAI) { return new FleeFromAddsStrategy(botAI); }
};
class AssistStrategyContext : public NamedObjectContext<Strategy>
{ {
public: creators["follow"] = &MovementStrategyContext::follow_master;
AssistStrategyContext() : NamedObjectContext<Strategy>(false, true) creators["stay"] = &MovementStrategyContext::stay;
{ creators["runaway"] = &MovementStrategyContext::runaway;
creators["dps assist"] = &AssistStrategyContext::dps_assist; creators["flee from adds"] = &MovementStrategyContext::flee_from_adds;
creators["dps aoe"] = &AssistStrategyContext::dps_aoe; creators["guard"] = &MovementStrategyContext::guard;
creators["tank assist"] = &AssistStrategyContext::tank_assist; }
}
private: private:
static Strategy* dps_assist(PlayerbotAI* botAI) { return new DpsAssistStrategy(botAI); } static Strategy* guard(PlayerbotAI* botAI) { return new GuardStrategy(botAI); }
static Strategy* dps_aoe(PlayerbotAI* botAI) { return new DpsAoeStrategy(botAI); } static Strategy* follow_master(PlayerbotAI* botAI) { return new FollowMasterStrategy(botAI); }
static Strategy* tank_assist(PlayerbotAI* botAI) { return new TankAssistStrategy(botAI); } static Strategy* stay(PlayerbotAI* botAI) { return new StayStrategy(botAI); }
static Strategy* runaway(PlayerbotAI* botAI) { return new RunawayStrategy(botAI); }
static Strategy* flee_from_adds(PlayerbotAI* botAI) { return new FleeFromAddsStrategy(botAI); }
};
class AssistStrategyContext : public NamedObjectContext<Strategy>
{
public:
AssistStrategyContext() : NamedObjectContext<Strategy>(false, true)
{
creators["dps assist"] = &AssistStrategyContext::dps_assist;
creators["dps aoe"] = &AssistStrategyContext::dps_aoe;
creators["tank assist"] = &AssistStrategyContext::tank_assist;
}
private:
static Strategy* dps_assist(PlayerbotAI* botAI) { return new DpsAssistStrategy(botAI); }
static Strategy* dps_aoe(PlayerbotAI* botAI) { return new DpsAoeStrategy(botAI); }
static Strategy* tank_assist(PlayerbotAI* botAI) { return new TankAssistStrategy(botAI); }
}; };
class QuestStrategyContext : public NamedObjectContext<Strategy> class QuestStrategyContext : public NamedObjectContext<Strategy>
{ {
public: public:
QuestStrategyContext() : NamedObjectContext<Strategy>(false, true) QuestStrategyContext() : NamedObjectContext<Strategy>(false, true)
{ {
creators["quest"] = &QuestStrategyContext::quest; creators["quest"] = &QuestStrategyContext::quest;
creators["accept all quests"] = &QuestStrategyContext::accept_all_quests; creators["accept all quests"] = &QuestStrategyContext::accept_all_quests;
} }
private: private:
static Strategy* quest(PlayerbotAI* botAI) { return new DefaultQuestStrategy(botAI); } static Strategy* quest(PlayerbotAI* botAI) { return new DefaultQuestStrategy(botAI); }
static Strategy* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsStrategy(botAI); } static Strategy* accept_all_quests(PlayerbotAI* botAI) { return new AcceptAllQuestsStrategy(botAI); }
}; };
#endif #endif

View File

@@ -1,38 +1,36 @@
/* /*
* 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. * 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 "Trigger.h" #include "Trigger.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Timer.h" #include "Timer.h"
Trigger::Trigger(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : Trigger::Trigger(PlayerbotAI* botAI, std::string const name, int32 checkInterval)
AiNamedObject(botAI, name), checkInterval(checkInterval == 1 ? 1 : (checkInterval < 100 ? checkInterval * 1000 : checkInterval)), lastCheckTime(0) : AiNamedObject(botAI, name),
checkInterval(checkInterval == 1 ? 1 : (checkInterval < 100 ? checkInterval * 1000 : checkInterval)),
lastCheckTime(0)
{ {
} }
Event Trigger::Check() Event Trigger::Check()
{ {
if (IsActive()) if (IsActive())
{ {
Event event(getName()); Event event(getName());
return event; return event;
} }
Event event; Event event;
return event; return event;
} }
Value<Unit*>* Trigger::GetTargetValue() Value<Unit*>* Trigger::GetTargetValue() { return context->GetValue<Unit*>(GetTargetName()); }
{
return context->GetValue<Unit*>(GetTargetName());
}
Unit* Trigger::GetTarget() Unit* Trigger::GetTarget() { return GetTargetValue()->Get(); }
{
return GetTargetValue()->Get();
}
bool Trigger::needCheck() bool Trigger::needCheck()
{ {

View File

@@ -1,69 +1,64 @@
/* /*
* 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. * 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_TRIGGER_H #ifndef _PLAYERBOT_TRIGGER_H
#define _PLAYERBOT_TRIGGER_H #define _PLAYERBOT_TRIGGER_H
#include "Common.h"
#include "Action.h" #include "Action.h"
#include "Common.h"
class PlayerbotAI; class PlayerbotAI;
class Unit; class Unit;
class Trigger : public AiNamedObject class Trigger : public AiNamedObject
{ {
public: public:
Trigger(PlayerbotAI* botAI, std::string const name = "trigger", int32 checkInterval = 1); Trigger(PlayerbotAI* botAI, std::string const name = "trigger", int32 checkInterval = 1);
virtual ~Trigger() { } virtual ~Trigger() {}
virtual Event Check(); virtual Event Check();
virtual void ExternalEvent([[maybe_unused]] std::string const param, [[maybe_unused]] Player* owner = nullptr) { } virtual void ExternalEvent([[maybe_unused]] std::string const param, [[maybe_unused]] Player* owner = nullptr) {}
virtual void ExternalEvent([[maybe_unused]] WorldPacket& packet, [[maybe_unused]] Player* owner = nullptr) { } virtual void ExternalEvent([[maybe_unused]] WorldPacket& packet, [[maybe_unused]] Player* owner = nullptr) {}
virtual bool IsActive() { return false; } virtual bool IsActive() { return false; }
virtual NextAction** getHandlers() { return nullptr; } virtual NextAction** getHandlers() { return nullptr; }
void Update() { } void Update() {}
virtual void Reset() { } virtual void Reset() {}
virtual Unit* GetTarget(); virtual Unit* GetTarget();
virtual Value<Unit*>* GetTargetValue(); virtual Value<Unit*>* GetTargetValue();
virtual std::string const GetTargetName() { return "self target"; } virtual std::string const GetTargetName() { return "self target"; }
bool needCheck(); bool needCheck();
protected: protected:
int32 checkInterval; int32 checkInterval;
uint32 lastCheckTime; uint32 lastCheckTime;
}; };
class TriggerNode class TriggerNode
{ {
public: public:
TriggerNode(std::string const name, NextAction** handlers = nullptr) : trigger(nullptr), handlers(handlers), name(name) { } // reorder args - whipowill TriggerNode(std::string const name, NextAction** handlers = nullptr)
: trigger(nullptr), handlers(handlers), name(name)
{
} // reorder args - whipowill
virtual ~TriggerNode() virtual ~TriggerNode() { NextAction::destroy(handlers); }
{
NextAction::destroy(handlers);
}
Trigger* getTrigger() { return trigger; } Trigger* getTrigger() { return trigger; }
void setTrigger(Trigger* trigger) { this->trigger = trigger; } void setTrigger(Trigger* trigger) { this->trigger = trigger; }
std::string const getName() { return name; } std::string const getName() { return name; }
NextAction** getHandlers() NextAction** getHandlers() { return NextAction::merge(NextAction::clone(handlers), trigger->getHandlers()); }
{
return NextAction::merge(NextAction::clone(handlers), trigger->getHandlers());
}
float getFirstRelevance() float getFirstRelevance() { return handlers[0] ? handlers[0]->getRelevance() : -1; }
{
return handlers[0] ? handlers[0]->getRelevance() : -1;
}
private: private:
Trigger* trigger; Trigger* trigger;
NextAction** handlers; NextAction** handlers;
std::string const name; std::string const name;
}; };
#endif #endif

View File

@@ -1,13 +1,16 @@
/* /*
* 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. * 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 "Value.h" #include "Value.h"
#include "PerformanceMonitor.h" #include "PerformanceMonitor.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "Timer.h" #include "Timer.h"
UnitCalculatedValue::UnitCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : CalculatedValue<Unit*>(botAI, name, checkInterval) UnitCalculatedValue::UnitCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval)
: CalculatedValue<Unit*>(botAI, name, checkInterval)
{ {
} }
@@ -44,8 +47,8 @@ std::string const FloatCalculatedValue::Format()
return out.str(); return out.str();
} }
CDPairCalculatedValue::CDPairCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : CDPairCalculatedValue::CDPairCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval)
CalculatedValue<CreatureData const*>(botAI, name, checkInterval) : CalculatedValue<CreatureData const*>(botAI, name, checkInterval)
{ {
// lastCheckTime = getMSTime() - checkInterval / 2; // lastCheckTime = getMSTime() - checkInterval / 2;
} }
@@ -62,15 +65,16 @@ std::string const CDPairCalculatedValue::Format()
return "<none>"; return "<none>";
} }
CDPairListCalculatedValue::CDPairListCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : CDPairListCalculatedValue::CDPairListCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval)
CalculatedValue<std::vector<CreatureData const*>>(botAI, name, checkInterval) : CalculatedValue<std::vector<CreatureData const*>>(botAI, name, checkInterval)
{ {
// lastCheckTime = time(nullptr) - checkInterval / 2; // lastCheckTime = time(nullptr) - checkInterval / 2;
} }
std::string const CDPairListCalculatedValue::Format() std::string const CDPairListCalculatedValue::Format()
{ {
std::ostringstream out; out << "{"; std::ostringstream out;
out << "{";
std::vector<CreatureData const*> cdPairs = Calculate(); std::vector<CreatureData const*> cdPairs = Calculate();
for (CreatureData const* cdPair : cdPairs) for (CreatureData const* cdPair : cdPairs)
{ {
@@ -81,8 +85,8 @@ std::string const CDPairListCalculatedValue::Format()
return out.str(); return out.str();
} }
ObjectGuidCalculatedValue::ObjectGuidCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : ObjectGuidCalculatedValue::ObjectGuidCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval)
CalculatedValue<ObjectGuid>(botAI, name, checkInterval) : CalculatedValue<ObjectGuid>(botAI, name, checkInterval)
{ {
// lastCheckTime = time(nullptr) - checkInterval / 2; // lastCheckTime = time(nullptr) - checkInterval / 2;
} }
@@ -93,8 +97,9 @@ std::string const ObjectGuidCalculatedValue::Format()
return guid ? std::to_string(guid.GetRawValue()) : "<none>"; return guid ? std::to_string(guid.GetRawValue()) : "<none>";
} }
ObjectGuidListCalculatedValue::ObjectGuidListCalculatedValue(PlayerbotAI* botAI, std::string const name, int32 checkInterval) : ObjectGuidListCalculatedValue::ObjectGuidListCalculatedValue(PlayerbotAI* botAI, std::string const name,
CalculatedValue<GuidVector>(botAI, name, checkInterval) int32 checkInterval)
: CalculatedValue<GuidVector>(botAI, name, checkInterval)
{ {
} }
@@ -116,17 +121,22 @@ std::string const ObjectGuidListCalculatedValue::Format()
Unit* UnitCalculatedValue::Get() Unit* UnitCalculatedValue::Get()
{ {
if (checkInterval < 2) { if (checkInterval < 2)
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); {
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
value = Calculate(); value = Calculate();
if (pmo) if (pmo)
pmo->finish(); pmo->finish();
} else { }
else
{
time_t now = getMSTime(); time_t now = getMSTime();
if (!lastCheckTime || now - lastCheckTime >= checkInterval) if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{ {
lastCheckTime = now; lastCheckTime = now;
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
value = Calculate(); value = Calculate();
if (pmo) if (pmo)
pmo->finish(); pmo->finish();

View File

@@ -1,388 +1,418 @@
/* /*
* 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. * 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_VALUE_H #ifndef _PLAYERBOT_VALUE_H
#define _PLAYERBOT_VALUE_H #define _PLAYERBOT_VALUE_H
#include <time.h>
#include "AiObject.h" #include "AiObject.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "PerformanceMonitor.h" #include "PerformanceMonitor.h"
#include "Timer.h" #include "Timer.h"
#include "Unit.h" #include "Unit.h"
#include <time.h>
class PlayerbotAI; class PlayerbotAI;
class Unit; class Unit;
class FleeInfo class FleeInfo
{ {
public: public:
Position fromPos; Position fromPos;
float radius; float radius;
float angle; float angle;
uint32 timestamp; uint32 timestamp;
int GetAngleRangeIndex() { return (angle + 2 * M_PI) / (M_PI / 2); } // [0, 7) int GetAngleRangeIndex() { return (angle + 2 * M_PI) / (M_PI / 2); } // [0, 7)
}; };
struct CreatureData; struct CreatureData;
class UntypedValue : public AiNamedObject class UntypedValue : public AiNamedObject
{ {
public: public:
UntypedValue(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) { } UntypedValue(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) {}
virtual ~UntypedValue() { } virtual ~UntypedValue() {}
virtual void Update() { } virtual void Update() {}
virtual void Reset() { } virtual void Reset() {}
virtual std::string const Format() { return "?"; } virtual std::string const Format() { return "?"; }
virtual std::string const Save() { return "?"; } virtual std::string const Save() { return "?"; }
virtual bool Load([[maybe_unused]] std::string const value) { return false; } virtual bool Load([[maybe_unused]] std::string const value) { return false; }
}; };
template<class T> template <class T>
class Value class Value
{ {
public: public:
virtual ~Value() { } virtual ~Value() {}
virtual T Get() = 0; virtual T Get() = 0;
virtual T LazyGet() = 0; virtual T LazyGet() = 0;
virtual T& RefGet() = 0; virtual T& RefGet() = 0;
virtual void Reset() { } virtual void Reset() {}
virtual void Set(T value) = 0; virtual void Set(T value) = 0;
operator T() { return Get(); } operator T() { return Get(); }
}; };
template<class T> template <class T>
class CalculatedValue : public UntypedValue, public Value<T> class CalculatedValue : public UntypedValue, public Value<T>
{ {
public: public:
CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1) : UntypedValue(botAI, name), CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1)
checkInterval(checkInterval == 1 ? 1 : (checkInterval < 100 ? checkInterval * 1000 : checkInterval)) /*turn s -> ms?*/, lastCheckTime(0) { } : UntypedValue(botAI, name),
checkInterval(
checkInterval == 1 ? 1 : (checkInterval < 100 ? checkInterval * 1000 : checkInterval)) /*turn s -> ms?*/,
lastCheckTime(0)
{
}
virtual ~CalculatedValue() { } virtual ~CalculatedValue() {}
T Get() override T Get() override
{
if (checkInterval < 2)
{ {
if (checkInterval < 2) { // PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(),
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); // this->context ? &this->context->performanceStack : nullptr);
value = Calculate();
// if (pmo)
// pmo->finish();
}
else
{
time_t now = getMSTime();
if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{
lastCheckTime = now;
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(),
// this->context ? &this->context->performanceStack : nullptr);
value = Calculate(); value = Calculate();
// if (pmo) // if (pmo)
// pmo->finish(); // pmo->finish();
} else {
time_t now = getMSTime();
if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{
lastCheckTime = now;
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
value = Calculate();
// if (pmo)
// pmo->finish();
}
} }
return value;
} }
return value;
}
T LazyGet() override T LazyGet() override
{
if (!lastCheckTime)
return Get();
return value;
}
T& RefGet() override
{
if (checkInterval < 2)
{ {
if (!lastCheckTime) // PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(),
return Get(); // this->context ? &this->context->performanceStack : nullptr);
value = Calculate();
return value; // if (pmo)
// pmo->finish();
} }
T& RefGet() override else
{ {
if (checkInterval < 2) { time_t now = getMSTime();
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{
lastCheckTime = now;
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(),
// this->context ? &this->context->performanceStack : nullptr);
value = Calculate(); value = Calculate();
// if (pmo) // if (pmo)
// pmo->finish(); // pmo->finish();
} else {
time_t now = getMSTime();
if (!lastCheckTime || now - lastCheckTime >= checkInterval)
{
lastCheckTime = now;
// PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
value = Calculate();
// if (pmo)
// pmo->finish();
}
} }
return value;
} }
void Set(T val) override { value = val; } return value;
void Update() override {} }
void Reset() override { lastCheckTime = 0; } void Set(T val) override { value = val; }
void Update() override {}
void Reset() override { lastCheckTime = 0; }
protected: protected:
virtual T Calculate() = 0; virtual T Calculate() = 0;
uint32 checkInterval; uint32 checkInterval;
uint32 lastCheckTime; uint32 lastCheckTime;
T value; T value;
}; };
template <class T> template <class T>
class SingleCalculatedValue : public CalculatedValue<T> class SingleCalculatedValue : public CalculatedValue<T>
{ {
public: public:
SingleCalculatedValue(PlayerbotAI* botAI, std::string const name = "value") : CalculatedValue<T>(botAI, name) SingleCalculatedValue(PlayerbotAI* botAI, std::string const name = "value") : CalculatedValue<T>(botAI, name)
{
this->Reset();
}
T Get() override
{
time_t now = time(0);
if (!this->lastCheckTime)
{ {
this->Reset(); this->lastCheckTime = now;
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
this->value = this->Calculate();
if (pmo)
pmo->finish();
} }
T Get() override return this->value;
{ }
time_t now = time(0);
if (!this->lastCheckTime)
{
this->lastCheckTime = now;
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr);
this->value = this->Calculate();
if (pmo)
pmo->finish();
}
return this->value;
}
}; };
template<class T> template <class T>
class MemoryCalculatedValue : public CalculatedValue<T> class MemoryCalculatedValue : public CalculatedValue<T>
{ {
public: public:
MemoryCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1) : CalculatedValue<T>(botAI, name, checkInterval) MemoryCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1)
{ : CalculatedValue<T>(botAI, name, checkInterval)
lastChangeTime = time(0); {
} lastChangeTime = time(0);
}
virtual bool EqualToLast(T value) = 0; virtual bool EqualToLast(T value) = 0;
virtual bool CanCheckChange() virtual bool CanCheckChange() { return time(0) - lastChangeTime < minChangeInterval || EqualToLast(this->value); }
{
return time(0) - lastChangeTime < minChangeInterval || EqualToLast(this->value);
}
virtual bool UpdateChange() virtual bool UpdateChange()
{ {
if (CanCheckChange()) if (CanCheckChange())
return false; return false;
lastChangeTime = time(0); lastChangeTime = time(0);
lastValue = this->value; lastValue = this->value;
return true; return true;
} }
void Set([[maybe_unused]] T value) override void Set([[maybe_unused]] T value) override
{ {
CalculatedValue<T>::Set(this->value); CalculatedValue<T>::Set(this->value);
UpdateChange(); UpdateChange();
} }
T Get() override T Get() override
{ {
this->value = CalculatedValue<T>::Get(); this->value = CalculatedValue<T>::Get();
UpdateChange(); UpdateChange();
return this->value; return this->value;
} }
T LazyGet() override T LazyGet() override { return this->value; }
{
return this->value;
}
time_t LastChangeOn() time_t LastChangeOn()
{ {
Get(); Get();
UpdateChange(); UpdateChange();
return lastChangeTime; return lastChangeTime;
} }
uint32 LastChangeDelay() { return time(0) - LastChangeOn(); } uint32 LastChangeDelay() { return time(0) - LastChangeOn(); }
void Reset() override void Reset() override
{ {
CalculatedValue<T>::Reset(); CalculatedValue<T>::Reset();
lastChangeTime = time(0); lastChangeTime = time(0);
} }
protected: protected:
T lastValue; T lastValue;
uint32 minChangeInterval = 0; uint32 minChangeInterval = 0;
time_t lastChangeTime; time_t lastChangeTime;
}; };
template<class T> template <class T>
class LogCalculatedValue : public MemoryCalculatedValue<T> class LogCalculatedValue : public MemoryCalculatedValue<T>
{ {
public: public:
LogCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1) : MemoryCalculatedValue<T>(botAI, name, checkInterval) { } LogCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1)
: MemoryCalculatedValue<T>(botAI, name, checkInterval)
{
}
bool UpdateChange() override bool UpdateChange() override
{ {
if (MemoryCalculatedValue<T>::UpdateChange()) if (MemoryCalculatedValue<T>::UpdateChange())
return false; return false;
valueLog.push_back(std::make_pair(this->value, time(0))); valueLog.push_back(std::make_pair(this->value, time(0)));
if (valueLog.size() > logLength) if (valueLog.size() > logLength)
valueLog.pop_front(); valueLog.pop_front();
return true; return true;
} }
std::list<std::pair<T, time_t>> ValueLog() { return valueLog; } std::list<std::pair<T, time_t>> ValueLog() { return valueLog; }
void Reset() override void Reset() override
{ {
MemoryCalculatedValue<T>::Reset(); MemoryCalculatedValue<T>::Reset();
valueLog.clear(); valueLog.clear();
} }
protected: protected:
std::list<std::pair<T, time_t>> valueLog; std::list<std::pair<T, time_t>> valueLog;
uint8 logLength = 10; uint8 logLength = 10;
}; };
class Uint8CalculatedValue : public CalculatedValue<uint8> class Uint8CalculatedValue : public CalculatedValue<uint8>
{ {
public: public:
Uint8CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1) : Uint8CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1)
CalculatedValue<uint8>(botAI, name, checkInterval) { } : CalculatedValue<uint8>(botAI, name, checkInterval)
{
}
std::string const Format() override; std::string const Format() override;
}; };
class Uint32CalculatedValue : public CalculatedValue<uint32> class Uint32CalculatedValue : public CalculatedValue<uint32>
{ {
public: public:
Uint32CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : Uint32CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1)
CalculatedValue<uint32>(botAI, name, checkInterval) { } : CalculatedValue<uint32>(botAI, name, checkInterval)
{
}
std::string const Format() override; std::string const Format() override;
}; };
class FloatCalculatedValue : public CalculatedValue<float> class FloatCalculatedValue : public CalculatedValue<float>
{ {
public: public:
FloatCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : FloatCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1)
CalculatedValue<float>(botAI, name, checkInterval) { } : CalculatedValue<float>(botAI, name, checkInterval)
{
}
std::string const Format() override; std::string const Format() override;
}; };
class BoolCalculatedValue : public CalculatedValue<bool> class BoolCalculatedValue : public CalculatedValue<bool>
{ {
public: public:
BoolCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : BoolCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1)
CalculatedValue<bool>(botAI, name, checkInterval) { } : CalculatedValue<bool>(botAI, name, checkInterval)
{
}
std::string const Format() override std::string const Format() override { return Calculate() ? "true" : "false"; }
{
return Calculate() ? "true" : "false";
}
}; };
class UnitCalculatedValue : public CalculatedValue<Unit*> class UnitCalculatedValue : public CalculatedValue<Unit*>
{ {
public: public:
UnitCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); UnitCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1);
std::string const Format() override; std::string const Format() override;
Unit* Get() override; Unit* Get() override;
}; };
class CDPairCalculatedValue : public CalculatedValue<CreatureData const*> class CDPairCalculatedValue : public CalculatedValue<CreatureData const*>
{ {
public: public:
CDPairCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); CDPairCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1);
std::string const Format() override; std::string const Format() override;
}; };
class CDPairListCalculatedValue : public CalculatedValue<std::vector<CreatureData const*>> class CDPairListCalculatedValue : public CalculatedValue<std::vector<CreatureData const*>>
{ {
public: public:
CDPairListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); CDPairListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1);
std::string const Format() override; std::string const Format() override;
}; };
class ObjectGuidCalculatedValue : public CalculatedValue<ObjectGuid> class ObjectGuidCalculatedValue : public CalculatedValue<ObjectGuid>
{ {
public: public:
ObjectGuidCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); ObjectGuidCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1);
std::string const Format() override; std::string const Format() override;
}; };
class ObjectGuidListCalculatedValue : public CalculatedValue<GuidVector> class ObjectGuidListCalculatedValue : public CalculatedValue<GuidVector>
{ {
public: public:
ObjectGuidListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); ObjectGuidListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1);
std::string const Format() override; std::string const Format() override;
}; };
template<class T> template <class T>
class ManualSetValue : public UntypedValue, public Value<T> class ManualSetValue : public UntypedValue, public Value<T>
{ {
public: public:
ManualSetValue(PlayerbotAI* botAI, T defaultValue, std::string const name = "value") : ManualSetValue(PlayerbotAI* botAI, T defaultValue, std::string const name = "value")
UntypedValue(botAI, name), value(defaultValue), defaultValue(defaultValue) { } : UntypedValue(botAI, name), value(defaultValue), defaultValue(defaultValue)
{
}
virtual ~ManualSetValue() { } virtual ~ManualSetValue() {}
T Get() override { return value; } T Get() override { return value; }
T LazyGet() override { return value; } T LazyGet() override { return value; }
T& RefGet() override { return value; } T& RefGet() override { return value; }
void Set(T val) override { value = val; } void Set(T val) override { value = val; }
void Update() override {} void Update() override {}
void Reset() override void Reset() override { value = defaultValue; }
{
value = defaultValue;
}
protected: protected:
T value; T value;
T defaultValue; T defaultValue;
}; };
class UnitManualSetValue : public ManualSetValue<Unit*> class UnitManualSetValue : public ManualSetValue<Unit*>
{ {
public: public:
UnitManualSetValue(PlayerbotAI* botAI, Unit* defaultValue, std::string const name = "value") : UnitManualSetValue(PlayerbotAI* botAI, Unit* defaultValue, std::string const name = "value")
ManualSetValue<Unit*>(botAI, defaultValue, name) { } : ManualSetValue<Unit*>(botAI, defaultValue, name)
{
}
std::string const Format() override; std::string const Format() override;
Unit* Get() override; Unit* Get() override;
}; };
class DisperseDistanceValue : public ManualSetValue<float> class DisperseDistanceValue : public ManualSetValue<float>
{ {
public: public:
DisperseDistanceValue(PlayerbotAI* botAI, float defaultValue = -1.0f, std::string const name = "disperse distance") : DisperseDistanceValue(PlayerbotAI* botAI, float defaultValue = -1.0f, std::string const name = "disperse distance")
ManualSetValue<float>(botAI, defaultValue, name) { } : ManualSetValue<float>(botAI, defaultValue, name)
{
}
}; };
class LastFleeAngleValue : public ManualSetValue<float> class LastFleeAngleValue : public ManualSetValue<float>
{ {
public: public:
LastFleeAngleValue(PlayerbotAI* botAI, float defaultValue = 0.0f, std::string const name = "last flee angle") : LastFleeAngleValue(PlayerbotAI* botAI, float defaultValue = 0.0f, std::string const name = "last flee angle")
ManualSetValue<float>(botAI, defaultValue, name) { } : ManualSetValue<float>(botAI, defaultValue, name)
{
}
}; };
class LastFleeTimestampValue : public ManualSetValue<uint32> class LastFleeTimestampValue : public ManualSetValue<uint32>
{ {
public: public:
LastFleeTimestampValue(PlayerbotAI* botAI, uint32 defaultValue = 0, std::string const name = "last flee timestamp") : LastFleeTimestampValue(PlayerbotAI* botAI, uint32 defaultValue = 0, std::string const name = "last flee timestamp")
ManualSetValue<uint32>(botAI, defaultValue, name) { } : ManualSetValue<uint32>(botAI, defaultValue, name)
{
}
}; };
class RecentlyFleeInfo : public ManualSetValue<std::list<FleeInfo>> class RecentlyFleeInfo : public ManualSetValue<std::list<FleeInfo>>
{ {
public: public:
RecentlyFleeInfo(PlayerbotAI* botAI, std::list<FleeInfo> defaultValue = {}, std::string const name = "recently flee info") : RecentlyFleeInfo(PlayerbotAI* botAI, std::list<FleeInfo> defaultValue = {},
ManualSetValue<std::list<FleeInfo>>(botAI, defaultValue, name) { } std::string const name = "recently flee info")
: ManualSetValue<std::list<FleeInfo>>(botAI, defaultValue, name)
{
}
}; };
#endif #endif

View File

@@ -1,22 +1,24 @@
/* /*
* 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. * 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 "AcceptBattlegroundInvitationAction.h" #include "AcceptBattlegroundInvitationAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
bool AcceptBgInvitationAction::Execute(Event event) bool AcceptBgInvitationAction::Execute(Event event)
{ {
uint8 type = 0; // arenatype if arena uint8 type = 0; // arenatype if arena
uint8 unk2 = 0; // unk, can be 0x0 (may be if was invited?) and 0x1 uint8 unk2 = 0; // unk, can be 0x0 (may be if was invited?) and 0x1
uint32 bgTypeId_ = BATTLEGROUND_WS; // type id from dbc uint32 bgTypeId_ = BATTLEGROUND_WS; // type id from dbc
uint16 unk = 0x1F90; // 0x1F90 constant?*/ uint16 unk = 0x1F90; // 0x1F90 constant?*/
uint8 action = 1; uint8 action = 1;
WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20); WorldPacket packet(CMSG_BATTLEFIELD_PORT, 20);
packet << type << unk2 << (uint32)bgTypeId_ << unk << action; packet << type << unk2 << (uint32)bgTypeId_ << unk << action;
//packet << bgTypeId_ << action; // packet << bgTypeId_ << action;
bot->GetSession()->HandleBattleFieldPortOpcode(packet); bot->GetSession()->HandleBattleFieldPortOpcode(packet);
botAI->ResetStrategies(); botAI->ResetStrategies();

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ACCEPTBATTLEGROUNDINVITATIONACTION_H #ifndef _PLAYERBOT_ACCEPTBATTLEGROUNDINVITATIONACTION_H
@@ -11,10 +12,10 @@ class PlayerbotAI;
class AcceptBgInvitationAction : public Action class AcceptBgInvitationAction : public Action
{ {
public: public:
AcceptBgInvitationAction(PlayerbotAI* botAI) : Action(botAI, "accept bg invitatio") { } AcceptBgInvitationAction(PlayerbotAI* botAI) : Action(botAI, "accept bg invitatio") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "AcceptDuelAction.h" #include "AcceptDuelAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -16,7 +18,8 @@ bool AcceptDuelAction::Execute(Event event)
p >> playerGuid; p >> playerGuid;
// do not auto duel with low hp // do not auto duel with low hp
if ((!botAI->HasRealPlayerMaster() || (botAI->GetMaster() && botAI->GetMaster()->GetGUID() != playerGuid)) && AI_VALUE2(uint8, "health", "self target") < 90) if ((!botAI->HasRealPlayerMaster() || (botAI->GetMaster() && botAI->GetMaster()->GetGUID() != playerGuid)) &&
AI_VALUE2(uint8, "health", "self target") < 90)
{ {
WorldPacket packet(CMSG_DUEL_CANCELLED, 8); WorldPacket packet(CMSG_DUEL_CANCELLED, 8);
packet << flagGuid; packet << flagGuid;

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ACCEPTDUELACTION_H #ifndef _PLAYERBOT_ACCEPTDUELACTION_H
@@ -11,10 +12,10 @@ class PlayerbotAI;
class AcceptDuelAction : public Action class AcceptDuelAction : public Action
{ {
public: public:
AcceptDuelAction(PlayerbotAI* botAI) : Action(botAI, "accept duel") { } AcceptDuelAction(PlayerbotAI* botAI) : Action(botAI, "accept duel") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -1,13 +1,15 @@
/* /*
* 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. * 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 "AcceptInvitationAction.h" #include "AcceptInvitationAction.h"
#include "Event.h" #include "Event.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "Playerbots.h"
#include "PlayerbotSecurity.h" #include "PlayerbotSecurity.h"
#include "Playerbots.h"
#include "WorldPacket.h" #include "WorldPacket.h"
bool AcceptInvitationAction::Execute(Event event) bool AcceptInvitationAction::Execute(Event event)
@@ -41,8 +43,8 @@ bool AcceptInvitationAction::Execute(Event event)
if (sRandomPlayerbotMgr->IsRandomBot(bot)) if (sRandomPlayerbotMgr->IsRandomBot(bot))
botAI->SetMaster(inviter); botAI->SetMaster(inviter);
//else // else
//sPlayerbotDbStore->Save(botAI); // sPlayerbotDbStore->Save(botAI);
botAI->ResetStrategies(); botAI->ResetStrategies();
botAI->ChangeStrategy("+follow,-lfg,-bg", BOT_STATE_NON_COMBAT); botAI->ChangeStrategy("+follow,-lfg,-bg", BOT_STATE_NON_COMBAT);
@@ -50,7 +52,8 @@ bool AcceptInvitationAction::Execute(Event event)
botAI->TellMaster("Hello"); botAI->TellMaster("Hello");
if (sPlayerbotAIConfig->summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig->sightDistance) { if (sPlayerbotAIConfig->summonWhenGroup && bot->GetDistance(inviter) > sPlayerbotAIConfig->sightDistance)
{
Teleport(inviter, bot); Teleport(inviter, bot);
} }
return true; return true;

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ACCEPTINVITATIONACTION_H #ifndef _PLAYERBOT_ACCEPTINVITATIONACTION_H
@@ -12,10 +13,10 @@ class PlayerbotAI;
class AcceptInvitationAction : public SummonAction class AcceptInvitationAction : public SummonAction
{ {
public: public:
AcceptInvitationAction(PlayerbotAI* botAI) : SummonAction(botAI, "accept invitation") { } AcceptInvitationAction(PlayerbotAI* botAI) : SummonAction(botAI, "accept invitation") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "AcceptQuestAction.h" #include "AcceptQuestAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -112,7 +114,7 @@ bool AcceptQuestShareAction::Execute(Event event)
bot->SetDivider(ObjectGuid::Empty); bot->SetDivider(ObjectGuid::Empty);
} }
if (bot->CanAddQuest( qInfo, false)) if (bot->CanAddQuest(qInfo, false))
{ {
bot->AddQuest(qInfo, master); bot->AddQuest(qInfo, master);
@@ -125,7 +127,7 @@ bool AcceptQuestShareAction::Execute(Event event)
if (qInfo->GetSrcSpell() > 0) if (qInfo->GetSrcSpell() > 0)
{ {
bot->CastSpell( bot, qInfo->GetSrcSpell(), true); bot->CastSpell(bot, qInfo->GetSrcSpell(), true);
} }
botAI->TellMaster("Quest accepted"); botAI->TellMaster("Quest accepted");

View File

@@ -1,5 +1,6 @@
/* /*
* 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. * 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_ACCEPTQUESTACTION_H #ifndef _PLAYERBOT_ACCEPTQUESTACTION_H
@@ -13,25 +14,27 @@ class WorldObject;
class AcceptAllQuestsAction : public QuestAction class AcceptAllQuestsAction : public QuestAction
{ {
public: public:
AcceptAllQuestsAction(PlayerbotAI* botAI, std::string const name = "accept all quests") : QuestAction(botAI, name) { } AcceptAllQuestsAction(PlayerbotAI* botAI, std::string const name = "accept all quests") : QuestAction(botAI, name)
{
}
protected: protected:
void ProcessQuest(Quest const* quest, Object* questGiver) override; void ProcessQuest(Quest const* quest, Object* questGiver) override;
}; };
class AcceptQuestAction : public AcceptAllQuestsAction class AcceptQuestAction : public AcceptAllQuestsAction
{ {
public: public:
AcceptQuestAction(PlayerbotAI* botAI) : AcceptAllQuestsAction(botAI, "accept quest") { } AcceptQuestAction(PlayerbotAI* botAI) : AcceptAllQuestsAction(botAI, "accept quest") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
class AcceptQuestShareAction : public Action class AcceptQuestShareAction : public Action
{ {
public: public:
AcceptQuestShareAction(PlayerbotAI* botAI) : Action(botAI, "accept quest share") { } AcceptQuestShareAction(PlayerbotAI* botAI) : Action(botAI, "accept quest share") {}
bool Execute(Event event) override; bool Execute(Event event) override;
}; };
#endif #endif

View File

@@ -1,8 +1,10 @@
/* /*
* 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. * 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 "AcceptResurrectAction.h" #include "AcceptResurrectAction.h"
#include "Event.h" #include "Event.h"
#include "Playerbots.h" #include "Playerbots.h"
@@ -18,8 +20,8 @@ bool AcceptResurrectAction::Execute(Event event)
WorldPacket packet(CMSG_RESURRECT_RESPONSE, 8 + 1); WorldPacket packet(CMSG_RESURRECT_RESPONSE, 8 + 1);
packet << guid; packet << guid;
packet << uint8(1); // accept packet << uint8(1); // accept
bot->GetSession()->HandleResurrectResponseOpcode(packet); // queue the packet to get around race condition bot->GetSession()->HandleResurrectResponseOpcode(packet); // queue the packet to get around race condition
botAI->ChangeEngine(BOT_STATE_NON_COMBAT); botAI->ChangeEngine(BOT_STATE_NON_COMBAT);

Some files were not shown because too many files have changed in this diff Show More