1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
|
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TRINITY_ACHIEVEMENTMGR_H
#define __TRINITY_ACHIEVEMENTMGR_H
#include <map>
#include <string>
#include "Common.h"
#include "DatabaseEnv.h"
#include "DBCEnums.h"
#include "DBCStores.h"
#include "ObjectGuid.h"
class Unit;
class Player;
class WorldPacket;
typedef std::vector<AchievementCriteriaEntry const*> AchievementCriteriaEntryList;
typedef std::vector<AchievementEntry const*> AchievementEntryList;
typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
typedef std::unordered_map<uint32, AchievementEntryList> AchievementListByReferencedId;
struct CriteriaProgress
{
uint64 counter;
time_t date; // latest update time.
ObjectGuid CompletedGUID; // GUID of the player that completed this criteria (guild achievements)
bool changed;
};
enum AchievementCriteriaDataType
{ // value1 value2 comment
ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx
ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8, // minvalue value provided with achievement update must be not less that limit
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9, // minlevel minlevel of target
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10, // gender 0=male; 1=female
ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11, // scripted requirement
// REUSE
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13, // count "with less than %u people in the zone"
ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14, // team HORDE(67), ALLIANCE(469)
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15, // drunken_state 0 (enum DrunkenState) of player
ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16, // holiday_id 0 event in holiday time
ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // min_score max_score player's team win bg and opposition team have team score in range
ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id
// REUSE
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23, // title_id known (pvp) title, values from dbc
ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT = 24, // game_event_id 0
MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE
};
struct AchievementCriteriaData
{
AchievementCriteriaDataType dataType;
union
{
// ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1
struct
{
uint32 id;
} creature;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21
struct
{
uint32 class_id;
uint32 race_id;
} classRace;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH = 3
struct
{
uint32 percent;
} health;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7
struct
{
uint32 spell_id;
uint32 effect_idx;
} aura;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8
struct
{
uint32 value;
uint32 compType;
} value;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9
struct
{
uint32 minlevel;
} level;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER = 10
struct
{
uint32 gender;
} gender;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT = 11 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
struct
{
uint32 maxcount;
} map_players;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14
struct
{
uint32 team;
} team;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15
struct
{
uint32 state;
} drunk;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16
struct
{
uint32 id;
} holiday;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE= 17
struct
{
uint32 min_score;
uint32 max_score;
} bg_loss_team_score;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data)
// ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19
struct
{
uint32 item_level;
uint32 item_quality;
} equipped_item;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20
struct
{
uint32 mapId;
} map_id;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 22
struct
{
uint32 title_id;
} known_title;
// ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT = 24
struct
{
uint32 id;
} game_event;
// raw
struct
{
uint32 value1;
uint32 value2;
} raw;
};
uint32 ScriptId;
AchievementCriteriaData() : dataType(ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
{
raw.value1 = 0;
raw.value2 = 0;
ScriptId = 0;
}
AchievementCriteriaData(uint32 _dataType, uint32 _value1, uint32 _value2, uint32 _scriptId) : dataType(AchievementCriteriaDataType(_dataType))
{
raw.value1 = _value1;
raw.value2 = _value2;
ScriptId = _scriptId;
}
bool IsValid(AchievementCriteriaEntry const* criteria);
bool Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 = 0) const;
};
struct AchievementCriteriaDataSet
{
AchievementCriteriaDataSet() : criteria_id(0) { }
typedef std::vector<AchievementCriteriaData> Storage;
void Add(AchievementCriteriaData const& data) { storage.push_back(data); }
bool Meets(Player const* source, Unit const* target, uint32 miscValue = 0) const;
void SetCriteriaId(uint32 id) {criteria_id = id;}
private:
uint32 criteria_id;
Storage storage;
};
typedef std::map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
struct AchievementReward
{
uint32 titleId[2];
uint32 itemId;
uint32 sender;
std::string subject;
std::string text;
uint32 mailTemplate;
};
typedef std::unordered_map<uint32, AchievementReward> AchievementRewards;
struct AchievementRewardLocale
{
std::vector<std::string> subject;
std::vector<std::string> text;
};
typedef std::unordered_map<uint32, AchievementRewardLocale> AchievementRewardLocales;
struct CompletedAchievementData
{
time_t date;
GuidSet guids;
bool changed;
};
typedef std::unordered_map<uint32, CriteriaProgress> CriteriaProgressMap;
typedef std::unordered_map<uint32, CompletedAchievementData> CompletedAchievementMap;
enum ProgressType
{
PROGRESS_SET,
PROGRESS_ACCUMULATE,
PROGRESS_HIGHEST
};
template<class T>
class AchievementMgr
{
public:
AchievementMgr(T* owner);
~AchievementMgr();
void Reset();
static void DeleteFromDB(ObjectGuid lowguid);
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(SQLTransaction& trans);
void ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit const* unit = NULL, Player* referencePlayer = NULL);
void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
void CheckAllAchievementCriteria(Player* referencePlayer);
void SendAllAchievementData(Player* receiver) const;
void SendAllTrackedCriterias(Player* receiver, std::set<uint32> const& trackedCriterias) const;
void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
bool HasAchieved(uint32 achievementId) const;
T* GetOwner() const { return _owner; }
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
uint32 GetAchievementPoints() const { return _achievementPoints; }
private:
void SendAchievementEarned(AchievementEntry const* achievement) const;
void SendCriteriaUpdate(AchievementCriteriaEntry const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const;
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype = PROGRESS_SET);
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
void CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer);
bool IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement);
bool IsCompletedAchievement(AchievementEntry const* entry);
bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer);
void SendPacket(WorldPacket* data) const;
bool ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const;
bool RequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const;
bool AdditionalRequirementsSatisfied(AchievementCriteriaEntry const* criteria, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const;
T* _owner;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
typedef std::map<uint32, uint32> TimedAchievementMap;
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
uint32 _achievementPoints;
};
class AchievementGlobalMgr
{
AchievementGlobalMgr() { }
~AchievementGlobalMgr() { }
public:
static char const* GetCriteriaTypeString(AchievementCriteriaTypes type);
static char const* GetCriteriaTypeString(uint32 type);
static AchievementGlobalMgr* instance()
{
static AchievementGlobalMgr instance;
return &instance;
}
AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, bool guild = false) const
{
return guild ? m_GuildAchievementCriteriasByType[type] : m_AchievementCriteriasByType[type];
}
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
{
return m_AchievementCriteriasByTimedType[type];
}
AchievementCriteriaEntryList const* GetAchievementCriteriaByAchievement(uint32 id) const
{
AchievementCriteriaListByAchievement::const_iterator itr = m_AchievementCriteriaListByAchievement.find(id);
return itr != m_AchievementCriteriaListByAchievement.end() ? &itr->second : NULL;
}
AchievementEntryList const* GetAchievementByReferencedId(uint32 id) const
{
AchievementListByReferencedId::const_iterator itr = m_AchievementListByReferencedId.find(id);
return itr != m_AchievementListByReferencedId.end() ? &itr->second : NULL;
}
AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const
{
AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID);
return iter != m_achievementRewards.end() ? &iter->second : NULL;
}
AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const
{
AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID);
return iter != m_achievementRewardLocales.end() ? &iter->second : NULL;
}
AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const* achievementCriteria) const
{
AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID);
return iter != m_criteriaDataMap.end() ? &iter->second : NULL;
}
bool IsRealmCompleted(AchievementEntry const* achievement, uint32 instanceId) const
{
AllCompletedAchievements::const_iterator itr = m_allCompletedAchievements.find(achievement->ID);
if (itr == m_allCompletedAchievements.end())
return false;
if (achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)
return itr->second != instanceId;
return true;
}
void SetRealmCompleted(AchievementEntry const* achievement, uint32 instanceId)
{
if (IsRealmCompleted(achievement, instanceId))
return;
m_allCompletedAchievements[achievement->ID] = instanceId;
}
bool IsGroupCriteriaType(AchievementCriteriaTypes type) const
{
switch (type)
{
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // NYI
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: // NYI
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND: // NYI
return true;
default:
break;
}
return false;
}
// Removes instanceId as valid id to complete realm first kill achievements
void OnInstanceDestroyed(uint32 instanceId);
void LoadAchievementCriteriaList();
void LoadAchievementCriteriaData();
void LoadAchievementReferenceList();
void LoadCompletedAchievements();
void LoadRewards();
void LoadRewardLocales();
AchievementEntry const* GetAchievement(uint32 achievementId) const;
AchievementCriteriaEntry const* GetAchievementCriteria(uint32 achievementId) const;
private:
AchievementCriteriaDataMap m_criteriaDataMap;
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_GuildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
// store achievement criterias by achievement to speed up lookup
AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement;
// store achievements by referenced achievement id to speed up lookup
AchievementListByReferencedId m_AchievementListByReferencedId;
typedef std::map<uint32 /*achievementId*/, uint32 /*instanceId*/> AllCompletedAchievements;
AllCompletedAchievements m_allCompletedAchievements;
AchievementRewards m_achievementRewards;
AchievementRewardLocales m_achievementRewardLocales;
};
#define sAchievementMgr AchievementGlobalMgr::instance()
#endif
|