Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
CharacterBoost.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "CharacterBoost.h"
7#include "Config.h"
8#include "WorldSession.h"
9
11
12SlotEquipmentMap const* CharacterBooster::_GetCharBoostItems(std::vector<std::pair<uint32, uint32> >& itemsToMail) const
13{
14 itemsToMail.push_back(std::make_pair(LEMON_FLAVOUR_PUDING_ID, LEMON_FLAVOUR_PUDING_COUNT));
15
16 switch (m_charBoostInfo.specialization)
17 {
28 return &druidEquipmentFeral;
34 return &hunterEquipment;
36 case SPEC_MAGE_FIRE:
37 case SPEC_MAGE_FROST:
38 //itemsToMail.push_back(std::make_pair(101081, 1));
39 return &mageEquipment;
54 //itemsToMail.push_back(std::make_pair(101172, 1));
57 //itemsToMail.push_back(std::make_pair(101172, 1));
74 //itemsToMail.push_back(std::make_pair(101275, 1));
75 return &warlockEquipment;
82 default:
83 return NULL;
84 }
85}
86
88{
89 ObjectGuid guid = m_charBoostInfo.charGuid;
90 WorldPacket data(SMSG_BATTLE_PAY_BOOST_ITEMS, 8 + 3 + items->size());
91
92 data.WriteGuidMask(guid, 2, 0, 7, 5, 3, 4, 1);
93 data.WriteBits(items->size(), 22);
94 data.WriteBit(guid[6]);
95
96 data.FlushBits();
97
98 data.WriteGuidBytes(guid, 7, 2, 6, 5);
99
100 for (SlotEquipmentMap::const_iterator itr = items->begin(); itr != items->end(); ++itr)
101 data << (uint32)itr->second;
102
103 data.WriteGuidBytes(guid, 0, 1, 3, 4);
104
105 m_session->SendPacket(&data);
106}
107
108uint32 CharacterBooster::_PrepareMail(SQLTransaction& trans, std::string const& subject, std::string const& body) const
109{
110 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL);
111 uint32 mailId = sObjectMgr->GenerateMailID();
112
113 stmt->setUInt32(0, mailId);
114 stmt->setUInt8(1, MAIL_NORMAL);
116 stmt->setUInt16(3, 0);
117 stmt->setUInt32(4, m_charBoostInfo.lowGuid);
118 stmt->setUInt32(5, m_charBoostInfo.lowGuid);
119 stmt->setString(6, subject);
120 stmt->setString(7, body);
121 stmt->setBool(8, true);
122 stmt->setUInt64(9, time(NULL) + 180 * DAY);
123 stmt->setUInt64(10, time(NULL));
124 stmt->setUInt32(11, 0);
125 stmt->setUInt32(12, 0);
126 stmt->setUInt8(13, 0);
127
128 trans->Append(stmt);
129
130 return mailId;
131}
132
133void CharacterBooster::_SendMail(SQLTransaction& trans, std::vector<std::pair<uint32, uint32> > const& items) const
134{
135 if (items.empty())
136 return;
137
139 PreparedStatement* stmt = NULL;
140
141 Player* player = sObjectAccessor->FindPlayer(m_charBoostInfo.charGuid);
142 for (uint8 i = 0; i < items.size(); i++)
143 {
144 if (Item* item = Item::CreateItem(items[i].first, items[i].second, player))
145 {
146 item->SetBinding(true);
147 item->SaveToDB(trans);
148 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM);
149
150 stmt->setUInt32(0, mailId);
151 stmt->setUInt32(1, item->GetGUIDLow());
152 stmt->setUInt32(2, m_charBoostInfo.lowGuid);
153
154 trans->Append(stmt);
155 }
156 }
157}
158
160{
162 stmt->setUInt32(0, 0);
164 stmt->setUInt32(2, m_charBoostInfo.lowGuid);
165 PreparedQueryResult result = CharacterDatabase.Query(stmt);
166
167 if (!result)
168 return;
169
171 uint32 itemCount = 0;
172
173 do
174 {
175 if (itemCount++ > 10)
176 {
177 itemCount = 0;
179 }
180
181 uint32 itemGuid = (*result)[0].GetUInt32();
182 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM);
183
184 stmt->setUInt32(0, mailId);
185 stmt->setUInt32(1, itemGuid);
186 stmt->setUInt32(2, m_charBoostInfo.lowGuid);
187
188 trans->Append(stmt);
189 } while (result->NextRow());
190
191 // unEquip after sending
193
194 stmt->setUInt32(0, 0);
196 stmt->setUInt32(2, m_charBoostInfo.lowGuid);
197
198 trans->Append(stmt);
199}
200
201std::string CharacterBooster::_SetSpecialization(SQLTransaction& trans, uint8 const& classId) const
202{
203 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_TALENT);
204 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
205 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
206 {
207 do
208 {
209 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
210 stmt->setUInt32(0, (*result)[0].GetUInt32());
211 stmt->setUInt32(1, m_charBoostInfo.lowGuid);
212 trans->Append(stmt);
213 } while (result->NextRow());
214 }
215
216 if (uint32 const* specs = GetClassSpecializations(classId))
217 {
218 for (uint8 i = 0; i < MAX_TALENT_TABS; i++)
219 {
220 if (std::vector<uint32> const* spells = GetSpecializationSpells(specs[i]))
221 {
222 for (std::vector<uint32>::const_iterator iter = spells->begin(); iter != spells->end(); ++iter)
223 {
224 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL);
225 stmt->setUInt32(0, *iter);
226 stmt->setUInt32(1, m_charBoostInfo.lowGuid);
227 trans->Append(stmt);
228 }
229 }
230 }
231 }
232
233 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT);
234 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
235 trans->Append(stmt);
236
237 std::ostringstream talentTree;
238 talentTree << m_charBoostInfo.specialization << " 0 ";
239 return talentTree.str();
240}
241
242void CharacterBooster::_LearnSpells(SQLTransaction& trans, uint8 const& raceId, uint8 const& classId) const
243{
244 PreparedStatement* stmt;
245 uint32 const* languageSpells = NULL;
246
247 if (raceId == RACE_PANDAREN_HORDE)
248 languageSpells = pandarenLanguageSpellsHorde;
249 else if (raceId == RACE_PANDAREN_ALLIANCE)
250 languageSpells = pandarenLanguageSpellsAlliance;
251
252 if (languageSpells)
253 {
254 for (uint8 i = 0; i < PANDAREN_FACTION_LANGUAGE_COUNT; i++)
255 {
256 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SPELL);
257
258 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
259 stmt->setUInt32(1, languageSpells[i]);
260 stmt->setBool(2, true);
261 stmt->setBool(3, false);
262
263 trans->Append(stmt);
264 }
265 }
266
267 std::vector<uint32> spellsToLearn(CharBoostSpells);
268 spellsToLearn.push_back(m_charBoostInfo.allianceFaction ? SWIFT_PURPLE_GRYPGON_SPELL : SWIFT_PURPLE_WIND_RIDER_SPELL);
269
270 switch (classId)
271 {
272 case CLASS_WARRIOR:
273 case CLASS_PALADIN:
274 spellsToLearn.push_back(PLATE_MAIL_ARMOR_SPELL);
275 break;
276 default:
277 break;
278 }
279
280 for (uint8 i = 0; i < spellsToLearn.size(); i++)
281 {
282 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_SPELL);
283
284 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
285 stmt->setUInt32(1, spellsToLearn[i]);
286 stmt->setBool(2, true);
287 stmt->setBool(3, false);
288
289 trans->Append(stmt);
290 }
291}
292
294{
295 uint8 charRace = 0;
296 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE);
297 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
298
299 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
300 {
301 charRace = (*result)[0].GetUInt8();
302 if (charRace == RACE_PANDAREN_NEUTRAL)
303 charRace = m_charBoostInfo.allianceFaction ? RACE_PANDAREN_ALLIANCE : RACE_PANDAREN_HORDE;
304 }
305
306 return charRace;
307}
308
309std::string CharacterBooster::_EquipItems(SQLTransaction& trans, SlotEquipmentMap const* itemsToEquip) const
310{
311 SlotEquipmentMap::const_iterator itr;
312 std::ostringstream items;
313 PreparedStatement* stmt;
314 Player* player = sObjectAccessor->FindPlayer(m_charBoostInfo.charGuid);
315
316 for (uint8 i = 0; i < INVENTORY_SLOT_BAG_END; i++)
317 {
318 itr = itemsToEquip->find(i);
319 if (itr != itemsToEquip->end())
320 {
321 if (Item* item = Item::CreateItem(itr->second, 1, player))
322 {
323 item->SetBinding(true);
324 item->SaveToDB(trans);
325
326 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_INVENTORY);
327
328 stmt->setUInt32(0, m_charBoostInfo.lowGuid);
329 stmt->setUInt32(1, 0);
330 stmt->setUInt8(2, itr->first);
331 stmt->setUInt32(3, item->GetGUIDLow());
332
333 trans->Append(stmt);
334
335 items << (itr->second) << " 0 ";
336 }
337 else
338 items << "0 0 ";
339 }
340 else
341 items << "0 0 ";
342 }
343
344 return items.str();
345}
346
347void CharacterBooster::_SaveBoostedChar(SQLTransaction& trans, std::string const& items, uint8 const& raceId, uint8 const& classId) const
348{
349 float const* position = m_charBoostInfo.allianceFaction ? startPosition[1] : startPosition[0];
351
352 stmt->setUInt8(0, raceId);
355 stmt->setFloat(3, position[0]);
356 stmt->setFloat(4, position[1]);
357 stmt->setFloat(5, position[2]);
358 stmt->setFloat(6, position[3]);
360 stmt->setString(8, _SetSpecialization(trans, classId));
361 stmt->setUInt16(9, AT_LOGIN_FIRST);
362 stmt->setString(10, items);
363 stmt->setUInt32(11, m_charBoostInfo.lowGuid);
364
365 trans->Append(stmt);
366}
367
369{
370 uint8 classId = 0;
371
372 if (ChrSpecializationEntry const* specEntry = sChrSpecializationStore.LookupEntry(m_charBoostInfo.specialization))
373 classId = specEntry->classId;
374
375 if (!classId)
376 return;
377
378 uint8 raceId = _GetRace();
379 if (!raceId)
380 return;
381
382 std::vector<std::pair<uint32, uint32> > itemsToMail;
383 SlotEquipmentMap const* itemsToEquip = _GetCharBoostItems(itemsToMail);
384 if (!itemsToEquip)
385 return;
386
387 SQLTransaction trans = CharacterDatabase.BeginTransaction();
388 _MailEquipedItems(trans);
389 _SendMail(trans, itemsToMail);
390 _LearnSpells(trans, raceId, classId);
391 _EquipItems(trans, &embersilkBags);
392 _SaveBoostedChar(trans, _EquipItems(trans, itemsToEquip), raceId, classId);
393 CharacterDatabase.CommitTransaction(trans);
394 m_session->SetBoosting(false);
395 _SendCharBoostPacket(itemsToEquip);
396}
397
399{
400 if (!m_charBoostInfo.charGuid)
401 return;
402
403 switch (m_charBoostInfo.action)
404 {
406 m_session->SendBattlePayDistributionUpdate(m_charBoostInfo.charGuid, CHARACTER_BOOST, m_charBoostInfo.action,
409 m_timer = 500;
410 m_sendPacket = true;
411 break;
413 m_session->SendBattlePayDistributionUpdate(m_charBoostInfo.charGuid, CHARACTER_BOOST, m_charBoostInfo.action,
416 break;
417 default:
418 break;
419 }
420}
421
422void CharacterBooster::SetBoostedCharInfo(uint64 guid, uint32 action, uint32 specialization, bool allianceFaction)
423{
424 m_boosting = true;
425 m_charBoostInfo.charGuid = guid;
426 m_charBoostInfo.lowGuid = GUID_LOPART(guid);
427 m_charBoostInfo.action = action;
428 m_charBoostInfo.specialization = specialization;
429 m_charBoostInfo.allianceFaction = allianceFaction;
430}
431
433{
434 if (m_sendPacket)
435 {
436 if (m_timer <= diff)
437 {
438 m_sendPacket = false;
440 }
441 else
442 m_timer -= diff;
443 }
444}
SlotEquipmentMap const deathKnightEquipmentUnholy
SlotEquipmentMap const druidEquipmentBalance
SlotEquipmentMap const shamanEquipmentRestoration
SlotEquipmentMap const embersilkBags
std::map< uint8, uint32 > SlotEquipmentMap
SlotEquipmentMap const druidEquipmentRestoration
SlotEquipmentMap const paladinEquipmentHoly
SlotEquipmentMap const monkEquipmentWindwalker
SlotEquipmentMap const deathKnightEquipmentFrost
#define CHARRACTER_BOOST_EQUIPED_ITEMS_MAIL_BODY
SlotEquipmentMap const shamanEquipmentElemental
float const startPosition[2][4]
SlotEquipmentMap const warriorEquipmentProtection
SlotEquipmentMap const monkEquipmentMistweaver
SlotEquipmentMap const shamanEquipmentEnhancement
SlotEquipmentMap const rogueEquipmentCombat
#define CHARRACTER_BOOST_EQUIPED_ITEMS_MAIL_SUBJECT
std::vector< uint32 > const CharBoostSpells
SlotEquipmentMap const paladinEquipmentProtection
@ SWIFT_PURPLE_GRYPGON_SPELL
@ PLATE_MAIL_ARMOR_SPELL
@ LEMON_FLAVOUR_PUDING_ID
@ LEMON_FLAVOUR_PUDING_COUNT
@ SWIFT_PURPLE_WIND_RIDER_SPELL
@ VALE_OF_ETERNAL_BLOSSOMS_MAP_ID
SlotEquipmentMap const paladinEquipmentRetribution
SlotEquipmentMap const deathKnightEquipmentBlood
SlotEquipmentMap const priestEquipmentDisciplineAndHoly
SlotEquipmentMap const warlockEquipment
SlotEquipmentMap const hunterEquipment
SlotEquipmentMap const monkEquipmentBrewmaster
SlotEquipmentMap const warriorEquipmentArms
SlotEquipmentMap const mageEquipment
SlotEquipmentMap const priestEquipmentShadow
SlotEquipmentMap const rogueEquipmentAssassionation
SlotEquipmentMap const druidEquipmentFeral
SlotEquipmentMap const warriorEquipmentFury
@ CHAR_UPD_CHARACTER_BOOST
@ CHAR_INS_CHAR_SPELL
@ CHAR_INS_CHAR_INVENTORY
@ CHAR_SEL_CHAR_INVENTORY_ITEM_GUID_UNTIL_BAG_SLOT
@ CHAR_INS_MAIL_ITEM
@ CHAR_DEL_CHAR_INVENTORY_UNTIL_BAG_SLOT
@ CHAR_SEL_CHAR_TALENT
@ CHAR_DEL_CHAR_SPELL_BY_SPELL
@ CHAR_DEL_CHAR_TALENT
@ CHAR_INS_MAIL
@ CHAR_SEL_CHAR_RACE
@ DAY
Definition Common.h:121
std::vector< uint32 > const * GetSpecializationSpells(uint32 specializationId)
uint32 const * GetClassSpecializations(uint8 classId)
DBCStorage< ChrSpecializationEntry > sChrSpecializationStore(ChrSpecializationfmt)
#define MAX_TALENT_TABS
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
@ MAIL_STATIONERY_DEFAULT
Definition Mail.h:46
@ MAIL_NORMAL
Definition Mail.h:24
#define sObjectAccessor
uint32 GUID_LOPART(uint64 x)
#define sObjectMgr
Definition ObjectMgr.h:1617
uint32 const pandarenLanguageSpellsAlliance[]
Definition Player.h:113
uint32 const pandarenLanguageSpellsHorde[]
Definition Player.h:120
@ INVENTORY_SLOT_BAG_END
Definition Player.h:714
@ EQUIPMENT_SLOT_END
Definition Player.h:708
@ AT_LOGIN_FIRST
Definition Player.h:622
#define PANDAREN_FACTION_LANGUAGE_COUNT
Definition Player.h:127
Skyfire::AutoPtr< PreparedResultSet, Skyfire::Mutex > PreparedQueryResult
Definition QueryResult.h:94
@ SPEC_WARRIOR_PROTECTION
@ SPEC_WARRIOR_FURY
@ SPEC_PALADIN_RETRIBUTION
@ SPEC_WARLOCK_DEMONOLOGY
@ SPEC_ROGUE_COMBAT
@ SPEC_DRUID_GUARDIAN
@ SPEC_MONK_WINDWALKER
@ SPEC_MONK_BREWMASTER
@ SPEC_MONK_MISTWEAVER
@ SPEC_DRUID_BALANCE
@ SPEC_PRIEST_SHADOW
@ SPEC_PALADIN_PROTECTION
@ SPEC_DRUID_RESTORATION
@ SPEC_MAGE_FIRE
@ SPEC_DEATH_KNIGHT_FROST
@ SPEC_HUNTER_BEAST_MASTERY
@ SPEC_DEATH_KNIGHT_UNHOLY
@ SPEC_DEATH_KNIGHT_BLOOD
@ SPEC_PRIEST_HOLY
@ SPEC_SHAMAN_ELEMENTAL
@ SPEC_HUNTER_MARKSMANSHIP
@ SPEC_MAGE_FROST
@ SPEC_WARRIOR_ARMS
@ SPEC_DRUID_FERAL
@ SPEC_MAGE_ARCANE
@ SPEC_WARLOCK_DESTRUCTION
@ SPEC_SHAMAN_RESTORATION
@ SPEC_PRIEST_DISCIPLINE
@ SPEC_HUNTER_SURVIVAL
@ SPEC_PALADIN_HOLY
@ SPEC_ROGUE_ASSASSINATION
@ SPEC_WARLOCK_AFFLICTION
@ SPEC_SHAMAN_ENHANCEMENT
@ SPEC_ROGUE_SUBTLETY
#define CHARACTER_BOOST_BONUS_TEXT2
@ CLASS_WARRIOR
@ CLASS_PALADIN
@ CHARACTER_BOOST
@ CHARACTER_BOOST_APPLIED
@ CHARACTER_BOOST_ITEMS
@ CHARACTER_BOOST_TEXT_ID
@ RACE_PANDAREN_NEUTRAL
@ RACE_PANDAREN_ALLIANCE
@ RACE_PANDAREN_HORDE
#define CHARACTER_BOOST_BONUS_TEXT
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void FlushBits()
Definition ByteBuffer.h:154
WorldSession * m_session
CharacterBooster(WorldSession *session)
CharacterBoostData m_charBoostInfo
std::string _EquipItems(SQLTransaction &trans, SlotEquipmentMap const *itemsToEquip) const
uint32 _PrepareMail(SQLTransaction &trans, std::string const &subject, std::string const &body) const
void _HandleCharacterBoost() const
void SetBoostedCharInfo(uint64 guid, uint32 action, uint32 specialization, bool allianceFaction)
uint8 _GetRace() const
void _SendMail(SQLTransaction &trans, std::vector< std::pair< uint32, uint32 > > const &items) const
void _SaveBoostedChar(SQLTransaction &trans, std::string const &items, uint8 const &raceId, uint8 const &classId) const
void _LearnSpells(SQLTransaction &trans, uint8 const &raceId, uint8 const &classId) const
std::string _SetSpecialization(SQLTransaction &trans, uint8 const &classId) const
void Update(uint32 diff)
void _SendCharBoostPacket(SlotEquipmentMap const *items) const
SlotEquipmentMap const * _GetCharBoostItems(std::vector< std::pair< uint32, uint32 > > &itemsToMail) const
void _MailEquipedItems(SQLTransaction &trans) const
Definition Item.h:202
static Item * CreateItem(uint32 itemEntry, uint32 count, Player const *player=NULL)
Definition Item.cpp:1012
void setBool(const uint8 index, const bool value)
void setFloat(const uint8 index, const float value)
void setString(const uint8 index, const std::string &value)
void setUInt16(const uint8 index, const uint16 value)
void setUInt64(const uint8 index, const uint64 value)
void setInt8(const uint8 index, const int8 value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt8(const uint8 index, const uint8 value)
Player session in the World.
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_BATTLE_PAY_BOOST_ITEMS
Definition Opcodes.h:551
#define sWorld
Definition World.h:910
@ CONFIG_BOOST_START_MONEY
Definition World.h:367
@ CONFIG_BOOST_START_LEVEL
Definition World.h:368