TrinityCore
SkillExtraItems.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 "SkillExtraItems.h"
19#include "DatabaseEnv.h"
20#include "Log.h"
21#include "ObjectMgr.h"
22#include "Player.h"
23#include "SpellMgr.h"
24
25// some type definitions
26// no use putting them in the header file, they're only used in this .cpp
27
28// struct to store information about perfection procs
29// one entry per spell
31{
32 // the spell id of the spell required - it's named "specialization" to conform with SkillExtraItemEntry
34 // perfection proc chance
36 // itemid of the resulting perfect item
38
43};
44
45// map to store perfection info. key = spellId of the creation spell, value is the perfectitementry as specified above
46typedef std::map<uint32, SkillPerfectItemEntry> SkillPerfectItemMap;
47
49
50// loads the perfection proc info from DB
52{
53 uint32 oldMSTime = getMSTime();
54
55 SkillPerfectItemStore.clear(); // reload capability
56
57 // 0 1 2 3
58 QueryResult result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, perfectCreateChance, perfectItemType FROM skill_perfect_item_template");
59
60 if (!result)
61 {
62 TC_LOG_INFO("server.loading", ">> Loaded 0 spell perfection definitions. DB table `skill_perfect_item_template` is empty.");
63 return;
64 }
65
66 uint32 count = 0;
67
68 do /* fetch data and run sanity checks */
69 {
70 Field* fields = result->Fetch();
71
72 uint32 spellId = fields[0].GetUInt32();
73
74 if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
75 {
76 TC_LOG_ERROR("sql.sql", "Skill perfection data for spell {} has a non-existing spell id in the `skill_perfect_item_template`!", spellId);
77 continue;
78 }
79
80 uint32 requiredSpecialization = fields[1].GetUInt32();
81 if (!sSpellMgr->GetSpellInfo(requiredSpecialization, DIFFICULTY_NONE))
82 {
83 TC_LOG_ERROR("sql.sql", "Skill perfection data for spell {} has a non-existing required specialization spell id {} in the `skill_perfect_item_template`!", spellId, requiredSpecialization);
84 continue;
85 }
86
87 float perfectCreateChance = fields[2].GetFloat();
88 if (perfectCreateChance <= 0.0f)
89 {
90 TC_LOG_ERROR("sql.sql", "Skill perfection data for spell {} has impossibly low proc chance in the `skill_perfect_item_template`!", spellId);
91 continue;
92 }
93
94 uint32 perfectItemType = fields[3].GetUInt32();
95 if (!sObjectMgr->GetItemTemplate(perfectItemType))
96 {
97 TC_LOG_ERROR("sql.sql", "Skill perfection data for spell {} references a non-existing perfect item id {} in the `skill_perfect_item_template`!", spellId, perfectItemType);
98 continue;
99 }
100
101 SkillPerfectItemEntry& skillPerfectItemEntry = SkillPerfectItemStore[spellId];
102
103 skillPerfectItemEntry.requiredSpecialization = requiredSpecialization;
104 skillPerfectItemEntry.perfectCreateChance = perfectCreateChance;
105 skillPerfectItemEntry.perfectItemType = perfectItemType;
106
107 ++count;
108 }
109 while (result->NextRow());
110
111 TC_LOG_INFO("server.loading", ">> Loaded {} spell perfection definitions in {} ms.", count, GetMSTimeDiffToNow(oldMSTime));
112}
113
114// struct to store information about extra item creation
115// one entry for every spell that is able to create an extra item
117{
118 // the spell id of the specialization required to create extra items
120 // the chance to create one additional item
122 // maximum number of extra items created per crafting
124
127
128 SkillExtraItemEntry(uint32 rS, float aCC, uint8 aMN)
130};
131
132// map to store the extra item creation info, the key is the spellId of the creation spell, the mapped value is the assigned SkillExtraItemEntry
133typedef std::map<uint32, SkillExtraItemEntry> SkillExtraItemMap;
134
136
137// loads the extra item creation info from DB
139{
140 uint32 oldMSTime = getMSTime();
141
142 SkillExtraItemStore.clear(); // need for reload
143
144 // 0 1 2 3
145 QueryResult result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template");
146
147 if (!result)
148 {
149 TC_LOG_INFO("server.loading", ">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty.");
150 return;
151 }
152
153 uint32 count = 0;
154
155 do
156 {
157 Field* fields = result->Fetch();
158
159 uint32 spellId = fields[0].GetUInt32();
160
161 if (!sSpellMgr->GetSpellInfo(spellId, DIFFICULTY_NONE))
162 {
163 TC_LOG_ERROR("sql.sql", "Skill specialization {} has a non-existing spell id in the `skill_extra_item_template`!", spellId);
164 continue;
165 }
166
167 uint32 requiredSpecialization = fields[1].GetUInt32();
168 if (!sSpellMgr->GetSpellInfo(requiredSpecialization, DIFFICULTY_NONE))
169 {
170 TC_LOG_ERROR("sql.sql", "Skill specialization {} has a non-existing required specialization spell id {} in the `skill_extra_item_template`!", spellId, requiredSpecialization);
171 continue;
172 }
173
174 float additionalCreateChance = fields[2].GetFloat();
175 if (additionalCreateChance <= 0.0f)
176 {
177 TC_LOG_ERROR("sql.sql", "Skill specialization {} has too low additional create chance in the `skill_extra_item_template`!", spellId);
178 continue;
179 }
180
181 uint8 additionalMaxNum = fields[3].GetUInt8();
182 if (!additionalMaxNum)
183 {
184 TC_LOG_ERROR("sql.sql", "Skill specialization {} has 0 max number of extra items in the `skill_extra_item_template`!", spellId);
185 continue;
186 }
187
188 SkillExtraItemEntry& skillExtraItemEntry = SkillExtraItemStore[spellId];
189
190 skillExtraItemEntry.requiredSpecialization = requiredSpecialization;
191 skillExtraItemEntry.additionalCreateChance = additionalCreateChance;
192 skillExtraItemEntry.additionalMaxNum = additionalMaxNum;
193
194 ++count;
195 }
196 while (result->NextRow());
197
198 TC_LOG_INFO("server.loading", ">> Loaded {} spell specialization definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
199}
200
201bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType)
202{
203 SkillPerfectItemMap::const_iterator ret = SkillPerfectItemStore.find(spellId);
204 // no entry in DB means no perfection proc possible
205 if (ret == SkillPerfectItemStore.end())
206 return false;
207
208 SkillPerfectItemEntry const* thisEntry = &ret->second;
209
210 // if you don't have the spell needed, then no procs for you
211 if (!player->HasSpell(thisEntry->requiredSpecialization))
212 return false;
213
214 // set values as appropriate
215 perfectCreateChance = thisEntry->perfectCreateChance;
216 perfectItemType = thisEntry->perfectItemType;
217
218 // and tell the caller to start rolling the dice
219 return true;
220}
221
222bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax)
223{
224 // get the info for the specified spell
225 SkillExtraItemMap::const_iterator ret = SkillExtraItemStore.find(spellId);
226 if (ret == SkillExtraItemStore.end())
227 return false;
228
229 SkillExtraItemEntry const* specEntry = &ret->second;
230
231 // the player doesn't have the required specialization, return false
232 if (!player->HasSpell(specEntry->requiredSpecialization))
233 return false;
234
235 // set the arguments to the appropriate values
236 additionalChance = specEntry->additionalCreateChance;
237 additionalMax = specEntry->additionalMaxNum;
238
239 // enable extra item creation
240 return true;
241}
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
#define sObjectMgr
Definition: ObjectMgr.h:1946
void LoadSkillPerfectItemTable()
bool CanCreateExtraItems(Player *player, uint32 spellId, float &additionalChance, uint8 &additionalMax)
void LoadSkillExtraItemTable()
bool CanCreatePerfectItem(Player *player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType)
std::map< uint32, SkillExtraItemEntry > SkillExtraItemMap
SkillPerfectItemMap SkillPerfectItemStore
SkillExtraItemMap SkillExtraItemStore
std::map< uint32, SkillPerfectItemEntry > SkillPerfectItemMap
#define sSpellMgr
Definition: SpellMgr.h:849
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:90
uint8 GetUInt8() const
Definition: Field.cpp:30
float GetFloat() const
Definition: Field.cpp:94
uint32 GetUInt32() const
Definition: Field.cpp:62
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3792
SkillExtraItemEntry(uint32 rS, float aCC, uint8 aMN)
SkillPerfectItemEntry(uint32 rS, float pCC, uint32 pIT)