mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
1st commit
This commit is contained in:
@@ -20,3 +20,7 @@
|
||||
DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
|
||||
DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
|
||||
DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
DatabaseWorkerPool<PlayerbotDatabaseConnection> PlayerbotDatabase;
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#include "Implementation/LoginDatabase.h"
|
||||
#include "Implementation/WorldDatabase.h"
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "PlayerbotDatabase.h"
|
||||
#endif
|
||||
|
||||
#include "Field.h"
|
||||
#include "PreparedStatement.h"
|
||||
#include "QueryCallback.h"
|
||||
@@ -38,4 +42,9 @@ AC_DATABASE_API extern DatabaseWorkerPool<CharacterDatabaseConnection> Character
|
||||
/// Accessor to the realm/login database
|
||||
AC_DATABASE_API extern DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
/// Accessor to the playerbot database
|
||||
AC_DATABASE_API extern DatabaseWorkerPool<PlayerbotDatabaseConnection> PlayerbotDatabase;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,10 @@ class CharacterDatabaseConnection;
|
||||
class LoginDatabaseConnection;
|
||||
class WorldDatabaseConnection;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
class PlayerbotDatabaseConnection;
|
||||
#endif
|
||||
|
||||
class PreparedStatementBase;
|
||||
|
||||
template<typename T>
|
||||
@@ -42,6 +46,10 @@ using CharacterDatabasePreparedStatement = PreparedStatement<CharacterDatabaseCo
|
||||
using LoginDatabasePreparedStatement = PreparedStatement<LoginDatabaseConnection>;
|
||||
using WorldDatabasePreparedStatement = PreparedStatement<WorldDatabaseConnection>;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
using PlayerbotDatabasePreparedStatement = PreparedStatement<PlayerbotDatabaseConnection>;
|
||||
#endif
|
||||
|
||||
class PreparedResultSet;
|
||||
using PreparedQueryResult = std::shared_ptr<PreparedResultSet>;
|
||||
using PreparedQueryResultFuture = std::future<PreparedQueryResult>;
|
||||
@@ -71,6 +79,10 @@ using CharacterDatabaseTransaction = SQLTransaction<CharacterDatabaseConnection>
|
||||
using LoginDatabaseTransaction = SQLTransaction<LoginDatabaseConnection>;
|
||||
using WorldDatabaseTransaction = SQLTransaction<WorldDatabaseConnection>;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
using PlayerbotDatabaseTransaction = SQLTransaction<PlayerbotDatabaseConnection>;
|
||||
#endif
|
||||
|
||||
class SQLQueryHolderBase;
|
||||
using QueryResultHolderFuture = std::future<void>;
|
||||
using QueryResultHolderPromise = std::promise<void>;
|
||||
@@ -82,6 +94,10 @@ using CharacterDatabaseQueryHolder = SQLQueryHolder<CharacterDatabaseConnection>
|
||||
using LoginDatabaseQueryHolder = SQLQueryHolder<LoginDatabaseConnection>;
|
||||
using WorldDatabaseQueryHolder = SQLQueryHolder<WorldDatabaseConnection>;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
using PlayerbotDatabaseQueryHolder = SQLQueryHolder<PlayerbotDatabaseConnection>;
|
||||
#endif
|
||||
|
||||
class SQLQueryHolderCallback;
|
||||
|
||||
// mysql
|
||||
|
||||
@@ -204,3 +204,8 @@ template AC_DATABASE_API
|
||||
DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
|
||||
template AC_DATABASE_API
|
||||
DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
template AC_DATABASE_API
|
||||
DatabaseLoader& DatabaseLoader::AddDatabase<PlayerbotDatabaseConnection>(DatabaseWorkerPool<PlayerbotDatabaseConnection>&, std::string const&);
|
||||
#endif
|
||||
|
||||
@@ -48,8 +48,13 @@ public:
|
||||
DATABASE_LOGIN = 1,
|
||||
DATABASE_CHARACTER = 2,
|
||||
DATABASE_WORLD = 4,
|
||||
#ifdef PLAYERBOTS
|
||||
DATABASE_PLAYERBOT = 8,
|
||||
|
||||
DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD | DATABASE_PLAYERBOT
|
||||
#else
|
||||
DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD
|
||||
#endif
|
||||
};
|
||||
|
||||
[[nodiscard]] uint32 GetUpdateFlags() const
|
||||
@@ -57,6 +62,11 @@ public:
|
||||
return _updateFlags;
|
||||
}
|
||||
|
||||
void SetUpdateFlags(uint32 newUpdateFlags)
|
||||
{
|
||||
_updateFlags |= newUpdateFlags;
|
||||
}
|
||||
|
||||
private:
|
||||
bool OpenDatabases();
|
||||
bool PopulateDatabases();
|
||||
@@ -73,7 +83,7 @@ private:
|
||||
std::string const _logger;
|
||||
std::string_view _modulesList;
|
||||
bool const _autoSetup;
|
||||
uint32 const _updateFlags;
|
||||
uint32 _updateFlags;
|
||||
|
||||
std::queue<Predicate> _open, _populate, _update, _prepare;
|
||||
std::stack<Closer> _close;
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "PlayerbotDatabase.h"
|
||||
#endif
|
||||
|
||||
#if MARIADB_VERSION_ID >= 100600
|
||||
#define MIN_MYSQL_SERVER_VERSION 100200u
|
||||
#define MIN_MYSQL_CLIENT_VERSION 30203u
|
||||
@@ -530,3 +534,7 @@ void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction<T>& trans, PreparedSt
|
||||
template class AC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>;
|
||||
template class AC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>;
|
||||
template class AC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
template class AC_DATABASE_API DatabaseWorkerPool<PlayerbotDatabaseConnection>;
|
||||
#endif
|
||||
|
||||
@@ -89,7 +89,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_LAST_ATTEMPT_IP, "UPDATE account SET last_attempt_ip = ? WHERE username = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = 1 WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS, "DELETE FROM account_access WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -160,6 +160,40 @@ std::string DBUpdater<CharacterDatabaseConnection>::GetDBModuleName()
|
||||
return "db-characters";
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
// Playerbot Database
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotDatabaseConnection>::GetConfigEntry()
|
||||
{
|
||||
return "Updates.Playerbot";
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotDatabaseConnection>::GetTableName()
|
||||
{
|
||||
return "Playerbot";
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotDatabaseConnection>::GetBaseFilesDirectory()
|
||||
{
|
||||
return BuiltInConfig::GetSourceDirectory() + "/modules/mod-playerbots/sql/base/db_playerbot/";
|
||||
}
|
||||
|
||||
template<>
|
||||
bool DBUpdater<PlayerbotDatabaseConnection>::IsEnabled(uint32 const updateMask)
|
||||
{
|
||||
// This way silences warnings under msvc
|
||||
return (updateMask & DatabaseLoader::DATABASE_PLAYERBOT) ? true : false;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string DBUpdater<PlayerbotDatabaseConnection>::GetDBModuleName()
|
||||
{
|
||||
return "db-playerbot";
|
||||
}
|
||||
#endif
|
||||
|
||||
// All
|
||||
template<class T>
|
||||
BaseLocation DBUpdater<T>::GetBaseLocationType()
|
||||
@@ -514,3 +548,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
|
||||
template class AC_DATABASE_API DBUpdater<LoginDatabaseConnection>;
|
||||
template class AC_DATABASE_API DBUpdater<WorldDatabaseConnection>;
|
||||
template class AC_DATABASE_API DBUpdater<CharacterDatabaseConnection>;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
template class AC_DATABASE_API DBUpdater<PlayerbotDatabaseConnection>;
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,8 @@ typedef std::map<uint32, uint32> AreaFlagByMapID;
|
||||
typedef std::tuple<int16, int8, int32> WMOAreaTableKey;
|
||||
typedef std::map<WMOAreaTableKey, WMOAreaTableEntry const*> WMOAreaInfoByTripple;
|
||||
|
||||
typedef std::multimap<uint32, CharSectionsEntry const*> CharSectionsMap;
|
||||
|
||||
DBCStorage <AreaTableEntry> sAreaTableStore(AreaTableEntryfmt);
|
||||
DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt);
|
||||
DBCStorage <AreaPOIEntry> sAreaPOIStore(AreaPOIEntryfmt);
|
||||
@@ -51,6 +53,10 @@ DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryf
|
||||
DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt);
|
||||
DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt);
|
||||
std::map<uint32, CharStartOutfitEntry const*> sCharStartOutfitMap;
|
||||
|
||||
DBCStorage <CharSectionsEntry> sCharSectionsStore(CharSectionsEntryfmt);
|
||||
CharSectionsMap sCharSectionMap;
|
||||
|
||||
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
|
||||
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
|
||||
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
|
||||
@@ -72,6 +78,10 @@ DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
|
||||
DBCStorage <EmotesEntry> sEmotesStore(EmotesEntryfmt);
|
||||
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmotesTextEntryfmt);
|
||||
|
||||
typedef std::tuple<uint32, uint32, uint32> EmotesTextSoundKey;
|
||||
static std::map<EmotesTextSoundKey, EmotesTextSoundEntry const*> sEmotesTextSoundMap;
|
||||
DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore(EmotesTextSoundEntryfmt);
|
||||
|
||||
typedef std::map<uint32, SimpleFactionsList> FactionTeamMap;
|
||||
static FactionTeamMap sFactionTeamMap;
|
||||
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
|
||||
@@ -275,6 +285,7 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
LOAD_DBC(sBattlemasterListStore, "BattlemasterList.dbc", "battlemasterlist_dbc");
|
||||
LOAD_DBC(sBarberShopStyleStore, "BarberShopStyle.dbc", "barbershopstyle_dbc");
|
||||
LOAD_DBC(sCharStartOutfitStore, "CharStartOutfit.dbc", "charstartoutfit_dbc");
|
||||
LOAD_DBC(sCharSectionsStore, "CharSections.dbc", "charsections_dbc");
|
||||
LOAD_DBC(sCharTitlesStore, "CharTitles.dbc", "chartitles_dbc");
|
||||
LOAD_DBC(sChatChannelsStore, "ChatChannels.dbc", "chatchannels_dbc");
|
||||
LOAD_DBC(sChrClassesStore, "ChrClasses.dbc", "chrclasses_dbc");
|
||||
@@ -293,6 +304,7 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
LOAD_DBC(sDurabilityQualityStore, "DurabilityQuality.dbc", "durabilityquality_dbc");
|
||||
LOAD_DBC(sEmotesStore, "Emotes.dbc", "emotes_dbc");
|
||||
LOAD_DBC(sEmotesTextStore, "EmotesText.dbc", "emotestext_dbc");
|
||||
LOAD_DBC(sEmotesTextSoundStore, "EmotesTextSound.dbc", "emotetextsound_dbc");
|
||||
LOAD_DBC(sFactionStore, "Faction.dbc", "faction_dbc");
|
||||
LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc", "factiontemplate_dbc");
|
||||
LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc", "gameobjectdisplayinfo_dbc");
|
||||
@@ -377,6 +389,10 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
for (CharStartOutfitEntry const* outfit : sCharStartOutfitStore)
|
||||
sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit;
|
||||
|
||||
for (CharSectionsEntry const* charSection : sCharSectionsStore)
|
||||
if (charSection->Race && ((1 << (charSection->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) //ignore Nonplayable races
|
||||
sCharSectionMap.insert({ charSection->GenType | (charSection->Gender << 8) | (charSection->Race << 16), charSection });
|
||||
|
||||
for (FactionEntry const* faction : sFactionStore)
|
||||
{
|
||||
if (faction->team)
|
||||
@@ -398,6 +414,9 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
std::swap(*(float*)(&info->maxZ), *(float*)(&info->minZ));
|
||||
}
|
||||
|
||||
for (EmotesTextSoundEntry const* emoteTextSound : sEmotesTextSoundStore)
|
||||
sEmotesTextSoundMap[EmotesTextSoundKey(emoteTextSound->EmotesTextId, emoteTextSound->RaceId, emoteTextSound->SexId)] = emoteTextSound;
|
||||
|
||||
// fill data
|
||||
for (MapDifficultyEntry const* entry : sMapDifficultyStore)
|
||||
sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0');
|
||||
@@ -1089,6 +1108,18 @@ CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, ui
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color)
|
||||
{
|
||||
std::pair<CharSectionsMap::const_iterator, CharSectionsMap::const_iterator> eqr = sCharSectionMap.equal_range(uint32(genType) | uint32(gender << 8) | uint32(race << 16));
|
||||
for (CharSectionsMap::const_iterator itr = eqr.first; itr != eqr.second; ++itr)
|
||||
{
|
||||
if (itr->second->Type == type && itr->second->Color == color)
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery)
|
||||
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty)
|
||||
{
|
||||
@@ -1134,3 +1165,9 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender)
|
||||
{
|
||||
auto itr = sEmotesTextSoundMap.find(EmotesTextSoundKey(emote, race, gender));
|
||||
return itr != sEmotesTextSoundMap.end() ? itr->second : nullptr;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB
|
||||
|
||||
CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
|
||||
|
||||
CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color);
|
||||
|
||||
LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
|
||||
uint32 GetDefaultMapLight(uint32 mapId);
|
||||
|
||||
@@ -70,6 +72,8 @@ typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRac
|
||||
typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds;
|
||||
SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
|
||||
|
||||
EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender);
|
||||
|
||||
extern DBCStorage <AchievementEntry> sAchievementStore;
|
||||
extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
|
||||
extern DBCStorage <AchievementCategoryEntry> sAchievementCategoryStore;
|
||||
@@ -82,6 +86,7 @@ extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore;
|
||||
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
|
||||
extern DBCStorage <ChatChannelsEntry> sChatChannelsStore;
|
||||
extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
|
||||
extern DBCStorage <CharSectionsEntry> sCharSectionsStore;
|
||||
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
|
||||
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
|
||||
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
|
||||
@@ -99,6 +104,7 @@ extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
|
||||
extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
|
||||
extern DBCStorage <EmotesEntry> sEmotesStore;
|
||||
extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
|
||||
extern DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore;
|
||||
extern DBCStorage <FactionEntry> sFactionStore;
|
||||
extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
|
||||
extern DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
|
||||
|
||||
@@ -401,6 +401,22 @@ namespace lfg
|
||||
return LFG_COMPATIBLES_WITH_LESS_PLAYERS;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
bool nonBotFound = false;
|
||||
for (uint8 i = 0; i < 5 && check.guids[i]; ++i)
|
||||
{
|
||||
ObjectGuid guid = check.guids[i];
|
||||
Player* player = ObjectAccessor::FindPlayer(guid);
|
||||
if (guid.IsGroup() || (player && !player->GetPlayerbotAI()))
|
||||
{
|
||||
nonBotFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nonBotFound)
|
||||
return LFG_INCOMPATIBLES_HAS_IGNORES;
|
||||
#endif
|
||||
|
||||
proposal.queues = strGuids;
|
||||
proposal.isNew = numLfgGroups != 1 || sLFGMgr->GetOldState(proposal.group) != LFG_STATE_DUNGEON;
|
||||
|
||||
|
||||
@@ -1038,6 +1038,11 @@ void Item::SendUpdateSockets()
|
||||
// time.
|
||||
void Item::SendTimeUpdate(Player* owner)
|
||||
{
|
||||
#ifdef PLAYERBOTS
|
||||
if (!owner || !owner->IsInWorld() || owner->GetPlayerbotAI())
|
||||
return;
|
||||
#endif
|
||||
|
||||
uint32 duration = GetUInt32Value(ITEM_FIELD_DURATION);
|
||||
if (!duration)
|
||||
return;
|
||||
|
||||
@@ -260,7 +260,7 @@ enum SocketColor
|
||||
|
||||
#define SOCKET_COLOR_ALL (SOCKET_COLOR_META | SOCKET_COLOR_RED | SOCKET_COLOR_YELLOW | SOCKET_COLOR_BLUE)
|
||||
|
||||
enum InventoryType
|
||||
enum InventoryType : uint32
|
||||
{
|
||||
INVTYPE_NON_EQUIP = 0,
|
||||
INVTYPE_HEAD = 1,
|
||||
|
||||
@@ -92,6 +92,10 @@
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "Playerbot.h"
|
||||
#endif
|
||||
|
||||
enum CharacterFlags
|
||||
{
|
||||
CHARACTER_FLAG_NONE = 0x00000000,
|
||||
@@ -410,6 +414,11 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this)
|
||||
|
||||
m_isInstantFlightOn = true;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
_playerbotAI = nullptr;
|
||||
_playerbotMgr = nullptr;
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnConstructPlayer(this);
|
||||
}
|
||||
|
||||
@@ -461,6 +470,14 @@ Player::~Player()
|
||||
u->RemovePlayerFromVision(this);
|
||||
} while (!m_isInSharedVisionOf.empty());
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
delete _playerbotAI;
|
||||
_playerbotAI = nullptr;
|
||||
|
||||
delete _playerbotMgr;
|
||||
_playerbotMgr = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Player::CleanupsBeforeDelete(bool finalCleanup)
|
||||
@@ -15435,3 +15452,34 @@ std::string Player::GetPlayerName()
|
||||
|
||||
return "|Hplayer:" + name + "|h" + color + name + "|h|r";
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
void Player::SetPlayerbotAI(PlayerbotAI* ai)
|
||||
{
|
||||
ASSERT(!_playerbotAI && !_playerbotMgr);
|
||||
|
||||
_playerbotAI = ai;
|
||||
}
|
||||
|
||||
PlayerbotAI* Player::GetPlayerbotAI()
|
||||
{
|
||||
return _playerbotAI;
|
||||
}
|
||||
|
||||
void Player::SetPlayerbotMgr(PlayerbotMgr* mgr)
|
||||
{
|
||||
ASSERT(!_playerbotAI && !_playerbotMgr);
|
||||
|
||||
_playerbotMgr = mgr;
|
||||
}
|
||||
|
||||
PlayerbotMgr* Player::GetPlayerbotMgr()
|
||||
{
|
||||
return _playerbotMgr;
|
||||
}
|
||||
|
||||
void Player::SetBotDeathTimer()
|
||||
{
|
||||
m_deathTimer = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -60,6 +60,9 @@ class PlayerSocial;
|
||||
class SpellCastTargets;
|
||||
class UpdateMask;
|
||||
|
||||
class PlayerbotAI;
|
||||
class PlayerbotMgr;
|
||||
|
||||
typedef std::deque<Mail*> PlayerMails;
|
||||
typedef void(*bgZoneRef)(Battleground*, WorldPacket&);
|
||||
|
||||
@@ -660,7 +663,7 @@ enum PlayerSlots
|
||||
|
||||
#define INVENTORY_SLOT_BAG_0 255
|
||||
|
||||
enum EquipmentSlots // 19 slots
|
||||
enum EquipmentSlots : uint32 // 19 slots
|
||||
{
|
||||
EQUIPMENT_SLOT_START = 0,
|
||||
EQUIPMENT_SLOT_HEAD = 0,
|
||||
@@ -1247,7 +1250,7 @@ public:
|
||||
InventoryResult CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item* pItem, bool swap, bool not_loading = true) const;
|
||||
InventoryResult CanUseItem(Item* pItem, bool not_loading = true) const;
|
||||
[[nodiscard]] bool HasItemTotemCategory(uint32 TotemCategory) const;
|
||||
bool IsTotemCategoryCompatiableWith(const ItemTemplate* pProto, uint32 requiredTotemCategoryId) const;
|
||||
bool IsTotemCategoryCompatiableWith(ItemTemplate const* pProto, uint32 requiredTotemCategoryId) const;
|
||||
InventoryResult CanUseItem(ItemTemplate const* pItem) const;
|
||||
[[nodiscard]] InventoryResult CanUseAmmo(uint32 item) const;
|
||||
InventoryResult CanRollForItemInLFG(ItemTemplate const* item, WorldObject const* lootedObject) const;
|
||||
@@ -1274,7 +1277,7 @@ public:
|
||||
void SetAmmo(uint32 item);
|
||||
void RemoveAmmo();
|
||||
[[nodiscard]] float GetAmmoDPS() const { return m_ammoDPS; }
|
||||
bool CheckAmmoCompatibility(const ItemTemplate* ammo_proto) const;
|
||||
bool CheckAmmoCompatibility(ItemTemplate const* ammo_proto) const;
|
||||
void QuickEquipItem(uint16 pos, Item* pItem);
|
||||
void VisualizeItem(uint8 slot, Item* pItem);
|
||||
void SetVisibleItemSlot(uint8 slot, Item* pItem);
|
||||
@@ -2589,15 +2592,16 @@ public:
|
||||
std::string GetMapAreaAndZoneString();
|
||||
std::string GetCoordsMapAreaAndZoneString();
|
||||
|
||||
void SetFarSightDistance(float radius);
|
||||
void ResetFarSightDistance();
|
||||
Optional<float> GetFarSightDistance() const;
|
||||
// Playerbot mod
|
||||
// A Player can either have a playerbotMgr (to manage its bots), or have playerbotAI (if it is a bot), or
|
||||
// neither. Code that enables bots must create the playerbotMgr and set it using SetPlayerbotMgr.
|
||||
void SetPlayerbotAI(PlayerbotAI* ai);
|
||||
PlayerbotAI* GetPlayerbotAI();
|
||||
void SetPlayerbotMgr(PlayerbotMgr* mgr);
|
||||
PlayerbotMgr* GetPlayerbotMgr();
|
||||
void SetBotDeathTimer();
|
||||
|
||||
float GetSightRange(const WorldObject* target = nullptr) const override;
|
||||
|
||||
std::string GetPlayerName();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
// Gamemaster whisper whitelist
|
||||
WhisperListContainer WhisperList;
|
||||
|
||||
@@ -2952,6 +2956,10 @@ private:
|
||||
WorldLocation _corpseLocation;
|
||||
|
||||
Optional<float> _farSightDistance = { };
|
||||
|
||||
// Playerbot mod
|
||||
PlayerbotAI* _playerbotAI;
|
||||
PlayerbotMgr* _playerbotMgr;
|
||||
};
|
||||
|
||||
void AddItemsSetItem(Player* player, Item* item);
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include "Vehicle.h"
|
||||
#include "WeatherMgr.h"
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "Playerbot.h"
|
||||
#endif
|
||||
|
||||
// Zone Interval should be 1 second
|
||||
constexpr auto ZONE_UPDATE_INTERVAL = 1000;
|
||||
|
||||
@@ -434,6 +438,18 @@ void Player::Update(uint32 p_time)
|
||||
m_delayed_unit_relocation_timer = 0;
|
||||
RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (_playerbotAI)
|
||||
{
|
||||
_playerbotAI->UpdateAI(p_time);
|
||||
}
|
||||
|
||||
if (_playerbotMgr)
|
||||
{
|
||||
_playerbotMgr->UpdateAI(p_time);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Player::UpdateMirrorTimers()
|
||||
|
||||
@@ -250,10 +250,12 @@ public:
|
||||
GroupJoinBattlegroundResult CanJoinBattlegroundQueue(Battleground const* bgTemplate, BattlegroundQueueTypeId bgQueueTypeId, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot);
|
||||
|
||||
void ChangeMembersGroup(ObjectGuid guid, uint8 group);
|
||||
void SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid);
|
||||
void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag);
|
||||
void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag);
|
||||
|
||||
void SetTargetIcon(uint8 id, ObjectGuid whoGuid, ObjectGuid targetGuid);
|
||||
ObjectGuid const GetTargetIcon(uint8 id) const { return m_targetIcons[i]; }
|
||||
|
||||
Difficulty GetDifficulty(bool isRaid) const;
|
||||
Difficulty GetDungeonDifficulty() const;
|
||||
Difficulty GetRaidDifficulty() const;
|
||||
@@ -292,6 +294,8 @@ public:
|
||||
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise);
|
||||
void EndRoll(Loot* loot, Map* allowedMap);
|
||||
|
||||
Rolls GetRolls() const { return RollId; }
|
||||
|
||||
// related to disenchant rolls
|
||||
void ResetMaxEnchantingLevel();
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "Playerbot.h"
|
||||
#endif
|
||||
|
||||
class LoginQueryHolder : public CharacterDatabaseQueryHolder
|
||||
{
|
||||
private:
|
||||
@@ -208,6 +212,22 @@ bool LoginQueryHolder::Initialize()
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
class PlayerbotLoginQueryHolder : public LoginQueryHolder
|
||||
{
|
||||
private:
|
||||
uint32 masterAccountId;
|
||||
PlayerbotHolder* playerbotHolder;
|
||||
|
||||
public:
|
||||
PlayerbotLoginQueryHolder(PlayerbotHolder* playerbotHolder, uint32 masterAccount, uint32 accountId, ObjectGuid guid)
|
||||
: LoginQueryHolder(accountId, guid), masterAccountId(masterAccount), playerbotHolder(playerbotHolder) { }
|
||||
|
||||
uint32 GetMasterAccountId() const { return masterAccountId; }
|
||||
PlayerbotHolder* GetPlayerbotHolder() { return playerbotHolder; }
|
||||
};
|
||||
#endif
|
||||
|
||||
void WorldSession::HandleCharEnum(PreparedQueryResult result)
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
|
||||
@@ -901,8 +921,7 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
LoginDatabasePreparedStatement* loginStmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_ONLINE);
|
||||
loginStmt->setUInt32(0, realm.Id.Realm);
|
||||
loginStmt->setUInt32(1, GetAccountId());
|
||||
loginStmt->setUInt32(0, GetAccountId());
|
||||
LoginDatabase.Execute(loginStmt);
|
||||
|
||||
pCurrChar->SetInGameTime(World::GetGameTimeMS());
|
||||
@@ -1106,6 +1125,14 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (!pCurrChar->GetPlayerbotAI())
|
||||
{
|
||||
pCurrChar->SetPlayerbotMgr(new PlayerbotMgr(pCurrChar));
|
||||
sRandomPlayerbotMgr->OnPlayerLogin(pCurrChar);
|
||||
}
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnPlayerLogin(pCurrChar);
|
||||
|
||||
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST))
|
||||
@@ -2546,3 +2573,65 @@ void WorldSession::SendSetPlayerDeclinedNamesResult(DeclinedNameResult result, O
|
||||
data << guid;
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
void PlayerbotHolder::AddPlayerBot(ObjectGuid playerGuid, uint32 masterAccountId)
|
||||
{
|
||||
// has bot already been added?
|
||||
if (ObjectAccessor::FindConnectedPlayer(playerGuid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(playerGuid.GetCounter());
|
||||
if (!accountId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerbotLoginQueryHolder* holder = new PlayerbotLoginQueryHolder(this, masterAccountId, accountId, playerGuid);
|
||||
if (!holder->Initialize())
|
||||
{
|
||||
delete holder; // delete all unprocessed queries
|
||||
return;
|
||||
}
|
||||
|
||||
QueryResultHolderFuture future = CharacterDatabase.DelayQueryHolder(holder);
|
||||
SQLQueryHolder* param;
|
||||
future.get(param);
|
||||
|
||||
PlayerbotHolder* playerbotHolder = holder->GetPlayerbotHolder();
|
||||
uint32 masterAccount = holder->GetMasterAccountId();
|
||||
WorldSession* masterSession = masterAccount ? sWorld->FindSession(masterAccount) : NULL;
|
||||
|
||||
// The bot's WorldSession is owned by the bot's Player object
|
||||
// The bot's WorldSession is deleted by PlayerbotMgr::LogoutPlayerBot
|
||||
uint32 botAccountId = holder->GetAccountId();
|
||||
WorldSession* botSession = new WorldSession(botAccountId, NULL, SEC_PLAYER, EXPANSION_WRATH_OF_THE_LICH_KING, time_t(0), LOCALE_enUS, false, false, false, 0);
|
||||
botSession->SetAddress("bot");
|
||||
botSession->HandlePlayerLoginFromDB(holder); // will delete lqh
|
||||
|
||||
Player* bot = botSession->GetPlayer();
|
||||
if (!bot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool allowed = false;
|
||||
if (botAccountId == masterAccount)
|
||||
allowed = true;
|
||||
else if (masterSession && sPlayerbotAIConfig->allowGuildBots && bot->GetGuildId() == masterSession->GetPlayer()->GetGuildId())
|
||||
allowed = true;
|
||||
else if (sPlayerbotAIConfig->IsInRandomAccountList(botAccountId))
|
||||
allowed = true;
|
||||
|
||||
if (allowed)
|
||||
playerbotHolder->OnBotLogin(bot);
|
||||
else if (masterSession)
|
||||
{
|
||||
ChatHandler ch(masterSession);
|
||||
ch.PSendSysMessage("You are not allowed to control bot %s...", bot->GetName());
|
||||
playerbotHolder->LogoutPlayerBot(bot->GetGUID());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "Playerbot.h"
|
||||
#endif
|
||||
|
||||
inline bool isNasty(uint8 c)
|
||||
{
|
||||
if (c == '\t')
|
||||
@@ -409,7 +413,16 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
if (!senderIsPlayer && !sender->isAcceptWhispers() && !sender->IsInWhisperWhiteList(receiver->GetGUID()))
|
||||
sender->AddWhisperWhiteList(receiver->GetGUID());
|
||||
|
||||
GetPlayer()->Whisper(msg, Language(lang), receiver);
|
||||
#ifdef PLAYERBOTS
|
||||
if (receiver->GetPlayerbotAI())
|
||||
{
|
||||
receiver->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
GetPlayer()->m_speakTime = 0;
|
||||
GetPlayer()->m_speakCount = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
GetPlayer()->Whisper(msg, Language(lang), receiver);
|
||||
}
|
||||
break;
|
||||
case CHAT_MSG_PARTY:
|
||||
@@ -432,6 +445,21 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
if (Player* player = itr->GetSource())
|
||||
{
|
||||
if (player->GetPlayerbotAI())
|
||||
{
|
||||
player->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
GetPlayer()->m_speakTime = 0;
|
||||
GetPlayer()->m_speakCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
|
||||
|
||||
WorldPacket data;
|
||||
@@ -454,6 +482,22 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
|
||||
guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (PlayerbotMgr* mgr = GetPlayer()->GetPlayerbotMgr())
|
||||
{
|
||||
for (PlayerBotMap::const_iterator it = mgr->GetPlayerBotsBegin(); it != mgr->GetPlayerBotsEnd(); ++it)
|
||||
{
|
||||
if (Player* const bot = it->second)
|
||||
{
|
||||
if (bot->GetGuildId() == GetPlayer()->GetGuildId())
|
||||
{
|
||||
bot->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -491,6 +535,21 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
if (Player* player = itr->GetSource())
|
||||
{
|
||||
if (player->GetPlayerbotAI())
|
||||
{
|
||||
player->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
GetPlayer()->m_speakTime = 0;
|
||||
GetPlayer()->m_speakCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
|
||||
|
||||
WorldPacket data;
|
||||
@@ -514,6 +573,21 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
if (Player* player = itr->GetSource())
|
||||
{
|
||||
if (player->GetPlayerbotAI())
|
||||
{
|
||||
player->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
GetPlayer()->m_speakTime = 0;
|
||||
GetPlayer()->m_speakCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
|
||||
|
||||
WorldPacket data;
|
||||
@@ -532,6 +606,21 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
if (Player* player = itr->GetSource())
|
||||
{
|
||||
if (player->GetPlayerbotAI())
|
||||
{
|
||||
player->GetPlayerbotAI()->HandleCommand(type, msg, GetPlayer());
|
||||
GetPlayer()->m_speakTime = 0;
|
||||
GetPlayer()->m_speakCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group);
|
||||
|
||||
// In battleground, raid warning is sent only to players in battleground - code is ok
|
||||
@@ -598,6 +687,14 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (_player->GetPlayerbotMgr() && chn->GetFlags() & 0x18)
|
||||
{
|
||||
_player->GetPlayerbotMgr()->HandleCommand(type, msg);
|
||||
}
|
||||
|
||||
sRandomPlayerbotMgr->HandleCommand(type, msg, _player);
|
||||
#endif
|
||||
sScriptMgr->OnPlayerChat(sender, type, lang, msg, chn);
|
||||
|
||||
chn->Say(sender->GetGUID(), msg.c_str(), lang);
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
#include "WorldSocket.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "Playerbot.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string const DefaultPlayerName = "<none>";
|
||||
@@ -211,6 +215,20 @@ void WorldSession::SendPacket(WorldPacket const* packet)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (Player* player = GetPlayer())
|
||||
{
|
||||
if (PlayerbotAI* playerbotAI = player->GetPlayerbotAI())
|
||||
{
|
||||
playerbotAI->HandleBotOutgoingPacket(*packet);
|
||||
}
|
||||
else if (PlayerbotMgr* playerbotMgr = GetPlayer()->GetPlayerbotMgr())
|
||||
{
|
||||
playerbotMgr->HandleMasterOutgoingPacket(*packet);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_Socket)
|
||||
return;
|
||||
|
||||
@@ -287,6 +305,11 @@ void WorldSession::LogUnprocessedTail(WorldPacket* packet)
|
||||
/// Update the WorldSession (triggered by World update)
|
||||
bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
{
|
||||
#ifdef PLAYERBOTS
|
||||
if (GetPlayer() && GetPlayer()->GetPlayerbotAI())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
///- Before we process anything:
|
||||
/// If necessary, kick the player because the client didn't send anything for too long
|
||||
/// (or they've been idling in character select)
|
||||
@@ -347,6 +370,11 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
|
||||
opHandle->Call(this, *packet);
|
||||
LogUnprocessedTail(packet);
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (_player && _player->GetPlayerbotMgr())
|
||||
_player->GetPlayerbotMgr()->HandleMasterIncomingPacket(*packet);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case STATUS_TRANSFER:
|
||||
@@ -457,6 +485,11 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
|
||||
ProcessQueryCallbacks();
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
if (GetPlayer() && GetPlayer()->GetPlayerbotMgr())
|
||||
GetPlayer()->GetPlayerbotMgr()->UpdateSessions(0);
|
||||
#endif
|
||||
|
||||
//check if we are safe to proceed with logout
|
||||
//logout procedure should happen only in World::UpdateSessions() method!!!
|
||||
if (updater.ProcessUnsafe())
|
||||
@@ -613,6 +646,7 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
// there are some positive auras from boss encounters that can be kept by logging out and logging in after boss is dead, and may be used on next bosses
|
||||
_player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP);
|
||||
|
||||
#ifndef PLAYERBOTS
|
||||
///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group.
|
||||
_player->UninviteFromGroup();
|
||||
|
||||
@@ -621,6 +655,7 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket)
|
||||
_player->RemoveFromGroup();
|
||||
|
||||
#endif
|
||||
// pussywizard: checked second time after being removed from a group
|
||||
if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster())
|
||||
_player->RepopAtGraveyard();
|
||||
@@ -1614,3 +1649,17 @@ void WorldSession::SendTimeSync()
|
||||
_timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000;
|
||||
_timeSyncNextCounter++;
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
void WorldSession::HandleBotPackets()
|
||||
{
|
||||
WorldPacket* packet;
|
||||
while (_recvQueue.next(packet))
|
||||
{
|
||||
OpcodeClient opcode = static_cast<OpcodeClient>(packet->GetOpcode());
|
||||
ClientOpcodeHandler const* opHandle = opcodeTable[opcode];
|
||||
opHandle->Call(this, *packet);
|
||||
delete packet;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -442,6 +442,11 @@ public:
|
||||
// Time Synchronisation
|
||||
void ResetTimeSync();
|
||||
void SendTimeSync();
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
void HandleBotPackets();
|
||||
#endif
|
||||
|
||||
public: // opcodes handlers
|
||||
void Handle_NULL(WorldPacket& null); // not used
|
||||
void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead
|
||||
@@ -984,6 +989,8 @@ public: // opcodes handlers
|
||||
bool GetShouldSetOfflineInDB() const { return _shouldSetOfflineInDB; }
|
||||
bool IsSocketClosed() const;
|
||||
|
||||
void SetAddress(std::string const& address) { m_Address = address; }
|
||||
|
||||
/*
|
||||
* CALLBACKS
|
||||
*/
|
||||
|
||||
@@ -92,6 +92,10 @@
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
#include "RandomPlayerbotMgr.h"
|
||||
#endif
|
||||
|
||||
std::atomic_long World::m_stopEvent = false;
|
||||
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
|
||||
uint32 World::m_worldLoopCounter = 0;
|
||||
@@ -2274,6 +2278,11 @@ void World::Update(uint32 diff)
|
||||
ResetGuildCap();
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
sRandomPlayerbotMgr->UpdateAI(diff);
|
||||
sRandomPlayerbotMgr->UpdateSessions(diff);
|
||||
#endif
|
||||
|
||||
// pussywizard:
|
||||
// acquire mutex now, this is kind of waiting for listing thread to finish it's work (since it can't process next packet)
|
||||
// so we don't have to do it in every packet that modifies auctions
|
||||
@@ -2432,6 +2441,9 @@ void World::Update(uint32 diff)
|
||||
CharacterDatabase.KeepAlive();
|
||||
LoginDatabase.KeepAlive();
|
||||
WorldDatabase.KeepAlive();
|
||||
#ifdef PLAYERBOTS
|
||||
PlayerbotDatabase.KeepAlive();
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@@ -2719,6 +2731,10 @@ void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode, const std:
|
||||
ShutdownMsg(true, nullptr, reason);
|
||||
}
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
sRandomPlayerbotMgr->LogoutAllBots();
|
||||
#endif
|
||||
|
||||
sScriptMgr->OnShutdownInitiate(ShutdownExitCode(exitcode), ShutdownMask(options));
|
||||
}
|
||||
|
||||
|
||||
@@ -627,6 +627,33 @@ struct CharStartOutfitEntry
|
||||
//int32 ItemInventorySlot[MAX_OUTFIT_ITEMS]; // 53-76 not required at server side
|
||||
};
|
||||
|
||||
enum CharSectionFlags
|
||||
{
|
||||
SECTION_FLAG_PLAYER = 0x01,
|
||||
SECTION_FLAG_DEATH_KNIGHT = 0x04
|
||||
};
|
||||
|
||||
enum CharSectionType
|
||||
{
|
||||
SECTION_TYPE_SKIN = 0,
|
||||
SECTION_TYPE_FACE = 1,
|
||||
SECTION_TYPE_FACIAL_HAIR = 2,
|
||||
SECTION_TYPE_HAIR = 3,
|
||||
SECTION_TYPE_UNDERWEAR = 4
|
||||
};
|
||||
|
||||
struct CharSectionsEntry
|
||||
{
|
||||
//uint32 Id;
|
||||
uint32 Race;
|
||||
uint32 Gender;
|
||||
uint32 GenType;
|
||||
//char* TexturePath[3];
|
||||
uint32 Flags;
|
||||
uint32 Type;
|
||||
uint32 Color;
|
||||
};
|
||||
|
||||
struct CharTitlesEntry
|
||||
{
|
||||
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
|
||||
@@ -864,6 +891,15 @@ struct EmotesTextEntry
|
||||
uint32 textid;
|
||||
};
|
||||
|
||||
struct EmotesTextSoundEntry
|
||||
{
|
||||
uint32 Id; // 0
|
||||
uint32 EmotesTextId; // 1
|
||||
uint32 RaceId; // 2
|
||||
uint32 SexId; // 3, 0 male / 1 female
|
||||
uint32 SoundId; // 4
|
||||
};
|
||||
|
||||
struct FactionEntry
|
||||
{
|
||||
uint32 ID; // 0 m_ID
|
||||
|
||||
@@ -29,6 +29,7 @@ char constexpr BankBagSlotPricesEntryfmt[] = "ni";
|
||||
char constexpr BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
|
||||
char constexpr BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
|
||||
char constexpr CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
char constexpr CharSectionsEntryfmt[] = "diiixxxiii";
|
||||
char constexpr CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi";
|
||||
char constexpr ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; // ChatChannelsEntryfmt, index not used (more compact store)
|
||||
char constexpr ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
|
||||
@@ -47,6 +48,7 @@ char constexpr DurabilityCostsfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
|
||||
char constexpr DurabilityQualityfmt[] = "nf";
|
||||
char constexpr EmotesEntryfmt[] = "nxxiiix";
|
||||
char constexpr EmotesTextEntryfmt[] = "nxixxxxxxxxxxxxxxxx";
|
||||
char constexpr EmotesTextSoundEntryfmt[] = "niiii";
|
||||
char constexpr FactionEntryfmt[] = "niiiiiiiiiiiiiiiiiiffixssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||
char constexpr FactionTemplateEntryfmt[] = "niiiiiiiiiiiii";
|
||||
char constexpr GameObjectDisplayInfofmt[] = "nsxxxxxxxxxxffffffx";
|
||||
|
||||
@@ -3116,7 +3116,7 @@ enum WeatherType
|
||||
#define MAX_WEATHER_TYPE 4
|
||||
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum ChatMsg
|
||||
enum ChatMsg : uint32
|
||||
{
|
||||
CHAT_MSG_ADDON = 0xFFFFFFFF,
|
||||
CHAT_MSG_SYSTEM = 0x00,
|
||||
|
||||
@@ -456,6 +456,14 @@ bool StartDB()
|
||||
if (!loader.Load())
|
||||
return false;
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
DatabaseLoader playerbotLoader("server.playerbot");
|
||||
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("Playerbot.Updates.EnableDatabases", true) ? DatabaseLoader::DATABASE_PLAYERBOT : 0);
|
||||
playerbotLoader.AddDatabase(PlayerbotDatabase, "Playerbot");
|
||||
if (!playerbotLoader.Load())
|
||||
return false;
|
||||
#endif
|
||||
|
||||
///- Get the realm Id from the configuration file
|
||||
realm.Id.Realm = sConfigMgr->GetIntDefault("RealmID", 0);
|
||||
if (!realm.Id.Realm)
|
||||
@@ -499,6 +507,10 @@ void StopDB()
|
||||
WorldDatabase.Close();
|
||||
LoginDatabase.Close();
|
||||
|
||||
#ifdef PLAYERBOTS
|
||||
PlayerbotDatabase.Close();
|
||||
#endif
|
||||
|
||||
MySQL::Library_End();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user