diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-08-10 00:05:56 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-08-10 00:05:56 +0200 |
commit | bd3541d106bbdb50ad53e38e6c7f2bc78dd6c1dc (patch) | |
tree | fe04d16d9ca7e5f8afa0e87926cf45aeb357ef16 /src | |
parent | 51657e44d1430a93a4256a535af0a67660c95119 (diff) |
Core/DataStores: Implemented all curve types from Curve.db2
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.cpp | 3 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.h | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 194 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 6 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.cpp | 20 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Item/ItemTemplate.h | 7 |
8 files changed, 196 insertions, 45 deletions
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 71a874d7198..65d1b825570 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -183,6 +183,9 @@ void HotfixDatabaseConnection::DoPrepareStatements() "CategoryID, SpellCategory, Quality, SpellWeight FROM currency_types ORDER BY ID DESC", CONNECTION_SYNCH); PREPARE_LOCALE_STMT(HOTFIX_SEL_CURRENCY_TYPES, "SELECT ID, Name_lang, Description_lang FROM currency_types_locale WHERE locale = ?", CONNECTION_SYNCH); + // Curve.db2 + PrepareStatement(HOTFIX_SEL_CURVE, "SELECT ID, Type, Unused FROM curve ORDER BY ID DESC", CONNECTION_SYNCH); + // CurvePoint.db2 PrepareStatement(HOTFIX_SEL_CURVE_POINT, "SELECT ID, X, Y, CurveID, `Index` FROM curve_point ORDER BY ID DESC", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 66d9d65cb07..1b6fef8b5d0 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -114,6 +114,8 @@ enum HotfixDatabaseStatements HOTFIX_SEL_CURRENCY_TYPES, HOTFIX_SEL_CURRENCY_TYPES_LOCALE, + HOTFIX_SEL_CURVE, + HOTFIX_SEL_CURVE_POINT, HOTFIX_SEL_DESTRUCTIBLE_MODEL_DATA, diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index f86cc7da260..be7e67b49a4 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -57,6 +57,7 @@ DB2Storage<CreatureTypeEntry> sCreatureTypeStore("CreatureType DB2Storage<CriteriaEntry> sCriteriaStore("Criteria.db2", CriteriaMeta::Instance(), HOTFIX_SEL_CRITERIA); DB2Storage<CriteriaTreeEntry> sCriteriaTreeStore("CriteriaTree.db2", CriteriaTreeMeta::Instance(), HOTFIX_SEL_CRITERIA_TREE); DB2Storage<CurrencyTypesEntry> sCurrencyTypesStore("CurrencyTypes.db2", CurrencyTypesMeta::Instance(), HOTFIX_SEL_CURRENCY_TYPES); +DB2Storage<CurveEntry> sCurveStore("Curve.db2", CurveMeta::Instance(), HOTFIX_SEL_CURVE); DB2Storage<CurvePointEntry> sCurvePointStore("CurvePoint.db2", CurvePointMeta::Instance(), HOTFIX_SEL_CURVE_POINT); DB2Storage<DestructibleModelDataEntry> sDestructibleModelDataStore("DestructibleModelData.db2", DestructibleModelDataMeta::Instance(), HOTFIX_SEL_DESTRUCTIBLE_MODEL_DATA); DB2Storage<DifficultyEntry> sDifficultyStore("Difficulty.db2", DifficultyMeta::Instance(), HOTFIX_SEL_DIFFICULTY); @@ -319,6 +320,7 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) LOAD_DB2(sCriteriaStore); LOAD_DB2(sCriteriaTreeStore); LOAD_DB2(sCurrencyTypesStore); + LOAD_DB2(sCurveStore); LOAD_DB2(sCurvePointStore); LOAD_DB2(sDestructibleModelDataStore); LOAD_DB2(sDifficultyStore); @@ -565,6 +567,13 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) _chrSpecializationsByIndex[storageIndex][chrSpec->OrderIndex] = chrSpec; } + for (CurvePointEntry const* curvePoint : sCurvePointStore) + if (sCurveStore.LookupEntry(curvePoint->CurveID)) + _curvePoints[curvePoint->CurveID].push_back(curvePoint); + + for (auto itr = _curvePoints.begin(); itr != _curvePoints.end(); ++itr) + std::sort(itr->second.begin(), itr->second.end(), [](CurvePointEntry const* point1, CurvePointEntry const* point2) { return point1->Index < point2->Index; }); + ASSERT(MAX_DIFFICULTY >= sDifficultyStore.GetNumRows(), "MAX_DIFFICULTY is not large enough to contain all difficulties! (current value %d, required %d)", MAX_DIFFICULTY, sDifficultyStore.GetNumRows()); @@ -626,16 +635,6 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) for (ItemXBonusTreeEntry const* itemBonusTreeAssignment : sItemXBonusTreeStore) _itemToBonusTree.insert({ itemBonusTreeAssignment->ItemID, itemBonusTreeAssignment->BonusTreeID }); - { - std::set<uint32> scalingCurves; - for (ScalingStatDistributionEntry const* ssd : sScalingStatDistributionStore) - scalingCurves.insert(ssd->ItemLevelCurveID); - - for (CurvePointEntry const* curvePoint : sCurvePointStore) - if (scalingCurves.count(curvePoint->CurveID)) - _heirloomCurvePoints[curvePoint->CurveID][curvePoint->Index] = curvePoint; - } - for (MapDifficultyEntry const* entry : sMapDifficultyStore) _mapDifficulties[entry->MapID][entry->DifficultyID] = entry; _mapDifficulties[0][0] = _mapDifficulties[1][0]; // map 0 is missing from MapDifficulty.dbc so we cheat a bit @@ -997,6 +996,162 @@ char const* DB2Manager::GetCreatureFamilyPetName(uint32 petfamily, uint32 locale return petFamily->Name->Str[locale][0] != '\0' ? petFamily->Name->Str[locale] : nullptr; } +enum class CurveInterpolationMode : uint8 +{ + Linear = 0, + Cosine = 1, + CatmullRom = 2, + Bezier3 = 3, + Bezier4 = 4, + Bezier = 5, + Constant = 6, +}; + +static CurveInterpolationMode DetermineCurveType(CurveEntry const* curve, std::vector<CurvePointEntry const*> const& points) +{ + switch (curve->Type) + { + case 1: + return points.size() < 4 ? CurveInterpolationMode::Cosine : CurveInterpolationMode::CatmullRom; + case 2: + { + switch (points.size()) + { + case 1: + return CurveInterpolationMode::Constant; + case 2: + return CurveInterpolationMode::Linear; + case 3: + return CurveInterpolationMode::Bezier3; + case 4: + return CurveInterpolationMode::Bezier4; + default: + break; + } + return CurveInterpolationMode::Bezier; + } + case 3: + return CurveInterpolationMode::Cosine; + default: + break; + } + + return points.size() != 1 ? CurveInterpolationMode::Linear : CurveInterpolationMode::Constant; +} + +float DB2Manager::GetCurveValueAt(uint32 curveId, float x) const +{ + auto itr = _curvePoints.find(curveId); + if (itr == _curvePoints.end()) + return 0.0f; + + CurveEntry const* curve = sCurveStore.AssertEntry(curveId); + std::vector<CurvePointEntry const*> const& points = itr->second; + if (points.empty()) + return 0.0f; + + switch (DetermineCurveType(curve, points)) + { + case CurveInterpolationMode::Linear: + { + std::size_t pointIndex = 0; + while (pointIndex < points.size() && points[pointIndex]->X <= x) + ++pointIndex; + if (!pointIndex) + return points[0]->Y; + if (pointIndex >= points.size()) + return points.back()->Y; + float xDiff = points[pointIndex]->X - points[pointIndex - 1]->X; + if (xDiff == 0.0) + return points[pointIndex]->Y; + return (((x - points[pointIndex - 1]->X) / xDiff) * (points[pointIndex]->Y - points[pointIndex - 1]->Y)) + points[pointIndex - 1]->Y; + } + case CurveInterpolationMode::Cosine: + { + std::size_t pointIndex = 0; + while (pointIndex < points.size() && points[pointIndex]->X <= x) + ++pointIndex; + if (!pointIndex) + return points[0]->Y; + if (pointIndex >= points.size()) + return points.back()->Y; + float xDiff = points[pointIndex]->X - points[pointIndex - 1]->X; + if (xDiff == 0.0) + return points[pointIndex]->Y; + return ((points[pointIndex]->Y - points[pointIndex - 1]->Y) * (1.0f - std::cos((x - points[pointIndex - 1]->X) / xDiff * float(M_PI))) * 0.5f) + points[pointIndex - 1]->Y; + } + case CurveInterpolationMode::CatmullRom: + { + std::size_t pointIndex = 1; + while (pointIndex < points.size() && points[pointIndex]->X <= x) + ++pointIndex; + if (pointIndex == 1) + return points[1]->Y; + if (pointIndex >= points.size() - 1) + return points[points.size() - 2]->Y; + float xDiff = points[pointIndex]->X - points[pointIndex - 1]->X; + if (xDiff == 0.0) + return points[pointIndex]->Y; + + float mu = (x - points[pointIndex - 1]->X) / xDiff; + float a0 = -0.5f * points[pointIndex - 2]->Y + 1.5f * points[pointIndex - 1]->Y - 1.5f * points[pointIndex]->Y + 0.5f * points[pointIndex + 1]->Y; + float a1 = points[pointIndex - 2]->Y - 2.5f * points[pointIndex - 1]->Y + 2.0f * points[pointIndex]->Y - 0.5f * points[pointIndex + 1]->Y; + float a2 = -0.5f * points[pointIndex - 2]->Y + 0.5f * points[pointIndex]->Y; + float a3 = points[pointIndex - 1]->Y; + + return a0 * mu * mu * mu + a1 * mu * mu + a2 * mu + a3; + } + case CurveInterpolationMode::Bezier3: + { + float xDiff = points[2]->X - points[0]->X; + if (xDiff == 0.0) + return points[1]->Y; + float mu = (x - points[0]->X) / xDiff; + return ((1.0f - mu) * (1.0f - mu) * points[0]->Y) + (1.0f - mu) * 2.0f * mu * points[1]->Y + mu * mu * points[2]->Y; + } + case CurveInterpolationMode::Bezier4: + { + float xDiff = points[3]->X - points[0]->X; + if (xDiff == 0.0) + return points[1]->Y; + float mu = (x - points[0]->X) / xDiff; + return (1.0f - mu) * (1.0f - mu) * (1.0f - mu) * points[0]->Y + + 3.0f * mu * (1.0f - mu) * (1.0f - mu) * points[1]->Y + + 3.0f * mu * mu * (1.0f - mu) * points[2]->Y + + mu * mu * mu * points[3]->Y; + } + case CurveInterpolationMode::Bezier: + { + float xDiff = points.back()->X - points[0]->X; + if (xDiff == 0.0f) + return points.back()->Y; + + std::vector<float> tmp(points.size()); + for (std::size_t i = 0; i < points.size(); ++i) + tmp[i] = points[i]->Y; + + float mu = (x - points[0]->X) / xDiff; + int32 i = int32(points.size()) - 1; + while (i > 0) + { + for (int32 k = 0; k < i; ++k) + { + float val = tmp[k] + mu * (tmp[k + 1] - tmp[k]); + tmp[k] = val; + } + --i; + } + return tmp[0]; + } + case CurveInterpolationMode::Constant: + return points[0]->Y; + default: + break; + } + + return 0.0f; +} + EmotesTextSoundEntry const* DB2Manager::GetTextSoundEmoteFor(uint32 emote, uint8 race, uint8 gender, uint8 class_) const { auto itr = _emoteTextSounds.find(EmotesTextSoundContainer::key_type(emote, race, gender, class_)); @@ -1019,25 +1174,6 @@ std::vector<uint32> const* DB2Manager::GetFactionTeamList(uint32 faction) const return nullptr; } -uint32 DB2Manager::GetHeirloomItemLevel(uint32 curveId, uint32 level) const -{ - // Assuming linear item level scaling for heirlooms - auto itr = _heirloomCurvePoints.find(curveId); - if (itr == _heirloomCurvePoints.end()) - return 0; - - auto it2 = itr->second.begin(); // Highest scaling point - if (level >= it2->second->X) - return it2->second->Y; - - auto previousItr = it2++; - for (; it2 != itr->second.end(); ++it2, ++previousItr) - if (level >= it2->second->X) - return uint32((previousItr->second->Y - it2->second->Y) / (previousItr->second->X - it2->second->X) * (float(level) - it2->second->X) + it2->second->Y); - - return uint32(previousItr->second->Y); // Lowest scaling point -} - HeirloomEntry const* DB2Manager::GetHeirloomByItemId(uint32 itemId) const { auto itr = _heirlooms.find(itemId); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 35550f9ce0d..c5715a54fc0 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -224,9 +224,9 @@ public: typedef std::unordered_multimap<uint32, CharSectionsEntry const*> CharSectionsContainer; typedef std::unordered_map<uint32, CharStartOutfitEntry const*> CharStartOutfitContainer; typedef ChrSpecializationEntry const* ChrSpecializationByIndexContainer[MAX_CLASSES + 1][MAX_SPECIALIZATIONS]; + typedef std::unordered_map<uint32 /*curveID*/, std::vector<CurvePointEntry const*>> CurvePointsContainer; typedef std::map<std::tuple<uint32, uint8, uint8, uint8>, EmotesTextSoundEntry const*> EmotesTextSoundContainer; typedef std::unordered_map<uint32, std::vector<uint32>> FactionTeamContainer; - typedef std::map<uint32 /*curveID*/, std::map<uint32/*index*/, CurvePointEntry const*, std::greater<uint32>>> HeirloomCurvesContainer; typedef std::unordered_map<uint32, HeirloomEntry const*> HeirloomItemsContainer; typedef std::vector<ItemBonusEntry const*> ItemBonusList; typedef std::unordered_map<uint32 /*bonusListId*/, ItemBonusList> ItemBonusListContainer; @@ -274,9 +274,9 @@ public: static char const* GetChrRaceName(uint8 race, LocaleConstant locale = DEFAULT_LOCALE); ChrSpecializationEntry const* GetChrSpecializationByIndex(uint32 class_, uint32 index) const; static char const* GetCreatureFamilyPetName(uint32 petfamily, uint32 locale); + float GetCurveValueAt(uint32 curveId, float x) const; EmotesTextSoundEntry const* GetTextSoundEmoteFor(uint32 emote, uint8 race, uint8 gender, uint8 class_) const; std::vector<uint32> const* GetFactionTeamList(uint32 faction) const; - uint32 GetHeirloomItemLevel(uint32 curveId, uint32 level) const; HeirloomEntry const* GetHeirloomByItemId(uint32 itemId) const; ItemBonusList const* GetItemBonusList(uint32 bonusListId) const; std::set<uint32> GetItemBonusTree(uint32 itemId, uint32 itemBonusTreeMod) const; @@ -326,10 +326,10 @@ private: CharStartOutfitContainer _charStartOutfits; uint32 _powersByClass[MAX_CLASSES][MAX_POWERS]; ChrSpecializationByIndexContainer _chrSpecializationsByIndex; + CurvePointsContainer _curvePoints; EmotesTextSoundContainer _emoteTextSounds; FactionTeamContainer _factionTeams; HeirloomItemsContainer _heirlooms; - HeirloomCurvesContainer _heirloomCurvePoints; ItemBonusListContainer _itemBonusLists; ItemBonusTreeContainer _itemBonusTrees; ItemChildEquipmentContainer _itemChildEquipment; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 2101661912a..32868b632c3 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -628,6 +628,13 @@ struct CurrencyTypesEntry uint32 SpellWeight; }; +struct CurveEntry +{ + uint32 ID; + uint8 Type; + uint8 Unused; +}; + struct CurvePointEntry { uint32 ID; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 2fb7516ffb6..ce97bca9a35 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -654,9 +654,9 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie for (uint32 i = 0; i < MAX_GEM_SOCKETS; ++i) { gemData[i].ItemId = fields[29 + i * MAX_GEM_SOCKETS].GetUInt32(); - Tokenizer bonusListIDs(fields[30 + i * MAX_GEM_SOCKETS].GetString(), ' '); + Tokenizer gemBonusListIDs(fields[30 + i * MAX_GEM_SOCKETS].GetString(), ' '); uint32 b = 0; - for (char const* token : bonusListIDs) + for (char const* token : gemBonusListIDs) if (uint32 bonusListID = atoul(token)) gemData[i].BonusListIDs[b++] = bonusListID; @@ -1106,8 +1106,8 @@ bool Item::GemsFitSockets() const uint32 gemSlot = 0; for (ItemDynamicFieldGems const& gemData : GetGems()) { - uint8 SocketColor = GetTemplate()->GetSocketColor(gemSlot); - if (!SocketColor) // no socket slot + SocketColor color = GetTemplate()->GetSocketColor(gemSlot); + if (!color) // no socket slot continue; uint32 GemColor = 0; @@ -1120,7 +1120,7 @@ bool Item::GemsFitSockets() const GemColor = gemProperty->Type; } - if (!(GemColor & SocketColorToGemTypeMask[SocketColor])) // bad gem color on this socket + if (!(GemColor & SocketColorToGemTypeMask[color])) // bad gem color on this socket return false; } return true; @@ -1128,22 +1128,22 @@ bool Item::GemsFitSockets() const uint8 Item::GetGemCountWithID(uint32 GemID) const { - return std::count_if(GetGems().begin(), GetGems().end(), [GemID](ItemDynamicFieldGems const& gemData) + return uint8(std::count_if(GetGems().begin(), GetGems().end(), [GemID](ItemDynamicFieldGems const& gemData) { return gemData.ItemId == GemID; - }); + })); } uint8 Item::GetGemCountWithLimitCategory(uint32 limitCategory) const { - return std::count_if(GetGems().begin(), GetGems().end(), [limitCategory](ItemDynamicFieldGems const& gemData) + return uint8(std::count_if(GetGems().begin(), GetGems().end(), [limitCategory](ItemDynamicFieldGems const& gemData) { ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemData.ItemId); if (!gemProto) return false; return gemProto->GetItemLimitCategory() == limitCategory; - }); + })); } bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const @@ -1972,7 +1972,7 @@ uint32 Item::GetItemLevel(Player const* owner) const uint32 itemLevel = stats->GetBaseItemLevel(); if (ScalingStatDistributionEntry const* ssd = sScalingStatDistributionStore.LookupEntry(GetScalingStatDistribution())) - if (uint32 heirloomIlvl = sDB2Manager.GetHeirloomItemLevel(ssd->ItemLevelCurveID, owner->getLevel())) + if (uint32 heirloomIlvl = uint32(sDB2Manager.GetCurveValueAt(ssd->ItemLevelCurveID, owner->getLevel()))) itemLevel = heirloomIlvl; if (ItemUpgradeEntry const* upgrade = sItemUpgradeStore.LookupEntry(GetModifier(ITEM_MODIFIER_UPGRADE_ID))) diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 683353a7fe3..fe86591ccc3 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -224,7 +224,7 @@ enum ItemUpdateState ITEM_REMOVED = 3 }; -enum ItemModifier +enum ItemModifier : uint16 { ITEM_MODIFIER_TRANSMOG_APPEARANCE_ALL_SPECS = 0, ITEM_MODIFIER_TRANSMOG_APPEARANCE_SPEC_1 = 1, diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index d95b361da89..bbf89d18dbf 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -691,8 +691,11 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = #define MAX_ITEM_SUBCLASS_TOTAL 21 -#define MIN_ITEM_LEVEL 1 -#define MAX_ITEM_LEVEL 1000 +enum ItemLevelConstants : uint32 +{ + MIN_ITEM_LEVEL = 1, + MAX_ITEM_LEVEL = 1300 +}; class Player; struct ChrSpecializationEntry; |