TrinityCore
Loading...
Searching...
No Matches
ItemEnchantmentMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ItemEnchantmentMgr.h"
19#include "DatabaseEnv.h"
20#include "Log.h"
21#include "ObjectMgr.h"
22#include "Util.h"
23#include "DBCStores.h"
24#include "Random.h"
25#include "Timer.h"
26
27#include <list>
28#include <vector>
29#include <stdlib.h>
30
32{
34 float chance;
35
37 : ench(0), chance(0) { }
38
39 EnchStoreItem(uint32 _ench, float _chance)
40 : ench(_ench), chance(_chance) { }
41};
42
43typedef std::vector<EnchStoreItem> EnchStoreList;
44typedef std::unordered_map<uint32, EnchStoreList> EnchantmentStore;
45
47
49{
50 uint32 oldMSTime = getMSTime();
51
52 RandomItemEnch.clear(); // for reload case
53
54 // 0 1 2
55 QueryResult result = WorldDatabase.Query("SELECT entry, ench, chance FROM item_enchantment_template");
56
57 if (result)
58 {
59 uint32 count = 0;
60
61 do
62 {
63 Field* fields = result->Fetch();
64
65 uint32 entry = fields[0].GetUInt32();
66 uint32 ench = fields[1].GetUInt32();
67 float chance = fields[2].GetFloat();
68
69 if (chance > 0.000001f && chance <= 100.0f)
70 RandomItemEnch[entry].push_back(EnchStoreItem(ench, chance));
71
72 ++count;
73 } while (result->NextRow());
74
75 TC_LOG_INFO("server.loading", ">> Loaded {} Item Enchantment definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
76 }
77 else
78 TC_LOG_INFO("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
79}
80
82{
83 if (!entry)
84 return 0;
85
86 if (entry == -1)
87 return 0;
88
89 EnchantmentStore::const_iterator tab = RandomItemEnch.find(entry);
90 if (tab == RandomItemEnch.end())
91 {
92 TC_LOG_ERROR("sql.sql", "Item RandomProperty / RandomSuffix id #{} used in `item_template` but it does not have records in `item_enchantment_template` table.", entry);
93 return 0;
94 }
95
96 double dRoll = rand_chance();
97 float fCount = 0;
98
99 for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter)
100 {
101 fCount += ench_iter->chance;
102
103 if (fCount > dRoll)
104 return ench_iter->ench;
105 }
106
107 //we could get here only if sum of all enchantment chances is lower than 100%
108 dRoll = (irand(0, (int)floor(fCount * 100) + 1)) / 100;
109 fCount = 0;
110
111 for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter)
112 {
113 fCount += ench_iter->chance;
114
115 if (fCount > dRoll)
116 return ench_iter->ench;
117 }
118
119 return 0;
120}
121
123{
124 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
125
126 if (!itemProto)
127 return 0;
128
129 // item must have one from this field values not null if it can have random enchantments
130 if ((!itemProto->RandomProperty) && (!itemProto->RandomSuffix))
131 return 0;
132
133 // item can have not null only one from field values
134 if ((itemProto->RandomProperty) && (itemProto->RandomSuffix))
135 {
136 TC_LOG_ERROR("sql.sql", "Item template {} have RandomProperty == {} and RandomSuffix == {}, but must have one from field =0", itemProto->ItemId, itemProto->RandomProperty, itemProto->RandomSuffix);
137 return 0;
138 }
139
140 // RandomProperty case
141 if (itemProto->RandomProperty)
142 {
143 uint32 randomPropId = GetItemEnchantMod(itemProto->RandomProperty);
144 ItemRandomPropertiesEntry const* random_id = sItemRandomPropertiesStore.LookupEntry(randomPropId);
145 if (!random_id)
146 {
147 TC_LOG_ERROR("sql.sql", "Enchantment id #{} used but it doesn't have records in 'ItemRandomProperties.dbc'", randomPropId);
148 return 0;
149 }
150
151 return random_id->ID;
152 }
153 // RandomSuffix case
154 else
155 {
156 uint32 randomPropId = GetItemEnchantMod(itemProto->RandomSuffix);
157 ItemRandomSuffixEntry const* random_id = sItemRandomSuffixStore.LookupEntry(randomPropId);
158 if (!random_id)
159 {
160 TC_LOG_ERROR("sql.sql", "Enchantment id #{} used but it doesn't have records in sItemRandomSuffixStore.", randomPropId);
161 return 0;
162 }
163
164 return -int32(random_id->ID);
165 }
166}
167
169{
170 ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
171
172 if (!itemProto)
173 return 0;
174 if (!itemProto->RandomSuffix)
175 return 0;
176
177 RandPropPointsEntry const* randomProperty = sRandPropPointsStore.LookupEntry(itemProto->ItemLevel);
178 if (!randomProperty)
179 return 0;
180
181 uint32 suffixFactor;
182 switch (itemProto->InventoryType)
183 {
184 // Items of that type don`t have points
186 case INVTYPE_BAG:
187 case INVTYPE_TABARD:
188 case INVTYPE_AMMO:
189 case INVTYPE_QUIVER:
190 case INVTYPE_RELIC:
191 return 0;
192 // Select point coefficient
193 case INVTYPE_HEAD:
194 case INVTYPE_BODY:
195 case INVTYPE_CHEST:
196 case INVTYPE_LEGS:
197 case INVTYPE_2HWEAPON:
198 case INVTYPE_ROBE:
199 suffixFactor = 0;
200 break;
202 case INVTYPE_WAIST:
203 case INVTYPE_FEET:
204 case INVTYPE_HANDS:
205 case INVTYPE_TRINKET:
206 suffixFactor = 1;
207 break;
208 case INVTYPE_NECK:
209 case INVTYPE_WRISTS:
210 case INVTYPE_FINGER:
211 case INVTYPE_SHIELD:
212 case INVTYPE_CLOAK:
213 case INVTYPE_HOLDABLE:
214 suffixFactor = 2;
215 break;
216 case INVTYPE_WEAPON:
219 suffixFactor = 3;
220 break;
221 case INVTYPE_RANGED:
222 case INVTYPE_THROWN:
224 suffixFactor = 4;
225 break;
226 default:
227 return 0;
228 }
229 // Select rare/epic modifier
230 switch (itemProto->Quality)
231 {
233 return randomProperty->Good[suffixFactor];
235 return randomProperty->Superior[suffixFactor];
237 return randomProperty->Epic[suffixFactor];
240 return 0; // not have random properties
241 default:
242 break;
243 }
244 return 0;
245}
DBCStorage< RandPropPointsEntry > sRandPropPointsStore(RandPropPointsfmt)
DBCStorage< ItemRandomSuffixEntry > sItemRandomSuffixStore(ItemRandomSuffixfmt)
DBCStorage< ItemRandomPropertiesEntry > sItemRandomPropertiesStore(ItemRandomPropertiesfmt)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
uint32 GenerateEnchSuffixFactor(uint32 item_id)
void LoadRandomEnchantmentsTable()
static EnchantmentStore RandomItemEnch
uint32 GetItemEnchantMod(int32 entry)
int32 GenerateItemRandomPropertyId(uint32 item_id)
std::unordered_map< uint32, EnchStoreList > EnchantmentStore
std::vector< EnchStoreItem > EnchStoreList
@ INVTYPE_BODY
@ INVTYPE_FINGER
@ INVTYPE_HEAD
@ INVTYPE_CLOAK
@ INVTYPE_ROBE
@ INVTYPE_HOLDABLE
@ INVTYPE_TRINKET
@ INVTYPE_RELIC
@ INVTYPE_RANGED
@ INVTYPE_THROWN
@ INVTYPE_WAIST
@ INVTYPE_RANGEDRIGHT
@ INVTYPE_WRISTS
@ INVTYPE_WEAPON
@ INVTYPE_WEAPONMAINHAND
@ INVTYPE_WEAPONOFFHAND
@ INVTYPE_2HWEAPON
@ INVTYPE_BAG
@ INVTYPE_NECK
@ INVTYPE_SHOULDERS
@ INVTYPE_FEET
@ INVTYPE_NON_EQUIP
@ INVTYPE_AMMO
@ INVTYPE_QUIVER
@ INVTYPE_SHIELD
@ INVTYPE_TABARD
@ INVTYPE_LEGS
@ INVTYPE_CHEST
@ INVTYPE_HANDS
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition Log.h:159
#define sObjectMgr
Definition ObjectMgr.h:1721
double rand_chance()
Definition Random.cpp:81
int32 irand(int32 min, int32 max)
Definition Random.cpp:35
@ ITEM_QUALITY_UNCOMMON
@ ITEM_QUALITY_RARE
@ ITEM_QUALITY_LEGENDARY
@ ITEM_QUALITY_ARTIFACT
@ ITEM_QUALITY_EPIC
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
Class used to access individual fields of database query result.
Definition Field.h:92
float GetFloat() const
Definition Field.cpp:93
uint32 GetUInt32() const
Definition Field.cpp:61
EnchStoreItem(uint32 _ench, float _chance)
int32 RandomProperty
uint32 InventoryType