Compare commits

..

1 Commits

Author SHA1 Message Date
bashermens
057ba2ab5e Minor fix 2026-01-15 00:41:41 +01:00
1168 changed files with 591 additions and 1065 deletions

View File

@@ -25,25 +25,21 @@ jobs:
with:
repository: 'mod-playerbots/azerothcore-wotlk'
ref: 'Playerbot'
path: 'ac'
- name: Checkout Playerbot Module
uses: actions/checkout@v3
with:
repository: 'mod-playerbots/mod-playerbots'
#path: 'modules/mod-playerbots'
path: ac/modules/mod-playerbots
path: 'modules/mod-playerbots'
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.13
- name: Configure OS
shell: bash
working-directory: ac
env:
CONTINUOUS_INTEGRATION: true
run: |
./acore.sh install-deps
- name: Build
shell: bash
working-directory: ac
run: |
export CTOOLS_BUILD=all
./acore.sh compiler build

View File

@@ -1,127 +0,0 @@
# Pull Request
Describe what this change does and why it is needed...
---
## Design Philosophy
We prioritize **stability, performance, and predictability** over behavioral realism.
Complex player-mimicking logic is intentionally limited due to its negative impact on scalability, maintainability, and
long-term robustness.
Excessive processing overhead can lead to server hiccups, increased CPU usage, and degraded performance for all
participants. Because every action and
decision tree is executed **per bot and per trigger**, even small increases in logic complexity can scale poorly and
negatively affect both players and
world (random) bots. Bots are not expected to behave perfectly, and perfect simulation of human decision-making is not a
project goal. Increased behavioral
realism often introduces disproportionate cost, reduced predictability, and significantly higher maintenance overhead.
Every additional branch of logic increases long-term responsibility. All decision paths must be tested, validated, and
maintained continuously as the system evolves.
If advanced or AI-intensive behavior is introduced, the **default configuration must remain the lightweight decision
model**. More complex behavior should only be
available as an **explicit opt-in option**, clearly documented as having a measurable performance cost.
Principles:
- **Stability before intelligence**
A stable system is always preferred over a smarter one.
- **Performance is a shared resource**
Any increase in bot cost affects all players and all bots.
- **Simple logic scales better than smart logic**
Predictable behavior under load is more valuable than perfect decisions.
- **Complexity must justify itself**
If a feature cannot clearly explain its cost, it should not exist.
- **Defaults must be cheap**
Expensive behavior must always be optional and clearly communicated.
- **Bots should look reasonable, not perfect**
The goal is believable behavior, not human simulation.
Before submitting, confirm that this change aligns with those principles.
---
## Feature Evaluation
Please answer the following:
- Describe the **minimum logic** required to achieve the intended behavior?
- Describe the **cheapest implementation** that produces an acceptable result?
- Describe the **runtime cost** when this logic executes across many bots?
---
## How to Test the Changes
- Step-by-step instructions to test the change
- Any required setup (e.g. multiple players, bots, specific configuration)
- Expected behavior and how to verify it
## Complexity & Impact
- Does this change add new decision branches?
- [ ] No
- [ ] Yes (**explain below**)
- Does this change increase per-bot or per-tick processing?
- [ ] No
- [ ] Yes (**describe and justify impact**)
- Could this logic scale poorly under load?
- [ ] No
- [ ] Yes (**explain why**)
---
## Defaults & Configuration
- Does this change modify default bot behavior?
- [ ] No
- [ ] Yes (**explain why**)
If this introduces more advanced or AI-heavy logic:
- [ ] Lightweight mode remains the default
- [ ] More complex behavior is optional and thereby configurable
---
## AI Assistance
- Was AI assistance (e.g. ChatGPT or similar tools) used while working on this change?
- [ ] No
- [ ] Yes (**explain below**)
If yes, please specify:
- AI tool or model used (e.g. ChatGPT, GPT-4, Claude, etc.)
- Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation)
- Which parts of the change were influenced or generated
- Whether the result was manually reviewed and adapted
AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor.
Any AI-influenced changes must be verified against existing CORE and PB logic. We expect contributors to be honest
about what they do and do not understand.
---
## Final Checklist
- [ ] Stability is not compromised
- [ ] Performance impact is understood, tested, and acceptable
- [ ] Added logic complexity is justified and explained
- [ ] Documentation updated if needed
---
## Notes for Reviewers
Anything that significantly improves realism at the cost of stability or performance should be carefully discussed
before merging.

View File

@@ -3,9 +3,8 @@
##################################################
# Overview
# "Randombot": randomly generated bots that log in separately from players and populate the world. Randombots may automatically grind, quest, level up, and upgrade equipment and can be invited to groups and given commands.
# "AddClass bot": bots from the AddClassAccountPoolSize accounts. They are used for quickly adding a leveled and geared bot of any class to your party. They are recommended for a quick formation of a party.
# "Altbot": characters created on player accounts, which may be logged in by the player and invited to groups and given commands like randombots. They are best suited for long-progression playthroughs.
# "Randombot": randomly generated bots that log in separately from players and populate the world. Depending on settings, randombots may automatically grind, quest, and upgrade equipment and can be invited to groups and given commands.
# "Altbot": characters created on player accounts, which may be logged in by the player and invited to groups and given commands like randombots. Depending on settings, altbots can be limited to characters on the active player's account or in the active player's guild.
# Information about commands to control bots and set their strategies can be found on the wiki at https://github.com/mod-playerbots/mod-playerbots/wiki/Playerbot-Commands.
####################################################################################################
@@ -270,7 +269,7 @@ AiPlayerbot.UseFastFlyMountAtMinLevel = 70
AiPlayerbot.RandomBotShowHelmet = 1
AiPlayerbot.RandomBotShowCloak = 1
# Toggles whether altbots will automatically equip items in their inventory that are sufficient upgrades
# Randombots and altbots automatically equip any items in their inventory that are sufficient upgrades
# Default: 1 (enabled)
AiPlayerbot.AutoEquipUpgradeLoot = 1
@@ -670,7 +669,7 @@ AiPlayerbot.DisableDeathKnightLogin = 0
# Default: 0 (disabled)
AiPlayerbot.LimitTalentsExpansion = 0
# Configure randombot trading (0: Disabled, 1: Enabled, 2: Only Buy, 3: Only Sell)
# Configure randombots and addClass bot trading (0: Disabled, 1: Enabled, 2: Only Buy, 3: Only Sell)
# Default: 1 (enabled)
AiPlayerbot.EnableRandomBotTrading = 1

View File

@@ -1,21 +0,0 @@
#ifndef _PLAYERBOT_WOTLKDUNGEONACTIONCONTEXT_H
#define _PLAYERBOT_WOTLKDUNGEONACTIONCONTEXT_H
#include "UtgardeKeep/UtgardeKeepActionContext.h"
#include "Nexus/NexusActionContext.h"
#include "AzjolNerub/AzjolNerubActionContext.h"
#include "OldKingdom/OldKingdomActionContext.h"
#include "DraktharonKeep/DrakTharonKeepActionContext.h"
#include "VioletHold/VioletHoldActionContext.h"
#include "Gundrak/GundrakActionContext.h"
#include "HallsOfStone/HallsOfStoneActionContext.h"
#include "HallsOfLightning/HallsOfLightningActionContext.h"
#include "Oculus/OculusActionContext.h"
#include "UtgardePinnacle/UtgardePinnacleActionContext.h"
#include "CullingOfStratholme/CullingOfStratholmeActionContext.h"
#include "ForgeOfSouls/ForgeOfSoulsActionContext.h"
#include "PitOfSaron/PitOfSaronActionContext.h"
#include "TrialOfTheChampion/TrialOfTheChampionActionContext.h"
// #include "HallsOfReflection/HallsOfReflectionActionContext.h"
#endif

View File

@@ -1,21 +0,0 @@
#ifndef _PLAYERBOT_WOTLKDUNGEONTRIGGERCONTEXT_H
#define _PLAYERBOT_WOTLKDUNGEONTRIGGERCONTEXT_H
#include "UtgardeKeep/UtgardeKeepTriggerContext.h"
#include "Nexus/NexusTriggerContext.h"
#include "AzjolNerub/AzjolNerubTriggerContext.h"
#include "OldKingdom/OldKingdomTriggerContext.h"
#include "DraktharonKeep/DrakTharonKeepTriggerContext.h"
#include "VioletHold/VioletHoldTriggerContext.h"
#include "Gundrak/GundrakTriggerContext.h"
#include "HallsOfStone/HallsOfStoneTriggerContext.h"
#include "HallsOfLightning/HallsOfLightningTriggerContext.h"
#include "Oculus/OculusTriggerContext.h"
#include "UtgardePinnacle/UtgardePinnacleTriggerContext.h"
#include "CullingOfStratholme/CullingOfStratholmeTriggerContext.h"
#include "ForgeOfSouls/ForgeOfSoulsTriggerContext.h"
#include "PitOfSaron/PitOfSaronTriggerContext.h"
#include "TrialOfTheChampion/TrialOfTheChampionTriggerContext.h"
// #include "HallsOfReflection/HallsOfReflectionTriggerContext.h"
#endif

View File

@@ -1,39 +0,0 @@
#include "FlightMasterCache.h"
void FlightMasterCache::AddHordeFlightMaster(uint32 entry, WorldPosition pos)
{
hordeFlightMasterCache[entry] = pos;
}
void FlightMasterCache::AddAllianceFlightMaster(uint32 entry, WorldPosition pos)
{
allianceFlightMasterCache[entry] = pos;
}
Creature* FlightMasterCache::GetNearestFlightMaster(Player* bot)
{
std::map<uint32, WorldPosition>& flightMasterCache =
(bot->GetTeamId() == ALLIANCE) ? allianceFlightMasterCache : hordeFlightMasterCache;
Creature* nearestFlightMaster = nullptr;
float nearestDistance = std::numeric_limits<float>::max();
for (auto const& [entry, pos] : flightMasterCache)
{
if (pos.GetMapId() == bot->GetMapId())
{
float distance = bot->GetExactDist2dSq(pos);
if (distance < nearestDistance)
{
Creature* flightMaster = ObjectAccessor::GetSpawnedCreatureByDBGUID(bot->GetMapId(), entry);
if (flightMaster)
{
nearestDistance = distance;
nearestFlightMaster = flightMaster;
}
}
}
}
return nearestFlightMaster;
}

View File

@@ -1,27 +0,0 @@
#ifndef _PLAYERBOT_FLIGHTMASTER_H
#define _PLAYERBOT_FLIGHTMASTER_H
#include "Creature.h"
#include "Player.h"
#include "TravelMgr.h"
class FlightMasterCache
{
public:
static FlightMasterCache* Instance()
{
static FlightMasterCache instance;
return &instance;
}
Creature* GetNearestFlightMaster(Player* bot);
void AddHordeFlightMaster(uint32 entry, WorldPosition pos);
void AddAllianceFlightMaster(uint32 entry, WorldPosition pos);
private:
std::map<uint32, WorldPosition> allianceFlightMasterCache;
std::map<uint32, WorldPosition> hordeFlightMasterCache;
};
#define sFlightMasterCache FlightMasterCache::Instance()
#endif

50
src/Helpers.cpp Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "Helpers.h"
char* strstri(char const* haystack, char const* needle)
{
if (!*needle)
{
return (char*)haystack;
}
for (; *haystack; ++haystack)
{
if (tolower(*haystack) == tolower(*needle))
{
char const *h = haystack, *n = needle;
for (; *h && *n; ++h, ++n)
{
if (tolower(*h) != tolower(*n))
{
break;
}
}
if (!*n)
{
return (char*)haystack;
}
}
}
return 0;
}
std::string& ltrim(std::string& s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
return 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());
return s;
}
std::string& trim(std::string& s) { return ltrim(rtrim(s)); }

55
src/Helpers.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_HELPERS_H
#define _PLAYERBOT_HELPERS_H
#include <stdio.h>
#include <string.h>
#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)
{
char* pTempStr = strdup(str.c_str());
char* pWord = strtok(pTempStr, delim);
while (pWord != nullptr)
{
dest.push_back(pWord);
pWord = strtok(nullptr, delim);
}
free(pTempStr);
}
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems)
{
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(std::string const s, char delim)
{
std::vector<std::string> elems;
return split(s, delim, elems);
}
#endif

39
src/LazyCalculatedValue.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_LAZYCALCULATEDVALUE_H
#define _PLAYERBOT_LAZYCALCULATEDVALUE_H
template <class TValue, class TOwner>
class LazyCalculatedValue
{
public:
typedef TValue (TOwner::*Calculator)();
public:
LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner) { Reset(); }
public:
TValue GetValue()
{
if (!calculated)
{
value = (owner->*calculator)();
calculated = true;
}
return value;
}
void Reset() { calculated = false; }
protected:
Calculator calculator;
TOwner* owner;
bool calculated;
TValue value;
};
#endif

View File

@@ -3,11 +3,11 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "Playerbots.h"
PerfMonitorOperation* PerfMonitor::start(PerformanceMetric metric, std::string const name,
PerformanceMonitorOperation* PerformanceMonitor::start(PerformanceMetric metric, std::string const name,
PerformanceStack* stack)
{
if (!sPlayerbotAIConfig->perfMonEnabled)
@@ -45,10 +45,10 @@ PerfMonitorOperation* PerfMonitor::start(PerformanceMetric metric, std::string c
data[metric][stackName] = pd;
}
return new PerfMonitorOperation(pd, name, stack);
return new PerformanceMonitorOperation(pd, name, stack);
}
void PerfMonitor::PrintStats(bool perTick, bool fullStack)
void PerformanceMonitor::PrintStats(bool perTick, bool fullStack)
{
if (data.empty())
return;
@@ -247,7 +247,7 @@ void PerfMonitor::PrintStats(bool perTick, bool fullStack)
}
}
void PerfMonitor::Reset()
void PerformanceMonitor::Reset()
{
for (std::map<PerformanceMetric, std::map<std::string, PerformanceData*>>::iterator i = data.begin();
i != data.end(); ++i)
@@ -265,7 +265,7 @@ void PerfMonitor::Reset()
}
}
PerfMonitorOperation::PerfMonitorOperation(PerformanceData* data, std::string const name,
PerformanceMonitorOperation::PerformanceMonitorOperation(PerformanceData* data, std::string const name,
PerformanceStack* stack)
: data(data), name(name), stack(stack)
{
@@ -273,7 +273,7 @@ PerfMonitorOperation::PerfMonitorOperation(PerformanceData* data, std::string co
.time_since_epoch();
}
void PerfMonitorOperation::finish()
void PerformanceMonitorOperation::finish()
{
std::chrono::microseconds finished =
(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()))

View File

@@ -34,10 +34,10 @@ enum PerformanceMetric
PERF_MON_TOTAL
};
class PerfMonitorOperation
class PerformanceMonitorOperation
{
public:
PerfMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack);
PerformanceMonitorOperation(PerformanceData* data, std::string const name, PerformanceStack* stack);
void finish();
private:
@@ -47,19 +47,19 @@ private:
std::chrono::microseconds started;
};
class PerfMonitor
class PerformanceMonitor
{
public:
PerfMonitor(){};
virtual ~PerfMonitor(){};
static PerfMonitor* instance()
PerformanceMonitor(){};
virtual ~PerformanceMonitor(){};
static PerformanceMonitor* instance()
{
static PerfMonitor instance;
static PerformanceMonitor instance;
return &instance;
}
public:
PerfMonitorOperation* start(PerformanceMetric metric, std::string const name,
PerformanceMonitorOperation* start(PerformanceMetric metric, std::string const name,
PerformanceStack* stack = nullptr);
void PrintStats(bool perTick = false, bool fullStack = false);
void Reset();
@@ -69,6 +69,6 @@ private:
std::mutex lock;
};
#define sPerfMonitor PerfMonitor::instance()
#define sPerformanceMonitor PerformanceMonitor::instance()
#endif

View File

@@ -10,7 +10,7 @@
#include "Common.h"
#include "Player.h"
#include "PlayerbotDungeonRepository.h"
#include "PlayerbotDungeonSuggestionMgr.h"
typedef std::map<std::string, std::string> PlaceholderMap;

View File

@@ -38,10 +38,10 @@
#include "NewRpgStrategy.h"
#include "ObjectGuid.h"
#include "ObjectMgr.h"
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "Player.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotRepository.h"
#include "PlayerbotDbStore.h"
#include "PlayerbotMgr.h"
#include "PlayerbotGuildMgr.h"
#include "Playerbots.h"
@@ -89,10 +89,8 @@ void PacketHandlingHelper::Handle(ExternalEventHelper& helper)
{
while (!queue.empty())
{
WorldPacket packet = queue.top();
queue.pop(); // remove first so handling can't modify the queue while we're using it
helper.HandlePacket(handlers, packet);
helper.HandlePacket(handlers, queue.top());
queue.pop();
}
}
@@ -439,19 +437,12 @@ void PlayerbotAI::UpdateAIGroupMaster()
void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal)
{
if (!bot || !bot->GetSession())
if (!bot || bot->IsBeingTeleported() || !bot->IsInWorld())
return;
if (!bot->IsInWorld() || bot->IsBeingTeleported() || bot->IsDuringRemoveFromWorld())
return;
if (!bot->GetMap())
return; // instances are created and destroyed on demand
std::string const mapString = WorldPosition(bot).isOverworld() ? std::to_string(bot->GetMapId()) : "I";
PerfMonitorOperation* pmo =
sPerfMonitor->start(PERF_MON_TOTAL, "PlayerbotAI::UpdateAIInternal " + mapString);
PerformanceMonitorOperation* pmo =
sPerformanceMonitor->start(PERF_MON_TOTAL, "PlayerbotAI::UpdateAIInternal " + mapString);
ExternalEventHelper helper(aiObjectContext);
// chat replies
@@ -1740,7 +1731,7 @@ void PlayerbotAI::ResetStrategies(bool load)
engines[i]->Init();
// if (load)
// sPlayerbotRepository->Load(this);
// sPlayerbotDbStore->Load(this);
}
bool PlayerbotAI::IsRanged(Player* player, bool bySpec)
@@ -1796,46 +1787,35 @@ bool PlayerbotAI::IsCombo(Player* player)
bool PlayerbotAI::IsRangedDps(Player* player, bool bySpec) { return IsRanged(player, bySpec) && IsDps(player, bySpec); }
bool PlayerbotAI::IsAssistHealOfIndex(Player* player, int index, bool ignoreDeadPlayers)
bool PlayerbotAI::IsHealAssistantOfIndex(Player* player, int index)
{
Group* group = player->GetGroup();
if (!group)
{
return false;
}
int counter = 0;
// First, assistants
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
continue;
if (ignoreDeadPlayers && !member->IsAlive())
continue;
if (group->IsAssistant(member->GetGUID()) && IsHeal(member))
{
if (index == counter)
return player == member;
counter++;
continue;
}
}
// If not enough assistants, get non-assistants
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
continue;
if (ignoreDeadPlayers && !member->IsAlive())
continue;
if (!group->IsAssistant(member->GetGUID()) && IsHeal(member))
if (IsHeal(member)) // Check if the member is a healer
{
if (index == counter)
bool isAssistant = group->IsAssistant(member->GetGUID());
// Check if the index matches for both assistant and non-assistant healers
if ((isAssistant && index == counter) || (!isAssistant && index == counter))
{
return player == member;
}
counter++;
}
}
@@ -1843,46 +1823,35 @@ bool PlayerbotAI::IsAssistHealOfIndex(Player* player, int index, bool ignoreDead
return false;
}
bool PlayerbotAI::IsAssistRangedDpsOfIndex(Player* player, int index, bool ignoreDeadPlayers)
bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index)
{
Group* group = player->GetGroup();
if (!group)
{
return false;
}
int counter = 0;
// First, assistants
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
continue;
if (ignoreDeadPlayers && !member->IsAlive())
continue;
if (group->IsAssistant(member->GetGUID()) && IsRangedDps(member))
{
if (index == counter)
return player == member;
counter++;
continue;
}
}
// If not enough assistants, get non-assistants
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
continue;
if (ignoreDeadPlayers && !member->IsAlive())
continue;
if (!group->IsAssistant(member->GetGUID()) && IsRangedDps(member))
if (IsRangedDps(member)) // Check if the member is a ranged DPS
{
if (index == counter)
bool isAssistant = group->IsAssistant(member->GetGUID());
// Check the index for both assistant and non-assistant ranges
if ((isAssistant && index == counter) || (!isAssistant && index == counter))
{
return player == member;
}
counter++;
}
}
@@ -2269,15 +2238,10 @@ bool PlayerbotAI::IsMainTank(Player* player)
bool PlayerbotAI::IsBotMainTank(Player* player)
{
if (!player || !player->IsInWorld() || player->IsDuringRemoveFromWorld())
return false;
WorldSession* session = player->GetSession();
if (!session || !session->IsBot())
return false;
if (!IsTank(player))
if (!player->GetSession()->IsBot() || !IsTank(player))
{
return false;
}
if (IsMainTank(player))
{
@@ -2357,16 +2321,18 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead
{
Group* group = player->GetGroup();
if (!group)
{
return false;
}
int counter = 0;
// First, assistants
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
{
continue;
}
if (ignoreDeadPlayers && !member->IsAlive())
continue;
@@ -2374,17 +2340,21 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead
if (group->IsAssistant(member->GetGUID()) && IsAssistTank(member))
{
if (index == counter)
{
return player == member;
}
counter++;
}
}
// If not enough assistants, get non-assistants
// not enough
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member)
{
continue;
}
if (ignoreDeadPlayers && !member->IsAlive())
continue;
@@ -2392,7 +2362,9 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead
if (!group->IsAssistant(member->GetGUID()) && IsAssistTank(member))
{
if (index == counter)
{
return player == member;
}
counter++;
}
}

View File

@@ -429,8 +429,8 @@ public:
static uint32 GetGroupTankNum(Player* player);
static bool IsAssistTank(Player* player);
static bool IsAssistTankOfIndex(Player* player, int index, bool ignoreDeadPlayers = false);
static bool IsAssistHealOfIndex(Player* player, int index, bool ignoreDeadPlayers = false);
static bool IsAssistRangedDpsOfIndex(Player* player, int index, bool ignoreDeadPlayers = false);
static bool IsHealAssistantOfIndex(Player* player, int index);
static bool IsRangedDpsAssistantOfIndex(Player* player, int index);
bool HasAggro(Unit* unit);
static int32 GetAssistTankIndex(Player* player);
int32 GetGroupSlotIndex(Player* player);

View File

@@ -14,7 +14,7 @@ void PlayerbotAIBase::UpdateAI(uint32 elapsed, bool minimal)
if (totalPmo)
totalPmo->finish();
totalPmo = sPerfMonitor->start(PERF_MON_TOTAL, "PlayerbotAIBase::FullTick");
totalPmo = sPerformanceMonitor->start(PERF_MON_TOTAL, "PlayerbotAIBase::FullTick");
if (nextAICheckDelay > elapsed)
nextAICheckDelay -= elapsed;

View File

@@ -25,7 +25,7 @@ public:
protected:
uint32 nextAICheckDelay;
class PerfMonitorOperation* totalPmo = nullptr;
class PerformanceMonitorOperation* totalPmo = nullptr;
private:
bool _isBotAI;

View File

@@ -7,7 +7,7 @@
#include <iostream>
#include "Config.h"
#include "NewRpgInfo.h"
#include "PlayerbotDungeonRepository.h"
#include "PlayerbotDungeonSuggestionMgr.h"
#include "PlayerbotFactory.h"
#include "Playerbots.h"
#include "PlayerbotGuildMgr.h"
@@ -678,7 +678,7 @@ bool PlayerbotAIConfig::Initialize()
if (sPlayerbotAIConfig->randomBotSuggestDungeons)
{
sPlayerbotDungeonRepository->LoadDungeonSuggestions();
sPlayerbotDungeonSuggestionMgr->LoadDungeonSuggestions();
}
excludedHunterPetFamilies.clear();

View File

@@ -3,13 +3,13 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "PlayerbotRepository.h"
#include "PlayerbotDbStore.h"
#include <iostream>
#include "Playerbots.h"
void PlayerbotRepository::Load(PlayerbotAI* botAI)
void PlayerbotDbStore::Load(PlayerbotAI* botAI)
{
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
@@ -46,7 +46,7 @@ void PlayerbotRepository::Load(PlayerbotAI* botAI)
}
}
void PlayerbotRepository::Save(PlayerbotAI* botAI)
void PlayerbotDbStore::Save(PlayerbotAI* botAI)
{
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
@@ -68,7 +68,7 @@ void PlayerbotRepository::Save(PlayerbotAI* botAI)
SaveValue(guid, "dead", FormatStrategies("dead", botAI->GetStrategies(BOT_STATE_DEAD)));
}
std::string const PlayerbotRepository::FormatStrategies(std::string const type, std::vector<std::string> strategies)
std::string const PlayerbotDbStore::FormatStrategies(std::string const type, std::vector<std::string> strategies)
{
std::ostringstream out;
for (std::vector<std::string>::iterator i = strategies.begin(); i != strategies.end(); ++i)
@@ -78,7 +78,7 @@ std::string const PlayerbotRepository::FormatStrategies(std::string const type,
return res.substr(0, res.size() - 1);
}
void PlayerbotRepository::Reset(PlayerbotAI* botAI)
void PlayerbotDbStore::Reset(PlayerbotAI* botAI)
{
ObjectGuid::LowType guid = botAI->GetBot()->GetGUID().GetCounter();
@@ -87,7 +87,7 @@ void PlayerbotRepository::Reset(PlayerbotAI* botAI)
PlayerbotsDatabase.Execute(stmt);
}
void PlayerbotRepository::SaveValue(uint32 guid, std::string const key, std::string const value)
void PlayerbotDbStore::SaveValue(uint32 guid, std::string const key, std::string const value)
{
PlayerbotsDatabasePreparedStatement* stmt = PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_INS_DB_STORE);
stmt->SetData(0, guid);

View File

@@ -3,8 +3,8 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_PLAYERBOTREPOSITORY_H
#define _PLAYERBOT_PLAYERBOTREPOSITORY_H
#ifndef _PLAYERBOT_PLAYERBOTDBSTORE_H
#define _PLAYERBOT_PLAYERBOTDBSTORE_H
#include <vector>
@@ -12,14 +12,14 @@
class PlayerbotAI;
class PlayerbotRepository
class PlayerbotDbStore
{
public:
PlayerbotRepository() {}
virtual ~PlayerbotRepository() {}
static PlayerbotRepository* instance()
PlayerbotDbStore() {}
virtual ~PlayerbotDbStore() {}
static PlayerbotDbStore* instance()
{
static PlayerbotRepository instance;
static PlayerbotDbStore instance;
return &instance;
}
@@ -32,6 +32,6 @@ private:
std::string const FormatStrategies(std::string const type, std::vector<std::string> strategies);
};
#define sPlayerbotRepository PlayerbotRepository::instance()
#define sPlayerbotDbStore PlayerbotDbStore::instance()
#endif

View File

@@ -3,16 +3,16 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "PlayerbotDungeonRepository.h"
#include "PlayerbotDungeonSuggestionMgr.h"
#include "Playerbots.h"
std::vector<DungeonSuggestion> const PlayerbotDungeonRepository::GetDungeonSuggestions()
std::vector<DungeonSuggestion> const PlayerbotDungeonSuggestionMgr::GetDungeonSuggestions()
{
return m_dungeonSuggestions;
}
void PlayerbotDungeonRepository::LoadDungeonSuggestions()
void PlayerbotDungeonSuggestionMgr::LoadDungeonSuggestions()
{
LOG_INFO("server.loading", "Loading playerbots dungeon suggestions...");
uint32 oldMSTime = getMSTime();

View File

@@ -3,8 +3,8 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_PLAYERBOTDUNGEONREPOSITORY_H
#define _PLAYERBOT_PLAYERBOTDUNGEONREPOSITORY_H
#ifndef _PLAYERBOT_PLAYERBOTDUNGEONSUGGESTIONMGR_H
#define _PLAYERBOT_PLAYERBOTDUNGEONSUGGESTIONMGR_H
#include <map>
#include <vector>
@@ -22,14 +22,14 @@ struct DungeonSuggestion
std::string strategy;
};
class PlayerbotDungeonRepository
class PlayerbotDungeonSuggestionMgr
{
public:
PlayerbotDungeonRepository(){};
~PlayerbotDungeonRepository(){};
static PlayerbotDungeonRepository* instance()
PlayerbotDungeonSuggestionMgr(){};
~PlayerbotDungeonSuggestionMgr(){};
static PlayerbotDungeonSuggestionMgr* instance()
{
static PlayerbotDungeonRepository instance;
static PlayerbotDungeonSuggestionMgr instance;
return &instance;
}
@@ -40,6 +40,6 @@ private:
std::vector<DungeonSuggestion> m_dungeonSuggestions;
};
#define sPlayerbotDungeonRepository PlayerbotDungeonRepository::instance()
#define sPlayerbotDungeonSuggestionMgr PlayerbotDungeonSuggestionMgr::instance()
#endif

View File

@@ -26,7 +26,7 @@
#include "ObjectGuid.h"
#include "ObjectMgr.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotRepository.h"
#include "PlayerbotDbStore.h"
#include "PlayerbotFactory.h"
#include "PlayerbotOperations.h"
#include "PlayerbotSecurity.h"
@@ -442,7 +442,7 @@ void PlayerbotHolder::DisablePlayerBot(ObjectGuid guid)
Group* group = bot->GetGroup();
if (group && !bot->InBattleground() && !bot->InBattlegroundQueue() && botAI->HasActivePlayerMaster())
{
sPlayerbotRepository->Save(botAI);
sPlayerbotDbStore->Save(botAI);
}
LOG_DEBUG("playerbots", "Bot {} logged out", bot->GetName().c_str());
@@ -554,7 +554,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot)
{
botAI->ResetStrategies(!sRandomPlayerbotMgr->IsRandomBot(bot));
}
sPlayerbotRepository->Load(botAI);
sPlayerbotDbStore->Load(botAI);
if (master && !master->HasUnitState(UNIT_STATE_IN_FLIGHT))
{

View File

@@ -15,7 +15,7 @@
#include "Player.h"
#include "PlayerbotAI.h"
#include "PlayerbotMgr.h"
#include "PlayerbotRepository.h"
#include "PlayerbotDbStore.h"
#include "RandomPlayerbotMgr.h"
#include "WorldSession.h"
#include "WorldSessionMgr.h"
@@ -418,7 +418,7 @@ public:
Group* group = bot->GetGroup();
if (group && !bot->InBattleground() && !bot->InBattlegroundQueue() && botAI->HasActivePlayerMaster())
sPlayerbotRepository->Save(botAI);
sPlayerbotDbStore->Save(botAI);
return true;
}

View File

@@ -26,11 +26,11 @@
#include "PlayerScript.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotGuildMgr.h"
#include "PlayerbotSpellRepository.h"
#include "PlayerbotSpellCache.h"
#include "PlayerbotWorldThreadProcessor.h"
#include "RandomPlayerbotMgr.h"
#include "ScriptMgr.h"
#include "PlayerbotCommandScript.h"
#include "cs_playerbots.h"
#include "cmath"
#include "BattleGroundTactics.h"
@@ -365,7 +365,7 @@ public:
LOG_INFO("server.loading", ">> Loaded playerbots config in {} ms", GetMSTimeDiffToNow(oldMSTime));
LOG_INFO("server.loading", " ");
sPlayerbotSpellRepository->Initialize();
sPlayerbotSpellCache->Initialize();
LOG_INFO("server.loading", "Playerbots World Thread Processor initialized");
}
@@ -515,6 +515,6 @@ void AddPlayerbotsScripts()
new PlayerbotsScript();
new PlayerBotsBGScript();
AddPlayerbotsSecureLoginScripts();
AddPlayerbotsCommandscripts();
AddSC_playerbots_commandscript();
PlayerBotsGuildValidationScript();
}

View File

@@ -26,7 +26,6 @@
#include "DatabaseEnv.h"
#include "Define.h"
#include "FleeManager.h"
#include "FlightMasterCache.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "GuildMgr.h"
@@ -36,7 +35,7 @@
#include "NewRpgInfo.h"
#include "NewRpgStrategy.h"
#include "ObjectGuid.h"
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h"
@@ -359,7 +358,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
if (totalPmo)
totalPmo->finish();
totalPmo = sPerfMonitor->start(PERF_MON_TOTAL, "RandomPlayerbotMgr::FullTick");
totalPmo = sPerformanceMonitor->start(PERF_MON_TOTAL, "RandomPlayerbotMgr::FullTick");
if (!sPlayerbotAIConfig->randomBotAutologin || !sPlayerbotAIConfig->enabled)
return;
@@ -402,7 +401,7 @@ void RandomPlayerbotMgr::UpdateAIInternal(uint32 elapsed, bool /*minimal*/)
uint32 updateIntervalTurboBoost = _isBotInitializing ? 1 : sPlayerbotAIConfig->randomBotUpdateInterval;
SetNextCheckDelay(updateIntervalTurboBoost * (onlineBotFocus + 25) * 10);
PerfMonitorOperation* pmo = sPerfMonitor->start(
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(
PERF_MON_TOTAL,
onlineBotCount < maxAllowedBotCount ? "RandomPlayerbotMgr::Login" : "RandomPlayerbotMgr::UpdateAIInternal");
@@ -1708,7 +1707,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector<WorldLocation>&
return;
}
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomTeleportByLocations");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "RandomTeleportByLocations");
std::shuffle(std::begin(tlocs), std::end(tlocs), RandomEngine::Instance());
for (uint32 i = 0; i < tlocs.size(); i++)
@@ -2003,12 +2002,14 @@ void RandomPlayerbotMgr::PrepareTeleportCache()
bool forAlliance = !(entry->hostileMask & 2);
if (tNpcflag & UNIT_NPC_FLAG_FLIGHTMASTER)
{
WorldPosition pos(mapId, x, y, z, orient);
if (forHorde)
sFlightMasterCache->AddHordeFlightMaster(guid, pos);
{
hordeFlightMasterCache.push_back(guid);
}
if (forAlliance)
sFlightMasterCache->AddAllianceFlightMaster(guid, pos);
{
allianceFlightMasterCache.push_back(guid);
}
}
const AreaTableEntry* area = sAreaTableStore.LookupEntry(map->GetAreaId(PHASEMASK_NORMAL, x, y, z));
uint32 zoneId = area->zone ? area->zone : area->ID;
@@ -2299,7 +2300,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot)
if (bot->InBattleground())
return;
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomTeleport");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "RandomTeleport");
std::vector<WorldLocation> locs;
std::list<Unit*> targets;
@@ -2361,7 +2362,7 @@ void RandomPlayerbotMgr::IncreaseLevel(Player* bot)
if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "IncreaseLevel");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "IncreaseLevel");
uint32 lastLevel = GetValue(bot, "level");
uint8 level = bot->GetLevel() + 1;
if (level > maxLevel)
@@ -2400,7 +2401,7 @@ void RandomPlayerbotMgr::RandomizeFirst(Player* bot)
minLevel = std::max(minLevel, sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL));
}
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomizeFirst");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "RandomizeFirst");
uint32 level;
@@ -2479,7 +2480,7 @@ void RandomPlayerbotMgr::RandomizeMin(Player* bot)
if (!botAI)
return;
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "RandomizeMin");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "RandomizeMin");
uint32 level = sPlayerbotAIConfig->randomBotMinLevel;
SetValue(bot, "level", level);
PlayerbotFactory factory(bot, level);
@@ -2568,7 +2569,7 @@ void RandomPlayerbotMgr::Refresh(Player* bot)
LOG_DEBUG("playerbots", "Refreshing bot {} <{}>", bot->GetGUID().ToString().c_str(), bot->GetName().c_str());
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "Refresh");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "Refresh");
botAI->Reset();
@@ -3213,12 +3214,6 @@ void RandomPlayerbotMgr::PrintStats()
lvlPerRace[bot->getRace()] += bot->GetLevel();
PlayerbotAI* botAI = GET_PLAYERBOT_AI(bot);
if (!botAI)
{
LOG_ERROR("playerbots", "Player/Bot {} is registered in sRandomPlayerbotMgr playerBots and has no bot AI!", bot->GetName().c_str());
continue;
}
if (botAI->AllowActivity())
++active;

View File

@@ -43,7 +43,7 @@ struct BattlegroundInfo
};
class ChatHandler;
class PerfMonitorOperation;
class PerformanceMonitorOperation;
class WorldLocation;
struct CachedEvent
@@ -171,7 +171,8 @@ public:
std::map<uint8, std::vector<WorldLocation>> locsPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> allianceStarterPerLevelCache;
std::map<uint8, std::vector<WorldLocation>> hordeStarterPerLevelCache;
std::vector<uint32> allianceFlightMasterCache;
std::vector<uint32> hordeFlightMasterCache;
struct LevelBracket {
uint32 low;
uint32 high;

View File

@@ -1 +0,0 @@
void AddPlayerbotsCommandscripts();

View File

@@ -45,13 +45,11 @@ void ServerFacade::SetFacingTo(Player* bot, WorldObject* wo, bool force)
return;
float angle = bot->GetAngle(wo);
// if (!force && bot->isMoving())
// bot->SetFacingTo(bot->GetAngle(wo));
// else
// {
bot->SetOrientation(angle);
if (!bot->IsRooted())
bot->SendMovementFlagUpdate();
// }
@@ -66,14 +64,16 @@ Unit* ServerFacade::GetChaseTarget(Unit* target)
{
return static_cast<ChaseMovementGenerator<Player> const*>(movementGen)->GetTarget();
}
return static_cast<ChaseMovementGenerator<Creature> const*>(movementGen)->GetTarget();
else
{
return static_cast<ChaseMovementGenerator<Creature> const*>(movementGen)->GetTarget();
}
}
return nullptr;
}
void ServerFacade::SendPacket(Player* player, WorldPacket* packet)
void ServerFacade::SendPacket(Player *player, WorldPacket *packet)
{
player->GetSession()->SendPacket(packet);
return player->GetSession()->SendPacket(packet);
}

43
src/ServerFacade.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_SERVERFACADE_H
#define _PLAYERBOT_SERVERFACADE_H
#include "Common.h"
class Player;
class Unit;
class WorldObject;
class WorldPacket;
class ServerFacade
{
public:
ServerFacade(){};
virtual ~ServerFacade(){};
static ServerFacade* instance()
{
static ServerFacade instance;
return &instance;
}
public:
float GetDistance2d(Unit* unit, WorldObject* wo);
float GetDistance2d(Unit* unit, float x, float y);
bool IsDistanceLessThan(float dist1, float dist2);
bool IsDistanceGreaterThan(float dist1, float dist2);
bool IsDistanceGreaterOrEqualThan(float dist1, float dist2);
bool IsDistanceLessOrEqualThan(float dist1, float dist2);
void SetFacingTo(Player* bot, WorldObject* wo, bool force = false);
Unit* GetChaseTarget(Unit* target);
void SendPacket(Player *player, WorldPacket* packet);
};
#define sServerFacade ServerFacade::instance()
#endif

View File

@@ -1,114 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "Helpers.h"
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <string>
#include <vector>
/**
* Case-insensitive substring search.
*/
char* strstri(char const* haystack, char const* needle)
{
if (!*needle)
{
return (char*)haystack;
}
for (; *haystack; ++haystack)
{
if (tolower(*haystack) == tolower(*needle))
{
char const* h = haystack;
char const* n = needle;
for (; *h && *n; ++h, ++n)
{
if (tolower(*h) != tolower(*n))
{
break;
}
}
if (!*n)
{
return (char*)haystack;
}
}
}
return 0;
}
/**
* Trim whitespace from the left side of a string (in place).
*/
std::string& ltrim(std::string& s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); }));
return s;
}
/**
* Trim whitespace from the right side of a string (in place).
*/
std::string& rtrim(std::string& s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return !std::isspace(c); }).base(), s.end());
return s;
}
/**
* Trim whitespace from both ends of a string (in place).
*/
std::string& trim(std::string& s) { return ltrim(rtrim(s)); }
/**
* Split a string using a C-string delimiter.
*/
void split(std::vector<std::string>& dest, std::string const str, char const* delim)
{
char* pTempStr = strdup(str.c_str());
char* pWord = strtok(pTempStr, delim);
while (pWord != nullptr)
{
dest.push_back(pWord);
pWord = strtok(nullptr, delim);
}
free(pTempStr);
}
/**
* Split a string using a single character delimiter.
*/
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems)
{
std::stringstream ss(s);
std::string item;
while (getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
/**
* Split a string using a single character delimiter.
*/
std::vector<std::string> split(std::string const s, char delim)
{
std::vector<std::string> elems;
return split(s, delim, elems);
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_HELPERS_H
#define _PLAYERBOT_HELPERS_H
#include <string>
#include <vector>
/**
* Case-insensitive substring search.
*
* @param haystack The string to search in
* @param needle The substring to search for
* @return Pointer to the first matching position in haystack, or nullptr if not found.
*/
char* strstri(char const* haystack, char const* needle);
/**
* Trim whitespace from the left side of a string (in place).
*
* @param s The string to trim
* @return Reference to the modified string
*/
std::string& ltrim(std::string& s);
/**
* Trim whitespace from the right side of a string (in place).
*
* @param s The string to trim
* @return Reference to the modified string
*/
std::string& rtrim(std::string& s);
/**
* Trim whitespace from both ends of a string (in place).
*
* @param s The string to trim
* @return Reference to the modified string
*/
std::string& trim(std::string& s);
/**
* Split a string using a C-string delimiter.
*
* @param dest Vector to store split tokens
* @param str String to split
* @param delim C-string delimiter
*/
void split(std::vector<std::string>& dest, std::string const str, char const* delim);
/**
* Split a string using a single character delimiter.
*
* @param s String to split
* @param delim Delimiter character
* @param elems Vector to store split tokens
* @return Reference to the vector containing tokens
*/
std::vector<std::string>& split(std::string const s, char delim, std::vector<std::string>& elems);
/**
* Split a string using a single character delimiter.
*
* @param s String to split
* @param delim Delimiter character
* @return Vector containing split tokens
*/
std::vector<std::string> split(std::string const s, char delim);
#endif

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_LAZYCALCULATEDVALUE_H
#define _PLAYERBOT_LAZYCALCULATEDVALUE_H
/**
* @brief Lazy calculation helper.
*
* Stores a function pointer (calculator) and its owner instance, and
* calculates the value only when it is requested for the first time.
* The result is cached until Reset() is called.
*
* @tparam TValue Type of the calculated value.
* @tparam TOwner Type of the owner class containing the calculator function.
*/
template <class TValue, class TOwner>
class LazyCalculatedValue
{
public:
/**
* @brief Type of the calculator function.
*
* This is a pointer to a member function of TOwner returning TValue.
*/
typedef TValue (TOwner::*Calculator)();
public:
/**
* @brief Constructor.
*
* @param owner Pointer to the owner object.
* @param calculator Pointer to the member function used to calculate the value.
*/
LazyCalculatedValue(TOwner* owner, Calculator calculator) : calculator(calculator), owner(owner) { Reset(); }
public:
/**
* @brief Get the cached value or calculate it if needed.
*
* If the value has not been calculated yet, it calls the calculator
* on the owner and caches the result.
*
* @return TValue The calculated or cached value.
*/
TValue GetValue()
{
if (!calculated)
{
value = (owner->*calculator)();
calculated = true;
}
return value;
}
/**
* @brief Reset the cached state.
*
* After calling Reset(), the next call to GetValue() will recalculate
* the value again.
*/
void Reset() { calculated = false; }
protected:
Calculator calculator; ///< Pointer to calculator member function
TOwner* owner; ///< Owner instance
bool calculated; ///< Whether value has already been calculated
TValue value; ///< Cached value
};
#endif

View File

@@ -1,129 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_SERVERFACADE_H
#define _PLAYERBOT_SERVERFACADE_H
#include "Common.h"
class Player;
class Unit;
class WorldObject;
class WorldPacket;
/**
* @brief Provides a simplified interface to server engine operations.
*
* ServerFacade acts as a wrapper around common server functions used by
* the Playerbot system. It centralizes utility methods for distance
* calculations, facing, chase target retrieval, and packet sending.
*/
class ServerFacade
{
public:
ServerFacade() {}
virtual ~ServerFacade() {}
/**
* @brief Get singleton instance.
*
* @return ServerFacade* Pointer to the singleton instance.
*/
static ServerFacade* instance()
{
static ServerFacade instance;
return &instance;
}
public:
/**
* @brief Get 2D distance between a unit and a world object.
*
* The result is rounded to one decimal place.
*
* @param unit Source unit.
* @param wo Target world object.
* @return float Distance in yards.
*/
float GetDistance2d(Unit* unit, WorldObject* wo);
/**
* @brief Get 2D distance between a unit and coordinates.
*
* The result is rounded to one decimal place.
*
* @param unit Source unit.
* @param x Target X coordinate.
* @param y Target Y coordinate.
* @return float Distance in yards.
*/
float GetDistance2d(Unit* unit, float x, float y);
/**
* @brief Compare two distances.
*
* @param dist1 First distance.
* @param dist2 Second distance.
* @return true if dist1 < dist2.
*/
bool IsDistanceLessThan(float dist1, float dist2);
/**
* @brief Compare two distances.
*
* @param dist1 First distance.
* @param dist2 Second distance.
* @return true if dist1 > dist2.
*/
bool IsDistanceGreaterThan(float dist1, float dist2);
/**
* @brief Compare two distances.
*
* @param dist1 First distance.
* @param dist2 Second distance.
* @return true if dist1 >= dist2.
*/
bool IsDistanceGreaterOrEqualThan(float dist1, float dist2);
/**
* @brief Compare two distances.
*
* @param dist1 First distance.
* @param dist2 Second distance.
* @return true if dist1 <= dist2.
*/
bool IsDistanceLessOrEqualThan(float dist1, float dist2);
/**
* @brief Set bot facing towards a world object.
*
* @param bot Player bot to rotate.
* @param wo Target world object.
* @param force If true, force facing even while moving.
*/
void SetFacingTo(Player* bot, WorldObject* wo, bool force = false);
/**
* @brief Get the current chase target of a unit.
*
* @param target Unit that is chasing.
* @return Unit* The chase target, or nullptr if not chasing.
*/
Unit* GetChaseTarget(Unit* target);
/**
* @brief Send a raw packet to a player.
*
* @param player Player to receive the packet.
* @param packet Packet to send.
*/
void SendPacket(Player* player, WorldPacket* packet);
};
/** Global singleton accessor. */
#define sServerFacade ServerFacade::instance()
#endif

View File

@@ -16,7 +16,7 @@
#include "BattleGroundTactics.h"
#include "Chat.h"
#include "GuildTaskMgr.h"
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "PlayerbotMgr.h"
#include "RandomPlayerbotMgr.h"
#include "ScriptMgr.h"
@@ -76,19 +76,19 @@ public:
{
if (!strcmp(args, "reset"))
{
sPerfMonitor->Reset();
sPerformanceMonitor->Reset();
return true;
}
if (!strcmp(args, "tick"))
{
sPerfMonitor->PrintStats(true, false);
sPerformanceMonitor->PrintStats(true, false);
return true;
}
if (!strcmp(args, "stack"))
{
sPerfMonitor->PrintStats(false, true);
sPerformanceMonitor->PrintStats(false, true);
return true;
}
@@ -102,7 +102,7 @@ public:
return true;
}
sPerfMonitor->PrintStats();
sPerformanceMonitor->PrintStats();
return true;
}
@@ -209,4 +209,4 @@ public:
}
};
void AddPlayerbotsCommandscripts() { new playerbots_commandscript(); }
void AddSC_playerbots_commandscript() { new playerbots_commandscript(); }

1
src/cs_playerbots.h Normal file
View File

@@ -0,0 +1 @@
void AddSC_playerbots_commandscript();

View File

@@ -1,10 +1,9 @@
#include "PlayerbotSpellRepository.h"
#include "PlayerbotSpellCache.h"
// caches the result set
void PlayerbotSpellRepository::Initialize()
void PlayerbotSpellCache::Initialize()
{
LOG_INFO("playerbots", "Playerbots: ListSpellsAction caches initialized");
LOG_INFO("playerbots",
"Playerbots: ListSpellsAction caches initialized");
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
{
if (SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j))
@@ -32,7 +31,7 @@ void PlayerbotSpellRepository::Initialize()
skillSpells.size(), vendorItems.size());
}
SkillLineAbilityEntry const* PlayerbotSpellRepository::GetSkillLine(uint32 spellId) const
SkillLineAbilityEntry const* PlayerbotSpellCache::GetSkillLine(uint32 spellId) const
{
auto itr = skillSpells.find(spellId);
if (itr != skillSpells.end())
@@ -40,7 +39,7 @@ SkillLineAbilityEntry const* PlayerbotSpellRepository::GetSkillLine(uint32 spell
return nullptr;
}
bool PlayerbotSpellRepository::IsItemBuyable(uint32 itemId) const
bool PlayerbotSpellCache::IsItemBuyable(uint32 itemId) const
{
return vendorItems.find(itemId) != vendorItems.end();
}

View File

@@ -3,17 +3,17 @@
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_PLAYERBOTSPELLREPOSITORY_H
#define _PLAYERBOT_PLAYERBOTSPELLREPOSITORY_H
#ifndef _PLAYERBOT_PLAYERBOTSPELLCACHE_H
#define _PLAYERBOT_PLAYERBOTSPELLCACHE_H
#include "Playerbots.h"
class PlayerbotSpellRepository
class PlayerbotSpellCache
{
public:
static PlayerbotSpellRepository* Instance()
static PlayerbotSpellCache* Instance()
{
static PlayerbotSpellRepository instance;
static PlayerbotSpellCache instance;
return &instance;
}
@@ -23,12 +23,12 @@ public:
bool IsItemBuyable(uint32 itemId) const;
private:
PlayerbotSpellRepository() = default;
PlayerbotSpellCache() = default;
std::map<uint32, SkillLineAbilityEntry const*> skillSpells;
std::set<uint32> vendorItems;
};
#define sPlayerbotSpellRepository PlayerbotSpellRepository::Instance()
#define sPlayerbotSpellCache PlayerbotSpellCache::Instance()
#endif

View File

@@ -24,12 +24,12 @@
#include "LootMgr.h"
#include "MapMgr.h"
#include "ObjectMgr.h"
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "PetDefines.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include "PlayerbotAIConfig.h"
#include "PlayerbotRepository.h"
#include "PlayerbotDbStore.h"
#include "PlayerbotGuildMgr.h"
#include "Playerbots.h"
#include "QuestDef.h"
@@ -240,7 +240,7 @@ void PlayerbotFactory::Randomize(bool incremental)
// LOG_DEBUG("playerbots", "Preparing to {} randomize...", (incremental ? "incremental" : "full"));
Prepare();
LOG_DEBUG("playerbots", "Resetting player...");
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reset");
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reset");
if (!sPlayerbotAIConfig->equipmentPersistence || level < sPlayerbotAIConfig->equipmentPersistenceLevel)
{
bot->resetTalents(true);
@@ -266,7 +266,7 @@ void PlayerbotFactory::Randomize(bool incremental)
if (pmo)
pmo->finish();
// pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Immersive");
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Immersive");
// LOG_INFO("playerbots", "Initializing immersive...");
// InitImmersive();
// if (pmo)
@@ -274,7 +274,7 @@ void PlayerbotFactory::Randomize(bool incremental)
if (sPlayerbotAIConfig->randomBotPreQuests)
{
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
InitInstanceQuests();
InitAttunementQuests();
if (pmo)
@@ -282,27 +282,27 @@ void PlayerbotFactory::Randomize(bool incremental)
}
else
{
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Quests");
InitAttunementQuests();
if (pmo)
pmo->finish();
}
LOG_DEBUG("playerbots", "Initializing skills (step 1)...");
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1");
bot->LearnDefaultSkills();
InitSkills();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells1");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells1");
LOG_DEBUG("playerbots", "Initializing spells (step 1)...");
bot->LearnDefaultSkills();
InitClassSpells();
InitAvailableSpells();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents");
LOG_DEBUG("playerbots", "Initializing skills (step 1)...");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills1");
InitSkills();
if (pmo)
pmo->finish();
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Talents");
LOG_DEBUG("playerbots", "Initializing talents...");
if (!incremental || !sPlayerbotAIConfig->equipmentPersistence ||
bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
@@ -312,45 +312,45 @@ void PlayerbotFactory::Randomize(bool incremental)
sRandomPlayerbotMgr->SetValue(bot->GetGUID().GetCounter(), "specNo", 0);
if (botAI)
{
sPlayerbotRepository->Reset(botAI);
sPlayerbotDbStore->Reset(botAI);
// botAI->DoSpecificAction("auto talents");
botAI->ResetStrategies(false); // fix wrong stored strategy
}
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells2");
LOG_DEBUG("playerbots", "Initializing spells (step 2)...");
InitAvailableSpells();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reputation");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reputation");
LOG_DEBUG("playerbots", "Initializing reputation...");
InitReputation();
if (pmo)
pmo->finish();
LOG_DEBUG("playerbots", "Initializing special spells...");
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells3");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Spells3");
InitSpecialSpells();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Mounts");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Mounts");
LOG_DEBUG("playerbots", "Initializing mounts...");
InitMounts();
// bot->SaveToDB(false, false);
if (pmo)
pmo->finish();
// pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills2");
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Skills2");
// LOG_INFO("playerbots", "Initializing skills (step 2)...");
// UpdateTradeSkills();
// if (pmo)
// pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Equip");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Equip");
LOG_DEBUG("playerbots", "Initializing equipmemt...");
if (!incremental || !sPlayerbotAIConfig->equipmentPersistence ||
bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel)
@@ -364,51 +364,51 @@ void PlayerbotFactory::Randomize(bool incremental)
// if (bot->GetLevel() >= sPlayerbotAIConfig->minEnchantingBotLevel)
// {
// pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Enchant");
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Enchant");
// LOG_INFO("playerbots", "Initializing enchant templates...");
// LoadEnchantContainer();
// if (pmo)
// pmo->finish();
// }
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Bags");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Bags");
LOG_DEBUG("playerbots", "Initializing bags...");
InitBags();
// bot->SaveToDB(false, false);
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Ammo");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Ammo");
LOG_DEBUG("playerbots", "Initializing ammo...");
InitAmmo();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Food");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Food");
LOG_DEBUG("playerbots", "Initializing food...");
InitFood();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Potions");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Potions");
LOG_DEBUG("playerbots", "Initializing potions...");
InitPotions();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reagents");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Reagents");
LOG_DEBUG("playerbots", "Initializing reagents...");
InitReagents();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Keys");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Keys");
LOG_DEBUG("playerbots", "Initializing keys...");
InitKeyring();
if (pmo)
pmo->finish();
// pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EqSets");
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EqSets");
// LOG_DEBUG("playerbots", "Initializing second equipment set...");
// InitSecondEquipmentSet();
// if (pmo)
@@ -419,20 +419,20 @@ void PlayerbotFactory::Randomize(bool incremental)
ApplyEnchantAndGemsNew();
}
// {
// pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EnchantTemplate");
// pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_EnchantTemplate");
// LOG_INFO("playerbots", "Initializing enchant templates...");
// ApplyEnchantTemplate();
// if (pmo)
// pmo->finish();
// }
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Inventory");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Inventory");
LOG_DEBUG("playerbots", "Initializing inventory...");
// InitInventory();
if (pmo)
pmo->finish();
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Consumable");
LOG_DEBUG("playerbots", "Initializing consumables...");
InitConsumables();
if (pmo)
@@ -442,7 +442,7 @@ void PlayerbotFactory::Randomize(bool incremental)
InitGlyphs();
// bot->SaveToDB(false, false);
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Guilds");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Guilds");
// bot->SaveToDB(false, false);
if (sPlayerbotAIConfig->randomBotGuildCount > 0)
{
@@ -455,7 +455,7 @@ void PlayerbotFactory::Randomize(bool incremental)
if (bot->GetLevel() >= 70)
{
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Arenas");
// LOG_INFO("playerbots", "Initializing arena teams...");
InitArenaTeam();
if (pmo)
@@ -470,7 +470,7 @@ void PlayerbotFactory::Randomize(bool incremental)
}
if (bot->GetLevel() >= 10)
{
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Pet");
LOG_DEBUG("playerbots", "Initializing pet...");
InitPet();
// bot->SaveToDB(false, false);
@@ -479,7 +479,7 @@ void PlayerbotFactory::Randomize(bool incremental)
pmo->finish();
}
pmo = sPerfMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save");
pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save");
LOG_DEBUG("playerbots", "Saving to DB...");
bot->SetMoney(urand(level * 100000, level * 5 * 100000));
bot->SetHealth(bot->GetMaxHealth());
@@ -506,9 +506,9 @@ void PlayerbotFactory::Refresh()
InitPotions();
InitPet();
InitPetTalents();
InitSkills();
InitClassSpells();
InitAvailableSpells();
InitSkills();
InitReputation();
InitSpecialSpells();
InitMounts();
@@ -2550,19 +2550,13 @@ void PlayerbotFactory::InitAvailableSpells()
for (auto& spell : trainer->GetSpells())
{
// simplified version of Trainer::TeachSpell method
Trainer::Spell const* trainerSpell = trainer->GetSpell(spell.SpellId);
if (!trainerSpell)
if (!trainer->CanTeachSpell(bot, trainer->GetSpell(spell.SpellId)))
continue;
if (!trainer->CanTeachSpell(bot, trainerSpell))
continue;
if (trainerSpell->IsCastable())
bot->CastSpell(bot, trainerSpell->SpellId, true);
if (spell.IsCastable())
bot->CastSpell(bot, spell.SpellId, true);
else
bot->learnSpell(trainerSpell->SpellId, false);
bot->learnSpell(spell.SpellId, false);
}
}
}

View File

@@ -27,32 +27,32 @@
#include "WarriorAiObjectContext.h"
#include "WorldPacketActionContext.h"
#include "WorldPacketTriggerContext.h"
#include "Ai/Dungeon/DungeonStrategyContext.h"
#include "Ai/Dungeon/WotlkDungeonActionContext.h"
#include "Ai/Dungeon/WotlkDungeonTriggerContext.h"
#include "Ai/Raid/RaidStrategyContext.h"
#include "Ai/Raid/Aq20/RaidAq20ActionContext.h"
#include "Ai/Raid/Aq20/RaidAq20TriggerContext.h"
#include "Ai/Raid/MoltenCore/RaidMcActionContext.h"
#include "Ai/Raid/MoltenCore/RaidMcTriggerContext.h"
#include "Ai/Raid/BlackwingLair/RaidBwlActionContext.h"
#include "Ai/Raid/BlackwingLair/RaidBwlTriggerContext.h"
#include "Ai/Raid/Karazhan/RaidKarazhanActionContext.h"
#include "Ai/Raid/Karazhan/RaidKarazhanTriggerContext.h"
#include "Ai/Raid/Magtheridon/RaidMagtheridonActionContext.h"
#include "Ai/Raid/Magtheridon/RaidMagtheridonTriggerContext.h"
#include "Ai/Raid/GruulsLair/RaidGruulsLairActionContext.h"
#include "Ai/Raid/GruulsLair/RaidGruulsLairTriggerContext.h"
#include "Ai/Raid/EyeOfEternity/RaidEoEActionContext.h"
#include "Ai/Raid/EyeOfEternity/RaidEoETriggerContext.h"
#include "Ai/Raid/VaultOfArchavon/RaidVoAActionContext.h"
#include "Ai/Raid/VaultOfArchavon/RaidVoATriggerContext.h"
#include "Ai/Raid/ObsidianSanctum/RaidOsActionContext.h"
#include "Ai/Raid/ObsidianSanctum/RaidOsTriggerContext.h"
#include "Ai/Raid/Onyxia/RaidOnyxiaActionContext.h"
#include "Ai/Raid/Onyxia/RaidOnyxiaTriggerContext.h"
#include "Ai/Raid/Icecrown/RaidIccActionContext.h"
#include "Ai/Raid/Icecrown/RaidIccTriggerContext.h"
#include "dungeons/DungeonStrategyContext.h"
#include "dungeons/wotlk/WotlkDungeonActionContext.h"
#include "dungeons/wotlk/WotlkDungeonTriggerContext.h"
#include "raids/RaidStrategyContext.h"
#include "raids/aq20/RaidAq20ActionContext.h"
#include "raids/aq20/RaidAq20TriggerContext.h"
#include "raids/moltencore/RaidMcActionContext.h"
#include "raids/moltencore/RaidMcTriggerContext.h"
#include "raids/blackwinglair/RaidBwlActionContext.h"
#include "raids/blackwinglair/RaidBwlTriggerContext.h"
#include "raids/karazhan/RaidKarazhanActionContext.h"
#include "raids/karazhan/RaidKarazhanTriggerContext.h"
#include "raids/magtheridon/RaidMagtheridonActionContext.h"
#include "raids/magtheridon/RaidMagtheridonTriggerContext.h"
#include "raids/gruulslair/RaidGruulsLairActionContext.h"
#include "raids/gruulslair/RaidGruulsLairTriggerContext.h"
#include "raids/eyeofeternity/RaidEoEActionContext.h"
#include "raids/eyeofeternity/RaidEoETriggerContext.h"
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
#include "raids/obsidiansanctum/RaidOsActionContext.h"
#include "raids/obsidiansanctum/RaidOsTriggerContext.h"
#include "raids/onyxia/RaidOnyxiaActionContext.h"
#include "raids/onyxia/RaidOnyxiaTriggerContext.h"
#include "raids/icecrown/RaidIccActionContext.h"
#include "raids/icecrown/RaidIccTriggerContext.h"
SharedNamedObjectContextList<Strategy> AiObjectContext::sharedStrategyContexts;
SharedNamedObjectContextList<Action> AiObjectContext::sharedActionContexts;

View File

@@ -7,7 +7,7 @@
#include "Action.h"
#include "Event.h"
#include "PerfMonitor.h"
#include "PerformanceMonitor.h"
#include "Playerbots.h"
#include "Queue.h"
#include "Strategy.h"
@@ -204,7 +204,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
}
}
PerfMonitorOperation* pmo = sPerfMonitor->start(PERF_MON_ACTION, action->getName(), &aiObjectContext->performanceStack);
PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_ACTION, action->getName(), &aiObjectContext->performanceStack);
actionExecuted = ListenAndExecute(action, event);
if (pmo)
pmo->finish();
@@ -456,8 +456,8 @@ void Engine::ProcessTriggers(bool minimal)
if (minimal && node->getFirstRelevance() < 100)
continue;
PerfMonitorOperation* pmo =
sPerfMonitor->start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack);
PerformanceMonitorOperation* pmo =
sPerformanceMonitor->start(PERF_MON_TRIGGER, trigger->getName(), &aiObjectContext->performanceStack);
Event event = trigger->Check();
if (pmo)
pmo->finish();

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