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