diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 | ||||
-rw-r--r-- | src/server/game/Garrison/Garrison.cpp | 90 | ||||
-rw-r--r-- | src/server/game/Garrison/Garrison.h | 3 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMgr.cpp | 100 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMgr.h | 9 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 8 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 7 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.h | 5 |
9 files changed, 218 insertions, 17 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 419992f3408..55ae58fe342 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4590,6 +4590,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS); + stmt->setUInt64(0, guid); + trans->Append(stmt); + CharacterDatabase.CommitTransaction(trans); sWorld->DeleteCharacterInfo(playerguid); @@ -17344,8 +17348,6 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) _LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES)); - m_achievementMgr->CheckAllAchievementCriteria(this); - _LoadEquipmentSets(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS)); _LoadCUFProfiles(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES)); @@ -17353,9 +17355,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) std::unique_ptr<Garrison> garrison = Trinity::make_unique<Garrison>(this); if (garrison->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS), - holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS))) + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES))) _garrison = std::move(garrison); + m_achievementMgr->CheckAllAchievementCriteria(this); return true; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index c7af9426623..f17b304409e 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -987,6 +987,8 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_GARRISON, PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, + PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS, + PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, MAX_PLAYER_LOGIN_QUERY }; diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp index 3087de37472..8e27bbd930d 100644 --- a/src/server/game/Garrison/Garrison.cpp +++ b/src/server/game/Garrison/Garrison.cpp @@ -25,7 +25,8 @@ Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followe { } -bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings) +bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings, + PreparedQueryResult followers, PreparedQueryResult abilities) { if (!garrison) return false; @@ -76,6 +77,60 @@ bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blue } while (buildings->NextRow()); } + // 0 1 2 3 4 5 6 7 8 9 + // SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ? + if (followers) + { + std::unordered_map<uint64, Follower*> followersByDbId; + do + { + Field* fields = followers->Fetch(); + + uint32 followerId = fields[1].GetUInt32(); + if (!sGarrFollowerStore.LookupEntry(followerId)) + continue; + + Follower& follower = _followers[followerId]; + follower.PacketInfo.DbID = fields[0].GetUInt64(); + follower.PacketInfo.GarrFollowerID = followerId; + follower.PacketInfo.Quality = fields[2].GetUInt32(); + follower.PacketInfo.FollowerLevel = fields[3].GetUInt32(); + follower.PacketInfo.ItemLevelWeapon = fields[4].GetUInt32(); + follower.PacketInfo.ItemLevelArmor = fields[5].GetUInt32(); + follower.PacketInfo.Xp = fields[6].GetUInt32(); + follower.PacketInfo.CurrentBuildingID = fields[7].GetUInt32(); + follower.PacketInfo.CurrentMissionID = fields[8].GetUInt32(); + follower.PacketInfo.FollowerStatus = fields[9].GetUInt32(); + if (!sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID)) + follower.PacketInfo.CurrentBuildingID = 0; + + //if (!sGarrMissionStore.LookupEntry(follower.PacketInfo.CurrentMissionID)) + // follower.PacketInfo.CurrentMissionID = 0; + + followersByDbId[follower.PacketInfo.DbID] = &follower; + + } while (followers->NextRow()); + + if (abilities) + { + do + { + Field* fields = abilities->Fetch(); + uint64 dbId = fields[0].GetUInt64(); + GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(fields[1].GetUInt32()); + + if (!ability) + continue; + + auto itr = followersByDbId.find(dbId); + if (itr == followersByDbId.end()) + continue; + + itr->second->PacketInfo.AbilityID.push_back(ability); + } while (abilities->NextRow()); + } + } + return true; } @@ -93,6 +148,10 @@ void Garrison::SaveToDB(SQLTransaction& trans) stmt->setUInt64(0, _owner->GetGUID().GetCounter()); trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS); + stmt->setUInt64(0, _owner->GetGUID().GetCounter()); + trans->Append(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON); stmt->setUInt64(0, _owner->GetGUID().GetCounter()); stmt->setUInt32(1, _siteLevel->ID); @@ -121,6 +180,35 @@ void Garrison::SaveToDB(SQLTransaction& trans) trans->Append(stmt); } } + + for (auto const& p : _followers) + { + Follower const& follower = p.second; + uint8 index = 0; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS); + stmt->setUInt64(index++, follower.PacketInfo.DbID); + stmt->setUInt64(index++, _owner->GetGUID().GetCounter()); + stmt->setUInt32(index++, follower.PacketInfo.GarrFollowerID); + stmt->setUInt32(index++, follower.PacketInfo.Quality); + stmt->setUInt32(index++, follower.PacketInfo.FollowerLevel); + stmt->setUInt32(index++, follower.PacketInfo.ItemLevelWeapon); + stmt->setUInt32(index++, follower.PacketInfo.ItemLevelArmor); + stmt->setUInt32(index++, follower.PacketInfo.Xp); + stmt->setUInt32(index++, follower.PacketInfo.CurrentBuildingID); + stmt->setUInt32(index++, follower.PacketInfo.CurrentMissionID); + stmt->setUInt32(index++, follower.PacketInfo.FollowerStatus); + trans->Append(stmt); + + uint8 slot = 0; + for (GarrAbilityEntry const* ability : follower.PacketInfo.AbilityID) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES); + stmt->setUInt64(0, follower.PacketInfo.DbID); + stmt->setUInt32(1, ability->ID); + stmt->setUInt8(2, slot++); + trans->Append(stmt); + } + } } bool Garrison::Create(uint32 garrSiteId) diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h index be92b9e14f3..dc48a43c5cc 100644 --- a/src/server/game/Garrison/Garrison.h +++ b/src/server/game/Garrison/Garrison.h @@ -105,7 +105,8 @@ public: explicit Garrison(Player* owner); - bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings); + bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings, + PreparedQueryResult followers, PreparedQueryResult abilities); void SaveToDB(SQLTransaction& trans); bool Create(uint32 garrSiteId); diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp index 75f4289c385..f95acef952c 100644 --- a/src/server/game/Garrison/GarrisonMgr.cpp +++ b/src/server/game/Garrison/GarrisonMgr.cpp @@ -17,6 +17,7 @@ #include "GarrisonMgr.h" #include "Containers.h" +#include "DatabaseEnv.h" #include "Garrison.h" #include "ObjectDefines.h" #include "World.h" @@ -55,6 +56,9 @@ void GarrisonMgr::Initialize() } } } + + InitializeDbIdSequences(); + LoadFollowerClassSpecAbilities(); } GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const @@ -185,13 +189,18 @@ std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollow Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size())); Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size())); - // Add counters specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation + // Add abilities specified in GarrFollowerXAbility.db2 before generic classspec ones on follower creation if (initial) { forcedAbilities.splice(forcedAbilities.end(), abilityList); forcedTraits.splice(forcedTraits.end(), traitList); } + forcedAbilities.sort(); + abilityList.sort(); + forcedTraits.sort(); + traitList.sort(); + // check if we have a trait from exclusive category for (GarrAbilityEntry const* ability : forcedTraits) { @@ -204,18 +213,18 @@ std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollow if (slots[0] > forcedAbilities.size() + abilityList.size()) { - std::list<GarrAbilityEntry const*> classSpecAbilities; // = GetDefaultClassSpecAbilities(follower, faction) - - abilityList.splice(abilityList.end(), classSpecAbilities); - abilityList.sort(); - abilityList.unique(); + std::list<GarrAbilityEntry const*> classSpecAbilities = GetClassSpecAbilities(follower, faction); + std::list<GarrAbilityEntry const*> classSpecAbilitiesTemp, classSpecAbilitiesTemp2; + classSpecAbilitiesTemp2.swap(abilityList); + std::set_difference(classSpecAbilities.begin(), classSpecAbilities.end(), forcedAbilities.begin(), forcedAbilities.end(), std::back_inserter(classSpecAbilitiesTemp)); + std::set_union(classSpecAbilitiesTemp.begin(), classSpecAbilitiesTemp.end(), classSpecAbilitiesTemp2.begin(), classSpecAbilitiesTemp2.end(), std::back_inserter(abilityList)); Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size())); } if (slots[1] > forcedTraits.size() + traitList.size()) { - std::list<GarrAbilityEntry const*> genericTraits; + std::list<GarrAbilityEntry const*> genericTraits, genericTraitsTemp; for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits) { if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE) @@ -227,9 +236,10 @@ std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollow if (hasForcedExclusiveTrait && ability->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE) continue; - genericTraits.push_back(ability); + genericTraitsTemp.push_back(ability); } + std::set_difference(genericTraitsTemp.begin(), genericTraitsTemp.end(), forcedTraits.begin(), forcedTraits.end(), std::back_inserter(genericTraits)); genericTraits.splice(genericTraits.begin(), traitList); // "split" the list into two parts [nonexclusive, exclusive] to make selection later easier genericTraits.sort([](GarrAbilityEntry const* a1, GarrAbilityEntry const* a2) @@ -248,7 +258,7 @@ std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollow if ((*itr)->Flags & GARRISON_ABILITY_FLAG_EXCLUSIVE) break; - while (traitList.size() < std::max<int32>(0, slots[1] - forcedTraits.size()) && !genericTraits.empty()) + while (traitList.size() < std::max<int32>(0, slots[1] - forcedTraits.size()) && total) { auto itr = genericTraits.begin(); std::advance(itr, urand(0, total-- - 1)); @@ -269,3 +279,75 @@ std::list<GarrAbilityEntry const*> GarrisonMgr::RollFollowerAbilities(GarrFollow return result; } + +std::list<GarrAbilityEntry const*> GarrisonMgr::GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const +{ + std::list<GarrAbilityEntry const*> abilities; + uint32 classSpecId; + switch (faction) + { + case GARRISON_FACTION_INDEX_HORDE: + classSpecId = follower->HordeGarrClassSpecID; + break; + case GARRISON_FACTION_INDEX_ALLIANCE: + classSpecId = follower->AllianceGarrClassSpecID; + break; + default: + return abilities; + } + + if (!sGarrClassSpecStore.LookupEntry(classSpecId)) + return abilities; + + auto itr = _garrisonFollowerClassSpecAbilities.find(classSpecId); + if (itr != _garrisonFollowerClassSpecAbilities.end()) + abilities = itr->second; + + return abilities; +} + +void GarrisonMgr::InitializeDbIdSequences() +{ + if (QueryResult result = CharacterDatabase.Query("SELECT MAX(dbId) FROM character_garrison_followers")) + _followerDbIdGenerator = (*result)[0].GetUInt64() + 1; +} + +void GarrisonMgr::LoadFollowerClassSpecAbilities() +{ + QueryResult result = WorldDatabase.Query("SELECT classSpecId, abilityId FROM garrison_follower_class_spec_abilities"); + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 garrison follower class spec abilities. DB table `garrison_follower_class_spec_abilities` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + uint32 classSpecId = fields[0].GetUInt32(); + uint32 abilityId = fields[1].GetUInt32(); + + if (!sGarrClassSpecStore.LookupEntry(classSpecId)) + { + TC_LOG_ERROR("sql.sql", "Non-existing GarrClassSpec.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", classSpecId, classSpecId, abilityId); + continue; + } + + GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(abilityId); + if (!ability) + { + TC_LOG_ERROR("sql.sql", "Non-existing GarrAbility.db2 entry %u was referenced in `garrison_follower_class_spec_abilities` by row (%u, %u).", abilityId, classSpecId, abilityId); + continue; + } + + _garrisonFollowerClassSpecAbilities[classSpecId].push_back(ability); + ++count; + + } while (result->NextRow()); + + for (auto& pair : _garrisonFollowerClassSpecAbilities) + pair.second.sort(); + + TC_LOG_INFO("server.loading", ">> Loaded %u garrison follower class spec abilities.", count); +} diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h index a54606dd9b1..68514f4a2f3 100644 --- a/src/server/game/Garrison/GarrisonMgr.h +++ b/src/server/game/Garrison/GarrisonMgr.h @@ -46,17 +46,22 @@ public: GarrBuildingEntry const* GetPreviousLevelBuilding(uint32 buildingType, uint32 currentLevel) const; uint64 GenerateFollowerDbId(); std::list<GarrAbilityEntry const*> RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const; + std::list<GarrAbilityEntry const*> GetClassSpecAbilities(GarrFollowerEntry const* follower, uint32 faction) const; private: + void InitializeDbIdSequences(); + void LoadFollowerClassSpecAbilities(); + std::unordered_map<uint32 /*garrSiteId*/, std::vector<GarrSiteLevelPlotInstEntry const*>> _garrisonPlotInstBySiteLevel; std::unordered_map<uint32 /*mapId*/, std::unordered_map<uint32 /*garrPlotId*/, GameObjectsEntry const*>> _garrisonPlots; std::unordered_map<uint32 /*garrPlotId*/, std::unordered_set<uint32/*garrBuildingId*/>> _garrisonBuildingsByPlot; std::unordered_map<uint64 /*garrBuildingId | garrSiteLevelPlotInstId << 32*/, uint32 /*garrBuildingPlotInstId*/> _garrisonBuildingPlotInstances; std::unordered_map<uint32 /*buildingType*/, std::vector<GarrBuildingEntry const*>> _garrisonBuildingsByType; std::unordered_map<uint32 /*garrFollowerId*/, GarrAbilities> _garrisonFollowerAbilities[2]; - std::unordered_set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits; + std::unordered_map<uint32 /*classSpecId*/, std::list<GarrAbilityEntry const*>> _garrisonFollowerClassSpecAbilities; + std::set<GarrAbilityEntry const*> _garrisonFollowerRandomTraits; - uint64 _followerDbIdGenerator; + uint64 _followerDbIdGenerator = UI64LIT(0); }; #define sGarrisonMgr GarrisonMgr::Instance() diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 56d865e5d06..65f05e4dbbb 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -248,6 +248,14 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWERS, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GARRISON_FOLLOWER_ABILITIES, stmt); + return res; } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index e9ce253d1cf..277ccd4569a 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -690,7 +690,12 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "INSERT INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "INSERT INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, "SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status FROM character_garrison_followers WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, "INSERT INTO character_garrison_followers (dbId, guid, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "SELECT gfab.dbId, gfab.abilityId FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE guid = ? ORDER BY gfab.slot", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "INSERT INTO character_garrison_follower_abilities (dbId, abilityId, slot) VALUES (?, ?, ?)", CONNECTION_ASYNC); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 53c42a0b852..fc9c930e6b1 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -608,6 +608,11 @@ enum CharacterDatabaseStatements CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, CHAR_INS_CHARACTER_GARRISON_BUILDINGS, CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, + CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, + CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, + CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, + CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, + CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, MAX_CHARACTERDATABASE_STATEMENTS }; |