diff options
author | Shauren <shauren.trinity@gmail.com> | 2015-05-08 00:03:15 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2015-05-08 00:03:15 +0200 |
commit | 5b725db033c656bda5e718ea05a79005946e089e (patch) | |
tree | c15ad544c542cdd7dd7cb395c8ec6d3d35e4d2e9 /src/server/game/Garrison | |
parent | 0972552e84068cf453231b372bcb232cf2d2f42b (diff) |
Core/Garrisons: Basics for garrisons
Diffstat (limited to 'src/server/game/Garrison')
-rw-r--r-- | src/server/game/Garrison/Garrison.cpp | 420 | ||||
-rw-r--r-- | src/server/game/Garrison/Garrison.h | 117 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMap.cpp | 125 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMap.h | 39 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMgr.cpp | 83 | ||||
-rw-r--r-- | src/server/game/Garrison/GarrisonMgr.h | 49 |
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__ |