aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Garrison
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2015-05-08 00:03:15 +0200
committerShauren <shauren.trinity@gmail.com>2015-05-08 00:03:15 +0200
commit5b725db033c656bda5e718ea05a79005946e089e (patch)
treec15ad544c542cdd7dd7cb395c8ec6d3d35e4d2e9 /src/server/game/Garrison
parent0972552e84068cf453231b372bcb232cf2d2f42b (diff)
Core/Garrisons: Basics for garrisons
Diffstat (limited to 'src/server/game/Garrison')
-rw-r--r--src/server/game/Garrison/Garrison.cpp420
-rw-r--r--src/server/game/Garrison/Garrison.h117
-rw-r--r--src/server/game/Garrison/GarrisonMap.cpp125
-rw-r--r--src/server/game/Garrison/GarrisonMap.h39
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp83
-rw-r--r--src/server/game/Garrison/GarrisonMgr.h49
6 files changed, 833 insertions, 0 deletions
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
new file mode 100644
index 00000000000..24fdd1fb30b
--- /dev/null
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Garrison.h"
+#include "GameObject.h"
+#include "GarrisonMgr.h"
+#include "MapManager.h"
+
+Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1)
+{
+}
+
+bool Garrison::LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings)
+{
+ if (!garrison)
+ return false;
+
+ Field* fields = garrison->Fetch();
+ _siteLevel = sGarrSiteLevelStore.LookupEntry(fields[0].GetUInt32());
+ _followerActivationsRemainingToday = fields[1].GetUInt32();
+ if (!_siteLevel)
+ return false;
+
+ InitializePlots();
+
+ if (blueprints)
+ {
+ do
+ {
+ fields = blueprints->Fetch();
+ if (GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(fields[0].GetUInt32()))
+ _knownBuildings.insert(building->ID);
+
+ } while (blueprints->NextRow());
+ }
+
+ if (buildings)
+ {
+ do
+ {
+ fields = buildings->Fetch();
+ uint32 plotInstanceId = fields[0].GetUInt32();
+ uint32 buildingId = fields[1].GetUInt32();
+ time_t timeBuilt = time_t(fields[2].GetUInt64());
+ bool active = fields[3].GetBool();
+
+
+ Plot* plot = GetPlot(plotInstanceId);
+ if (!plot)
+ continue;
+
+ if (!sGarrBuildingStore.LookupEntry(buildingId))
+ continue;
+
+ plot->BuildingInfo.PacketInfo = boost::in_place();
+ plot->BuildingInfo.PacketInfo->GarrPlotInstanceID = plotInstanceId;
+ plot->BuildingInfo.PacketInfo->GarrBuildingID = buildingId;
+ plot->BuildingInfo.PacketInfo->TimeBuilt = timeBuilt;
+ plot->BuildingInfo.PacketInfo->Active = active;
+
+ } while (buildings->NextRow());
+ }
+
+ return true;
+}
+
+void Garrison::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS);
+ 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);
+ stmt->setUInt32(2, _followerActivationsRemainingToday);
+ trans->Append(stmt);
+
+ for (uint32 building : _knownBuildings)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, building);
+ trans->Append(stmt);
+ }
+
+ for (auto const& p : _plots)
+ {
+ Plot const& plot = p.second;
+ if (plot.BuildingInfo.PacketInfo)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, plot.BuildingInfo.PacketInfo->GarrPlotInstanceID);
+ stmt->setUInt32(2, plot.BuildingInfo.PacketInfo->GarrBuildingID);
+ stmt->setUInt64(3, plot.BuildingInfo.PacketInfo->TimeBuilt);
+ stmt->setBool(4, plot.BuildingInfo.PacketInfo->Active);
+ trans->Append(stmt);
+ }
+ }
+}
+
+bool Garrison::Create(uint32 garrSiteId)
+{
+ _siteLevel = sGarrisonMgr.GetGarrSiteLevelEntry(garrSiteId, 1);
+ if (!_siteLevel)
+ return false;
+
+ InitializePlots();
+
+ WorldPackets::Garrison::GarrisonCreateResult garrisonCreateResult;
+ garrisonCreateResult.GarrSiteLevelID = _siteLevel->ID;
+ _owner->SendDirectMessage(garrisonCreateResult.Write());
+ _owner->SendUpdatePhasing();
+ SendRemoteInfo();
+ return true;
+}
+
+void Garrison::InitializePlots()
+{
+ if (std::vector<GarrSiteLevelPlotInstEntry const*> const* plots = sGarrisonMgr.GetGarrPlotInstForSiteLevel(_siteLevel->ID))
+ {
+ for (std::size_t i = 0; i < plots->size(); ++i)
+ {
+ uint32 garrPlotInstanceId = plots->at(i)->GarrPlotInstanceID;
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
+ GameObjectsEntry const* gameObject = sGarrisonMgr.GetPlotGameObject(_siteLevel->MapID, garrPlotInstanceId);
+ if (!plotInstance || !gameObject)
+ continue;
+
+ GarrPlotEntry const* plot = sGarrPlotStore.LookupEntry(plotInstance->GarrPlotID);
+ if (!plot)
+ continue;
+
+ Plot& plotInfo = _plots[garrPlotInstanceId];
+ plotInfo.PacketInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ plotInfo.PacketInfo.PlotPos.Relocate(gameObject->Position.X, gameObject->Position.Y, gameObject->Position.Z, 2 * std::acos(gameObject->RotationW));
+ plotInfo.PacketInfo.PlotType = plot->PlotType;
+ plotInfo.EmptyGameObjectId = gameObject->ID;
+ plotInfo.GarrSiteLevelPlotInstId = plots->at(i)->ID;
+ }
+ }
+}
+
+void Garrison::Upgrade()
+{
+}
+
+void Garrison::Enter() const
+{
+ WorldLocation loc(_siteLevel->MapID);
+ loc.Relocate(_owner);
+ _owner->TeleportTo(loc, TELE_TO_SEAMLESS);
+}
+
+void Garrison::Leave() const
+{
+ if (MapEntry const* map = sMapStore.LookupEntry(_siteLevel->MapID))
+ {
+ WorldLocation loc(map->ParentMapID);
+ loc.Relocate(_owner);
+ _owner->TeleportTo(loc, TELE_TO_SEAMLESS);
+ }
+}
+
+GarrisonFactionIndex Garrison::GetFaction() const
+{
+ return _owner->GetTeam() == HORDE ? GARRISON_FACTION_INDEX_HORDE : GARRISON_FACTION_INDEX_ALLIANCE;
+}
+
+std::vector<Garrison::Plot*> Garrison::GetPlots()
+{
+ std::vector<Plot*> plots;
+ plots.reserve(_plots.size());
+ for (auto& p : _plots)
+ plots.push_back(&p.second);
+
+ return plots;
+}
+
+Garrison::Plot* Garrison::GetPlot(uint32 garrPlotInstanceId)
+{
+ auto itr = _plots.find(garrPlotInstanceId);
+ if (itr != _plots.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+void Garrison::LearnBlueprint(uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonLearnBlueprintResult learnBlueprintResult;
+ learnBlueprintResult.BuildingID = garrBuildingId;
+ learnBlueprintResult.Result = GARRISON_SUCCESS;
+
+ if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
+ learnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
+ else if (_knownBuildings.count(garrBuildingId))
+ learnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_KNOWN;
+ else
+ _knownBuildings.insert(garrBuildingId);
+
+ _owner->SendDirectMessage(learnBlueprintResult.Write());
+}
+
+void Garrison::UnlearnBlueprint(uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonUnlearnBlueprintResult unlearnBlueprintResult;
+ unlearnBlueprintResult.BuildingID = garrBuildingId;
+ unlearnBlueprintResult.Result = GARRISON_SUCCESS;
+
+ if (!sGarrBuildingStore.LookupEntry(garrBuildingId))
+ unlearnBlueprintResult.Result = GARRISON_ERROR_INVALID_BUILDINGID;
+ else if (!_knownBuildings.count(garrBuildingId))
+ unlearnBlueprintResult.Result = GARRISON_ERROR_BLUEPRINT_NOT_KNOWN;
+ else
+ _knownBuildings.erase(garrBuildingId);
+
+ _owner->SendDirectMessage(unlearnBlueprintResult.Write());
+}
+
+void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId)
+{
+ WorldPackets::Garrison::GarrisonPlaceBuildingResult placeBuildingResult;
+ placeBuildingResult.Result = CheckBuildingPlacement(garrPlotInstanceId, garrBuildingId);
+ if (placeBuildingResult.Result == GARRISON_SUCCESS)
+ {
+ placeBuildingResult.BuildingInfo.GarrPlotInstanceID = garrPlotInstanceId;
+ placeBuildingResult.BuildingInfo.GarrBuildingID = garrBuildingId;
+ placeBuildingResult.BuildingInfo.TimeBuilt = time(nullptr);
+
+ Plot* plot = GetPlot(garrPlotInstanceId);
+
+ if (Map* map = FindMap())
+ {
+ if (!plot->BuildingInfo.Guid.IsEmpty())
+ {
+ if (GameObject* oldBuilding = map->GetGameObject(plot->BuildingInfo.Guid))
+ oldBuilding->AddObjectToRemoveList();
+
+ plot->BuildingInfo.Guid.Clear();
+ }
+
+ plot->BuildingInfo.PacketInfo = placeBuildingResult.BuildingInfo;
+ if (GameObject* go = plot->CreateGameObject(map, GetFaction()))
+ {
+ map->AddToMap(go);
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(garrBuildingId);
+ _owner->ModifyCurrency(building->CostCurrencyID, -building->CostCurrencyAmount, false, true);
+ _owner->ModifyMoney(-building->CostMoney, false);
+ }
+ else
+ plot->BuildingInfo.PacketInfo = boost::none;
+ }
+ }
+
+ _owner->SendDirectMessage(placeBuildingResult.Write());
+}
+
+void Garrison::SendInfo()
+{
+ WorldPackets::Garrison::GetGarrisonInfoResult garrisonInfo;
+ garrisonInfo.GarrSiteID = _siteLevel->SiteID;
+ garrisonInfo.GarrSiteLevelID = _siteLevel->ID;
+ garrisonInfo.FactionIndex = GetFaction();
+ garrisonInfo.NumFollowerActivationsRemaining = _followerActivationsRemainingToday;
+ for (auto& p : _plots)
+ {
+ Plot& plot = p.second;
+ garrisonInfo.Plots.push_back(&plot.PacketInfo);
+ if (plot.BuildingInfo.PacketInfo)
+ garrisonInfo.Buildings.push_back(plot.BuildingInfo.PacketInfo.get_ptr());
+ }
+
+ _owner->SendDirectMessage(garrisonInfo.Write());
+}
+
+void Garrison::SendRemoteInfo() const
+{
+ MapEntry const* garrisonMap = sMapStore.LookupEntry(_siteLevel->MapID);
+ if (!garrisonMap || int32(_owner->GetMapId()) != garrisonMap->ParentMapID)
+ return;
+
+ WorldPackets::Garrison::GarrisonRemoteInfo remoteInfo;
+ remoteInfo.Sites.resize(1);
+
+ WorldPackets::Garrison::GarrisonRemoteSiteInfo& remoteSiteInfo = remoteInfo.Sites[0];
+ remoteSiteInfo.GarrSiteLevelID = _siteLevel->ID;
+ for (auto const& p : _plots)
+ if (p.second.BuildingInfo.PacketInfo)
+ remoteSiteInfo.Buildings.emplace_back(p.first, p.second.BuildingInfo.PacketInfo->GarrBuildingID);
+
+ _owner->SendDirectMessage(remoteInfo.Write());
+}
+
+void Garrison::SendBlueprintAndSpecializationData()
+{
+ WorldPackets::Garrison::GarrisonRequestBlueprintAndSpecializationDataResult data;
+ data.BlueprintsKnown = &_knownBuildings;
+ _owner->SendDirectMessage(data.Write());
+}
+
+void Garrison::SendBuildingLandmarks(Player* receiver) const
+{
+ WorldPackets::Garrison::GarrisonBuildingLandmarks buildingLandmarks;
+ buildingLandmarks.Landmarks.reserve(_plots.size());
+
+ for (auto const& p : _plots)
+ {
+ Plot const& plot = p.second;
+ if (plot.BuildingInfo.PacketInfo)
+ if (uint32 garrBuildingPlotInstId = sGarrisonMgr.GetGarrBuildingPlotInst(plot.BuildingInfo.PacketInfo->GarrBuildingID, plot.GarrSiteLevelPlotInstId))
+ buildingLandmarks.Landmarks.emplace_back(garrBuildingPlotInstId, plot.PacketInfo.PlotPos);
+ }
+
+ receiver->SendDirectMessage(buildingLandmarks.Write());
+}
+
+Map* Garrison::FindMap() const
+{
+ return sMapMgr->FindMap(_siteLevel->MapID, _owner->GetGUID().GetCounter());
+}
+
+GarrisonError Garrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const
+{
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.LookupEntry(garrPlotInstanceId);
+ if (!plotInstance || !_plots.count(garrPlotInstanceId))
+ return GARRISON_ERROR_INVALID_PLOT;
+
+ GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(garrBuildingId);
+ if (!building)
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
+ if (!sGarrisonMgr.IsPlotMatchingBuilding(plotInstance->GarrPlotID, garrBuildingId))
+ return GARRISON_ERROR_INVALID_PLOT_BUILDING;
+
+ if (building->Flags & GARRISON_BUILDING_FLAG_NEEDS_PLAN)
+ {
+ if (_knownBuildings.count(garrBuildingId))
+ return GARRISON_ERROR_BLUEPRINT_NOT_KNOWN;
+ }
+ else // Building is built as a quest reward
+ return GARRISON_ERROR_INVALID_BUILDINGID;
+
+ // Check all plots to find if we already have this building
+ GarrBuildingEntry const* existingBuilding;
+ for (auto const& p : _plots)
+ {
+ if (p.second.BuildingInfo.PacketInfo)
+ {
+ existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID);
+ if (existingBuilding->Type == building->Type)
+ if (p.first != garrPlotInstanceId || existingBuilding->Level != building->Level + 1) // check if its an upgrade in same plot
+ return GARRISON_ERROR_BUILDING_EXISTS;
+ }
+ }
+
+ if (!_owner->HasCurrency(building->CostCurrencyID, building->CostCurrencyAmount))
+ return GARRISON_ERROR_NOT_ENOUGH_CURRENCY;
+
+ if (!_owner->HasEnoughMoney(uint64(building->CostMoney)))
+ return GARRISON_ERROR_NOT_ENOUGH_GOLD;
+
+ return GARRISON_SUCCESS;
+}
+
+GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex faction)
+{
+ uint32 entry = EmptyGameObjectId;
+ if (BuildingInfo.PacketInfo)
+ {
+ GarrPlotInstanceEntry const* plotInstance = sGarrPlotInstanceStore.AssertEntry(PacketInfo.GarrPlotInstanceID);
+ GarrPlotEntry const* plot = sGarrPlotStore.AssertEntry(plotInstance->GarrPlotID);
+ GarrBuildingEntry const* building = sGarrBuildingStore.AssertEntry(BuildingInfo.PacketInfo->GarrBuildingID);
+ if (BuildingInfo.PacketInfo->TimeBuilt + building->BuildDuration <= time(nullptr) && BuildingInfo.PacketInfo->Active)
+ entry = faction == GARRISON_FACTION_INDEX_HORDE ? building->HordeGameObjectID : building->AllianceGameObjectID;
+ else
+ entry = faction == GARRISON_FACTION_INDEX_HORDE ? plot->HordeConstructionGameObjectID : plot->AllianceConstructionGameObjectID;
+ }
+
+ if (!sObjectMgr->GetGameObjectTemplate(entry))
+ {
+ TC_LOG_ERROR("garrison", "Garrison attempted to spawn gameobject whose template doesn't exist (%u)", entry);
+ return nullptr;
+ }
+
+ Position const& pos = PacketInfo.PlotPos;
+ GameObject* go = new GameObject();
+ if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, 0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(),
+ 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_ACTIVE))
+ {
+ delete go;
+ return nullptr;
+ }
+
+ BuildingInfo.Guid = go->GetGUID();
+ return go;
+}
diff --git a/src/server/game/Garrison/Garrison.h b/src/server/game/Garrison/Garrison.h
new file mode 100644
index 00000000000..37712386d0b
--- /dev/null
+++ b/src/server/game/Garrison/Garrison.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef Garrison_h__
+#define Garrison_h__
+
+#include "Player.h"
+#include "GarrisonPackets.h"
+
+enum GarrisonFactionIndex
+{
+ GARRISON_FACTION_INDEX_HORDE = 0,
+ GARRISON_FACTION_INDEX_ALLIANCE = 1
+};
+
+enum GarrisonBuildingFlags
+{
+ GARRISON_BUILDING_FLAG_NEEDS_PLAN = 0x1
+};
+
+enum GarrisonError
+{
+ GARRISON_SUCCESS = 0,
+ GARRISON_ERROR_INVALID_PLOT = 1,
+ GARRISON_ERROR_INVALID_BUILDINGID = 2,
+ GARRISON_ERROR_INVALID_PLOT_BUILDING = 7,
+ GARRISON_ERROR_NO_BUILDING = 8,
+ GARRISON_ERROR_SPECIALIZATION_KNOWN = 19,
+ GARRISON_ERROR_BLUEPRINT_KNOWN = 21,
+ GARRISON_ERROR_BLUEPRINT_NOT_KNOWN = 22,
+ GARRISON_ERROR_BUILDING_EXISTS = 24,
+ GARRISON_ERROR_NOT_ENOUGH_CURRENCY = 46,
+ GARRISON_ERROR_NOT_ENOUGH_GOLD = 47
+};
+
+enum GarrisonFollowerStatus
+{
+ FOLLOWER_STATUS_FAVORITE = 0x01,
+ FOLLOWER_STATUS_EXHAUSTED = 0x02,
+ FOLLOWER_STATUS_INACTIVE = 0x04
+};
+
+class GameObject;
+class Map;
+
+class Garrison
+{
+public:
+ struct Building
+ {
+ ObjectGuid Guid;
+ Optional<WorldPackets::Garrison::GarrisonBuildingInfo> PacketInfo;
+ };
+
+ struct Plot
+ {
+ GameObject* CreateGameObject(Map* map, GarrisonFactionIndex faction);
+
+ WorldPackets::Garrison::GarrisonPlotInfo PacketInfo;
+ uint32 EmptyGameObjectId = 0;
+ uint32 GarrSiteLevelPlotInstId = 0;
+ Building BuildingInfo;
+ };
+
+ explicit Garrison(Player* owner);
+
+ bool LoadFromDB(PreparedQueryResult garrison, PreparedQueryResult blueprints, PreparedQueryResult buildings);
+ void SaveToDB(SQLTransaction& trans);
+
+ bool Create(uint32 garrSiteId);
+ void Upgrade();
+
+ void Enter() const;
+ void Leave() const;
+
+ GarrisonFactionIndex GetFaction() const;
+ std::vector<Plot*> GetPlots();
+ Plot* GetPlot(uint32 garrPlotInstanceId);
+
+ void LearnBlueprint(uint32 garrBuildingId);
+ void UnlearnBlueprint(uint32 garrBuildingId);
+ void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId);
+
+ void SendInfo();
+ void SendRemoteInfo() const;
+ void SendBlueprintAndSpecializationData();
+ void SendBuildingLandmarks(Player* receiver) const;
+
+ void ResetFollowerActivationLimit() { _followerActivationsRemainingToday = 1; }
+
+private:
+ Map* FindMap() const;
+ void InitializePlots();
+ GarrisonError CheckBuildingPlacement(uint32 garrPlotInstanceId, uint32 garrBuildingId) const;
+ Player* _owner;
+ GarrSiteLevelEntry const* _siteLevel;
+ uint32 _followerActivationsRemainingToday;
+
+ std::unordered_map<uint32 /*garrPlotInstanceId*/, Plot> _plots;
+ std::unordered_set<uint32 /*garrBuildingId*/> _knownBuildings;
+};
+
+#endif // Garrison_h__
diff --git a/src/server/game/Garrison/GarrisonMap.cpp b/src/server/game/Garrison/GarrisonMap.cpp
new file mode 100644
index 00000000000..32b37cff03f
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMap.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "GarrisonMap.h"
+#include "Garrison.h"
+#include "ObjectAccessor.h"
+#include "ObjectGridLoader.h"
+
+class GarrisonGridLoader
+{
+public:
+ GarrisonGridLoader(NGridType* grid, GarrisonMap* map, Cell const& cell)
+ : i_cell(cell), i_grid(grid), i_map(map), i_garrison(map->GetGarrison()), i_gameObjects(0), i_creatures(0)
+ { }
+
+ void Visit(GameObjectMapType& m);
+ void Visit(CreatureMapType& m);
+
+ void LoadN();
+
+ template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord);
+ template<class T> void Visit(GridRefManager<T>& /*m*/) { }
+
+private:
+ Cell i_cell;
+ NGridType* i_grid;
+ GarrisonMap* i_map;
+ Garrison* i_garrison;
+ uint32 i_gameObjects;
+ uint32 i_creatures;
+};
+
+void GarrisonGridLoader::LoadN()
+{
+ if (i_garrison)
+ {
+ i_cell.data.Part.cell_y = 0;
+ for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x)
+ {
+ i_cell.data.Part.cell_x = x;
+ for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y)
+ {
+ i_cell.data.Part.cell_y = y;
+
+ //Load creatures and game objects
+ TypeContainerVisitor<GarrisonGridLoader, GridTypeMapContainer> visitor(*this);
+ i_grid->VisitGrid(x, y, visitor);
+ }
+ }
+ }
+
+ TC_LOG_DEBUG("maps", "%u GameObjects and %u Creatures loaded for grid %u on map %u", i_gameObjects, i_creatures, i_grid->GetGridId(), i_map->GetId());
+}
+
+void GarrisonGridLoader::Visit(GameObjectMapType& m)
+{
+ std::vector<Garrison::Plot*> plots = i_garrison->GetPlots();
+ if (!plots.empty())
+ {
+ CellCoord cellCoord = i_cell.GetCellCoord();
+ for (Garrison::Plot* plot : plots)
+ {
+ Position const& spawn = plot->PacketInfo.PlotPos;
+ if (cellCoord != Trinity::ComputeCellCoord(spawn.GetPositionX(), spawn.GetPositionY()))
+ continue;
+
+ GameObject* go = plot->CreateGameObject(i_map, i_garrison->GetFaction());
+ if (!go)
+ continue;
+
+ go->AddToGrid(m);
+ ObjectGridLoader::SetObjectCell(go, cellCoord);
+ go->AddToWorld();
+ ++i_gameObjects;
+ }
+ }
+}
+
+void GarrisonGridLoader::Visit(CreatureMapType& /*m*/)
+{
+
+}
+
+GarrisonMap::GarrisonMap(uint32 id, time_t expiry, uint32 instanceId, Map* parent, ObjectGuid const& owner)
+ : Map(id, expiry, instanceId, DIFFICULTY_NORMAL, parent), _owner(owner)
+{
+ GarrisonMap::InitVisibilityDistance();
+}
+
+void GarrisonMap::LoadGridObjects(NGridType* grid, Cell const& cell)
+{
+ Map::LoadGridObjects(grid, cell);
+
+ GarrisonGridLoader loader(grid, this, cell);
+ loader.LoadN();
+}
+
+Garrison* GarrisonMap::GetGarrison()
+{
+ if (Player* owner = ObjectAccessor::FindConnectedPlayer(_owner))
+ return owner->GetGarrison();
+
+ return nullptr;
+}
+
+void GarrisonMap::InitVisibilityDistance()
+{
+ //init visibility distance for instances
+ m_VisibleDistance = World::GetMaxVisibleDistanceInBGArenas();
+ m_VisibilityNotifyPeriod = World::GetVisibilityNotifyPeriodInBGArenas();
+}
diff --git a/src/server/game/Garrison/GarrisonMap.h b/src/server/game/Garrison/GarrisonMap.h
new file mode 100644
index 00000000000..0ccc77b05fa
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GarrisonMap_h__
+#define GarrisonMap_h__
+
+#include "Map.h"
+
+class Garrison;
+
+class GarrisonMap : public Map
+{
+public:
+ GarrisonMap(uint32 id, time_t, uint32 instanceId, Map* parent, ObjectGuid const& owner);
+
+ void LoadGridObjects(NGridType* grid, Cell const& cell) override;
+ Garrison* GetGarrison();
+
+ void InitVisibilityDistance() override;
+
+private:
+ ObjectGuid _owner;
+};
+
+#endif // GarrisonMap_h__
diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp
new file mode 100644
index 00000000000..dd3ff08c0d1
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "GarrisonMgr.h"
+
+void GarrisonMgr::Initialize()
+{
+ for (GarrSiteLevelPlotInstEntry const* plotInstance : sGarrSiteLevelPlotInstStore)
+ _garrisonPlotInstBySiteLevel[plotInstance->GarrSiteLevelID].push_back(plotInstance);
+
+ for (GameObjectsEntry const* gameObject : sGameObjectsStore)
+ if (gameObject->Type == GAMEOBJECT_TYPE_GARRISON_PLOT)
+ _garrisonPlots[gameObject->MapID][gameObject->Data[0]] = gameObject;
+
+ for (GarrPlotBuildingEntry const* plotBuilding : sGarrPlotBuildingStore)
+ _garrisonBuildingsByPlot[plotBuilding->GarrPlotID].insert(plotBuilding->GarrBuildingID);
+
+ for (GarrBuildingPlotInstEntry const* buildingPlotInst : sGarrBuildingPlotInstStore)
+ _garrisonBuildingPlotInstances[MAKE_PAIR64(buildingPlotInst->GarrBuildingID, buildingPlotInst->GarrSiteLevelPlotInstID)] = buildingPlotInst->ID;
+}
+
+GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
+{
+ for (GarrSiteLevelEntry const* garrSiteLevel : sGarrSiteLevelStore)
+ if (garrSiteLevel->SiteID == garrSiteId && garrSiteLevel->Level == level)
+ return garrSiteLevel;
+
+ return nullptr;
+}
+
+std::vector<GarrSiteLevelPlotInstEntry const*> const* GarrisonMgr::GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const
+{
+ auto itr = _garrisonPlotInstBySiteLevel.find(garrSiteLevelId);
+ if (itr != _garrisonPlotInstBySiteLevel.end())
+ return &itr->second;
+
+ return nullptr;
+}
+
+GameObjectsEntry const* GarrisonMgr::GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const
+{
+ auto mapItr = _garrisonPlots.find(mapId);
+ if (mapItr != _garrisonPlots.end())
+ {
+ auto plotItr = mapItr->second.find(garrPlotInstanceId);
+ if (plotItr != mapItr->second.end())
+ return plotItr->second;
+ }
+
+ return nullptr;
+}
+
+bool GarrisonMgr::IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const
+{
+ auto plotItr = _garrisonBuildingsByPlot.find(garrPlotId);
+ if (plotItr != _garrisonBuildingsByPlot.end())
+ return plotItr->second.count(garrBuildingId) > 0;
+
+ return false;
+}
+
+uint32 GarrisonMgr::GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const
+{
+ auto itr = _garrisonBuildingPlotInstances.find(MAKE_PAIR64(garrBuildingId, garrSiteLevelPlotInstId));
+ if (itr != _garrisonBuildingPlotInstances.end())
+ return itr->second;
+
+ return 0;
+}
diff --git a/src/server/game/Garrison/GarrisonMgr.h b/src/server/game/Garrison/GarrisonMgr.h
new file mode 100644
index 00000000000..ca6f4adbe48
--- /dev/null
+++ b/src/server/game/Garrison/GarrisonMgr.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GarrisonMgr_h__
+#define GarrisonMgr_h__
+
+#include "DB2Stores.h"
+
+class GarrisonMgr
+{
+public:
+ static GarrisonMgr& Instance()
+ {
+ static GarrisonMgr instance;
+ return instance;
+ }
+
+ void Initialize();
+
+ GarrSiteLevelEntry const* GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const;
+ std::vector<GarrSiteLevelPlotInstEntry const*> const* GetGarrPlotInstForSiteLevel(uint32 garrSiteLevelId) const;
+ GameObjectsEntry const* GetPlotGameObject(uint32 mapId, uint32 garrPlotInstanceId) const;
+ bool IsPlotMatchingBuilding(uint32 garrPlotId, uint32 garrBuildingId) const;
+ uint32 GetGarrBuildingPlotInst(uint32 garrBuildingId, uint32 garrSiteLevelPlotInstId) const;
+
+private:
+ 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;
+};
+
+#define sGarrisonMgr GarrisonMgr::Instance()
+
+#endif // GarrisonMgr_h__