aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Garrison/GarrisonMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Garrison/GarrisonMgr.cpp')
-rw-r--r--src/server/game/Garrison/GarrisonMgr.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp
index f81baa6ddf1..bb2d44d7141 100644
--- a/src/server/game/Garrison/GarrisonMgr.cpp
+++ b/src/server/game/Garrison/GarrisonMgr.cpp
@@ -16,7 +16,10 @@
*/
#include "GarrisonMgr.h"
+#include "Containers.h"
+#include "Garrison.h"
#include "ObjectDefines.h"
+#include "World.h"
void GarrisonMgr::Initialize()
{
@@ -35,6 +38,23 @@ void GarrisonMgr::Initialize()
for (GarrBuildingEntry const* building : sGarrBuildingStore)
_garrisonBuildingsByType[building->Type].push_back(building);
+
+ for (GarrFollowerXAbilityEntry const* followerAbility : sGarrFollowerXAbilityStore)
+ {
+ if (GarrAbilityEntry const* ability = sGarrAbilityStore.LookupEntry(followerAbility->GarrAbilityID))
+ {
+ if (!(ability->Flags & GARRISON_ABILITY_CANNOT_ROLL) && ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerRandomTraits.insert(ability);
+
+ if (followerAbility->FactionIndex < 2)
+ {
+ if (ability->Flags & GARRISON_ABILITY_FLAG_TRAIT)
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Traits.insert(ability);
+ else
+ _garrisonFollowerAbilities[followerAbility->FactionIndex][followerAbility->GarrFollowerID].Counters.insert(ability);
+ }
+ }
+ }
}
GarrSiteLevelEntry const* GarrisonMgr::GetGarrSiteLevelEntry(uint32 garrSiteId, uint32 level) const
@@ -96,3 +116,116 @@ GarrBuildingEntry const* GarrisonMgr::GetPreviousLevelBuilding(uint32 buildingTy
return nullptr;
}
+
+uint64 GarrisonMgr::GenerateFollowerDbId()
+{
+ if (_followerDbIdGenerator >= std::numeric_limits<uint64>::max())
+ {
+ TC_LOG_ERROR("misc", "Garrison follower db id oberflow! Can't continue, shutting down server. ");
+ World::StopNow(ERROR_EXIT_CODE);
+ }
+
+ return _followerDbIdGenerator++;
+}
+
+uint32 const AbilitiesForQuality[][2] =
+{
+ // Counters, Traits
+ { 0, 0 },
+ { 1, 0 },
+ { 1, 1 }, // Uncommon
+ { 1, 2 }, // Rare
+ { 2, 3 }, // Epic
+ { 2, 3 } // Legendary
+};
+
+std::list<uint32> GarrisonMgr::RollFollowerAbilities(GarrFollowerEntry const* follower, uint32 quality, uint32 faction, bool initial) const
+{
+ ASSERT(faction < 2);
+
+ std::list<uint32> result;
+ int32 slots[2] = { AbilitiesForQuality[quality][0], AbilitiesForQuality[quality][1] };
+
+ GarrAbilities const* abilities = nullptr;
+ auto itr = _garrisonFollowerAbilities[faction].find(follower->ID);
+ if (itr != _garrisonFollowerAbilities[faction].end())
+ abilities = &itr->second;
+
+ std::list<uint32> abilityList, forcedAbilities, traitList, forcedTraits;
+ if (abilities)
+ {
+ for (GarrAbilityEntry const* ability : abilities->Counters)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedAbilities.push_back(ability->ID);
+ else
+ abilityList.push_back(ability->ID);
+ }
+
+ for (GarrAbilityEntry const* ability : abilities->Traits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ if (ability->Flags & GARRISON_ABILITY_FLAG_CANNOT_REMOVE)
+ forcedTraits.push_back(ability->ID);
+ else
+ traitList.push_back(ability->ID);
+ }
+ }
+
+ 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
+ if (initial)
+ {
+ forcedAbilities.splice(forcedAbilities.end(), abilityList);
+ forcedTraits.splice(forcedTraits.end(), traitList);
+ }
+
+ if (slots[0] > forcedAbilities.size() + abilityList.size())
+ {
+ std::list<uint32> classSpecAbilities; // = GetDefaultClassSpecAbilities(follower, faction)
+
+ abilityList.splice(abilityList.end(), classSpecAbilities);
+ abilityList.sort();
+ abilityList.unique();
+
+ Trinity::Containers::RandomResizeList(abilityList, std::max<int32>(0, slots[0] - forcedAbilities.size()));
+ }
+
+ if (slots[1] > forcedTraits.size() + traitList.size())
+ {
+ std::list<uint32> genericTraits;
+ for (GarrAbilityEntry const* ability : _garrisonFollowerRandomTraits)
+ {
+ if (ability->Flags & GARRISON_ABILITY_HORDE_ONLY && faction != GARRISON_FACTION_INDEX_HORDE)
+ continue;
+ else if (ability->Flags & GARRISON_ABILITY_ALLIANCE_ONLY && faction != GARRISON_FACTION_INDEX_ALLIANCE)
+ continue;
+
+ genericTraits.push_back(ability->ID);
+ }
+
+ traitList.splice(traitList.end(), genericTraits);
+ traitList.sort();
+ traitList.unique();
+
+ Trinity::Containers::RandomResizeList(traitList, std::max<int32>(0, slots[1] - forcedTraits.size()));
+ }
+
+ result.splice(result.end(), forcedAbilities);
+ result.splice(result.end(), abilityList);
+ result.splice(result.end(), forcedTraits);
+ result.splice(result.end(), traitList);
+
+ return result;
+}