mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/DataStores: Implemented all curve types from Curve.db2
This commit is contained in:
11
sql/updates/hotfixes/6.x/2016_08_09_00_hotfixes.sql
Normal file
11
sql/updates/hotfixes/6.x/2016_08_09_00_hotfixes.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
--
|
||||
-- Table structure for table `curve`
|
||||
--
|
||||
DROP TABLE IF EXISTS `curve`;
|
||||
CREATE TABLE `curve` (
|
||||
`ID` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`Type` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`Unused` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ID`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -628,6 +628,13 @@ struct CurrencyTypesEntry
|
||||
uint32 SpellWeight;
|
||||
};
|
||||
|
||||
struct CurveEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint8 Type;
|
||||
uint8 Unused;
|
||||
};
|
||||
|
||||
struct CurvePointEntry
|
||||
{
|
||||
uint32 ID;
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user